【Android Framework (十) 】- ContentProvider


知识回顾

启动第一个流程init

1,挂载文件系统,创建文件目录 调用selinux_setup权限安全相关
2,初始化内存空间 初始化属性服务 创建Epoll 注册监听子进程重启异常操作等,对子进程进行线程守护
3,startPropertyServic 开启属性服务 进行监听
4,LoadBootScripts 加载init.rc文件 进行解析 调用do_class_start 文件开启service
5,Service::Start函数->fork子进程->并且执行app_process文件,开启了zygote

Zygote的流程

1,startVm函数注册jvm startReg函数注册jni环境唤起 Zygote.main
2,forkSystemServer
3,preload预加载class 系统资源
4,调用runSelectLoop函数循环等待客户端连接
5,有客户端的连接后调用processOneCommand()函数 fork进程,初始化进程,创建ProcessState初始化binder
6,根据请求的targetClass 执行Main函数

system_server

system_server是系统用来启动管理service的入口,比如我们常用的AMS、WMS、PMS等等都是它来创建的,system_server加载了framework-res.apk,接着调用startBootstrapServices、startCoreServices、startOtherServices开启了非常多的服务,以及开启了WatchDog监控service。

ServiceManager

它是一个服务的提供者,可以让应用获取到系统的各种服务,还有Binder机制。ServiceManager是Android系统为开发者提供的一个服务大管家,当开机之后,由内核态进入用户态之后,会启动system_server进程,在该进程里面会对AMS,PKMS,PMS等等进行创建。然后添加到ServiceManager中。SystemServer算是一个大管家,他整合了系统的各种服务,监控着我们服务,管理服务的周期。而ServiceManager只有一个功能就是提供binder通信,让应用可以获取到系统提供的服务。

Binder

是Android特有的一种通信方式。Android Binder的前身是OpenBinder,后来在OpenBinder的基础上开发了Android Binder。
Android基于Linux所以支持Linux原生的IPC通信机制:共享内存、Pipe、Socket。Binder是Android特有的。

性能上:稳定性: 安全:
Binder : 一次拷贝 c/s架构 客户端和服务端 稳定 内核层校验系统来保证通信安全
共享内存:0次 不稳定会有同步问题和并发死锁问题 自定义协议
管道pipe:需要两次拷贝 单管道 效率低只能读或者只能写 自定义协议
Socket:两次拷贝 c/s架构 不好的地方消耗性能握手和挥手 自定义协议

Launcher的启动

它是由system_server开启的,通过LauncherModel进行IPC通信(Binder)调用PackageManagerService的queryIntentActivities获取到所有应用的信息,然后绑定数据源到RecyclerView中,而它的点击事件则是通过ItemClickHandler来进行分发的

AMS

接着讲了AMS是如何开启应用进程的,首先我们从Launcher的点击开始,调用到Activity的startActivity函数,通过Instrumentation的execStartActivity经过两次IPC(1.通过ServiceManager获取到ATMS 2.调用ATMS的startActivity) 调用到AMS端在AMS端进行了一系列的信息处理,会判断进程是否存在,没有存在的话就会开启进程(通过Socket,给ZygoteServer发送信息),传入entryPoint为ActivityThread,通过Zygote来fork出来子进程(应用进程)调用ActivityThread.main,应用进程创建之后会调用到AMS,由AMS来attachApplication存储进程信息,然后告诉客户端,让客户端来创建Application,并在客户端创建成功之后 继续执行开启Activity的流程。客户端接收到AMS的数据之后会创建loadedApk,Instrumentation 以及Application调用attach(attachBaseContext),调用Instrumentation的callApplicationOncreate执行Application的Oncreate周期.

应用执行完Application的OnCreate之后 回到ATMS的attachApplication 接着调用 realStartActivityLocked 创建了ClientTransaction,设置callBack为LaunchActivityItem添加了stateRequest 为ResumeActivityItem,然后通过IApplicationThread 回到客户端执行这两个事务,调用了ActivityThread的scheduleTransaction 函数,调用executeCallBack 执行了LaunchActivityItem的execute 他会调用ActivityThread的 handleLaunchActivity,会创建Activity Context,通过Instrumentation.newActivity 反射创建Activity 并调用attach 绑定window 再通过Instrumentation的callActivityOnCreate执行Activity的onCreate,在Activity的onCreate中分发监听给ActivityLifecycleCallbacks。最后设置ActivityClientRecord的state为ON_CREATE。 接着执行executeLifecycleState,调用了cycleToPath,之前设置了state为ON_CREATE,所以会返回一个Int数组{2} 调用performLifecycleSequence会执行到ActivityThread的handleStartActivity分发ActivityLifecycleCallbacks,并且分发给Fragments,调用Instrumentation的callActivityOnStart 执行Activity的onStart并设置state为ON_START,接着执行ResumeActivityItem的execute,会调用到ActivityThread的handleResumeActivity,调用performResume 分发resume事件给ActivityLifecycleCallbacks,分发Fragments,调用Instrumentation的callActivityOnResume 执行Activity的onResume。 最后会调用ActivityClientRecord.activity.makeVisible 通过WindowManager 添加当前View 和 WMS(IPC) 通信 绘制UI,接着postResume 会执行 ATMS的activityresume 设置 AMS的Activity的状态。

