voiddoHandleMessage(Message msg){ switch (msg.what) { case INIT_COPY: { HandlerParams params = (HandlerParams) msg.obj; int idx = mPendingInstalls.size(); if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params); // If a bind was already initiated we dont really // need to do anything. The pending install // will be processed later on. //mBound用于标识是否绑定了服务,默认值为false if (!mBound) { Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); // If this is the only one pending we might // have to bind to the service again. //如果没有绑定服务,重新绑定,connectToService方法内部如果绑定成功会将mBound置为true if (!connectToService()) { Slog.e(TAG, "Failed to bind to media container service"); params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); if (params.traceMethod != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } return; } else { // Once we bind to the service, the first // pending request will be processed. //绑定服务成功,将请求添加到mPendingInstalls中,等待处理 mPendingInstalls.add(idx, params); } } else { //服务已经绑定成功,添加到mPendingInstalls中 mPendingInstalls.add(idx, params); // Already bound to the service. Just make // sure we trigger off processing the first request. if (idx == 0) { // 发送MCS_BOUND消息 mHandler.sendEmptyMessage(MCS_BOUND); } } break; }
case MCS_BOUND: { if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound"); if (msg.obj != null) { mContainerService = (IMediaContainerService) msg.obj; //1 Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS", System.identityHashCode(mHandler)); } if (mContainerService == null) { //2 if (!mBound) { //3 // Something seriously wrong since we are not bound and we are not // waiting for connection. Bail out. Slog.e(TAG, "Cannot bind to media container service"); for (HandlerParams params : mPendingInstalls) { // Indicate service bind error params.serviceError(); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params)); if (params.traceMethod != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod, params.traceCookie); } return; } mPendingInstalls.clear(); } else { Slog.w(TAG, "Waiting to connect to media container service");//4 } } elseif (mPendingInstalls.size() > 0) { //5 HandlerParams params = mPendingInstalls.get(0); if (params != null) { Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall", System.identityHashCode(params)); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy"); if (params.startCopy()) { //6 // We are done... look for more work or to // go idle. if (DEBUG_SD_INSTALL) Log.i(TAG, "Checking for more work or unbind..."); // Delete pending install if (mPendingInstalls.size() > 0) { //如果APK安装成功,删除本次安装请求 mPendingInstalls.remove(0); } if (mPendingInstalls.size() == 0) { if (mBound) { //如果没有安装请求了,发送解绑服务的请求 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting delayed MCS_UNBIND"); removeMessages(MCS_UNBIND); Message ubmsg = obtainMessage(MCS_UNBIND); // Unbind after a little delay, to avoid // continual thrashing. sendMessageDelayed(ubmsg, 10000); } } else { // There are more pending requests in queue. // Just post MCS_BOUND message to trigger processing // of next pending install. //如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting MCS_BOUND for next work"); mHandler.sendEmptyMessage(MCS_BOUND); } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } else { // Should never happen ideally. Slog.w(TAG, "Empty queue"); } break; }
final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() { @Override public ParcelFileDescriptor open(String name, int mode)throws RemoteException { if (!FileUtils.isValidExtFilename(name)) { thrownew IllegalArgumentException("Invalid filename: " + name); } try { final File file = new File(codeFile, name); final FileDescriptor fd = Os.open(file.getAbsolutePath(), O_RDWR | O_CREAT, 0644); Os.chmod(file.getAbsolutePath(), 0644); returnnew ParcelFileDescriptor(fd); } catch (ErrnoException e) { thrownew RemoteException("Failed to open: " + e.getMessage()); } } };
int ret = PackageManager.INSTALL_SUCCEEDED; ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);//2 if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Failed to copy package"); return ret; }
@Override voidhandleReturnCode(){ // 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) { Slog.d(TAG,"welen:" + "handleReturnCode"); processPendingInstall(mArgs, mRet); } }
privatevoidprocessPendingInstall(final InstallArgs args, finalint currentStatus){ // Queue up an async operation since the package installation may take a little while. mHandler.post(new Runnable() { publicvoidrun(){ Slog.d(TAG,"welen:" + "processPendingInstall"); mHandler.removeCallbacks(this); // Result object to be returned PackageInstalledInfo res = new PackageInstalledInfo(); res.setReturnCode(currentStatus); res.uid = -1; res.pkg = null; res.removedInfo = null; if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { //安装前准备 args.doPreInstall(res.returnCode); synchronized (mInstallLock) { installPackageTracedLI(args, res); } // 安装后处理 args.doPostInstall(res.returnCode, res.uid); } ......
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, finalint policyFlags, finalint scanFlags, long currentTime, UserHandle user) throws PackageManagerException { final File scanFile = new File(pkg.codePath); ......
// // 处理provider int N = pkg.providers.size(); StringBuilder r = null; int i; for (i=0; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); p.info.processName = fixProcessName(pkg.applicationInfo.processName, p.info.processName, pkg.applicationInfo.uid); mProviders.addProvider(p); } // 处理service N = pkg.services.size(); r = null; for (i=0; i<N; i++) { PackageParser.Service s = pkg.services.get(i); s.info.processName = fixProcessName(pkg.applicationInfo.processName, s.info.processName, pkg.applicationInfo.uid); mServices.addService(s); } // 处理receiver N = pkg.receivers.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.receivers.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName, pkg.applicationInfo.uid); mReceivers.addActivity(a, "receiver"); }
// 处理activity N = pkg.activities.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName, pkg.applicationInfo.uid); mActivities.addActivity(a, "activity"); }
// 处理permissionGroup权限组 N = pkg.permissionGroups.size(); r = null; for (i=0; i<N; i++) { PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i); PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name); final String curPackageName = cur == null ? null : cur.info.packageName; finalboolean isPackageUpdate = pg.info.packageName.equals(curPackageName); if (cur == null || isPackageUpdate) { mPermissionGroups.put(pg.info.name, pg); } }
// 处理permission N = pkg.permissions.size(); r = null; for (i=0; i<N; i++) { PackageParser.Permission p = pkg.permissions.get(i);
p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { p.group = mPermissionGroups.get(p.info.group); // Warn for a permission in an unknown group. if (p.info.group != null && p.group == null) { Slog.w(TAG, "Permission " + p.info.name + " from package " + p.info.packageName + " in an unknown group " + p.info.group); } }
String pkgName = newPackage.packageName; synchronized (mPackages) { //write settings. the installStatus will be incomplete at this stage. //note that the new package setting would have already been //added to mPackages. It hasn't been persisted yet. mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings"); mSettings.writeLPr(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }
synchronized (mPackages) { updatePermissionsLPw(newPackage.packageName, newPackage, UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0)); // For system-bundled packages, we assume that installing an upgraded version // of the package implies that the user actually wants to run that new code, // so we enable the package. PackageSetting ps = mSettings.mPackages.get(pkgName); finalint userId = user.getIdentifier(); if (ps != null) { if (isSystemApp(newPackage)) { if (DEBUG_INSTALL) { Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName); } // Enable system package for requested users if (res.origUsers != null) { for (int origUserId : res.origUsers) { if (userId == UserHandle.USER_ALL || userId == origUserId) { ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, origUserId, installerPackageName); } } } // Also convey the prior install/uninstall state if (allUsers != null && installedForUsers != null) { for (int currentUserId : allUsers) { finalboolean installed = ArrayUtils.contains( installedForUsers, currentUserId); if (DEBUG_INSTALL) { Slog.d(TAG, " user " + currentUserId + " => " + installed); } ps.setInstalled(installed, currentUserId); } // these install state changes will be persisted in the // upcoming call to mSettings.writeLPr(). } } // It's implied that when a user requests installation, they want the app to be // installed and enabled. if (userId != UserHandle.USER_ALL) { ps.setInstalled(true, userId); ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName); } } res.name = pkgName; res.uid = newPackage.applicationInfo.uid; res.pkg = newPackage; mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE); mSettings.setInstallerPackageName(pkgName, installerPackageName); res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); //to update install status Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings"); mSettings.writeLPr(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); }
// New settings successfully written, old ones are no longer // needed. mBackupSettingsFilename.delete(); FileUtils.setPermissions(mSettingsFilename.toString(), FileUtils.S_IRUSR|FileUtils.S_IWUSR |FileUtils.S_IRGRP|FileUtils.S_IWGRP, -1, -1);
privatevoidprepareAppDataLIF(PackageParser.Package pkg, int userId, int flags){ if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } prepareAppDataLeafLIF(pkg, userId, flags); finalint childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
privatevoidprepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags){ final String volumeUuid = pkg.volumeUuid; final String packageName = pkg.packageName; final ApplicationInfo app = pkg.applicationInfo; finalint appId = UserHandle.getAppId(app.uid);
privatevoidprepareAppDataContentsLeafLIF(PackageParser.Package pkg, int userId, int flags){ final String volumeUuid = pkg.volumeUuid; final String packageName = pkg.packageName; final ApplicationInfo app = pkg.applicationInfo;
if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { // Create a native library symlink only if we have native libraries // and if the native libraries are 32 bit libraries. We do not provide // this symlink for 64 bit libraries. if (app.primaryCpuAbi != null && !VMRuntime.is64BitAbi(app.primaryCpuAbi)) { final String nativeLibPath = app.nativeLibraryDir; try { mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName, nativeLibPath, userId); } catch (InstallerException e) { Slog.e(TAG, "Failed to link native for " + packageName + ": " + e); } } } }