Android应用程序组件Content Provider的启动过程源代码分析(3)

简介:
 Step 7. ActivityManagerService.getContentProviderImpl
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     private final ContentProviderHolder getContentProviderImpl(   
  6.             IApplicationThread caller, String name) {   
  7.         ContentProviderRecord cpr;   
  8.         ProviderInfo cpi = null;   
  9.    
  10.         synchronized(this) {   
  11.             ProcessRecord r = null;   
  12.             if (caller != null) {   
  13.                 r = getRecordForAppLocked(caller);   
  14.                 ......   
  15.             }   
  16.    
  17.             // First check if this content provider has been published...   
  18.             cpr = mProvidersByName.get(name);   
  19.             if (cpr != null) {   
  20.                 ......   
  21.             } else {   
  22.                 try {   
  23.                     cpi = AppGlobals.getPackageManager().   
  24.                         resolveContentProvider(name,   
  25.                         STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);   
  26.                 } catch (RemoteException ex) {   
  27.                 }   
  28.                 ......   
  29.             }   
  30.    
  31.             cpr = mProvidersByClass.get(cpi.name);   
  32.             final boolean firstClass = cpr == null;   
  33.             if (firstClass) {   
  34.                 try {   
  35.                     ApplicationInfo ai =   
  36.                         AppGlobals.getPackageManager().   
  37.                         getApplicationInfo(   
  38.                         cpi.applicationInfo.packageName,   
  39.                         STOCK_PM_FLAGS);   
  40.                     ......   
  41.                     cpr = new ContentProviderRecord(cpi, ai);   
  42.                 } catch (RemoteException ex) {   
  43.                     // pm is in same process, this will never happen.   
  44.                 }   
  45.             }   
  46.    
  47.             if (r != null && cpr.canRunHere(r)) {   
  48.                 // If this is a multiprocess provider, then just return its   
  49.                 // info and allow the caller to instantiate it.  Only do   
  50.                 // this if the provider is the same user as the caller's   
  51.                 // process, or can run as root (so can be in any process).   
  52.                 return cpr;   
  53.             }   
  54.    
  55.             ......   
  56.    
  57.             // This is single process, and our app is now connecting to it.   
  58.             // See if we are already in the process of launching this   
  59.             // provider.   
  60.             final int N = mLaunchingProviders.size();   
  61.             int i;   
  62.             for (i=0; i<N; i++) {   
  63.                 if (mLaunchingProviders.get(i) == cpr) {   
  64.                     break;   
  65.                 }   
  66.             }   
  67.    
  68.             // If the provider is not already being launched, then get it   
  69.             // started.   
  70.             if (i >= N) {   
  71.                 final long origId = Binder.clearCallingIdentity();   
  72.                 ProcessRecord proc = startProcessLocked(cpi.processName,   
  73.                     cpr.appInfo, false0"content provider",   
  74.                     new ComponentName(cpi.applicationInfo.packageName,   
  75.                     cpi.name), false);   
  76.                 ......   
  77.                 mLaunchingProviders.add(cpr);   
  78.                 ......   
  79.             }   
  80.    
  81.             // Make sure the provider is published (the same provider class   
  82.             // may be published under multiple names).   
  83.             if (firstClass) {   
  84.                 mProvidersByClass.put(cpi.name, cpr);   
  85.             }   
  86.             cpr.launchingApp = proc;   
  87.             mProvidersByName.put(name, cpr);   
  88.    
  89.             ......   
  90.         }   
  91.    
  92.         // Wait for the provider to be published...   
  93.         synchronized (cpr) {   
  94.             while (cpr.provider == null) {   
  95.                 ......   
  96.                 try {   
  97.                     cpr.wait();   
  98.                 } catch (InterruptedException ex) {   
  99.                 }   
  100.             }   
  101.         }   
  102.    
  103.         return cpr;   
  104.     }   
  105.        
  106.     ......   
  107. }   
    这个函数比较长,我们一步一步地分析。
        函数首先是获取调用者的进程记录块信息:
  1. ProcessRecord r = null;  
  2. if (caller != null) {  
  3.     r = getRecordForAppLocked(caller);  
  4.     ......  
  5. }  
        在我们这个情景中,要获取的就是应用程序Article的进程记录块信息了,后面会用到。
 
        在ActivityManagerService中,有两个成员变量是用来保存系统中的Content Provider信息的,一个是mProvidersByName,一个是mProvidersByClass,前者是以Content Provider的authoriry值为键值来保存的,后者是以Content Provider的类名为键值来保存的。一个Content Provider可以有多个authority,而只有一个类来和它对应,因此,这里要用两个Map来保存,这里为了方便根据不同条件来快速查找而设计的。下面的代码就是用来检查要获取的Content Provider是否已经加存在的了:
 
 
  1. // First check if this content provider has been published...   
  2. cpr = mProvidersByName.get(name);   
  3. if (cpr != null) {   
  4.     ......   
  5. else {   
  6.     try {   
  7.         cpi = AppGlobals.getPackageManager().   
  8.             resolveContentProvider(name,   
  9.             STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);   
  10.     } catch (RemoteException ex) {   
  11.     }   
  12.     ......   
  13. }   
  14.    
  15. cpr = mProvidersByClass.get(cpi.name);   
  16. final boolean firstClass = cpr == null;   
  17. if (firstClass) {   
  18.     try {   
  19.         ApplicationInfo ai =   
  20.             AppGlobals.getPackageManager().   
  21.             getApplicationInfo(   
  22.             cpi.applicationInfo.packageName,   
  23.             STOCK_PM_FLAGS);   
  24.         ......   
  25.         cpr = new ContentProviderRecord(cpi, ai);   
  26.     } catch (RemoteException ex) {   
  27.         // pm is in same process, this will never happen.   
  28.     }   
  29. }   
      在我们这个情景中,由于是第一次调用ArticlesProvider接口,因此,在mProvidersByName和mProvidersByClass两个Map中都不存在ArticlesProvider的相关信息,因此,这里会通过AppGlobals.getPackageManager函数来获得PackageManagerService服务接口,然后分别通过它的resolveContentProvider和getApplicationInfo函数来分别获取ArticlesProvider应用程序的相关信息,分别保存在cpi和cpr这两个本地变量中。这些信息都是在安装应用程序的过程中保存下来的,具体可以参考 Android应用程序安装过程源代码分析 一文。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966983,如需转载请自行联系原作者
目录
相关文章
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1608 4
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
724 64
|
9月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
589 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
989 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
522 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
425 14
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
316 13
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
存储 搜索推荐 Java
打造个性化安卓应用:从设计到实现
【10月更文挑战第30天】在数字化时代,拥有一个个性化的安卓应用不仅能够提升用户体验,还能加强品牌识别度。本文将引导您了解如何从零开始设计和实现一个安卓应用,涵盖用户界面设计、功能开发和性能优化等关键环节。我们将以一个简单的记事本应用为例,展示如何通过Android Studio工具和Java语言实现基本功能,同时确保应用流畅运行。无论您是初学者还是希望提升现有技能的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧。

热门文章

最新文章