service

接着讲了Service,介绍了Service是如何开启的,生命周期是怎么执行的,ANR 是如何弹出的。Service的启动分两种:startService和bindService。先回忆下startService:startService会调用到ContextImpl的startService,它会直接调用AMS的startService。在AMS这里会先检查Service是否可以执行(常驻内存、蓝牙、电源白名单允许直接启动服务),接着调用bringUpServiceLocked 判断是否需要隔离进程如果非隔离 就看是否已经启动进程 执行realStartServiceLocked,否则是隔离进程 直接开启新进程。开启成功之后会将ServiceRecord添加到mPendingServices中去。进程创建之后,会调用AMS的attachApplication 接着处理service(ActiveService),之前创建之后会添加到mPendingServices中,现在继续处理调用realStartServiceLocked来开启Service,在开启的过程中会埋入一个炸弹(给Handler发送一个SERVICE_TIMEOUT_MSG) 如果超时未处理会弹出ANR,然后调用app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用AMS的serviceDoneExecuting进行炸弹的拆除。 然后再埋炸弹 调用app.thread.scheduleServiceArgs 调用service.onStartCommand再通知AMS 拆除炸弹。 这样Service就运行起来了。

binderService

再回忆下bindService:首先ServiceConnection是无法跨进程通信的,所以在LoadedApk.java中帮我们封装了InnerConnection 它继承自Stub,也就是native层的JavaBBinder,然后通过bindIsolatedService将sd(InnerConnection)写入到Parcel中,调用AMS(BinderProxy)的transact进行IPC 通信,把InnerConnection存入到客户端的nodes中,以及给AMS的refs_by_node和refs_by_desc挂上InnerConnection 接着唤醒AMS,唤醒之后调用onTransact读取到传过来的sd并且包装成BpBinder(BinderProxy)返回,这样AMS就在bindIsolatedService的时候拿到了InnerConnection的BpBinder,接着AMS 通过pkms通过intent查找到服务端进程,创建AppBindRecord和ConnectionRecord,接着调用bringUpServiceLocked 看是否开启进程 如果没有开启就先开启进程,开启了进程之后 调用realStartServiceLocked 也埋了炸弹 接着调用 app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreate 把Service存入到mService中,调用serviceDoneExecutingLocked把炸弹拆除,再调用requestServiceBindingsLocked 去执行r.app.thread.scheduleBindService 执行服务端的onBind函数拿到了返回的Binder再调用AMS的publishService把服务发布到AMS(在服务端的进程创建binder_proc(server) 在AMS的refs_by_node 和refs_by_desc 挂上server),AMS的onTransact 中读取到服务端返回的server(Binder)包装成BpBinder,然后调用c.conn.connected(从refs_by_desc 和 refs_by_node 找到InnerConnection)调用connect 所以到了客户端进程会把server的BpBinder 挂在refs_by_desc和refs_by_node上边。再调用Servcie.onServiceConnected 之后拆除炸弹。

前言

ContentProvider是Android的四大组件之一,虽然他没有Broadcast和Service用的频繁。ContentProvider的作用是不同应用之间数据共享,提供一个统一的接口。例如我们我想让其他应用使用自己的数据 就需要使用ContentProvider。


源码分析

1.使用方法

process:指定ContentProvider的运行进程。
authorities:鉴权字符串列表。多个以;分割。必须至少指定一个。
multiprocess:该ContentProvider是否在其他应用中创建。默认是false。如果是true,每个进程都有自己的内容提供者对象,可以减少IPC通信的开销。

<provider
    android:multiprocess="false"
    android:name=".StudentContentProvider"
    android:exported="true"
    android:process=":provider"
    android:authorities="com.zenyyyng.student.provider" />

2.ContentProvider实现类。

//这里我使用了room
class StudentContentProvider : ContentProvider() {

    override fun onCreate(): Boolean {
        return true
    }


    companion object {
        private const val AUTHORITY = "com.zenyyyyng.student.provider"
        //URI的前缀必选是content://xxxx/table
        val URI_STUDENT: Uri = Uri.parse(
            "content://$AUTHORITY" + "/" + Student.TABLE_NAME
        )
    }


    override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
        val context = context ?: return null
        var cursor: Cursor =
            StudentDataBase.getInstance(context).getStudentDao()!!.getAll()
        cursor.setNotificationUri(context.contentResolver, uri)
        return cursor;
    }

    override fun getType(uri: Uri): String? {
        return null
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        val context = context ?: return null
        val id = StudentDataBase.getInstance(context).getStudentDao()
            .insert(Student.fromContentValues(values))
        context.contentResolver.notifyChange(uri, null)
        return ContentUris.withAppendedId(uri, id)
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        val context = context ?: return 0
        val count = StudentDataBase.getInstance(context).getStudentDao()
            .deleteById(ContentUris.parseId(uri))
        context.contentResolver.notifyChange(uri, null)
        return count
    }

    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<out String>?
    ): Int {
        val context = context ?: return 0
        val student = Student.fromContentValues(values);
        student.id = ContentUris.parseId(uri);
        val count = StudentDataBase.getInstance(context).getStudentDao()
            .update(student)
        context.contentResolver.notifyChange(uri, null);
        return count;
    }

    override fun applyBatch(operations: ArrayList<ContentProviderOperation>): Array<ContentProviderResult> {
        val context = context ?: return Array<ContentProviderResult>(1) { ContentProviderResult(0) }
        return StudentDataBase.getInstance(context)
            .runInTransaction(Callable<Array<ContentProviderResult>> {
                return@Callable super.applyBatch(
                    operations
                )
            })
    }


    override fun bulkInsert(uri: Uri, values: Array<ContentValues?>): Int {
        val context = context ?: return 0
        val studentDao = StudentDataBase.getInstance(context).getStudentDao()
        val notes = arrayOfNulls<Student>(values.size)
        var i = 0
        while (i < values.size) {
            notes[i] = Student.fromContentValues(values[i])
            i++
        }
        return studentDao.insertAll(notes).size
    }


}


3.使用方法

val studentValues = ContentValues()
studentValues.put("name", name)
studentValues.put("age", age)
requireActivity().contentResolver.insert(
    Uri.parse("content://com.iehshx.student.provider/student"),
    studentValues
)

4.注册Observer


requireActivity().contentResolver.registerContentObserver(
    Uri.parse("content://com.iehshx.student.provider/student"),true,object:ContentObserver(object:Handler(){}){
        override fun onChange(selfChange: Boolean, uri: Uri?) {
            super.onChange(selfChange, uri)
        }
    })

正文

ApplicationContentResolver mContentResolver = new ApplicationContentResolver(this, mainThread);
//获取到ContentResolver
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }
    
    //insert插入数据
    public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
                @Nullable ContentValues values) {
        Preconditions.checkNotNull(url, "url");

        try {//这里默认是null
            if (mWrapped != null) return mWrapped.insert(url, values);
        } catch (RemoteException e) {
            return null;
        }
        //获取到ContentProvider
        IContentProvider provider = acquireProvider(url);
        if (provider == null) {
            throw new IllegalArgumentException("Unknown URL " + url);
        }
        try {
            long startTime = SystemClock.uptimeMillis();
            Uri createdRow = provider.insert(mPackageName, url, values);
            long durationMillis = SystemClock.uptimeMillis() - startTime;
            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
            return createdRow;
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
            return null;
        } finally {
            releaseProvider(provider);
        }
    }
    
   
   public final IContentProvider acquireProvider(String name) {
        if (name == null) {
            return null;
        }
        //调用到ApplicationContentResolver
        return acquireProvider(mContext, name);
    }
    
    
    //调用到ActivityThread
        protected IContentProvider acquireProvider(Context context, String auth) {
            return mMainThread.acquireProvider(context,
                    ContentProvider.getAuthorityWithoutUserId(auth),
                    resolveUserIdFromAuthority(auth), true);
        }



