Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android源碼之“應用程序界面“分析二(PackageManager和PackageManagerService)

Android源碼之“應用程序界面“分析二(PackageManager和PackageManagerService)

編輯:關於Android編程

Android源碼之“應用程序界面“分析二(PackageManager和PackageManagerService):

一。PackageManager

上一篇中,我們用到了PackageManager的getPackageSizeInfo函數,來得到應用程序的詳細信息,這一篇中,我們將深入PackageManager的內部,來一探究竟。

1. PackageManager類:

它是一個抽象類,我們僅僅列出幾個要討論的函數:

定義: public abstract class PackageManager {


// @hide

public abstract void clearApplicationUserData(StringpackageName,

IPackageDataObserver observer);

// @hide

public abstract void getPackageSizeInfo(String packageName,
IPackageStatsObserver observer);

public void installPackage(Uri packageURI) {

installPackage(packageURI,null, 0);

}


說明:

1) Hide,意味著我們不能像上一篇文章中提到的settings中的實現方式來直接調用getPackageSizeInfo這樣的函數,也就是說,在我們的應用中,下面的做法是非法的:

PackageManager mPm = getPackageManager();
mSizeObserver = newPkgSizeObserver();
mPm.getPackageSizeInfo(packageName, mSizeObserver);

那麼,那麼,為了實現我們的功能,我們該如何做呢?

這就需要用到java反射機制來調用android framework層的hide的函數

在http://blog.csdn.net/liranke/article/details/13766349一篇文章中,詳細描述了這種實現方式。

2) 我們發現有installPackage這樣的函數,不難猜出,它是用來安裝應用程序的。

3) 再次提醒一下,這是一個定義為abstract的類,那麼,它的實現類在哪裡呢?

我們也沒有發現哪個類是繼承自它的啊。

事實上,實現它的類是在PackageManagerService中,而它的定義如下

class PackageManagerService extends IPackageManager.Stub {

final Installer mInstaller; // 非常重要

。。。

getPackageSizeInfo(。。。)

。。。},

這裡,我們僅僅以getPackageSizeInfo來做為例子進行分析。

2. getPackageSizeInfo函數

public void getPackageSizeInfo(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)。需要注意,permission.GET_PACKAGE_SIZE權限。

2)。PackageStats lStats將會存放著得到的數據,

3)。getPackageSizeInfoLI是主要的函數。

4) 。onGetStatsCompleted, 我們需要實現的回調函數,這在上一篇文章中已經有體現。

那麼,在getPackageSizeInfoLI中,有:

int res = mInstaller.getSizeInfo(packageName,p.mPath,

publicSrcDir, pStats);

mInstallerInstaller類型的一個實例,事實上,它是與android中的守護進程installd進行通信的,通過socket.

3. Installer的定義如下:

class Installer {

private static final String TAG ="Installer";

InputStream mIn;

OutputStream mOut;

LocalSocket mSocket;

byte buf[] = new byte[1024];

int buflen = 0;

private boolean connect() {

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 void disconnect(){

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 boolean readBytes(byte buffer[], int len)

private boolean writeCommand(String _cmd)

private synchronizedString transaction(String cmd)

private int execute(String cmd) {

String res = transaction(cmd);

try {

return Integer.parseInt(res);

} catch (NumberFormatException ex) {

return -1;

}

}

public int install(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 int freeCache(long freeStorageSize) {

StringBuilder builder = newStringBuilder("freecache");

builder.append(' ');

builder.append(String.valueOf(freeStorageSize));

return execute(builder.toString());

}

public int getSizeInfo(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;

}

}

分析:

1) 在connect函數中,與它進行socket連接的是installd。Installd是android中的守護進程,用ps可以看到它,它的父進程是init,關於Android啟動流程的更加詳細的說明,請看下面這篇文章:

http://blog.csdn.net/liranke/article/details/4694989。


2) 有一些read,write函數,當然是用於對socket讀取寫數據;

3) install, freeCache, getSizeInfo只是將固定字符串的命令傳入到execute函數中;

4) execute的實現,只是將命令字符串通過transaction傳下去,而在中會調用writeCommand,去真正地將命令寫入到與之連接好的守護進程Installd。


這下,好象理清一些了:

PackageManager------aidl------- > PackageManagerService的Installer ----socket--------> Installd(c程序)。

4. Installd這是一個用c寫成的帶有main函數的守護進程,在開機之後由init.rc調用,代碼位於:framworks/base/cmds/installd目錄下。其中,最後一個字母d,代碼的就是“dameon”,事實上,在android中,定義了好多這樣的守護進程,正是由於它們的存在,android系統才能夠正常運轉起來,也正是由於整個系統中,像這種實現方式是android中到處可以看見的。關於Installd,給出一些可以想像得到的有趣的代碼片段,有興趣的讀者,可以自己去看源碼。

Installd.c:

struct cmdinfo 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 },

};

哦,這不就是從PackageManagerService的Installer 傳遞過來的命令字符串麼,那麼,還能想到什麼呢?

祝閱讀此文的朋友在android上描繪出精彩的一筆。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved