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<files.length; i++) { File file = new File(dir, files[i]); if (!isPackageFilename(files[i])) { // Ignore entries which are not apk's continue; } PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime); // Don't mess around with apps in system partition. if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) { //Delete the apk Slog.w(TAG, "Cleaning up failed install of " + file); file.delete(); } } }
并且从该扫描方法中可以看出调用了scanPackageLI()
1 2
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanMode, long currentTime)
/*Called when a downloaded package installation has been confirmed by the user */ 由英文注释可见PackageManagerService 类的installPackage()函数为安装程序的入口。 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); }
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 a bind was already initiated we dont really // need to do anything. The pending install // will be processed later on. if (!mBound) {
// If this is the only one pending we might // have to bind to the service again. if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); return; } else { // Once we bind to the service, the first // pending request will be processed. mPendingInstalls.add(idx, params); }
} else { mPendingInstalls.add(idx, params); // Already bound to the service. Just make // sure we trigger off processing the first request. 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) { // Something seriously wrong. Bail out Slog.e(TAG, "Cannot bind to media container service"); for (HandlerParams params : mPendingInstalls) { mPendingInstalls.remove(0); // Indicate service bind error params.serviceError(); } mPendingInstalls.clear(); } else if (mPendingInstalls.size() > 0) { HandlerParams params = mPendingInstalls.get(0); if (params != null) { params.startCopy(); }
} else { // Should never happen ideally. Slog.w(TAG, "Empty queue"); } break; } ****************省略若干********************** } }
注: public final boolean sendMessage (Message msg) public final boolean sendEmptyMessage (int what) 两者参数有别。 然后调用抽象类HandlerParams中的一个startCopy()方法
1 2 3 4 5 6
abstract class HandlerParams { final void startCopy() { ***************若干if语句判定否这打回handler消息******* handleReturnCode(); } }
handleReturnCode()复写了两次其中有一次是删除时要调用的,只列出安装调用的一个方法
1 2 3 4 5 6 7 8 9
@Override void handleReturnCode() { // If mArgs is null, then MCS couldn't be reached. When it // reconnects, it will try again to install. At that point,this // will succeed. if (mArgs != null) { processPendingInstall(mArgs, mRet); } }
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")) { // Override if -s option is specified. installFlags |= PackageManager.INSTALL_EXTERNAL; } else if (opt.equals("-f")) { // Override if -s option is specified. 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); } }
其中:
1 2 3
PackageInstallObserver obs = new PackageInstallObserver(); mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags, installerPackageName);
如果 安装成功
1
obs.result == PackageManager.INSTALL_SUCCEEDED)
又因为有:
1 2 3 4 5 6 7 8 9
IPackageManage mPm; mPm = IpackageManager.Stub.asInterface(ServiceManager.getService("package")); Stub是接口IPackageManage的静态抽象类,asInterface是返回IPackageManager代理的静态方法。 因为class PackageManagerService extends IPackageManager.Stub 所以mPm.installPackage 调用 /* Called when a downloaded package installation has been confirmed by the user */
public void installPackage( final Uri packageURI, final IPackageInstallObserver observer, final int flags,final String installerPackageName)