Android中级——PackageManagerService和Intent

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);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/90384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据Doris(一):Doris概述篇

文章目录 Doris概述篇 一、前言 二、Doris简介

【数据仓库设计基础(四)】数据仓库实施步骤

文章目录 1&#xff0e;定义范围2&#xff0e;确定需求3&#xff0e;逻辑设计1&#xff09;建立需要的数据列表2&#xff09;识别数据源3&#xff09;制作实体关系图 4&#xff0e;物理设计1&#xff09;性能优化2&#xff09;数仓的拓展性 5&#xff0e;装载数据6&#xff0e;…

Vue封装全局SVG组件

1.SVG图标配置 1.安装插件 npm install vite-plugin-svg-icons -D 2.Vite.config.ts中配置 import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from path export default () > {return {plugins: [createSvgIconsPlugin({// Specify the icon fo…

04. 人工智能核心基础 - 导论(3)

文章目录 人工智能和其他学科的关系为什么学习人工智能怎么学好人工智能&#xff1f;一些问题 Hi&#xff0c;你好。我是茶桁。 基于上一节课咱们的整体强度有点大&#xff0c;而且咱们马上也要进入高强度内容了&#xff0c;那么这一篇咱们就稍微水一篇吧。来聊聊天&#xff0…

FPGA 多路视频处理:图像缩放+视频拼接显示,HDMI采集,提供2套工程源码和技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐FPGA图像缩放方案推荐FPGA视频拼接方案推荐 3、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条缓冲FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 视频拼接算法图像缓存视频输出 4、vivado工程1&am…

【计算机网络】图解路由器(一)

本系列包含&#xff1a; 图解路由器&#xff08;一&#xff09;图解路由器&#xff08;二&#xff09; 图解路由器&#xff08;一&#xff09; 1、什么是路由器&#xff1f;2、什么是路由选择&#xff1f;3、什么是转发&#xff1f;4、路由器设备有哪些类型&#xff1f;5、根据…

创建vue3项目、链式调用、setup函数、ref函数、reactive函数、计算和监听属性、vue3的生命周期、torefs的使用、vue3的setup写法

1 创建vue3项目 # 两种方式- vue-cli&#xff1a;vue脚手架---》创建vue项目---》构建vue项目--》工具链跟之前一样- vite &#xff1a;https://cn.vitejs.dev/-npm create vuelatest // 或者-npm create vitelatest一路选择即可# 运行vue3项目-vue-cli跟之前一样-vite 创建的…

【小笔记】fasttext文本分类问题分析

【学而不思则罔&#xff0c;思维不学则怠】 2023.9.28 关于fasttext的原理及实战文章很多&#xff0c;我也尝试在自己的任务中进行使用&#xff0c;是一个典型的短文本分类任务&#xff0c;对知识图谱抽取的实体进行校验&#xff0c;判断实体类别是否正确&#xff0c;我构建了…

高级时钟项目(2)Json文件解析学习---C语言版本

笔者来介绍一下json文件解析 1、背景介绍 笔者在获取天气数据的时候&#xff0c;是通过MCU的WIFI去获取&#xff0c;但是获取到的数据json数据&#xff0c;需要解析&#xff0c;C语言没那么解析库&#xff0c;所以就需要找一些开源的解析库。 笔者找到cjson这个适用于C语言…

Vue - 组件递归

目录 组件递归子组件父组件 组件递归 当要渲染一个目录时&#xff0c;因为可能有嵌套数据&#xff0c;并且组件的层级未知&#xff0c;可以使用组件递归来解决 注意点&#xff1a; 1&#xff0c;使用递归时必须提供 name&#xff0c;也就是通过组件的 name 递归自己。 2&am…

Anaconda添加channels后出现unexpected urllib3 DEBUG logging from conda-build

1.问题描述 anaconda更新之后添加channels后出现bug: (base) ~/zlib-feedstock % conda build recipe 2>&1 | tee out ... INFO:conda_build.metadata:Attempting to finalize metadata for libzlib DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1):…

【c语言】通讯录【动态版本:有排序和文件操作】

目录 一、通讯录定义 二、通讯录的实现 1、test.c中菜单的实现 2、通讯录的创建逻辑 3、初始化 4、检查容量和添加 5、查找 6、删除功能 7、修改功能 8、打印 9、查找并打印 10、qsort排序 11、摧毁 12、保存数据到文件 13、从文件中读数据 完整代码&#xff1a; 一、通讯录定…

ABC310D Peaceful Teams

ABC310D Peaceful Teams 洛谷[ABC310D] Peaceful Teams 题目大意 有 n n n个运动员以及 m m m对数&#xff0c;每对数为 A i A_i Ai​和 B i B_i Bi​&#xff0c;表示 A i A_i Ai​和 B i B_i Bi​不能分在同一小组。你需要将这些人分为 t t t个小组&#xff0c;每个小组不…

【C++进阶(六)】STL大法--栈和队列深度剖析优先级队列适配器原理

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 栈和队列 1. 前言2. 栈和队列的接口函数熟悉3. …

《淘宝电商业务场景》API接口教程获得淘口令真实url

淘口令API接口的本质就是一款调用相关技术的应用程序接口&#xff0c;同时也是一种通过互联网传输数据的方式&#xff0c;可以实现各种各样的应用场景。比如企业运用在分享商品页面的过程中&#xff0c;可以简单组成一个淘口令&#xff0c;以便于分享淘口令。淘口令解析API接口…

java easyexcel 导出多级表头

maven <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>${easyexcel.version}</version> </dependency> 导出行的对象 import com.alibaba.excel.annotation.ExcelIgnore; import …

基础算法--KMP字符串

KMP 算法是一个快速查找匹配串的算法&#xff0c;它的作用其实就是本题问题&#xff1a;如何快速在「原字符串」中找到「匹配字符串」。 在朴素解法中&#xff0c;不考虑剪枝的话复杂度是 O(m∗n) 的&#xff0c;而 KMP 算法的复杂度为 O(mn)。 KMP 之所以能够在O(mn) 复杂度内…

leetCode 213. 打家劫舍 II 动态规划 房间连成环怎么偷呢?

213. 打家劫舍 II - 力扣&#xff08;LeetCode&#xff09; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

websocket连接实例

websocket连接 此篇websocket是最简单的运用&#xff0c;虽然简单&#xff0c;但也是需要注意 还有其它方法货协议&#xff0c;比如socket.js等。今天时间不充裕虽然例子都写好了&#xff0c;下次更新websocket所有相关的东西。提前想了解的&#xff0c;可私信 前端 var webs…

Spring Cloud Stream Kafka(3.2.2版本)使用

问题 正在尝试只用Spring Cloud Stream Kafka。 步骤 配置 spring:cloud:function:definition: project2Building stream:kafka:binder:brokers: xxxx:9002configuration:enable.auto.commit: falsesession.timeout.ms: 30000max.poll.records: 30allow.auto.create.top…