//ActivityThread.java
    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
            //从本地找
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        if (provider != null) {//找到就返回
            return provider;
        }

        ContentProviderHolder holder = null;
        try {
            synchronized (getGetProviderLock(auth, userId)) {
            //通过AMS来找ContentProviderHolder
                holder = ActivityManager.getService().getContentProvider(
                        getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
            }
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        if (holder == null) {
            return null;
        }
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }
    
    //从本地找ContentProvider
    public final IContentProvider acquireExistingProvider(
            Context c, String auth, int userId, boolean stable) {
        synchronized (mProviderMap) {
            final ProviderKey key = new ProviderKey(auth, userId);
            //从map找 如果没有就返回null 第一次肯定是没有的
            final ProviderClientRecord pr = mProviderMap.get(key);
            if (pr == null) {
                return null;
            }

            IContentProvider provider = pr.mProvider;
            IBinder jBinder = provider.asBinder();
            if (!jBinder.isBinderAlive()) {
                handleUnstableProviderDiedLocked(jBinder, true);
                return null;
            }
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
            if (prc != null) {
                incProviderRefLocked(prc, stable);
            }
            return provider;
        }
    }
    
    
    
    public final ContentProviderHolder getContentProvider(
            IApplicationThread caller, String callingPackage, String name, int userId,
            boolean stable) {
            //隔离进程的判断
        enforceNotIsolatedCaller("getContentProvider");
        if (caller == null) {
            throw new SecurityException(msg);
        }
        //获取到调用者的uid
        final int callingUid = Binder.getCallingUid();
        if (callingPackage != null && mAppOpsService.checkPackage(callingUid, callingPackage)
                != AppOpsManager.MODE_ALLOWED) {//权限校验
            throw new SecurityException("Given calling package " + callingPackage
                    + " does not match caller's uid " + callingUid);
        }
        //调用getContentProviderImpl
        return getContentProviderImpl(caller, name, null, callingUid, callingPackage,
                null, stable, userId);
    }
    
    
    
    private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
            String name, IBinder token, int callingUid, String callingPackage, String callingTag,
            boolean stable, int userId) {
        ContentProviderRecord cpr;
        ContentProviderConnection conn = null;
        ProviderInfo cpi = null;
        boolean providerRunning = false;

        synchronized(this) {
            long startTime = SystemClock.uptimeMillis();

            ProcessRecord r = null;
            if (caller != null) {
                r = getRecordForAppLocked(caller);
                if (r == null) {//如果调用者进程不存在 抛出异常
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                          + " (pid=" + Binder.getCallingPid()
                          + ") when getting content provider " + name);
                }
            }

            boolean checkCrossUser = true;

            checkTime(startTime, "getContentProviderImpl: getProviderByName");
            //从mProviderMap中获取 第一次是null的 
            cpr = mProviderMap.getProviderByName(name, userId);
            if (cpr == null && userId != UserHandle.USER_SYSTEM) {
                cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
                if (cpr != null) {
                    cpi = cpr.info;
                    if (isSingleton(cpi.processName, cpi.applicationInfo,
                            cpi.name, cpi.flags)
                            && isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
                        userId = UserHandle.USER_SYSTEM;
                        checkCrossUser = false;
                    } else {
                        cpr = null;
                        cpi = null;
                    }
                }
            }
//providerRunning 默认是false
            if (providerRunning) {//不走这里 第一次是null 所以不会修改providerRunning
                cpi = cpr.info;
                String msg;

                if (r != null && cpr.canRunHere(r)) {
                    if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
                        throw new SecurityException("Content provider lookup "
                                + cpr.name.flattenToShortString()
                                + " failed: association not allowed with package " + msg);
                    }
                    checkTime(startTime,
                            "getContentProviderImpl: before checkContentProviderPermission");
                    if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
                            != null) {
                        throw new SecurityException(msg);
                    }
                    checkTime(startTime,
                            "getContentProviderImpl: after checkContentProviderPermission");
                    //ContentProvider 所在的进程已经存在,并且设置了可以在调用者进程创建  创建ContentProviderHolder
                    ContentProviderHolder holder = cpr.newHolder(null);
                    //设置一个空的provider
                    holder.provider = null;
                    return holder;
                }

                try {
                //从pkms中查找 差找不到返回null
                    if (AppGlobals.getPackageManager()
                            .resolveContentProvider(name, 0 /*flags*/, userId) == null) {
                        return null;
                    }
                } catch (RemoteException e) {
                }

               
                final long origId = Binder.clearCallingIdentity();

                checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");
        //provider已经运行的情况下 增加ContentProvider的引用计数
                conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
                        stable);
                if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
                    if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                        checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
                        mProcessList.updateLruProcessLocked(cpr.proc, false, null);
                        checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
                    }
                }

                checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
                final int verifiedAdj = cpr.proc.verifiedAdj;
                boolean success = updateOomAdjLocked(cpr.proc, true,
                        OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
                if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
                    success = false;
                }
                maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
                checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
                if (!success) {
                    boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
                    checkTime(startTime, "getContentProviderImpl: before appDied");
                    appDiedLocked(cpr.proc);
                    checkTime(startTime, "getContentProviderImpl: after appDied");
                    if (!lastRef) {
                        return null;
                    }
                    providerRunning = false;
                    conn = null;
                } else {
                    cpr.proc.verifiedAdj = cpr.proc.setAdj;
                }

                Binder.restoreCallingIdentity(origId);
            }

            if (!providerRunning) {//如果没有运行
                try {
                    //从pkms中查到ContentProvider的信息
                    cpi = AppGlobals.getPackageManager().
                        resolveContentProvider(name,
                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
                } catch (RemoteException ex) {
                }
                //找不到返回
                if (cpi == null) {
                    return null;
                }
                boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
                        cpi.name, cpi.flags)
                        && isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
                if (singleton) {
                    userId = UserHandle.USER_SYSTEM;
                }
                cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
                checkTime(startTime, "getContentProviderImpl: got app info for user");

                String msg;
                if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
                    throw new SecurityException("Content provider lookup " + name
                            + " failed: association not allowed with package " + msg);
                }
                checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
                if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
                        != null) {
                    throw new SecurityException(msg);
                }
                checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
                //AMS没有准备好 并且非系统进程
                if (!mProcessesReady
                        && !cpi.processName.equals("system")) {
                    throw new IllegalArgumentException(
                            "Attempt to launch content provider before system ready");
                }
                if (!mSystemProvidersInstalled && cpi.applicationInfo.isSystemApp()
                        && "system".equals(cpi.processName)) {
                    throw new IllegalStateException("Cannot access system provider: '"
                            + cpi.authority + "' before system providers are installed!");
                }

                if (!mUserController.isUserRunning(userId, 0)) {
                    return null;
                }
                //创建ComponentName
                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                //根据comp 查找ContentProviderRecord 第一次肯定找不到
                cpr = mProviderMap.getProviderByClass(comp, userId);
                checkTime(startTime, "getContentProviderImpl: after getProviderByClass");
                final boolean firstClass = cpr == null;
                if (firstClass) {//cpt为null 所以这里是true
                    final long ident = Binder.clearCallingIdentity();

                    try {
                    //从pkms获取到ApplicationInfo
                        ApplicationInfo ai =
                            AppGlobals.getPackageManager().
                                getApplicationInfo(
                                        cpi.applicationInfo.packageName,
                                        STOCK_PM_FLAGS, userId);
                        if (ai == null) {
                            return null;
                        }
                        //创建新的ApplicationInfo
                        ai = getAppInfoForUser(ai, userId);
                        //创建ContentProviderRecord对象
                        cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
                    } catch (RemoteException ex) {
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
                
                //查看ContentProvider能否安装在调用者进程,如果可以返回一个空的ContentProvider
                if (r != null && cpr.canRunHere(r)) {
                    return cpr.newHolder(null);
                }
               
                final int N = mLaunchingProviders.size();
                int i;
                //看mLaunchingProviders中是否有我们需要的ContentProvider
                for (i = 0; i < N; i++) {
                    if (mLaunchingProviders.get(i) == cpr) {
                        break;
                    }
                }
            
                if (i >= N) {
                    final long origId = Binder.clearCallingIdentity();

                    try {
                        try {
                        //设置PackageStopState = false
                            AppGlobals.getPackageManager().setPackageStoppedState(
                                    cpr.appInfo.packageName, false, userId);
                        } catch (RemoteException e) {
                        } catch (IllegalArgumentException e) {
                        }
                        //获取ContentProvider运行的进程信息 ProcessRecord 
                        ProcessRecord proc = getProcessRecordLocked(
                                cpi.processName, cpr.appInfo.uid, false);
                        if (proc != null && proc.thread != null && !proc.killed) {//如果进程存在
                            if (!proc.pubProviders.containsKey(cpi.name)) {//进程中发布的Providers没有就发布(存入map)
                                proc.pubProviders.put(cpi.name, cpr);
                                try {
                                //到ContentProvider的运行进程中执行scheduleInstallProvider
                                    proc.thread.scheduleInstallProvider(cpi);
                                } catch (RemoteException e) {
                                }
                            }
                        } else {//如果不存在
                        //开启进程
                            proc = startProcessLocked(cpi.processName,
                                    cpr.appInfo, false, 0,
                                    new HostingRecord("content provider",
                                    new ComponentName(cpi.applicationInfo.packageName,
                                            cpi.name)), false, false, false);
                            if (proc == null) {
                                return null;
                            }
                        }
                        //设置launchingApp
                        cpr.launchingApp = proc;
                        //把当前的ContentProviderRecord添加到mLaunchingProviders中
                        mLaunchingProviders.add(cpr);
                    } finally {
                        Binder.restoreCallingIdentity(origId);
                    }
                }

                if (firstClass) {//存入mProviderMap 以comp为key
                    mProviderMap.putProviderByClass(comp, cpr);
                }
                //以name为kay
                mProviderMap.putProviderByName(name, cpr);
                //引用计数+1
                conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
                        stable);
                if (conn != null) {
                //设置为等待状态
                    conn.waiting = true;
                }
            }
            grantEphemeralAccessLocked(userId, null /*intent*/,
                    UserHandle.getAppId(cpi.applicationInfo.uid),
                    UserHandle.getAppId(Binder.getCallingUid()));
        }
       
        final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT;
        boolean timedOut = false;
        synchronized (cpr) {
            while (cpr.provider == null) {
                if (cpr.launchingApp == null) {
                    return null;
                }
                try {
                    final long wait = Math.max(0L, timeout - SystemClock.uptimeMillis());
                    if (conn != null) {
                        conn.waiting = true;
                    }
                   //挂起调用者线程 直到ContentProvider安装完成
                    cpr.wait(wait);
                    if (cpr.provider == null) {
                        timedOut = true;
                        break;
                    }
                } catch (InterruptedException ex) {
                } finally {
                    if (conn != null) {
                        conn.waiting = false;
                    }
                }
            }
        }
        if (timedOut) {//超时
            String callerName = "unknown";
            synchronized (this) {
                final ProcessRecord record = mProcessList.getLRURecordForAppLocked(caller);
                if (record != null) {
                    callerName = record.processName;
                }
            }
            return null;
        }
        //返回ContentProviderHolder
        return cpr.newHolder(conn);
    }


