安装应用的过程解析
一.开机安装
PackageManagerService处理各种应用的安装,卸载,管理等工作,开机时由systemServer启动此服务
(源文件路径:android\frameworks\base\services\Java\com\android\server\PackageManagerService.java)
PackageManagerService服务启动的流程:
1.首先扫描安装“system\framework”目录下的jar包
mFrameworkInstallObserver = new AppDirObserver(mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_NO_DEX, 0);
2.扫描安装系统system/app的应用程序
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
3.制造商的目录下/vendor/app应用包
mVendorAppDir = new File("/vendor/app");
mVendorInstallObserver = new AppDirObserver(mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
mVendorInstallObserver.startWatching();
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
4.扫描“data\app”目录,即用户安装的第三方应用
scanDirLI(mAppInstallDir, 0, scanMode, 0);
5.扫描" data\app-private"目录,即安装DRM保护的APK文件(一个受保护的歌曲或受保护的视频是使用 DRM 保护的文件)
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,scanMode, 0);
扫描方法的代码清单:
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
String[] files = dir.list();
if (files == null) {
Log.d(TAG, "No files in app dir " + dir);
return;
}
if (false) {
Log.d(TAG, "Scanning app dir " + dir);
}
int i;
for (i=0; i
if (!isPackageFilename(files[i])) {
continue;
}
PackageParser.Package pkg = scanPackageLI(file,flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 && mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Slog.w(TAG, "Cleaning up failed install of " + file);
file.delete();
}
}
}
并且从该扫描方法中可以看出调用了scanPackageLI(),跟踪scanPackageLI()方法后发现,程序经过很多次的if else 的筛选,最后判定可以安装后调用了 mInstaller.install()方法
//private PackageParser.Package scanPackageLI(File scanFile,int parseFlags, int scanMode, long currentTime)
if (mInstaller != null) {
int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,pkg.applicationInfo.uid);
if(ret < 0) {
mLastScanError =PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
}
mInstaller.install()通过LocalSocketAddress address = new LocalSocketAddress("installd", LocalSocketAddress.Namespace.RESERVED)来指挥installd在C语言的文件中完成工作
PackageManagerService
1)从apk, xml中载入pacakge信息, 存储到内部成员变量中, 用于后面的查找. 关键的方法是scanPackageLI().
2)各种查询操作, 包括query Intent操作.
3)install package和delete package的操作. 还有后面的关键方法是installPackageLI().
安装应用的过程:
1.scanDirLI(Filedir, int flags, int scanMode) //遍历安装指定目录下的文件
2.scanPackageLI(FilescanFile,File destCodeFile, FiledestResourceFile, int parseFlags,int scanMode);//安装package文件
3.scanPackageLI( File scanFile, File destCodeFile, FiledestResourceFile,PackageParser.Package pkg, intparseFlags, int scanMode) ;//通过解析安装包parsePackage获取到安装包的信息结构
4.mInstaller.install(pkgName,pkg.applicationInfo.uid, pkg.applicationInfo.uid);//实现文件复制的安装过程,源文件路径frameworks\base\cmds\installd\installd.install
二、从网络上下载应用:
下载完成后,会自动调用Packagemanager的安装方法installPackage(),PackageManagerService类的installPackage()函数为安装程序入口
//final Uri packageURI:文件下载完成后保存的路径
//final IPackageInstallObserver observer:处理返回的安装结果
//final int flags:安装的参数,从market上下载的应用,安装参数为-r (replace)
//final String installerPackageName:安装完成后此名称保存在settings里一般为null,不是关键参数
public void installPackage(final Uri packageURI, final IPackageInstallObserver observer, final int flags,final String installerPackageName) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(packageURI, observer, flags, installerPackageName);
mHandler.sendMessage(msg);
}
其中是通过PackageHandler的实例mhandler.sendMessage(msg)把信息发给继承Handler的类HandleMessage()方法
class PackageHandler extends Handler{
/*****************省略若干********************/
public void handleMessage(Message msg) {
try {
doHandleMessage(msg);
} finally {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}
/******************省略若干**********************/
}
把信息发给doHandleMessage()方法
void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY:
{
if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
HandlerParams params = (HandlerParams) msg.obj;
int idx = mPendingInstalls.size();
if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
if (!mBound) {
if (!connectToService()) {
Slog.e(TAG, "Failed to bind to media container service");
params.serviceError();
return;
} else {
mPendingInstalls.add(idx, params);
}
} else {
mPendingInstalls.add(idx, params);
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
case MCS_BOUND:
{
if (DEBUG_SD_INSTALL)
Log.i(TAG, "mcs_bound");
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
}
if (mContainerService == null) {
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
mPendingInstalls.remove(0);
params.serviceError();
}
mPendingInstalls.clear();
} else if (mPendingInstalls.size() > 0) {
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
params.startCopy();
}
} else {
Slog.w(TAG, "Empty queue");
}
break;
}
/****************省略若干**********************/
}
}
然后调用抽象类HandlerParams中的一个startCopy()方法
abstract class HandlerParams {
final void startCopy() {
/***************若干if语句判定否这打回handler消息*******/
handleReturnCode();
}
}
handleReturnCode()复写了两次其中有一次是删除时要调用的,只列出安装调用的一个方法
@Override
void handleReturnCode() {
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
这时可以清楚的看见 processPendingInstall()被调用,其中run()方法如下
run(){
synchronized (mInstallLock) {
/************省略*****************/
installPackageLI(args, true, res);
}
}
其中InstallArgs 是在PackageService定义的static abstract class InstallArgs 静态抽象类
static abstract class InstallArgs {
/*********************************************************************
其中定义了flag标志,packageURL,创建文件,拷贝apk,修改包名称,
还有一些删除文件的清理,释放存储函数。
*********************************************************************/
}
class PackageInstalledInfo {
String name;
int uid;
PackageParser.Package pkg;
int returnCode;
PackageRemovedInfo removedInfo;
}
installPackageLI()的具体实现
private void installPackageLI(InstallArgs args, boolean newInstall, PackageInstalledInfo res) {
int pFlags = args.flags;
String installerPackageName = args.installerPackageName;
File tmpPackageFile = new File(args.getCodePath());
boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
boolean replace = false;
int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE | (newInstall ? SCAN_NEW_INSTALL : 0);
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
int parseFlags = PackageParser.PARSE_CHATTY | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
parseFlags |= mDefParseFlags;
//解析临时文件获取应用包名
PackageParser pp = new PackageParser(tmpPackageFile.getPath());
pp.setSeparateProcesses(mSeparateProcesses);
final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,null, mMetrics, parseFlags);
if (pkg == null) {
res.returnCode = pp.getParseError();
return;
}
String pkgName = res.name = pkg.packageName;
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
return;
}
}
if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
res.returnCode = pp.getParseError();
return;
}
pp = null;
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mSettings.mRenamedPackages.get(pkgName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName) && mPackages.containsKey(oldName)) {
pkg.setPackageName(oldName);
pkgName = pkg.packageName;
replace = true;
} else if (mPackages.containsKey(pkgName)) {
replace = true;
}
}
PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
systemApp = (ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
}
}
if (systemApp && onSd) {
Slog.w(TAG, "Cannot install updates to system apps on sdcard");
res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
return;
}
if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return;
}
setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
if (replace) {
//带有参数INSTALL_REPLACE_EXISTING
replacePackageLI(pkg, parseFlags, scanMode,installerPackageName, res);
} else {
//不带参数
installNewPackageLI(pkg, parseFlags, scanMode,installerPackageName,res);
}
}
最后判断如果以前不存在那么调用installNewPackageLI()
private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanMode, String installerPackageName, PackageInstalledInfo res) {
/***********************省略若干*************************************************/
PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,System.currentTimeMillis());
/***********************省略若干**************************************************/
}
三、从ADB工具安装
其入口函数源文件为pm.java(源文件路径:android\frameworks\base\cmds\pm\src\com\android\commands\pm\pm.java),
其中\system\framework\pm.jar 包管理库,包管理脚本 \system\bin\pm 解析
其中showUsage就是adb使用方法
private static void showUsage() {
System.err.println("usage: pm [list|path|install|uninstall]");
System.err.println("pm list packages [-f]");
System.err.println("pm list permission-groups");
System.err.println("pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
System.err.println("pm list instrumentation [-f] [TARGET-PACKAGE]");
System.err.println("pm list features");
System.err.println("pm path PACKAGE");
System.err.println(pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
System.err.println("pm uninstall [-k] PACKAGE");
System.err.println("pm enable PACKAGE_OR_COMPONENT");
System.err.println("pm disable PACKAGE_OR_COMPONENT");
System.err.println("pm setInstallLocation [0/auto] [1/internal] [2/external]");
/**********************省略**************************/
}
安装时候会调用 runInstall()方法
private void runInstall() {
int installFlags = 0;
String installerPackageName = null;
String opt;
while ((opt=nextOption()) != null) {
if (opt.equals("-l")) {
installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
} else if (opt.equals("-r")) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
} else if (opt.equals("-i")) {
installerPackageName = nextOptionData();
if (installerPackageName == null) {
System.err.println("Error: no value specified for -i");
showUsage();
return;
}
} else if (opt.equals("-t")) {
installFlags |= PackageManager.INSTALL_ALLOW_TEST;
} else if (opt.equals("-s")) {
installFlags |= PackageManager.INSTALL_EXTERNAL;
} else if (opt.equals("-f")) {
installFlags |= PackageManager.INSTALL_INTERNAL;
} else {
System.err.println("Error: Unknown option: " + opt);
showUsage();
return;
}
}
String apkFilePath = nextArg();
System.err.println("\tpkg: " + apkFilePath);
if (apkFilePath == null) {
System.err.println("Error: no package specified");
showUsage();
return;
}
PackageInstallObserver obs = new PackageInstallObserver();
try {
mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags, installerPackageName);
synchronized (obs) {
while (!obs.finished) {
try {
obs.wait();
} catch (InterruptedException e) {
}
}
if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
System.out.println("Success");
} else {
System.err.println("Failure [" + installFailureToString(obs.result) + "]");
}
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
}
}
其中的
PackageInstallObserver obs = new PackageInstallObserver();
mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,installerPackageName);
如果安装成功
obs.result == PackageManager.INSTALL_SUCCEEDED)
又因为有
IPackageManage mPm;
mPm = IpackageManager.Stub.asInterface(ServiceManager.getService("package"));
Stub是接口IPackageManage的静态抽象类,asInterface是返回IPackageManager代理的静态方法。
因为class PackageManagerService extends IPackageManager.Stub,所以mPm.installPackage 调用的是
public void installPackage( final Uri packageURI, final IPackageInstallObserver observer, final int flags,final String installerPackageName)
四、从SD卡安装
把APK安装包保存在SD卡中,从手机里访问SD卡中的APK安装包,点击就可以启动安装界面系统应用Packageinstaller.apk处理这种方式下的安装及卸载界面流程
PackageInstallerActivity负责解析包,判断是否是可用的Apk文件,创建临时安装文件/data/data/com.android.packageinstaller/files/ApiDemos.apk ,
并启动安装确认界面startInstallConfirm,列出解析得到的该应用基本信息。如果手机上已安装有同名应用,则需要用户确认是否要替换安装,确认安装后,
启动InstallAppProgress调用安装接口完成安装。
系统调用PackageInstallerActivity.java(/home/zhongda/androidSRC/vortex-8inch-for-hoperun/packages/apps/PackageInstaller/src/com/android/packageinstaller),
进入这个Activity会判断信息是否有错,然后调用然后调用private void initiateInstall()判断是否曾经有过同名包的安装,或者包已经安装,
最后通过后执行private void startInstallConfirm() ,点击OK按钮后经过一系列的安装信息的判断Intent跳转到InstallAppProgress类
public class InstallAppProgress extends Activity implements View.OnClickListener, OnCancelListener{
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent intent = getIntent();
mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = intent.getData();
initView();
}
}
在onCreate()方法中调用了initView()方法
public void initView() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.op_progress);
int installFlags = 0;
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,PackageManager.GET_UNINSTALLED_PACKAGES);
if(pi != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
}
} catch (NameNotFoundException e) {
}
if((installFlags & PackageManager.INSTALL_REPLACE_EXISTING )!= 0) {
Log.w(TAG, "Replacing package:" + mAppInfo.packageName);
}
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, mAppInfo, mPackageURI);
mLabel = as.label;
PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
mStatusTextView = (TextView)findViewById(R.id.center_text);
mStatusTextView.setText(R.string.installing);
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
mProgressBar.setIndeterminate(true);
mOkPanel = (View)findViewById(R.id.buttons_panel);
mDoneButton = (Button)findViewById(R.id.done_button);
mLaunchButton = (Button)findViewById(R.id.launch_button);
mOkPanel.setVisibility(View.INVISIBLE);
String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
PackageInstallObserver observer = new PackageInstallObserver();
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
}
其它:
1. PackageManagerService.java的内部类AppDirObserver实现了监听app目录的功能,当
把某个APK拖到app目录下时可以直接调用scanPackageLI完成安装。
2.手机数据区目录“data/system/packages.xml”文件中包含了手机上所有已安装应用的
基本信息,如安装路径、申请的permission等信息。