Android source code "application interface" Analysis 2 (PackageManager and PackageManagerService ):
I. PackageManager:
In the previous article, we usedPackageManager'sGetPackageSizeInfo function to obtain detailed information about the application.PackageManagerTo find out.
1. PackageManager class:
It is an abstract class. We only list several functions to be discussed:
Definition: publicAbstractClassPackageManager{
//@Hide
Public abstract voidClearApplicationUserData(StringpackageName,
IPackageDataObserver observer );
//@Hide
Public abstract voidGetPackageSizeInfo(String packageName,
IPackageStatsObserver observer );
Public voidInstallPackage(Uri packageURI ){
InstallPackage(PackageURI, null, 0 );
}
Note:
1)HideThis means that we cannot directly call the settings method as mentioned in the previous article.GetPackageSizeInfoThe following method is invalid in our application:
PackageManager mPm = getPackageManager ();
MSizeObserver = newPkgSizeObserver ();
MPm.GetPackageSizeInfo(PackageName, mSizeObserver );
So what should we do to implement our functions?
This requiresJavaReflection mechanism,To callHide on the android framework layerFunctions.
In.
2) We found thatInstallPackageIt is easy to guess that such a function is used to install the application.
3) Again, this is definedAbstractSo, where is its implementation class?
We have not found any class that inherits from it.
In fact, the class that implements it is inPackageManagerService,Its definition is as follows::
ClassPackageManagerServiceExtendsIPackageManager. Stub{
FinalInstallerMInstaller ;//Very important
...
GetPackageSizeInfo (...)
...},
Here, we only useGetPackageSizeInfoFor example.
2. getPackageSizeInfoFunction:
Public voidGetPackageSizeInfo(Final String packageName,
Final IPackageStatsObserverobserver ){
MContext. enforceCallingOrSelfPermission (
Android. Manifest.Permission. GET_PACKAGE_SIZE, Null );
// Queue up an async operation since the package deletion may take alittle while.
MHandler. post (new Runnable (){
Public void run (){
MHandler. removeCallbacks (this );
PackageStats lStats = new PackageStats (packageName);
Final boolean succeded;
Synchronized (mInstallLock ){
Succeded =GetPackageSizeInfoLI(PackageName, lStats );
}
If (observer! = Null ){
Try {
Observer. onGetStatsCompleted(LStats, succeded );
} Catch (RemoteException e ){
Log. I (TAG, "Observer no longer exists .");
}
} // End if observer
} // End run
});
}
1 ). Note that,Permission. GET_PACKAGE_SIZEPermission.
2 ).PackageStats lStatsThe data will be stored,
3 ).GetPackageSizeInfoLI isMain functions.
4 ).OnGetStatsCompleted,We need to implement the callback function, which has been reflected in the previous article.
InGetPackageSizeInfoLI, Including:
Int res =MInstaller. getSizeInfo(PackageName, p. mPath,
PublicSrcDir, pStats );
WhileMInstallerYesInstallerType of an instance, in fact, it is a daemon with androidInstalldFor communication, throughSocket.
3. the Installer is defined as follows:
ClassInstaller{
Private static final String TAG = "Installer ";
InputStream mIn;
OutputStream mOut;
LocalSocket mSocket;
Byte buf [] = new byte [1024];
Int buflen = 0;
Private booleanConnect(){
If (mSocket! = Null ){
Return true;
}
Log. I (TAG, "connecting ...");
Try {
MSocket = new LocalSocket ();
LocalSocketAddress address = newLocalSocketAddress (
"Installd", LocalSocketAddress. Namespace. RESERVED );
MSocket. connect (address );
MIn = mSocket. getInputStream ();
MOut = mSocket. getOutputStream ();
} Catch (IOException ex ){
Disconnect ();
Return false;
}
Return true;
}
Private voidDisconnect(){
Log. I (TAG, "disconnecting ...");
Try {
If (mSocket! = Null) mSocket. close ();
} Catch (IOException ex ){}
Try {
If (mIn! = Null) mIn. close ();
} Catch (IOException ex ){}
Try {
If (mOut! = Null) mOut. close ();
} Catch (IOException ex ){}
MSocket = null;
MIn = null;
MOut = null;
}
Private booleanReadBytes(Byte buffer [], int len)
Private booleanWriteCommand(String _ cmd)
Private synchronizedStringTransaction(String cmd)
Private intExecute(String cmd ){
String res =Transaction(Cmd );
Try {
Return Integer. parseInt (res );
} Catch (NumberFormatException ex ){
Return-1;
}
}
Public intInstall(String name, int uid, int gid ){
StringBuilder builder = newStringBuilder ("Install");
Builder. append ('');
Builder. append (name );
Builder. append ('');
Builder. append (uid );
Builder. append ('');
Builder. append (gid );
Return execute (builder. toString ());
}
Public intFreeCache(Long freeStorageSize ){
StringBuilder builder = newStringBuilder ("Freecache");
Builder. append ('');
Builder. append (String. valueOf (freeStorageSize ));
Return execute (builder. toString ());
}
Public intGetSizeInfo(String pkgName, StringapkPath,
String fwdLockApkPath, PackageStatspStats ){
StringBuilder builder = newStringBuilder ("Getsize");
Builder. append ('');
Builder. append (pkgName );
Builder. append ('');
Builder. append (apkPath );
Builder. append ('');
Builder. append (fwdLockApkPath! = Null? FwdLockApkPath :"! ");
String s = transaction (builder. toString ());
String res [] = s. split ("");
If (res = null) | (res. length! = 4 )){
Return-1;
}
Try {
PStats. codeSize = Long. parseLong (res [1]);
PStats. dataSize = Long. parseLong (res [2]);
PStats. cacheSize = Long. parseLong (res [3]);
Return Integer. parseInt (res [0]);
} Catch (NumberFormatException e ){
Return-1;
}
}
Analysis:
1) In the connect function, the socket connection with it isInstalld. Installd is a daemon in android,Ps shows it. Its parent process isInitFor more details about the Android startup process, see the following article:
Http://blog.csdn.net/liranke/article/details/4694989.
2) There are someRead,WriteFunction, of course, is used to read and write data to the socket;
3)Install, freeCache, getSizeInfoOnly PASS commands with fixed stringsExecuteFunction;
4)ExecuteImplementation,Just pass the command stringTransactionAnd will callWriteCommandTo truly write the command into the connectedDaemonInstalld.
Now, it seems to be clear:
PackageManager------Aidl------->PackageManagerServiceInstaller---- Socket -------->Installd (c program ).
4.Installd:This is a daemon process written in c with the main function.Init. rcCall, the code is located:Framworks/base/cmds/installdDirectory. Among them, the last letter d is the code "dameon". In fact, many such daemon processes are defined in android, precisely because of their existence, the android system can run normally, and it is precisely because, in the whole system, this implementation method can be seen everywhere in android. For Installd, some interesting code snippets can be imagined. If you are interested, you can view the source code by yourself.
Installd. c:
Struct raise info cmds [] = {
{"Ping", 0, do_ping },
{"Install", 3, do_install },
{"Dexopt", 3, do_dexopt },
{"Movedex", 2, do_move_dex },
{"Rmdex", 1, do_rm_dex },
{"Remove", 1, do_remove },
{"Freecache", 1, do_free_cache },
{"Rmcache", 1, do_rm_cache },
{"Protect", 2, do_protect },
{"Getsize", 3, do_get_size },
{"Rmuserdata", 1, do_rm_user_data },
};
Oh, this is not fromPackageManagerServiceInstallerCan you think of the passed command string?
I wish my friends who have read this article draw a wonderful picture on android.