由调用者进程调用到AMS中,如果ContentProvider已经发布了 通过canRunHere判断ContentProvider是否可以运行在调用者的进程中,如果允许 不会把已经发布的ContentProvider返回,而是返回新的ContentProviderHoder 但是会把provider设置成null。 如果不允许 设置OOMAdj 和 更新进程LRU 最终调用cpr.newHolder(conn)。如果没有发布还是会检查是否可以在调用者进程来创建,接下来看ContentProvider的进程是否创建,如果没有创建调用startProcessLocked启动进程。如果已经创建进程 调用ContentProvider进程的proc.thread.scheduleInstallProvider。 两种情况都会把ContentProvider添加到mLaunchingProviders和mProviderMap中。然后等待ContentProvider安装完成 唤醒。


        public void scheduleInstallProvider(ProviderInfo provider) {
            sendMessage(H.INSTALL_PROVIDER, provider);
        }
        
        
        case INSTALL_PROVIDER:  
            handleInstallProvider((ProviderInfo) msg.obj);  
            break;


    public void handleInstallProvider(ProviderInfo info) {
        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
        try {
            installContentProviders(mInitialApplication, Arrays.asList(info));
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
    }
    
    
    
    private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
        final ArrayList<ContentProviderHolder> results = new ArrayList<>();
        //从本进程中遍历providers 调用installProvider
        for (ProviderInfo cpi : providers) {
            ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }

        try {
        //告诉AMS发布ContentProvider
            ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
    
//ContentProvider进程安装Provider
    private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
        if (holder == null || holder.provider == null) {//传递的holder是null
            Context c = null;
            //获取到ApplicationInfo 得到Context
            ApplicationInfo ai = info.applicationInfo;
            if (context.getPackageName().equals(ai.packageName)) {
                c = context;
            } else if (mInitialApplication != null &&
                    mInitialApplication.getPackageName().equals(ai.packageName)) {
                c = mInitialApplication;
            } else {
                try {
                    c = context.createPackageContext(ai.packageName,
                            Context.CONTEXT_INCLUDE_CODE);
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
            if (c == null) {
                return null;
            }

            if (info.splitName != null) {
                try {
                    c = c.createContextForSplit(info.splitName);
                } catch (NameNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }

            try {
            //获取到ClassLoader
                final java.lang.ClassLoader cl = c.getClassLoader();
                //获取到loadedApk
                LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
                if (packageInfo == null) {
                    packageInfo = getSystemContext().mPackageInfo;
                }
                //反射创建Provider
                localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
                //调用getIContentProvider 获取到Transport 也就是ContentProviderNative 其实是一个BinderProxy 后续的通信都是通过他
                provider = localProvider.getIContentProvider();
                if (provider == null) {
                    return null;
                }
                //调用attach 最后会执行onCreate
                localProvider.attachInfo(c, info);
            } catch (java.lang.Exception e) {
                if (!mInstrumentation.onException(null, e)) {
                    throw new RuntimeException(
                            "Unable to get provider " + info.name
                            + ": " + e.toString(), e);
                }
                return null;
            }
        } else {//holder部位null的情况 可以直接使用
            provider = holder.provider;
        }

        ContentProviderHolder retHolder;

        synchronized (mProviderMap) {
            IBinder jBinder = provider.asBinder();
            if (localProvider != null) {//之前反射创建了 不是null
                ComponentName cname = new ComponentName(info.packageName, info.name);
                //获取ProviderClientRecord 第一次是null
                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
                if (pr != null) {
                    provider = pr.mProvider;
                } else {//创建 ContentProviderHolder 设置provider为反射创建的provider
                    holder = new ContentProviderHolder(info);
                    holder.provider = provider;
                    holder.noReleaseNeeded = true;
                    //通过installProviderAuthoritiesLocked创建ProviderClientRecord
                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                    //存入mLocalProviders 和 mLocalProvidersByName
                    mLocalProviders.put(jBinder, pr);
                    mLocalProvidersByName.put(cname, pr);
                }
                //拿到ContentProviderHolder
                retHolder = pr.mHolder;
            } else {//为null 就是之前就有了
                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
                if (prc != null) {
                    if (!noReleaseNeeded) {
                        incProviderRefLocked(prc, stable);
                        try {
                            ActivityManager.getService().removeContentProvider(
                                    holder.connection, stable);
                        } catch (RemoteException e) {
                            //do nothing content provider object is dead any way
                        }
                    }
                } else {
                //创建ProviderClientRecord
                    ProviderClientRecord client = installProviderAuthoritiesLocked(
                            provider, localProvider, holder);
                    if (noReleaseNeeded) {
                        prc = new ProviderRefCount(holder, client, 1000, 1000);
                    } else {
                        prc = stable
                                ? new ProviderRefCount(holder, client, 1, 0)
                                : new ProviderRefCount(holder, client, 0, 1);
                    }
                    mProviderRefCountMap.put(jBinder, prc);
                }
                retHolder = prc.holder;
            }
        }
        //返回ContentProviderHolder
        return retHolder;
    }


//创建ProviderClientRecord
    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
            ContentProvider localProvider, ContentProviderHolder holder) {
        final String auths[] = holder.info.authority.split(";");
        final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);

        if (provider != null) {
            for (String auth : auths) {
                switch (auth) {
                    case ContactsContract.AUTHORITY:
                    case CallLog.AUTHORITY:
                    case CallLog.SHADOW_AUTHORITY:
                    case BlockedNumberContract.AUTHORITY:
                    case CalendarContract.AUTHORITY:
                    case Downloads.Impl.AUTHORITY:
                    case "telephony":
                        Binder.allowBlocking(provider.asBinder());
                }
            }
        }

        final ProviderClientRecord pcr = new ProviderClientRecord(
                auths, provider, localProvider, holder);
        for (String auth : auths) {
            final ProviderKey key = new ProviderKey(auth, userId);
            final ProviderClientRecord existing = mProviderMap.get(key);
            if (existing != null) {
            } else {
                mProviderMap.put(key, pcr);
            }
        }
        return pcr;
    }

遍历AMS传递过来的providers调用installProvider反射创建ContentProvider调用attachInfo 执行onCreate 创建ProviderClientRecord(持有provider和ContentProviderInfo 以及ContentProviderHolder) 存入mLocalProviders和mLocalProvidersByName 返回ContentProviderHolder.然后调用AMS的publishContentProviders进行发布。

    public final void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) {
        if (providers == null) {
            return;
        }
        //判断隔离进程
        enforceNotIsolatedCaller("publishContentProviders");
        synchronized (this) {
        //获取到调用者的ProcessRecord
            final ProcessRecord r = getRecordForAppLocked(caller);
            if (r == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                      + " (pid=" + Binder.getCallingPid()
                      + ") when publishing content providers");
            }

            final long origId = Binder.clearCallingIdentity();
            //遍历反射创建的providers
            final int N = providers.size();
            for (int i = 0; i < N; i++) {
                ContentProviderHolder src = providers.get(i);
                if (src == null || src.info == null || src.provider == null) {
                    continue;
                }
                //获取到ContentProviderRecord
                ContentProviderRecord dst = r.pubProviders.get(src.info.name);
                if (dst != null) {
                //创建ComponentName
                    ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                    //存入 mProviderMap
                    mProviderMap.putProviderByClass(comp, dst);
                    //获取到authority
                    String names[] = dst.info.authority.split(";");
                    //存入mProviderMap
                    for (int j = 0; j < names.length; j++) {
                        mProviderMap.putProviderByName(names[j], dst);
                    }
                    int launchingCount = mLaunchingProviders.size();
                    int j;
                    boolean wasInLaunchingProviders = false;
                    for (j = 0; j < launchingCount; j++) {
                        //将ContentProvider从mLaunchingProviders中移除
                        if (mLaunchingProviders.get(j) == dst) {
                            mLaunchingProviders.remove(j);
                            wasInLaunchingProviders = true;
                            j--;
                            launchingCount--;
                        }
                    }
                    //移除超时
                    if (wasInLaunchingProviders) {
                        mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
                    }
                    r.addPackage(dst.info.applicationInfo.packageName,
                            dst.info.applicationInfo.longVersionCode, mProcessStats);
                    synchronized (dst) {
                        dst.provider = src.provider;
                        dst.setProcess(r);
                        //唤醒 唤醒之后返回cpt.newHolder
                        dst.notifyAll();
                    }
                    //更新OOMAdj
                    updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
                    maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
                            src.info.authority);
                }
            }

            Binder.restoreCallingIdentity(origId);
        }
    }

