PackageManagerService和Intent
- PackageManagerService
- Intent
PackageManagerService
PMS扫描已安装的apk,解析其AndroidManifest.xml获取App相关信息,如下是其构造函数的相关片段
......
if (partition.getPrivAppFolder() != null) { //扫描系统应用,路径/system/priv-appscanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,packageParser, executorService);
}......//扫描系统应用,路径/system/app
scanDirTracedLI(partition.getAppFolder(), systemParseFlags,systemScanFlags | partition.scanFlag, 0,packageParser, executorService);......
if (!mOnlyCore) { //扫描非系统应用,路径/data/data/app......scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,packageParser, executorService);
}......
调用scanDirTracedLI()、scanDirLI()
private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,PackageParser2 packageParser, ExecutorService executorService) {final File[] files = scanDir.listFiles();......ParallelPackageParser parallelPackageParser =new ParallelPackageParser(packageParser, executorService);int fileCount = 0;for (File file : files) { //判断是否是apk文件final boolean isPackage = (isApkFile(file) || file.isDirectory())&& !PackageInstallerService.isStageName(file.getName());if (!isPackage) {continue;}parallelPackageParser.submit(file, parseFlags);fileCount++;}......
}
- 调用ParallelPackageParser的submit()并行解析
- 调用PackageParser2的parsePackage()
- 调用ParsingPackageUtils的parsePackage()、parseMonolithicPackage()、parseBaseApk()、parseBaseApkTags()
parseBaseApkTags()开始解析AndroidManifest
private ParseResult<ParsingPackage> parseBaseApkTags(ParseInput input, ParsingPackage pkg, TypedArray sa, Resources res, XmlResourceParser parser, int flags) throws XmlPullParserException, IOException {ParseResult<ParsingPackage> sharedUserResult = parseSharedUser(input, pkg, sa);......boolean foundApp = false;final int depth = parser.getDepth();int type;while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG|| parser.getDepth() > depth)) {if (type != XmlPullParser.START_TAG) {continue;}String tagName = parser.getName(); //获取标签final ParseResult result;if (PackageParser.TAG_APPLICATION.equals(tagName)) {if (foundApp) {if (PackageParser.RIGID_PARSER) {result = input.error("<manifest> has more than one <application>");} else {Slog.w(TAG, "<manifest> has more than one <application>");result = input.success(null);}} else { // 解析Application标签foundApp = true;result = parseBaseApplication(input, pkg, res, parser, flags);}} else { //解析其他全局标签(如permission)result = parseBaseApkTag(tagName, input, pkg, res, parser, flags);}if (result.isError()) {return input.error(result);}}......return input.success(pkg);
}
parseBaseApplication()开始解析Application
private ParseResult<ParsingPackage> parseBaseApplication(ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags) throws XmlPullParserException, IOException {final String pkgName = pkg.getPackageName();int targetSdk = pkg.getTargetSdkVersion();TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestApplication);try {......String name = sa.getNonConfigurationString(R.styleable.AndroidManifestApplication_name, 0);if (name != null) { // 解析name属性String packageName = pkg.getPackageName();String outInfoName = ParsingUtils.buildClassName(packageName, name);......pkg.setClassName(outInfoName);}TypedValue labelValue = sa.peekValue(R.styleable.AndroidManifestApplication_label);if (labelValue != null) { // 解析label属性pkg.setLabelRes(labelValue.resourceId);if (labelValue.resourceId == 0) {pkg.setNonLocalizedLabel(labelValue.coerceToString());}}.......if (pkg.isAllowBackup()) { // 解析isAllowBackup属性......}......CharSequence pname; // 解析process属性if (targetSdk >= Build.VERSION_CODES.FROYO) {pname = sa.getNonConfigurationString(R.styleable.AndroidManifestApplication_process,Configuration.NATIVE_CONFIG_VERSION);} else { pname = sa.getNonResourceString(R.styleable.AndroidManifestApplication_process);}ParseResult<String> processNameResult = ComponentParseUtils.buildProcessName(pkgName, null, pname, flags, mSeparateProcesses, input);......String processName = processNameResult.getResult();pkg.setProcessName(processName);......} finally {sa.recycle();}......while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG|| parser.getDepth() > depth)) {if (type != XmlPullParser.START_TAG) {continue;}final ParseResult result;String tagName = parser.getName();boolean isActivity = false;switch (tagName) {case "activity": // 解析ActivityisActivity = true;// fall-throughcase "receiver": // 解析receiverParseResult<ParsedActivity> activityResult =ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,res, parser, flags, PackageParser.sUseRoundIcon, input);if (activityResult.isSuccess()) {ParsedActivity activity = activityResult.getResult();if (isActivity) {hasActivityOrder |= (activity.getOrder() != 0);pkg.addActivity(activity);} else {hasReceiverOrder |= (activity.getOrder() != 0);pkg.addReceiver(activity);}}result = activityResult;break;case "service": // 解析serviceParseResult<ParsedService> serviceResult =ParsedServiceUtils.parseService(mSeparateProcesses, pkg, res, parser,flags, PackageParser.sUseRoundIcon, input);if (serviceResult.isSuccess()) {ParsedService service = serviceResult.getResult();hasServiceOrder |= (service.getOrder() != 0);pkg.addService(service);}result = serviceResult;break;case "provider": // 解析providerParseResult<ParsedProvider> providerResult =ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,flags, PackageParser.sUseRoundIcon, input);if (providerResult.isSuccess()) {pkg.addProvider(providerResult.getResult());}result = providerResult;break;......default:result = parseBaseAppChildTag(input, tagName, pkg, res, parser, flags);break;}......}......return input.success(pkg);
}
上面通过PackageManager的submit()并行解析,解析完后封装成ParseResult放到一个队列里,后面再利用scanDirLI()的take()获取解析结果
for (; fileCount > 0; fileCount--) {ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();Throwable throwable = parseResult.throwable;int errorCode = PackageManager.INSTALL_SUCCEEDED;if (throwable == null) {......try {addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,currentTime, null);}......}......}
}
调用addForInitLI(),将ParsedPackage封装成ScanResult,再封装成ReconcileRequest
private AndroidPackage addForInitLI(ParsedPackage parsedPackage, @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException {......final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, scanFlags| SCAN_UPDATE_SIGNATURE, currentTime, user, null);if (scanResult.success) {synchronized (mLock) {boolean appIdCreated = false;try {final String pkgName = scanResult.pkgSetting.name;final Map<String, ReconciledPackage> reconcileResult = reconcilePackagesLocked(new ReconcileRequest(Collections.singletonMap(pkgName, scanResult),mSharedLibraries,mPackages,Collections.singletonMap(pkgName, getSettingsVersionForPackage(parsedPackage)),Collections.singletonMap(pkgName,getSharedLibLatestVersionSetting(scanResult))),mSettings.mKeySetManagerService);appIdCreated = optimisticallyRegisterAppId(scanResult);commitReconciledScanResultLocked(reconcileResult.get(pkgName), mUserManager.getUserIds());}......}}......return scanResult.pkgSetting.pkg;
}
调用commitReconciledScanResultLocked()封装成PackageSettings,再调用commitPackageSettings()将将解析到的四大组件(AndroidPackage)存入mComponentResolver
private void commitPackageSettings(AndroidPackage pkg,@Nullable AndroidPackage oldPkg, PackageSetting pkgSetting,final @ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) {......synchronized (mLock) {......mComponentResolver.addAllComponents(pkg, chatty);......}}......
}
ComponentResolver的addAllComponents()将四大组件分别存入到对应的列表
private final ActivityIntentResolver mActivities = new ActivityIntentResolver();private final ProviderIntentResolver mProviders = new ProviderIntentResolver();private final ActivityIntentResolver mReceivers = new ReceiverIntentResolver();private final ServiceIntentResolver mServices = new ServiceIntentResolver();void addAllComponents(AndroidPackage pkg, boolean chatty) {......synchronized (mLock) {addActivitiesLocked(pkg, newIntents, chatty);addReceiversLocked(pkg, chatty);addProvidersLocked(pkg, chatty);addServicesLocked(pkg, chatty);}......
}
Intent
startActivity()最终都会调用到startActivityForResult()
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),ar.getResultData());}if (requestCode >= 0) {mStartedActivity = true;}cancelInputsAndStartExitTransition(options);}......
}
上面调用Instrumentation的execStartActivity()
public ActivityResult execStartActivity(......) {......try {......int result = ActivityTaskManager.getService().startActivity(whoThread,who.getBasePackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;
}
上面获取ActivityTaskManagerService,是IPC过程,调用其startActivity()启动,然后调到startActivityAsUser()
private int startActivityAsUser(......) {......return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId).execute();
}
上面通过ActivityStartController获取ActivityStarter,调用execute()
int execute() {try {......if (mRequest.activityInfo == null) {mRequest.resolveActivity(mSupervisor);}int res;synchronized (mService.mGlobalLock) {......res = executeRequest(mRequest);......return getExternalResult(mRequest.waitResult == null ? res: waitForResult(res, mLastStartActivityRecord));}}......
}
通过ActivityStartController的resolveActivity()解析Intent解析再匹配到对应的ActivityInfo,后面通过executeRequest()启动Activity
void resolveActivity(ActivityStackSupervisor supervisor) {......resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,0 /* matchFlags */,computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid));......activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,profilerInfo);if (activityInfo != null) {intentGrants = supervisor.mService.mUgmInternal.checkGrantUriPermissionFromIntent(intent, resolvedCallingUid, activityInfo.applicationInfo.packageName,UserHandle.getUserId(activityInfo.applicationInfo.uid));}
}
调用到ActivityStackSupervisor的resolveIntent()
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags, int filterCallingUid) {try {......try {return mService.getPackageManagerInternalLocked().resolveIntent(intent, resolvedType, modifiedFlags, privateResolveFlags, userId, true,filterCallingUid);}......}......
}
调用到PackageManagerService的resolveIntent()、resolveIntentInternal()、resolveIntentInternal()
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags, int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {......final String pkgName = intent.getPackage();ComponentName comp = intent.getComponent();......if (comp != null) { // ComponentName不为空,显式启动Activityfinal List<ResolveInfo> list = new ArrayList<>(1);final ActivityInfo ai = getActivityInfo(comp, flags, userId);if (ai != null) {......if (......) {final ResolveInfo ri = new ResolveInfo();ri.activityInfo = ai;list.add(ri);}}List<ResolveInfo> result = applyPostResolutionFilter(list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,userId, intent);return result;}//ComponentName为空,下面进行隐式启动boolean sortResult = false; //若有多个匹配,则需要排序boolean addInstant = false;List<ResolveInfo> result;synchronized (mLock) {if (pkgName == null) { //包名为空,匹配schema、data等.....result = filterIfNotSystemUser(mComponentResolver.queryActivities(intent, resolvedType, flags, userId), userId);......if (intent.hasWebURI()) { //处理http标签......}} else { //包名不为空则获取PackageManagerService解析到的PackageSettingfinal PackageSetting setting = getPackageSettingInternal(pkgName, Process.SYSTEM_UID);result = null;if (setting != null && setting.pkg != null && (resolveForStart || !shouldFilterApplicationLocked(setting, filterCallingUid, userId))) {result = filterIfNotSystemUser(mComponentResolver.queryActivities(intent, resolvedType, flags, setting.pkg.getActivities(), userId), userId);}if (result == null || result.size() == 0) { //若未通过PackageManagerService解析,则可能是第三方安装的应用addInstant = isInstantAppResolutionAllowed(intent, null /*result*/, userId, true /*skipPackageCheck*/);if (result == null) {result = new ArrayList<>();}}}}if (addInstant) { //处理第三方应用String callingPkgName = getInstantAppPackageName(filterCallingUid);boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);result = maybeAddInstantAppInstaller(result, intent, resolvedType, flags, userId,resolveForStart, isRequesterInstantApp);}if (sortResult) {Collections.sort(result, RESOLVE_PRIORITY_SORTER);}return applyPostResolutionFilter(result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,userId, intent);
}
PackageManagerService解析AndroidManifest时会将四大组件存到mComponentResolver,调用其queryActivities()从mActivities取出ResolveInfo
@Nullable
List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,int userId) {synchronized (mLock) {return mActivities.queryIntent(intent, resolvedType, flags, userId);}
}@Nullable
List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,List<ParsedActivity> activities, int userId) {synchronized (mLock) {return mActivities.queryIntentForPackage(intent, resolvedType, flags, activities, userId);}
}