ContentProvider 启动过程
1.概述:
Content Provider 作为四大组件之一,主要用于进程内和进程间的数据共享。
本文主要讲解:应用程序 A 首次跨进程 query 应用程序 B 的 ContentProvider 的流程。
讲解代码为 AOSP Android 10,链接:http://aospxref.com/android-10.0.0_r2/
2.进程间首次访问 Content Provider 时序图:
3. 详细讲解
以时序图的步骤讲解。
3.1 step 1
|
public class MainActivity extends Activity { |
A 应用调用 query 方法,getContentResolver 方法调用关系如下:
|
59 Context mBase; ...... 101 @Override 102 public ContentResolver getContentResolver() { 103 return mBase.getContentResolver(); 104 } |
mBase 指的是 ContextImpl,其 getContentResolver 方法如下:
aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ContextImpl.java
|
199 private final ApplicationContentResolver mContentResolver; ...... 309 @Override 310 public ContentResolver getContentResolver() { 311 return mContentResolver; 312 } ...... 2516 private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread, 2517 @NonNull LoadedApk packageInfo, @Nullable String splitName, 2518 @Nullable IBinder activityToken, @Nullable UserHandle user, int flags, 2519 @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) { …… 2571 mContentResolver = new ApplicationContentResolver(this, mainThread); 2572 } ...... 2694 private static final class ApplicationContentResolver extends ContentResolver { …… 2749 } |
getContentResolver 返回了 ApplicationContentResolver 类型的 mContentResolver。
ApplicationContentResolver 是 ContextImpl 中的静态内部类,继承自 ContentProvider, 在 ContextImpl 构造方法中被创建。
query 方法在 ApplicationContentResolver 的父类 ContentResolver 中实现,最终会调用:
|
914 @Override 915 public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, 916 @Nullable String[] projection, @Nullable Bundle queryArgs, 917 @Nullable CancellationSignal cancellationSignal) { ...... 928 IContentProvider unstableProvider = acquireUnstableProvider(uri); // 1 ...... 934 try { ...... 942 } 943 try { 944 qCursor = unstableProvider.query(mPackageName, uri, projection, 945 queryArgs, remoteCancellationSignal); // 2 946 } catch (DeadObjectException e) { ...... 957 } ...... 974 } catch (RemoteException e) { ......
977 return null; 978 } finally { ...... 991 } 992 } |
//1 通过 acquireUnstableProvider 获得一个 IContentProvider 对象 unstableProvider。IContentProvider 是 业务实现类 ContentProvider 的本地代理 。
//2 调用代理对象 unstableProvider 的 query 方法,完成跨进程查询操作。
3.2 step 2
|
693 @UnsupportedAppUsage 694 protected abstract IContentProvider acquireUnstableProvider(Context c, String name); ...... 2111 public final IContentProvider acquireUnstableProvider(Uri uri) { 2112 if (!SCHEME_CONTENT.equals(uri.getScheme())) { 2113 return null; 2114 } 2115 String auth = uri.getAuthority(); 2116 if (auth != null) { 2117 return acquireUnstableProvider(mContext, uri.getAuthority()); 2118 } 2119 return null; 2120 } |
protected abstract IContentProvider acquireUnstableProvider(Context c, String name); 这个抽象方法是在 ContentResolver 的子类 ApplicationContentResolver 中实现的
3.3 step 3
ApplicationContentResolver 是 ContextImpl 中的静态内部类
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ContextImpl.java
|
2694 private static final class ApplicationContentResolver extends ContentResolver { 2695 @UnsupportedAppUsage 2696 private final ActivityThread mMainThread; 2697 2698 public ApplicationContentResolver(Context context, ActivityThread mainThread) { 2699 super(context); 2700 mMainThread = Preconditions.checkNotNull(mainThread); 2701 } ...... 2723 @Override 2724 protected IContentProvider acquireUnstableProvider(Context c, String auth) { 2725 return mMainThread.acquireProvider(c, 2726 ContentProvider.getAuthorityWithoutUserId(auth), 2727 resolveUserIdFromAuthority(auth), false); 2728 } ...... 2749 } |
调用了 ActivityThread 的 acquireUnstableProvider 方法
3.4 step 4
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
424 final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap 425 = new ArrayMap<ProviderKey, ProviderClientRecord>(); // 1 ...... 662 final class ProviderClientRecord { // 客户端使用的 663 final String[] mNames; 665 final IContentProvider mProvider; 667 final ContentProvider mLocalProvider; 669 final ContentProviderHolder mHolder; ...... 678 } ...... 6545 public final IContentProvider acquireProvider( 6546 Context c, String auth, int userId, boolean stable) { 6547 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); // 2 ...... 6558 ContentProviderHolder holder = null; // 3 6559 try { 6560 synchronized (getGetProviderLock(auth, userId)) { 6561 holder = ActivityManager.getService().getContentProvider( 6562 getApplicationThread(), c.getOpPackageName(), auth, userId, stable); // 4 6563 } 6564 } catch (RemoteException ex) { 6565 throw ex.rethrowFromSystemServer(); 6566 } ...... 6574 holder = installProvider(c, holder, holder.info, 6575 true /*noisy*/, holder.noReleaseNeeded, stable); // 5 6576 return holder.provider; 6577 } ...... 6659 @UnsupportedAppUsage 6660 public final IContentProvider acquireExistingProvider( 6661 Context c, String auth, int userId, boolean stable) { 6662 synchronized (mProviderMap) { 6663 final ProviderKey key = new ProviderKey(auth, userId); 6664 final ProviderClientRecord pr = mProviderMap.get(key); ...... 6669 IContentProvider provider = pr.mProvider; 6670 IBinder jBinder = provider.asBinder(); 6671 if (!jBinder.isBinderAlive()) { // 6 ...... 6676 handleUnstableProviderDiedLocked(jBinder, true); // 7 6677 return null; 6678 } ...... 6686 return provider; 6687 } 6688 } ...... 6827 final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) { 6828 ProviderRefCount prc = mProviderRefCountMap.get(provider); 6829 if (prc != null) { ...... 6832 mProviderRefCountMap.remove(provider); 6833 for (int i=mProviderMap.size()-1; i>=0; i--) { 6834 ProviderClientRecord pr = mProviderMap.valueAt(i); 6835 if (pr != null && pr.mProvider.asBinder() == provider) { 6836 Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString()); 6837 mProviderMap.removeAt(i); // 8 6838 } 6839 } 6840 6841 if (fromClient) { ...... 6847 try { 6848 ActivityManager.getService().unstableProviderDied( 6849 prc.holder.connection); // 9 6850 } catch (RemoteException e) { 6851 //do nothing content provider object is dead any way 6852 } 6853 } 6854 } 6855 } |
// 1 ActivityThread 本地用于缓存 ProviderClientRecord(包含 IContentProvider,ContentProvider ,ContentProviderHolder ) 的 ArrayMap 对象 mProviderMap
// 2 调用 acquireExistingProvider 查找缓存 mProviderMap 中是否有目标 ContentProvider,有则返回
// 3 ContentProviderHolder 用于进程间传递 ContentProvider 相关信息(ProviderInfo,IContentProvider,IBinder 等),如用于 AMS 和 应用进程间传递信息
|
33 public class ContentProviderHolder implements Parcelable { 35 public final ProviderInfo info; 37 public IContentProvider provider; 38 public IBinder connection; 40 public boolean noReleaseNeeded; 85 } |
ProviderInfo:用于存储有关 pm 的 ContentProvider 信息,信息包括权限、进程、用户等
|
30 public final class ProviderInfo extends ComponentInfo 31 implements Parcelable { 38 public String readPermission = null; 42 public String writePermission = null; 49 public boolean grantUriPermissions = false; 55 public boolean forceUriPermissions = false; 65 public PatternMatcher[] uriPermissionPatterns = null; 73 public PathPermission[] pathPermissions = null; 78 public boolean multiprocess = false; 82 public int initOrder = 0; 88 public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000; 95 public static final int FLAG_SINGLE_USER = 0x40000000; 102 public int flags = 0; 190 } |
// 4 调用 IActivityManager 的 getContentProvider 方法,最终会调用 AMS 的对应方法
// 5 installProvider 方法:把从 AMS 中返回的 ContentProvider 进行本地安装保存等,step 26 会重点说明
// 6 IBinder 对象挂掉了
// 7 处理善后工作
// 8 从 mProviderMap 中删除
// 9 通知 AMS 做善后工作
3.5 step 5
3.6 step 6
调用 AMS 的 getContentProvider
|
7221 @Override 7222 public final ContentProviderHolder getContentProvider( 7223 IApplicationThread caller, String callingPackage, String name, int userId, 7224 boolean stable) { ...... 7240 return getContentProviderImpl(caller, name, null, callingUid, callingPackage, 7241 null, stable, userId); 7242 } |
3.7 step 7
|
470 static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20 * 1000; // 连接一个新创建的 ContentProvider 的超时时间为20S
6706 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, 6707 String name, IBinder token, int callingUid, String callingPackage, String callingTag, 6708 boolean stable, int userId) { 6709 ContentProviderRecord cpr; // 1 ContentProviderRecord 只应用在 AMS 中,用来记录 ContentProvider 组件相关信息 6710 ContentProviderConnection conn = null; 6711 ProviderInfo cpi = null; // 用来描述 ContentProvider 组件相关信息 6712 boolean providerRunning = false; 6713 6714 synchronized(this) { 6717 ProcessRecord r = null; // 记录进程信息 6718 if (caller != null) { 6719 r = getRecordForAppLocked(caller); // 获取调用方的进程信息,即应用程序 A 的进程信息 6726 } // 检查目标 ContentProvider 组件是否已经发布了 6732 // First check if this content provider has been published... 6733 cpr = mProviderMap.getProviderByName(name, userId); 6752 if (cpr != null && cpr.proc != null) { 6753 providerRunning = !cpr.proc.killed; 6770 } 6772 if (providerRunning) { // ContentProvider 组件已经发布 6776 if (r != null && cpr.canRunHere(r)) { // 2 组件发布了并且能够运行在调用方所在的进程 6791 // This provider has been published or is in the process 6792 // of being published... but it is also allowed to run 6793 // in the caller's process, so don't make a connection 6794 // and just let the caller instantiate its own instance. 6795 ContentProviderHolder holder = cpr.newHolder(null); 6796 // don't give caller the provider object, it needs 6797 // to make its own. 6798 holder.provider = null; 6799 return holder; 6800 } 6889 if (!providerRunning) { // ContentProvider 组件还没有启动 6890 try { 6892 cpi = AppGlobals.getPackageManager(). 6893 resolveContentProvider(name, 6894 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId); 6896 } catch (RemoteException ex) { 6897 } 6898 if (cpi == null) { 6899 return null; 6900 } 6953 ComponentName comp = new ComponentName(cpi.packageName, cpi.name); // 通过 ContentProvider 组件名获取对应的 ContentProviderRecord 对象 6955 cpr = mProviderMap.getProviderByClass(comp, userId); // 3 6957 final boolean firstClass = cpr == null; 6958 if (firstClass) { // ContentProviderRecord 对象为空,没有找到 6959 final long ident = Binder.clearCallingIdentity(); 6968 try { 6970 ApplicationInfo ai = 6971 AppGlobals.getPackageManager(). 6972 getApplicationInfo( 6973 cpi.applicationInfo.packageName, 6974 STOCK_PM_FLAGS, userId); 6981 ai = getAppInfoForUser(ai, userId); 6982 cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton); // 创建一个新的 ContentProviderRecord 对象 6983 } catch (RemoteException ex) { 6984 // pm is in same process, this will never happen. 6985 } finally { 6986 Binder.restoreCallingIdentity(ident); 6987 } 6988 } 6992 if (r != null && cpr.canRunHere(r)) { // 能够在此访问进程中启动,即应用程序 A 6993 // If this is a multiprocess provider, then just return its 6994 // info and allow the caller to instantiate it. Only do 6995 // this if the provider is the same user as the caller's 6996 // process, or can run as root (so can be in any process). 6997 return cpr.newHolder(null); 6998 } // 成员变量 mLaunchingProviders 保存了所有正在启动的 ContentProvider 组件 7004 // This is single process, and our app is now connecting to it. 7005 // See if we are already in the process of launching this 7006 // provider. 7007 final int N = mLaunchingProviders.size(); 7008 int i; 7009 for (i = 0; i < N; i++) { 7010 if (mLaunchingProviders.get(i) == cpr) { // 在正在启动列表中 7011 break; 7012 } 7013 } 7014 7015 // If the provider is not already being launched, then get it 7016 // started. 7017 if (i >= N) { // 不在正在启动列表中 7018 final long origId = Binder.clearCallingIdentity(); 7020 try { 7035 ProcessRecord proc = getProcessRecordLocked( // 获取应用程序进程信息,即目标 ContentProvider 的进程信息 7036 cpi.processName, cpr.appInfo.uid, false); 7037 if (proc != null && proc.thread != null && !proc.killed) { // ContentProvider 所在进程在运行中 7040 if (!proc.pubProviders.containsKey(cpi.name)) { 7042 proc.pubProviders.put(cpi.name, cpr); 7043 try { 7044 proc.thread.scheduleInstallProvider(cpi); // 调度安装 ContentProvider 7045 } catch (RemoteException e) { 7046 } 7047 } 7048 } else { // ContentProvider 所在进程没有启动 // 创建一个新的进程来启动 ContentProvider 7050 proc = startProcessLocked(cpi.processName, 7051 cpr.appInfo, false, 0, 7052 new HostingRecord("content provider", 7053 new ComponentName(cpi.applicationInfo.packageName, 7054 cpi.name)), false, false, false); 7056 if (proc == null) { 7061 return null; 7062 } 7063 } 7064 cpr.launchingApp = proc; 7065 mLaunchingProviders.add(cpr); // 添加 ContentProvider 组件到正在启动列表中 7066 } finally { 7067 Binder.restoreCallingIdentity(origId); 7068 } 7069 } 7073 // Make sure the provider is published (the same provider class 7074 // may be published under multiple names). 7075 if (firstClass) { 7076 mProviderMap.putProviderByClass(comp, cpr); // 保存到全局变量中 7077 } 7079 mProviderMap.putProviderByName(name, cpr); // 保存到全局变量中 7085 } 7091 } 7092 7093 // Wait for the provider to be published... 7094 final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT; 7095 boolean timedOut = false; 7096 synchronized (cpr) { 7097 while (cpr.provider == null) { 7109 try { 7110 final long wait = Math.max(0L, timeout - SystemClock.uptimeMillis()); 7114 if (conn != null) { 7115 conn.waiting = true; 7116 } 7117 cpr.wait(wait); // 等待 ContentProviderRecord 对象 cpr 7118 if (cpr.provider == null) { 7119 timedOut = true; 7120 break; 7121 } 7122 } catch (InterruptedException ex) { 7123 } finally { 7124 if (conn != null) { 7125 conn.waiting = false; 7126 } 7127 } 7128 } 7129 } 7130 if (timedOut) { // 超时了,返回 null 7146 return null; 7147 } 7149 return cpr.newHolder(conn); // 创建成功 7150 } |
// 1 // 2 ContentProviderRecord 在 AMS 内部使用的,用来记录ContentProvider组件的发布(启动)信息,类型为 IContentProvider 的成员变量 provider 用来来记录ContentProvider 组件。在 ActivityManagerService 中,每一个已经启动的 ContentProvider 组件都使用一个 ContentProviderRecord 对象来描述。这些 ContentProviderRecord 对象保存在 AMS 类的成员变量 mProviderMap 中
|
40 final class ContentProviderRecord implements ComponentName.WithComponentName { 41 final ActivityManagerService service; 42 public final ProviderInfo info; 43 final int uid; 44 final ApplicationInfo appInfo; 45 final ComponentName name; 46 final boolean singleton; 47 public IContentProvider provider; 48 public boolean noReleaseNeeded; 49 // All attached clients 50 final ArrayList<ContentProviderConnection> connections 51 = new ArrayList<ContentProviderConnection>(); 52 //final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>(); 53 // Handles for non-framework processes supported by this provider 54 ArrayMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle; 55 // Count for external process for which we have no handles. 56 int externalProcessNoHandleCount; 57 ProcessRecord proc; // if non-null, hosting process. 58 ProcessRecord launchingApp; // if non-null, waiting for this app to be launched. 59 String stringName; 60 String shortStringName; 116 public boolean canRunHere(ProcessRecord app) { // 此方法被 步骤 // 2 所调用 117 return (info.multiprocess || info.processName.equals(app.processName)) 118 && uid == app.info.uid; 119 } ...... 335 } |
此类的 canRunHere 方法:当 uid 相同时,并且此 ContentProvider 允许在多进程中运行或者进程名称相同时,则判断为可在此进程运行。
// 3 mProviderMap 实质上是一个 HashMap,可通过两种方式进行查找,查找结果是一个 ContentProviderRecord 对象 cpr :
mProviderMap.getProviderByName() 函数,通过参数 name 和参数 userId 进行查找;参数 name 指向了将要启动的 ContentProvider 组件的 android:authorities 属性值,也就是 URI 值对应的权限部分;参数 userId 则是调用方应用程序的 Linux 用户 ID;
mProviderMap.getProviderByClass() 函数,通过 ContentProvider 组件的类名进行查找;
3.8 step 8
AMS 启动应用程序 B 的进程
startProcessLocked:它通过调用 Process 的静态成员函数 start() 创建一个新的应用程序进程,并且把这个新建的应用程序进程的入口设置为 ActivityThread 类的静态成员函数 main(),启动新的应用程序进程不是本文重点,故略。。。
3.9 step 9
执行应用 B 的 ActivityThread 的 main 方法
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
7310 public static void main(String[] args) { …… 7329 Looper.prepareMainLooper(); // 1 …… 7342 ActivityThread thread = new ActivityThread(); 7343 thread.attach(false, startSeq); // 2 7344 7345 if (sMainThreadHandler == null) { 7346 sMainThreadHandler = thread.getHandler(); 7347 } 7348 7349 if (false) { 7350 Looper.myLooper().setMessageLogging(new 7351 LogPrinter(Log.DEBUG, "ActivityThread")); 7352 } …… 7356 Looper.loop(); // 3 7357 7358 throw new RuntimeException("Main thread loop unexpectedly exited"); 7359 } |
// 1 // 3 Looper.prepareMainLooper() 获取了 Looper, Looper.loop() 开启消息循环
// 2 创建 ActivityThread 对象,调用 attach
3.10 step 10
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
7071 private void attach(boolean system, long startSeq) { …… 7074 if (!system) { …… 7078 final IActivityManager mgr = ActivityManager.getService(); // 1 7079 try { 7080 mgr.attachApplication(mAppThread, startSeq); // 2 7081 } catch (RemoteException ex) { 7082 throw ex.rethrowFromSystemServer(); 7083 } …… 7106 } …… 7144 } |
// 1 获得 IActivityManager 对象 mgr
// 2 将 ApplicationThread 类型的 mAppThread 对象传给 attachApplication 方法,最终调用的是 AMS 的 attachApplication 方法
3.11 step 11
3.12 step 12
调用到 AMS 的 attachApplication 方法
|
5174 @Override 5175 public final void attachApplication(IApplicationThread thread, long startSeq) { 5176 synchronized (this) { 5177 int callingPid = Binder.getCallingPid(); 5178 final int callingUid = Binder.getCallingUid(); 5179 final long origId = Binder.clearCallingIdentity(); 5180 attachApplicationLocked(thread, callingPid, callingUid, startSeq); 5181 Binder.restoreCallingIdentity(origId); 5182 } 5183 } |
3.13 step 13
|
4762 private final boolean attachApplicationLocked(IApplicationThread thread, 4763 int pid, int callingUid, long startSeq) { ...... 4891 try { …… 5041 if (app.isolatedEntryPoint != null) { …… 5045 } else if (instr2 != null) { 5046 thread.bindApplication(processName, appInfo, providers, 5047 instr2.mClass, 5048 profilerInfo, instr2.mArguments, 5049 instr2.mWatcher, 5050 instr2.mUiAutomationConnection, testMode, 5051 mBinderTransactionTrackingEnabled, enableTrackAllocation, 5052 isRestrictedBackupMode || !normalMode, app.isPersistent(), 5053 new Configuration(app.getWindowProcessController().getConfiguration()), 5054 app.compat, getCommonServicesLocked(app.isolated), 5055 mCoreSettingsObserver.getCoreSettingsLocked(), 5056 buildSerial, autofillOptions, contentCaptureOptions); 5057 } …… 5079 } catch (Exception e) { …… 5089 } …… 5171 return true; 5172 } |
thread 是 IApplicationThread 类型的,采用 AIDL 通信,是 ActivityThread 的内部类
3.14 step 14
3.15 step 15
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
996 public final void bindApplication(String processName, ApplicationInfo appInfo, 997 List<ProviderInfo> providers, ComponentName instrumentationName, 998 ProfilerInfo profilerInfo, Bundle instrumentationArgs, 999 IInstrumentationWatcher instrumentationWatcher, 1000 IUiAutomationConnection instrumentationUiConnection, int debugMode, 1001 boolean enableBinderTracking, boolean trackAllocation, 1002 boolean isRestrictedBackupMode, boolean persistent, Configuration config, 1003 CompatibilityInfo compatInfo, Map services, Bundle coreSettings, 1004 String buildSerial, AutofillOptions autofillOptions, 1005 ContentCaptureOptions contentCaptureOptions) { …… 1032 setCoreSettings(coreSettings); 1033 1034 AppBindData data = new AppBindData(); 1035 data.processName = processName; 1036 data.appInfo = appInfo; 1037 data.providers = providers; 1038 data.instrumentationName = instrumentationName; 1039 data.instrumentationArgs = instrumentationArgs; …… 1053 sendMessage(H.BIND_APPLICATION, data); 1054 } |
3.16 step 16
3.17 step 17
3.18 step 18
最终会由 H 类对象处理消息
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
1750 class H extends Handler { ...... 1853 public void handleMessage(Message msg) { 1854 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); 1855 switch (msg.what) { 1856 case BIND_APPLICATION: 1857 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); 1858 AppBindData data = (AppBindData)msg.obj; 1859 handleBindApplication(data); 1860 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); 1861 break; ...... 2031 } ...... 2037 } 2038 } |
最终由 ActivityThread 的内部类 H 的对象来处理
3.19 step 19
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
6122 private void handleBindApplication(AppBindData data) { …… 6312 final InstrumentationInfo ii; …… 6343 final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); // 创建 ContextImpl …… 6366 if (ii != null) { 6367 ApplicationInfo instrApp; …… 6379 final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, 6380 appContext.getClassLoader(), false, true, false); 6381 6385 final ContextImpl instrContext = ContextImpl.createAppContext(this, pi, 6386 appContext.getOpPackageName()); 6387 6388 try { 6389 final ClassLoader cl = instrContext.getClassLoader(); 6390 mInstrumentation = (Instrumentation) 6391 cl.loadClass(data.instrumentationName.getClassName()).newInstance(); // 1 6392 } catch (Exception e) { …… 6396 } 6397 6398 final ComponentName component = new ComponentName(ii.packageName, ii.name); 6399 mInstrumentation.init(this, instrContext, appContext, component, 6400 data.instrumentationWatcher, data.instrumentationUiAutomationConnection); // 2 …… 6409 } 6413 6425 Application app; …… 6428 try { …… 6431 app = data.info.makeApplication(data.restrictedBackupMode, null); // 3 …… 6439 mInitialApplication = app; …… 6443 if (!data.restrictedBackupMode) { 6444 if (!ArrayUtils.isEmpty(data.providers)) { 6445 installContentProviders(app, data.providers); // 4 启动目标 ContentProvider 6446 } 6447 } …… 6451 try { 6452 mInstrumentation.onCreate(data.instrumentationArgs); 6453 } 6454 catch (Exception e) { …… 6458 } 6459 try { 6460 mInstrumentation.callApplicationOnCreate(app); // 5 6461 } catch (Exception e) { …… 6467 } 6468 } finally { …… 6475 } …… 6497 } |
// 1 // 2 通过反射创建 Instrumentation,并初始化
// 3 // 5 创建 Application,并调用 onCreate 方法, 应用程序启动
// 4 调用 installContentProviders 启动 ContentProvider
3.20 step 20
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
6514 @UnsupportedAppUsage 6515 private void installContentProviders( 6516 Context context, List<ProviderInfo> providers) { 6517 final ArrayList<ContentProviderHolder> results = new ArrayList<>(); 6518 6519 for (ProviderInfo cpi : providers) { // 1 6520 if (DEBUG_PROVIDER) { 6521 StringBuilder buf = new StringBuilder(128); 6522 buf.append("Pub "); 6523 buf.append(cpi.authority); 6524 buf.append(": "); 6525 buf.append(cpi.name); 6526 Log.i(TAG, buf.toString()); 6527 } 6528 ContentProviderHolder cph = installProvider(context, null, cpi, 6529 false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); // 2 6530 if (cph != null) { 6531 cph.noReleaseNeeded = true; 6532 results.add(cph); 6533 } 6534 } 6535 6536 try { 6537 ActivityManager.getService().publishContentProviders( 6538 getApplicationThread(), results); // 3 6539 } catch (RemoteException ex) { 6540 throw ex.rethrowFromSystemServer(); 6541 } 6542 } |
// 1 遍历当前应用程序 B 进程的 ProviderInfo 列表
// 2 调用 installProvider 方法安装每个 ContentProvider
// 3 为 step 24, 把安装好的 ContentProvider 发布到 AMS 中
3.21 step 21
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
6923 private ContentProviderHolder installProvider(Context context, 6924 ContentProviderHolder holder, ProviderInfo info, 6925 boolean noisy, boolean noReleaseNeeded, boolean stable) { 6926 ContentProvider localProvider = null; 6927 IContentProvider provider; 6928 if (holder == null || holder.provider == null) { // 为空则需要启动 ContentProvider 组件 …… 6933 Context c = null; 6934 ApplicationInfo ai = info.applicationInfo; 6935 if (context.getPackageName().equals(ai.packageName)) { 6936 c = context; 6937 } …… 6963 6964 try { 6965 final java.lang.ClassLoader cl = c.getClassLoader(); 6966 LoadedApk packageInfo = peekPackageInfo(ai.packageName, true); 6967 if (packageInfo == null) { 6968 // System startup case. 6969 packageInfo = getSystemContext().mPackageInfo; 6970 } 6971 localProvider = packageInfo.getAppFactory() 6972 .instantiateProvider(cl, info.name); // 1 6973 provider = localProvider.getIContentProvider(); 6974 if (provider == null) { …… 6978 return null; 6979 } …… 6983 localProvider.attachInfo(c, info); // 2 6984 } catch (java.lang.Exception e) { …… 6990 return null; 6991 } 6992 } else { // 不为空时,不需启动 ContentProvider, 此 ContentProvider 是从 AMS 返回来的 6993 provider = holder.provider; …… 6996 } 6997 6998 ContentProviderHolder retHolder; 6999 7000 synchronized (mProviderMap) { …… 7003 IBinder jBinder = provider.asBinder(); 7004 if (localProvider != null) { 7005 ComponentName cname = new ComponentName(info.packageName, info.name); 7006 ProviderClientRecord pr = mLocalProvidersByName.get(cname); 7007 if (pr != null) { …… 7012 provider = pr.mProvider; 7013 } else { 7014 holder = new ContentProviderHolder(info); 7015 holder.provider = provider; 7016 holder.noReleaseNeeded = true; 7017 pr = installProviderAuthoritiesLocked(provider, localProvider, holder); 7018 mLocalProviders.put(jBinder, pr); 7019 mLocalProvidersByName.put(cname, pr); 7020 } 7021 retHolder = pr.mHolder; 7022 } else { 7023 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 7024 if (prc != null) { …… 7041 } else { 7042 ProviderClientRecord client = installProviderAuthoritiesLocked( 7043 provider, localProvider, holder); 7044 if (noReleaseNeeded) { 7045 prc = new ProviderRefCount(holder, client, 1000, 1000); 7046 } else { 7047 prc = stable 7048 ? new ProviderRefCount(holder, client, 1, 0) 7049 : new ProviderRefCount(holder, client, 0, 1); 7050 } 7051 mProviderRefCountMap.put(jBinder, prc); 7052 } 7053 retHolder = prc.holder; 7054 } 7055 } 7056 return retHolder; 7057 } |
// 1 通过反射创建 ContentProvider 类型的 localProvider 对象
|
144 public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl, 145 @NonNull String className) 146 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 147 return (ContentProvider) cl.loadClass(className).newInstance(); 148 } |
// 2 调用 attachInfo 方法
3.22 step 22
3.23 step 23
|
2069 private void attachInfo(Context context, ProviderInfo info, boolean testing) { 2070 mNoPerms = testing; 2071 mCallingPackage = new ThreadLocal<>(); 2072 2073 /* 2074 * Only allow it to be set once, so after the content service gives 2075 * this to us clients can't change it. 2076 */ 2077 if (mContext == null) { 2078 mContext = context; 2079 if (context != null && mTransport != null) { 2080 mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( 2081 Context.APP_OPS_SERVICE); 2082 } 2083 mMyUid = Process.myUid(); 2084 if (info != null) { 2085 setReadPermission(info.readPermission); // 设置权限 2086 setWritePermission(info.writePermission); // 设置权限 2087 setPathPermissions(info.pathPermissions); // 设置权限 2088 mExported = info.exported; 2089 mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0; 2090 setAuthorities(info.authority); 2091 } 2092 ContentProvider.this.onCreate(); // 1 2093 } 2094 } |
// 1 调用应用 B 中目标 XXContentProvider 的 onCreate 方法
3.24 step 24
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
6515 private void installContentProviders( 6516 Context context, List<ProviderInfo> providers) { …… 6536 try { 6537 ActivityManager.getService().publishContentProviders( 6538 getApplicationThread(), results); // 1 6539 } catch (RemoteException ex) { 6540 throw ex.rethrowFromSystemServer(); 6541 } 6542 } |
// 1 向 AMS 发布已安装的 ContentProvider
3.25 step 25
|
7335 public final void publishContentProviders(IApplicationThread caller, 7336 List<ContentProviderHolder> providers) { 7337 if (providers == null) { 7338 return; 7339 } …… 7342 synchronized (this) { 7343 final ProcessRecord r = getRecordForAppLocked(caller); …… 7354 final int N = providers.size(); 7355 for (int i = 0; i < N; i++) { 7356 ContentProviderHolder src = providers.get(i); …… 7360 ContentProviderRecord dst = r.pubProviders.get(src.info.name); …… 7362 if (dst != null) { 7363 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); 7364 mProviderMap.putProviderByClass(comp, dst); 7365 String names[] = dst.info.authority.split(";"); 7366 for (int j = 0; j < names.length; j++) { 7367 mProviderMap.putProviderByName(names[j], dst); // 放入到 mProviderMap 中 7368 } 7369 7370 int launchingCount = mLaunchingProviders.size(); 7371 int j; 7372 boolean wasInLaunchingProviders = false; 7373 for (j = 0; j < launchingCount; j++) { 7374 if (mLaunchingProviders.get(j) == dst) { 7375 mLaunchingProviders.remove(j); // 从 mLaunchingProviders 删除 7376 wasInLaunchingProviders = true; 7377 j--; 7378 launchingCount--; 7379 } 7380 } …… 7391 synchronized (dst) { 7392 dst.provider = src.provider; // 1 7393 dst.setProcess(r); // 1 7394 dst.notifyAll(); // 2 7395 } …… 7399 } 7400 } …… 7403 } 7404 } |
// 1 把 ContentProvider 存储在 ContentProviderRecord 对象中,之后保存到全局变量 mProviderMap 中
// 2 把等待这个 ContentProvider 的地方唤醒, 即 step 7 中的 getContentProviderImpl
|
6706 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, 6707 String name, IBinder token, int callingUid, String callingPackage, String callingTag, 6708 boolean stable, int userId) { …… 7096 synchronized (cpr) { 7097 while (cpr.provider == null) { …… 7109 try { …… 7117 cpr.wait(wait); …… 7122 } catch (InterruptedException ex) { 7123 } finally { …… 7127 } 7128 } 7129 } …… 7150 } |
3.26 step 26
应用程序 A 等待的 ContentProviderHolder 终于返回了,执行的是 installProvider 方法, 在 step 21 中提及过
http://aospxref.com/android-10.0.0_r2/xref/frameworks/base/core/java/android/app/ActivityThread.java
|
6923 private ContentProviderHolder installProvider(Context context, 6924 ContentProviderHolder holder, ProviderInfo info, 6925 boolean noisy, boolean noReleaseNeeded, boolean stable) { 6926 ContentProvider localProvider = null; 6927 IContentProvider provider; 6928 if (holder == null || holder.provider == null) { // 应用程序 B 执行的流程 …… 6992 } else { // 应用程序 A 执行的流程 6993 provider = holder.provider; …… 6996 } 6997 6998 ContentProviderHolder retHolder; 6999 7000 synchronized (mProviderMap) { ……
7003 IBinder jBinder = provider.asBinder(); 7004 if (localProvider != null) { 7005 ComponentName cname = new ComponentName(info.packageName, info.name); 7006 ProviderClientRecord pr = mLocalProvidersByName.get(cname); 7007 if (pr != null) { …… 7013 } else { 7014 holder = new ContentProviderHolder(info); 7015 holder.provider = provider; 7016 holder.noReleaseNeeded = true; 7017 pr = installProviderAuthoritiesLocked(provider, localProvider, holder); 7018 mLocalProviders.put(jBinder, pr); // 缓存到本地 7019 mLocalProvidersByName.put(cname, pr); // 缓存到本地 7020 } 7021 retHolder = pr.mHolder; 7022 } …… 7055 } 7056 return retHolder; 7057 } |
3.27 step 27
应用程序 A 拿到应用程序 B 目标 ContentProvider 的 IContentProvider 对象,调用 IContentProvider 对象的 query 方法进行查询,并给应用程序 A 返回结果 Cursor 对象
4.参考文档:
- 《Android 进阶解密》 作者:刘望舒
- https://www.jianshu.com/p/74014e1b18b0 作者:umbrella1
- https://www.jianshu.com/p/b23e47cbe581 作者:wondertwo1
- https://www.jianshu.com/p/7455bc417362 作者:wondertwo1
- https://www.jianshu.com/p/e58a9a25673f 作者:wondertwo1