//在ActivityThread创建ContentProvider的Context的时候会走这里
c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE);

 public Context createPackageContext(String packageName, int flags)
            throws NameNotFoundException {
        return createPackageContextAsUser(packageName, flags, mUser);
    }
    
    
    public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
            throws NameNotFoundException {
        if (packageName.equals("system") || packageName.equals("android")) {//这里不走
            return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,
                    flags, null, null);
        }
        //拿到loadedApk 从pkms中查询
        LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
        if (pi != null) {
        //创建ContentProvider进程的ContextImpl
            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,
                    flags, null, null);

            final int displayId = getDisplayId();

            c.setResources(createResources(mActivityToken, pi, null, displayId, null,
                    getDisplayAdjustments(displayId).getCompatibilityInfo()));
            if (c.mResources != null) {
                return c;
            }
        }

        throw new PackageManager.NameNotFoundException(
                "Application package " + packageName + " not found");
    }





    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
            int flags, int userId) {
        final boolean differentUser = (UserHandle.myUserId() != userId);
        ApplicationInfo ai;
        try {
        //从pkms中拿到ApplicationInfo
            ai = getPackageManager().getApplicationInfo(packageName,
                    PackageManager.GET_SHARED_LIBRARY_FILES
                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                    (userId < 0) ? UserHandle.myUserId() : userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (differentUser) {
                ref = null;
            } else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) {
                ref = mPackages.get(packageName);
            } else {
                ref = mResourcePackages.get(packageName);
            }

            LoadedApk packageInfo = ref != null ? ref.get() : null;
            if (ai != null && packageInfo != null) {
                if (!isLoadedApkResourceDirsUpToDate(packageInfo, ai)) {
                    packageInfo.updateApplicationInfo(ai, null);
                }

                if (packageInfo.isSecurityViolation()
                        && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
                    throw new SecurityException(
                            "Requesting code from " + packageName
                            + " to be run in process "
                            + mBoundApplication.processName
                            + "/" + mBoundApplication.appInfo.uid);
                }
                return packageInfo;
            }
        }

        if (ai != null) {
            return getPackageInfo(ai, compatInfo, flags);
        }

        return null;
    }

