staticintinstall_app(int argc, constchar** argv){ // The last argument must be the APK file constchar* file = argv[argc - 1]; if (!android::base::EndsWithIgnoreCase(file, ".apk")) { returnsyntax_error("filename doesn't end .apk: %s", file); }
structstat sb; if (stat(file, &sb) == -1) { fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno)); return1; }
int localFd = adb_open(file, O_RDONLY); if (localFd < 0) { fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno)); return1; }
// don't copy the APK name, but, copy the rest of the arguments as-is while (argc-- > 1) { cmd += " " + escape_arg(std::string(*argv++)); }
// add size parameter [required for streaming installs] // do last to override any user specified value cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
int remoteFd = adb_connect(cmd, &error); if (remoteFd < 0) { fprintf(stderr, "adb: connect error for write: %s\n", error.c_str()); adb_close(localFd); return1; }
for (size_t i=0; i<services.size(); i++) { sp<IBinder> service = sm->checkService(services[i]); if (service != NULL) { aout << " " << services[i] << endl; } } return0; }
Vector<String16> args; for (int i=2; i<argc; i++) { args.add(String16(argv[i])); } String16 cmd = String16(argv[1]);//cmd:package sp<IBinder> service = sm->checkService(cmd); //…… sp<MyShellCallback> cb = newMyShellCallback(); sp<MyResultReceiver> result = newMyResultReceiver();
// TODO: block until a result is returned to MyResultReceiver. status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args, cb, result); //…… return res; }
// Only system components can circumvent runtime permissions when installing. if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0 && mContext.checkCallingOrSelfPermission(Manifest.permission .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) { thrownewSecurityException("You need the " + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission " + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag"); }
switch (params.mode) { case SessionParams.MODE_FULL_INSTALL: case SessionParams.MODE_INHERIT_EXISTING: break; default: thrownewIllegalArgumentException("Invalid install mode: " + params.mode); }
// If caller requested explicit location, sanity check it, otherwise // resolve the best internal or adopted location. if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { //…… } elseif ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) { //…… } elseif ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) { // For now, installs to adopted media are treated as internal from // an install flag point-of-view. params.setInstallFlagsInternal(); } else { //adb 安装走这里 // For now, installs to adopted media are treated as internal from // an install flag point-of-view. params.setInstallFlagsInternal();
// Resolve best location for install, based on combination of // requested install flags, delta size, and manifest settings. finallongident= Binder.clearCallingIdentity(); try { params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params); } finally { Binder.restoreCallingIdentity(ident); } }
/** * Attempt to commit everything staged(暂存) in this session. This may require * user intervention(介入), and so it may not happen immediately. The final * result of the commit will be reported through the given callback. * <p> * Once this method is called, the session is sealed and no additional * mutations may be performed on the session. If the device reboots * before the session has been finalized, you may commit the session again. * * @throws SecurityException if streams opened through * {@link #openWrite(String, long, long)} are still open. */ publicvoidcommit(@NonNull IntentSender statusReceiver) { try { mSession.commit(statusReceiver, false); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
finalboolean wasSealed; synchronized (mLock) { //Check if the caller is the owner of this session. Otherwise throw a //SecurityException. assertCallerIsOwnerOrRootLocked(); assertPreparedAndNotDestroyedLocked("commit");
if (forTransfer) {//adb安装forTransfer值为false mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null); if (mInstallerUid == mOriginalInstallerUid) { thrownewIllegalArgumentException("Session has not been transferred"); } } else { if (mInstallerUid != mOriginalInstallerUid) { thrownewIllegalArgumentException("Session has been transferred"); } }
wasSealed = mSealed; if (!mSealed) { try { //Seal the session to prevent further modification and validate the contents of it. sealAndValidateLocked(); } catch (IOException e) { thrownewIllegalArgumentException(e); } catch (PackageManagerException e) { destroyInternal();
// Cannot call dispatchFinal synchronous as this might be called from inside the // system server on the main thread. Hence the call back scheduled in // dispachFinal has to be scheduled on a different thread. mHandler.obtainMessage(MSG_SESSION_FINISHED_WITH_EXCEPTION, e).sendToTarget();
return; } }
// Client staging is fully done at this point //更新callback中的进度,callback存在于Launcher和PackageInstaller中,本地安装 //时会回调到packageInstaller中 mClientProgress = 1f; computeProgressLocked(true);
// This ongoing commit should keep session active, even though client // will probably close their end. mActiveCount.incrementAndGet();
if (!wasSealed) { // Persist the fact that we've sealed ourselves to prevent // mutations of any hard links we create. We do this without holding // the session lock, since otherwise it's a lock inversion. mCallback.onSessionSealedBlocking(this); } }
privatevoidcommitLocked() throws PackageManagerException { //省略一些检测代码 if (needToAskForPermissionsLocked()) {//请求安装权限,adb安装不需要申请权限 // User needs to accept permissions; give installer an intent they // can use to involve user. finalIntentintent=newIntent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS); intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName()); intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); try { mRemoteObserver.onUserActionRequired(intent); } catch (RemoteException ignored) { }
// Commit was keeping session marked as active until now; release // that extra refcount so session appears idle. closeInternal(false); return; } //…… // Inherit any packages and native libraries from existing install that // haven't been overridden. if (params.mode == SessionParams.MODE_INHERIT_EXISTING) { //常见的安装模式是MODE_FULL_INSTALL=1,安装时带-p参数时会将该标志位置为1, //MODE_INHERIT_EXISTING的情况先不管 }
// TODO: surface more granular state from dexopt mInternalProgress = 0.5f; computeProgressLocked(true);//更新进度
// Unpack native libraries extractNativeLibraries(mResolvedStageDir, params.abiOverride); //…… // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. finalIPackageInstallObserver2localObserver=newIPackageInstallObserver2.Stub() { //省略 };
final UserHandle user; if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) { user = UserHandle.ALL; } else { user = newUserHandle(userId); }
case INIT_COPY: { HandlerParamsparams= (HandlerParams) msg.obj; intidx= 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. 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. 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.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; }
/** * Service that offers to inspect and copy files that may reside on removable * storage. This is designed to prevent the system process from holding onto * open files that cause the kernel to kill it when the underlying device is * removed. */
/* * Invoke remote method to get package information and install * location values. Override install location based on default * policy if needed and then create install arguments based * on the install location. */
@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) { 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(newRunnable() { publicvoidrun() { mHandler.removeCallbacks(this); // Result object to be returned PackageInstalledInfores=newPackageInstalledInfo(); 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); }
// A restore should be performed at this point if (a) the install // succeeded, (b) the operation is not an update, and (c) the new // package has not opted out of backup participation. finalbooleanupdate= res.removedInfo != null && res.removedInfo.removedPackage != null; finalintflags= (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags; booleandoRestore= !update && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
// Set up the post-install work request bookkeeping. This will be used // and cleaned up by the post-install event handling regardless of whether // there's a restore pass performed. Token values are >= 1. int token; if (mNextInstallToken < 0) mNextInstallToken = 1; token = mNextInstallToken++;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) { // Pass responsibility to the Backup Manager. It will perform a // restore if appropriate, then pass responsibility back to the // Package Manager to run the post-install observer callbacks // and broadcasts. IBackupManagerbm= IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); if (bm != null) { if (DEBUG_INSTALL) Log.v(TAG, "token " + token + " to BM for possible restore"); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token); try { // TODO: http://b/22388012 if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) { bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token); } else { doRestore = false; } } catch (RemoteException e) { // can't happen; the backup manager is local } catch (Exception e) { Slog.e(TAG, "Exception trying to enqueue restore", e); doRestore = false; } } else { Slog.e(TAG, "Backup Manager not found!"); doRestore = false; } }
if (!doRestore) { // No restore possible, or the Backup Manager was mysteriously not // available -- just fire the post-install work request directly. if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
if (args.move != null) { //…… // We did an in-place move, so dex is ready to roll } elseif (!forwardLocked && !pkg.applicationInfo.isExternalAsec()) { // Enable SCAN_NO_DEX flag to skip dexopt at a later stage scanFlags |= SCAN_NO_DEX;
privatevoidinstallNewPackageLIF(PackageParser.Package pkg, finalint policyFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res, int installReason) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
// Remember this for later, in case we need to rollback this install StringpkgName= pkg.packageName; //检测是否是新应用,若不是则退出并保存错误信息 try { PackageParser.PackagenewPackage= scanPackageTracedLI(pkg, policyFlags, scanFlags, System.currentTimeMillis(), user);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { prepareAppDataAfterInstallLIF(newPackage);
} else { // Remove package from internal structures, but keep around any // data that might have already existed deletePackageLIF(pkgName, UserHandle.ALL, false, null, PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null); } } catch (PackageManagerException e) { res.setError("Package couldn't be installed in " + pkg.codePath, e); }
// Now that we successfully installed the package, grant runtime // permissions if requested before broadcasting the install. Also // for legacy apps in permission review mode we clear the permission // review flag which is used to emulate runtime permissions for // legacy apps. if (grantPermissions) {//安装时带-g参数 grantRequestedRuntimePermissions(res.pkg, res.newUsers, grantedPermissions); }