//这样getClassLoader就获取到了ContentProvider应用的ClassLoader就可以通过反射创建调用了
final java.lang.ClassLoader cl = c.getClassLoader(); //获取到loadedApk LoadedApk packageInfo = peekPackageInfo(ai.packageName, true); if (packageInfo == null) { packageInfo = getSystemContext().mPackageInfo; } //反射创建Provider localProvider = packageInfo.getAppFactory() .instantiateProvider(cl, info.name);
   


拓展知识

在这里插入图片描述

总结

1.获取ContentProvider
调用者进程调用到AMS中,如果ContentProvider已经发布了 通过canRunHere判断ContentProvider是否可以运行在调用者的进程中,如果允许 不会把已经发布的ContentProvider返回,而是返回新的ContentProviderHoder 但是会把provider设置成null。 如果不允许 设置OOMAdj 和 更新进程LRU 最终调用cpr.newHolder(conn)。如果没有发布还是会检查是否可以在调用者进程来创建,接下来看ContentProvider的进程是否创建,如果没有创建调用startProcessLocked启动进程。如果已经创建进程 调用ContentProvider进程的proc.thread.scheduleInstallProvider。 两种情况都会把ContentProvider添加到mLaunchingProviders和mProviderMap中。然后等待ContentProvider安装完成 唤醒。唤醒之后返回ContentProviderHolder。
2.安装ContentProvider
遍历AMS传递过来的providers调用installProvider反射创建ContentProvider调用attachInfo 执行onCreate 创建ProviderClientRecord(持有provider和ContentProviderInfo 以及ContentProviderHolder) 存入mLocalProviders和mLocalProvidersByName 返回ContentProviderHolder.然后调用AMS的publishContentProviders进行发布:存入mProviderMap中 一个是以ComponentName为key 一个是以authority为key(authority可以是多个;分割 但是dst是同一个)。然后唤醒 之前的getContentProviderImpl返回ContentProviderHolder,
,通过provider(IContentProvider BinderProxy)
再去进行ipc通信。 当然也可以在本进程创建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值