当前位置: 萬仟网 > IT编程>移动开发>Android > 【Android开发艺术探索】四大组件的工作过程

【Android开发艺术探索】四大组件的工作过程

2020年01月10日 15:01  | 萬仟网IT编程  | 我要评论

个人博客

四大组件的工作过程

four_components.png

四大组件:activity、service、broadcastreceiver、contentprovider

四大组件的运行状态

android的四大组件中除了broadcastreceiver,其它三种组件必须在androidmanifest中注册。对于broadcastreceiver,既可以在androidmanifest中注册,也可以通过代码注册。调用方式上,activity、service和broadcastreceiver都需要借助intent,而contentprovider则不需要。

activity是一种展示型组件。activity的启动由intent触发,intent可以分为显示intent和隐式intent。

service是一种计算型组件,它有两种状态:启动状态和绑定状态。service虽然是运行在后台,但它本身是运行在主线程中。

broadcastreceiver是一种消息型组件。它的注册有两种:静态注册和动态注册。

contentprovider是一种数据共享型组件。它的内部需要实现增删改查这四种操作。这四个方法需要处理好线程同步。

activity的工作过程

从activity的startactivity方法开始分析,startactivity方法有几个重载,但最终都会调用startactivityforresult方法

public void startactivity(intent intent) {
        this.startactivity(intent, null);
    }

public void startactivity(intent intent, @nullable bundle options) {
        if (options != null) {
            startactivityforresult(intent, -1, options);
        } else {
            // note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startactivityforresult(intent, -1);
        }
    }

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) {
                // if this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  setting
                // this code during oncreate(bundle savedinstancestate) or onresume() will keep the
                // activity hidden during this time, to avoid flickering.
                // this can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mstartedactivity = true;
            }

            cancelinputsandstartexittransition(options);
            // todo consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mparent.startactivityfromchild(this, intent, requestcode, options);
            } else {
                // note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mparent.startactivityfromchild(this, intent, requestcode);
            }
        }
    }

在mparent == null的分支里,会调用instrumentation的execstartactivity方法

public activityresult execstartactivity(
            context who, ibinder contextthread, ibinder token, activity target,
            intent intent, int requestcode, bundle options) {
        iapplicationthread whothread = (iapplicationthread) contextthread;
        //...
        try {
            intent.migrateextrastreamtoclipdata();
            intent.preparetoleaveprocess(who);
            int result = activitymanager.getservice()
                .startactivity(whothread, who.getbasepackagename(), 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;
    }

可以看到,activitymanager.getservice()是一个单例,返回的是一个binder对象。

public static iactivitymanager getservice() {
        return iactivitymanagersingleton.get();
    }

private static final singleton<iactivitymanager> iactivitymanagersingleton =
            new singleton<iactivitymanager>() {
                @override
                protected iactivitymanager create() {
                    final ibinder b = servicemanager.getservice(context.activity_service);
                    final iactivitymanager am = iactivitymanager.stub.asinterface(b);
                    return am;
                }
            };

最终启动activity是由activitymanagerservice的startactivity方法实现。

public final int startactivity(iapplicationthread caller, string callingpackage,
            intent intent, string resolvedtype, ibinder resultto, string resultwho, int requestcode,
            int startflags, profilerinfo profilerinfo, bundle boptions) {
        return startactivityasuser(caller, callingpackage, intent, resolvedtype, resultto,
                resultwho, requestcode, startflags, profilerinfo, boptions,
                userhandle.getcallinguserid());
    }

public final int startactivityasuser(iapplicationthread caller, string callingpackage,
            intent intent, string resolvedtype, ibinder resultto, string resultwho, int requestcode,
            int startflags, profilerinfo profilerinfo, bundle boptions, int userid) {
        enforcenotisolatedcaller("startactivity");
        userid = musercontroller.handleincominguser(binder.getcallingpid(), binder.getcallinguid(),
                userid, false, allow_full_only, "startactivity", null);
        // todo: switch to user app stacks here.
        return mactivitystarter.startactivitymaywait(caller, -1, callingpackage, intent,
                resolvedtype, null, null, resultto, resultwho, requestcode, startflags,
                profilerinfo, null, null, boptions, false, userid, null, "startactivityasuser");
    }

activity的启动转移到了activitystarter的startactivitymaywait方法里

final int startactivitymaywait(iapplicationthread caller, int callinguid,
            string callingpackage, intent intent, string resolvedtype,
            ivoiceinteractionsession voicesession, ivoiceinteractor voiceinteractor,
            ibinder resultto, string resultwho, int requestcode, int startflags,
            profilerinfo profilerinfo, waitresult outresult,
            configuration globalconfig, bundle boptions, boolean ignoretargetsecurity, int userid,
            taskrecord intask, string reason) {
            //...
            final activityrecord[] outrecord = new activityrecord[1];
            int res = startactivitylocked(caller, intent, ephemeralintent, resolvedtype,
                    ainfo, rinfo, voicesession, voiceinteractor,
                    resultto, resultwho, requestcode, callingpid,
                    callinguid, callingpackage, realcallingpid, realcallinguid, startflags,
                    options, ignoretargetsecurity, componentspecified, outrecord, intask,
                    reason);
            //...
        }
    }

startactivitymaywait方法会调用startactivitylocked方法

int startactivitylocked(iapplicationthread caller, intent intent, intent ephemeralintent,
            string resolvedtype, activityinfo ainfo, resolveinfo rinfo,
            ivoiceinteractionsession voicesession, ivoiceinteractor voiceinteractor,
            ibinder resultto, string resultwho, int requestcode, int callingpid, int callinguid,
            string callingpackage, int realcallingpid, int realcallinguid, int startflags,
            activityoptions options, boolean ignoretargetsecurity, boolean componentspecified,
            activityrecord[] outactivity, taskrecord intask, string reason) {

        //...
        mlaststartactivityresult = startactivity(caller, intent, ephemeralintent, resolvedtype,
                ainfo, rinfo, voicesession, voiceinteractor, resultto, resultwho, requestcode,
                callingpid, callinguid, callingpackage, realcallingpid, realcallinguid, startflags,
                options, ignoretargetsecurity, componentspecified, mlaststartactivityrecord,
                intask);
        //...
    }

在startactivitylocked方法里调用了startactivity方法,startactivity方法内又调用dopendingactivitylauncheslocked方法

final void dopendingactivitylauncheslocked(boolean doresume) {
        while (!mpendingactivitylaunches.isempty()) {
            final pendingactivitylaunch pal = mpendingactivitylaunches.remove(0);
            final boolean resume = doresume && mpendingactivitylaunches.isempty();
            try {
                startactivity(pal.r, pal.sourcerecord, null, null, pal.startflags, resume, null,
                        null, null /*outrecords*/);
            } catch (exception e) {
                slog.e(tag, "exception during pending activity launch pal=" + pal, e);
                pal.senderrorresult(e.getmessage());
            }
        }
    }

private int startactivity(final activityrecord r, activityrecord sourcerecord,
            ivoiceinteractionsession voicesession, ivoiceinteractor voiceinteractor,
            int startflags, boolean doresume, activityoptions options, taskrecord intask,
            activityrecord[] outactivity) {
        int result = start_canceled;
        try {
            mservice.mwindowmanager.defersurfacelayout();
            result = startactivityunchecked(r, sourcerecord, voicesession, voiceinteractor,
                    startflags, doresume, options, intask, outactivity);
        } finally {
            // if we are not able to proceed, disassociate the activity from the task. leaving an
            // activity in an incomplete state can lead to issues, such as performing operations
            // without a window container.
            if (!activitymanager.isstartresultsuccessful(result)
                    && mstartactivity.gettask() != null) {
                mstartactivity.gettask().removeactivity(mstartactivity);
            }
            mservice.mwindowmanager.continuesurfacelayout();
        }

        poststartactivityprocessing(r, result, msupervisor.getlaststack().mstackid,  msourcerecord,
                mtargetstack);

        return result;
    }

startactivity调用startactivityunchecked方法

private int startactivityunchecked(final activityrecord r, activityrecord sourcerecord,
            ivoiceinteractionsession voicesession, ivoiceinteractor voiceinteractor,
            int startflags, boolean doresume, activityoptions options, taskrecord intask,
            activityrecord[] outactivity) {

        //...
        if (dontstart) {
            topstack.mlastpausedactivity = null;
            if (mdoresume) {
                msupervisor.resumefocusedstacktopactivitylocked();
            }
            //...
        }

        //...
    }

startactivityunchecked调用activitystacksupervisor中的resumefocusedstacktopactivitylocked方法

boolean resumefocusedstacktopactivitylocked() {
        return resumefocusedstacktopactivitylocked(null, null, null);
    }

boolean resumefocusedstacktopactivitylocked(
            activitystack targetstack, activityrecord target, activityoptions targetoptions) {

        if (!readytoresume()) {
            return false;
        }

        if (targetstack != null && isfocusedstack(targetstack)) {
            return targetstack.resumetopactivityuncheckedlocked(target, targetoptions);
        }

        final activityrecord r = mfocusedstack.toprunningactivitylocked();
        if (r == null || r.state != resumed) {
            mfocusedstack.resumetopactivityuncheckedlocked(null, null);
        } else if (r.state == resumed) {
            // kick off any lingering app transitions form the movetasktofront operation.
            mfocusedstack.executeapptransition(targetoptions);
        }

        return false;
    }

resumefocusedstacktopactivitylocked调用了activitystack的resumetopactivityuncheckedlocked方法

boolean resumetopactivityuncheckedlocked(activityrecord prev, activityoptions options) {
        if (mstacksupervisor.inresumetopactivity) {
            // don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // protect against recursion.
            mstacksupervisor.inresumetopactivity = true;
            result = resumetopactivityinnerlocked(prev, options);
        } finally {
            mstacksupervisor.inresumetopactivity = false;
        }

        // when resuming the top activity, it may be necessary to pause the top activity (for
        // example, returning to the lock screen. we suppress the normal pause logic in
        // {@link #resumetopactivityuncheckedlocked}, since the top activity is resumed at the end.
        // we call the {@link activitystacksupervisor#checkreadyforsleeplocked} again here to ensure
        // any necessary pause logic occurs. in the case where the activity will be shown regardless
        // of the lock screen, the call to {@link activitystacksupervisor#checkreadyforsleeplocked}
        // is skipped.
        final activityrecord next = toprunningactivitylocked(true /* focusableonly */);
        if (next == null || !next.canturnscreenon()) {
            checkreadyforsleep();
        }

        return result;
    }

resumetopactivityinnerlocked方法最终调用activitystacksupervisor中的startspecificactivitylocked方法

private boolean resumetopactivityinnerlocked(activityrecord prev, activityoptions options) {
        //...
        mstacksupervisor.startspecificactivitylocked(next, true, true);
        //...
    }

resumetopactivityinnerlocked方法调用realstartactivitylocked方法

void startspecificactivitylocked(activityrecord r,
            boolean andresume, boolean checkconfig) {
        // is this activity's application already running?
        processrecord app = mservice.getprocessrecordlocked(r.processname,
                r.info.applicationinfo.uid, true);

        r.getstack().setlaunchtime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&activityinfo.flag_multiprocess) == 0
                        || !"android".equals(r.info.packagename)) {
                    // don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addpackage(r.info.packagename, r.info.applicationinfo.versioncode,
                            mservice.mprocessstats);
                }
                realstartactivitylocked(r, app, andresume, checkconfig);
                return;
            } catch (remoteexception e) {
                slog.w(tag, "exception when starting activity "
                        + r.intent.getcomponent().flattentoshortstring(), e);
            }

            // if a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mservice.startprocesslocked(r.processname, r.info.applicationinfo, true, 0,
                "activity", r.intent.getcomponent(), false, false, true);
    }

在realstartactivitylocked方法中,通过processrecord的thread来启动activity。而thread是一个iapplicationthread类型的对象,它的具体实现为activitythread中的内部类applicationthread。

final boolean realstartactivitylocked(activityrecord r, processrecord app,
            boolean andresume, boolean checkconfig) throws remoteexception {
                //...
                        app.thread.schedulelaunchactivity(new intent(r.intent), r.apptoken,
                        system.identityhashcode(r), r.info,
                        // todo: have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedconfiguration.getglobalconfiguration(),
                        mergedconfiguration.getoverrideconfiguration(), r.compat,
                        r.launchedfrompackage, task.voiceinteractor, app.repprocstate, r.icicle,
                        r.persistentstate, results, newintents, !andresume,
                        mservice.isnexttransitionforward(), profilerinfo);

                //...
    }
public final void schedulelaunchactivity(intent intent, ibinder token, int ident,
                activityinfo info, configuration curconfig, configuration overrideconfig,
                compatibilityinfo compatinfo, string referrer, ivoiceinteractor voiceinteractor,
                int procstate, bundle state, persistablebundle persistentstate,
                list<resultinfo> pendingresults, list<referrerintent> pendingnewintents,
                boolean notresumed, boolean isforward, profilerinfo profilerinfo) {

            updateprocessstate(procstate, false);

            activityclientrecord r = new activityclientrecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceinteractor = voiceinteractor;
            r.activityinfo = info;
            r.compatinfo = compatinfo;
            r.state = state;
            r.persistentstate = persistentstate;

            r.pendingresults = pendingresults;
            r.pendingintents = pendingnewintents;

            r.startsnotresumed = notresumed;
            r.isforward = isforward;

            r.profilerinfo = profilerinfo;

            r.overrideconfig = overrideconfig;
            updatependingconfiguration(curconfig);

            sendmessage(h.launch_activity, r);
        }

到这里,activity的启动已经转到了applicationthread中。在schedulelaunchactivity方法中,发了一个启动的消息launch_activity出去。

public void handlemessage(message msg) {
            if (debug_messages) slog.v(tag, ">>> handling: " + codetostring(msg.what));
            switch (msg.what) {
                case launch_activity: {
                    trace.tracebegin(trace.trace_tag_activity_manager, "activitystart");
                    final activityclientrecord r = (activityclientrecord) msg.obj;

                    r.packageinfo = getpackageinfonocheck(
                            r.activityinfo.applicationinfo, r.compatinfo);
                    handlelaunchactivity(r, null, "launch_activity");
                    trace.traceend(trace.trace_tag_activity_manager);
                } break;
                //...
            }
            //...
}

在handler中,调用了activitythread的handlelaunchactivity方法

private void handlelaunchactivity(activityclientrecord r, intent customintent, string reason) {
        //...
        windowmanagerglobal.initialize();

        activity a = performlaunchactivity(r, customintent);

        if (a != null) {
            r.createdconfig = new configuration(mconfiguration);
            reportsizeconfigurations(r);
            bundle oldstate = r.state;
            handleresumeactivity(r.token, false, r.isforward,
                    !r.activity.mfinished && !r.startsnotresumed, r.lastprocessedseq, reason);

            if (!r.activity.mfinished && r.startsnotresumed) {
                // the activity manager actually wants this one to start out paused, because it
                // needs to be visible but isn't in the foreground. we accomplish this by going
                // through the normal startup (because activities expect to go through onresume()
                // the first time they run, before their window is displayed), and then pausing it.
                // however, in this case we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just retain the current
                // state it has.
                performpauseactivityifneeded(r, reason);

                // we need to keep around the original state, in case we need to be created again.
                // but we only do this for pre-honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. for hc and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isprehoneycomb()) {
                    r.state = oldstate;
                }
            }
        } else {
            // if there was an error, for any reason, tell the activity manager to stop us.
            try {
                activitymanager.getservice()
                    .finishactivity(r.token, activity.result_canceled, null,
                            activity.dont_finish_task_with_activity);
            } catch (remoteexception ex) {
                throw ex.rethrowfromsystemserver();
            }
        }
    }

在performlaunchactivity方法中,完成了activity对象的创建和启动过程。

private activity performlaunchactivity(activityclientrecord r, intent customintent) {
        //...
        contextimpl appcontext = createbasecontextforactivity(r);
        activity activity = null;
        try {
            java.lang.classloader cl = appcontext.getclassloader();
            activity = minstrumentation.newactivity(
                    cl, component.getclassname(), r.intent);
            //...
        } catch (exception e) {
            if (!minstrumentation.onexception(activity, e)) {
                throw new runtimeexception(
                    "unable to instantiate activity " + component
                    + ": " + e.tostring(), e);
            }
        }

        try {
            application app = r.packageinfo.makeapplication(false, minstrumentation);

            //...

            if (activity != null) {
                //...
                window window = null;
                if (r.mpendingremovewindow != null && r.mpreservewindow) {
                    window = r.mpendingremovewindow;
                    r.mpendingremovewindow = null;
                    r.mpendingremovewindowmanager = null;
                }
                appcontext.setoutercontext(activity);
                activity.attach(appcontext, this, getinstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityinfo, title, r.parent,
                        r.embeddedid, r.lastnonconfigurationinstances, config,
                        r.referrer, r.voiceinteractor, window, r.configcallback);

                //...
                if (r.ispersistable()) {
                    minstrumentation.callactivityoncreate(activity, r.state, r.persistentstate);
                } else {
                    minstrumentation.callactivityoncreate(activity, r.state);
                }
                if (!activity.mcalled) {
                    throw new supernotcalledexception(
                        "activity " + r.intent.getcomponent().toshortstring() +
                        " did not call through to super.oncreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mfinished) {
                    activity.performstart();
                    r.stopped = false;
                }
                if (!r.activity.mfinished) {
                    if (r.ispersistable()) {
                        if (r.state != null || r.persistentstate != null) {
                            minstrumentation.callactivityonrestoreinstancestate(activity, r.state,
                                    r.persistentstate);
                        }
                    } else if (r.state != null) {
                        minstrumentation.callactivityonrestoreinstancestate(activity, r.state);
                    }
                }
                if (!r.activity.mfinished) {
                    activity.mcalled = false;
                    if (r.ispersistable()) {
                        minstrumentation.callactivityonpostcreate(activity, r.state,
                                r.persistentstate);
                    } else {
                        minstrumentation.callactivityonpostcreate(activity, r.state);
                    }
                    if (!activity.mcalled) {
                        throw new supernotcalledexception(
                            "activity " + r.intent.getcomponent().toshortstring() +
                            " did not call through to super.onpostcreate()");
                    }
                }
            }
            r.paused = true;

            mactivities.put(r.token, r);

        } catch (supernotcalledexception e) {
            throw e;

        } catch (exception e) {
            if (!minstrumentation.onexception(activity, e)) {
                throw new runtimeexception(
                    "unable to start activity " + component
                    + ": " + e.tostring(), e);
            }
        }

        return activity;
    }

activity启动时序图

activity_start.jpg

service的工作过程

service的启动过程

service的启动是从contextwrapper的startservice开始

public componentname startservice(intent service) {
        return mbase.startservice(service);
    }

mbase的具体类型是contextimpl,activity创建时会通过attach将一个contextimpl对象关联起来。startservice方法会调用startservicecommon方法。

public componentname startservice(intent service) {
        warnifcallingfromsystemprocess();
        return startservicecommon(service, false, muser);
    }

startservicecommon对象会调用activitymanagerservice的startservice方法,这是一个远程调用的过程。

private componentname startservicecommon(intent service, boolean requireforeground,
            userhandle user) {
        //...
        componentname cn = activitymanager.getservice().startservice(
                mmainthread.getapplicationthread(), service, service.resolvetypeifneeded(
                            getcontentresolver()), requireforeground,
                            getoppackagename(), user.getidentifier());
        //...
    }

activitymanagerservice的startservice方法

public componentname startservice(iapplicationthread caller, intent service,
            string resolvedtype, boolean requireforeground, string callingpackage, int userid)
            throws transactiontoolargeexception {
        //...
        res = mservices.startservicelocked(caller, service,
                        resolvedtype, callingpid, callinguid,
                        requireforeground, callingpackage, userid);
        //...
    }

startservice方法会调用activeservices的startservicelocked方法

componentname startservicelocked(iapplicationthread caller, intent service, string resolvedtype,
            int callingpid, int callinguid, boolean fgrequired, string callingpackage, final int userid)
            throws transactiontoolargeexception {
        //...
        componentname cmp = startserviceinnerlocked(smap, service, r, callerfg, addtostarting);
        return cmp;
    }

在startservicelocked方法里会调用startserviceinnerlocked方法

componentname startserviceinnerlocked(servicemap smap, intent service, servicerecord r,
            boolean callerfg, boolean addtostarting) throws transactiontoolargeexception {
        //...
        string error = bringupservicelocked(r, service.getflags(), callerfg, false, false);
        if (error != null) {
            return new componentname("!!", error);
        }
        //...
    }

startserviceinnerlocked里调用了bringupservicelocked方法

private string bringupservicelocked(servicerecord r, int intentflags, boolean execinfg,
            boolean whilerestarting, boolean permissionsreviewrequired)
            throws transactiontoolargeexception {
        //...
        realstartservicelocked(r, app, execinfg);
        //...
    }

bringupservicelocked里调用realstartservicelocked方法

private final void realstartservicelocked(servicerecord r,
            processrecord app, boolean execinfg) throws remoteexception {
        //...
        //创建service
        app.thread.schedulecreateservice(r, r.serviceinfo,
                    mam.compatibilityinfoforpackagelocked(r.serviceinfo.applicationinfo),
                    app.repprocstate);
        //...
        //调用service的start方法
        sendserviceargslocked(r, execinfg, true);
        //...
    }

realstartservicelocked调用applicationthread中的schedulecreateservice方法

public final void schedulecreateservice(ibinder token,
                serviceinfo info, compatibilityinfo compatinfo, int processstate) {
            updateprocessstate(processstate, false);
            createservicedata s = new createservicedata();
            s.token = token;
            s.info = info;
            s.compatinfo = compatinfo;

            sendmessage(h.create_service, s);
        }

在schedulecreateservice方法里,发了一个创建服务的消息出去。handler处理create_service的消息,并通过activitythread的handlecreateservice方法来完成service的启动。

private void handlecreateservice(createservicedata data) {
        // if we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unschedulegcidler();

        loadedapk packageinfo = getpackageinfonocheck(
                data.info.applicationinfo, data.compatinfo);
        service service = null;
        try {
            java.lang.classloader cl = packageinfo.getclassloader();
            service = (service) cl.loadclass(data.info.name).newinstance();
        } catch (exception e) {
            if (!minstrumentation.onexception(service, e)) {
                throw new runtimeexception(
                    "unable to instantiate service " + data.info.name
                    + ": " + e.tostring(), e);
            }
        }

        try {
            if (locallogv) slog.v(tag, "creating service " + data.info.name);

            contextimpl context = contextimpl.createappcontext(this, packageinfo);
            context.setoutercontext(service);

            application app = packageinfo.makeapplication(false, minstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    activitymanager.getservice());
            service.oncreate();
            mservices.put(data.token, service);
            try {
                activitymanager.getservice().servicedoneexecuting(
                        data.token, service_done_executing_anon, 0, 0);
            } catch (remoteexception e) {
                throw e.rethrowfromsystemserver();
            }
        } catch (exception e) {
            if (!minstrumentation.onexception(service, e)) {
                throw new runtimeexception(
                    "unable to create service " + data.info.name
                    + ": " + e.tostring(), e);
            }
        }
    }

service启动的时序图

service_start.png

service的绑定过程

service的绑定是从contextwrapper的bindservice方法开始的

public boolean bindservice(intent service, serviceconnection conn,
            int flags) {
        return mbase.bindservice(service, conn, flags);
    }

然后调用contextimpl的bindservice方法

public boolean bindservice(intent service, serviceconnection conn,
            int flags) {
        warnifcallingfromsystemprocess();
        return bindservicecommon(service, conn, flags, mmainthread.gethandler(),
                process.myuserhandle());
    }

bindservice调用bindservicecommon方法

private boolean bindservicecommon(intent service, serviceconnection conn, int flags, handler
            handler, userhandle user) {
        //...
            int res = activitymanager.getservice().bindservice(
                mmainthread.getapplicationthread(), getactivitytoken(), service,
                service.resolvetypeifneeded(getcontentresolver()),
                sd, flags, getoppackagename(), user.getidentifier());
        //...
    }

bindservicecommon调用activitymanagerservice的bindservice方法

public int bindservice(iapplicationthread caller, ibinder token, intent service,
            string resolvedtype, iserviceconnection connection, int flags, string callingpackage,
            int userid) throws transactiontoolargeexception {
        //...
        synchronized(this) {
            return mservices.bindservicelocked(caller, token, service,
                    resolvedtype, connection, flags, callingpackage, userid);
        }
    }

bindservice调用activeservices中的bindservicelocked方法

int bindservicelocked(iapplicationthread caller, ibinder token, intent service,
            string resolvedtype, final iserviceconnection connection, int flags,
            string callingpackage, final int userid) throws transactiontoolargeexception {
        //...
         bringupservicelocked(servicerecord,serviceintent.getflags(),callerfg, false, false);
        //...
    }

bindservicelocked调用bringupservicelocked方法

private string bringupservicelocked(servicerecord r, int intentflags, boolean execinfg,
            boolean whilerestarting, boolean permissionsreviewrequired)
            throws transactiontoolargeexception {
        //...
        realstartservicelocked(r, app, execinfg);
        //...
    }

bringupservicelocked调用realstartservicelocked方法。这个过程和之前的启动过程已经是一样的。不同的是,service绑定过程还会调用applicationthread的schedulebindservice方法,这个过程是在activeservices的requestservicebindinglocked方法中

private final boolean requestservicebindinglocked(servicerecord r, intentbindrecord i,
            boolean execinfg, boolean rebind) throws transactiontoolargeexception {
        if (r.app == null || r.app.thread == null) {
            // if service is not currently running, can't yet bind.
            return false;
        }
        if (debug_service) slog.d(tag_service, "requestbind " + i + ": requested=" + i.requested
                + " rebind=" + rebind);
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpserviceexecutinglocked(r, execinfg, "bind");
                r.app.forceprocessstateupto(activitymanager.process_state_service);
                r.app.thread.schedulebindservice(r, i.intent.getintent(), rebind,
                        r.app.repprocstate);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasbound = true;
                i.dorebind = false;
            } catch (transactiontoolargeexception e) {
                // keep the executenesting count accurate.
                if (debug_service) slog.v(tag_service, "crashed while binding " + r, e);
                final boolean indestroying = mdestroyingservices.contains(r);
                servicedoneexecutinglocked(r, indestroying, indestroying);
                throw e;
            } catch (remoteexception e) {
                if (debug_service) slog.v(tag_service, "crashed while binding " + r);
                // keep the executenesting count accurate.
                final boolean indestroying = mdestroyingservices.contains(r);
                servicedoneexecutinglocked(r, indestroying, indestroying);
                return false;
            }
        }
        return true;
    }
public final void schedulebindservice(ibinder token, intent intent,
                boolean rebind, int processstate) {
            updateprocessstate(processstate, false);
            bindservicedata s = new bindservicedata();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            if (debug_service)
                slog.v(tag, "schedulebindservice token=" + token + " intent=" + intent + " uid="
                        + binder.getcallinguid() + " pid=" + binder.getcallingpid());
            sendmessage(h.bind_service, s);
        }

在schedulebindservice方法里,发送一个绑定服务的消息。在activitythread里调用handlebindservice方法

private void handlebindservice(bindservicedata data) {
        service s = mservices.get(data.token);
        if (debug_service)
            slog.v(tag, "handlebindservice s=" + s + " rebind=" + data.rebind);
        if (s != null) {
            try {
                data.intent.setextrasclassloader(s.getclassloader());
                data.intent.preparetoenterprocess();
                try {
                    if (!data.rebind) {
                        ibinder binder = s.onbind(data.intent);
                        activitymanager.getservice().publishservice(
                                data.token, data.intent, binder);
                    } else {
                        s.onrebind(data.intent);
                        activitymanager.getservice().servicedoneexecuting(
                                data.token, service_done_executing_anon, 0, 0);
                    }
                    ensurejitenabled();
                } catch (remoteexception ex) {
                    throw ex.rethrowfromsystemserver();
                }
            } catch (exception e) {
                if (!minstrumentation.onexception(s, e)) {
                    throw new runtimeexception(
                            "unable to bind to service " + s
                            + " with " + data.intent + ": " + e.tostring(), e);
                }
            }
        }
    }

服务的绑定时序图:

service_bind.png

broadcastreceiver的工作过程

广播的注册过程

广播的注册分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册。这里只分析广播的动态注册过程。动态注册是从contextwrapper的registerreceiver方法开始的

public intent registerreceiver(
        broadcastreceiver receiver, intentfilter filter) {
        return mbase.registerreceiver(receiver, filter);
    }

registerreceiver调用contextimpl中的registerreceiver方法

public intent registerreceiver(broadcastreceiver receiver, intentfilter filter) {
        return registerreceiver(receiver, filter, null, null);
    }

registerreceiver再调用内部的registerreceiver方法

public intent registerreceiver(broadcastreceiver receiver, intentfilter filter,
            string broadcastpermission, handler scheduler) {
        return registerreceiverinternal(receiver, getuserid(),
                filter, broadcastpermission, scheduler, getoutercontext(), 0);
    }

registerreceiver会调用registerreceiverinternal方法

private intent registerreceiverinternal(broadcastreceiver receiver, int userid,
            intentfilter filter, string broadcastpermission,
            handler scheduler, context context, int flags) {
        //...
        try {
            final intent intent = activitymanager.getservice().registerreceiver(
                    mmainthread.getapplicationthread(), mbasepackagename, rd, filter,
                    broadcastpermission, userid, flags);
            if (intent != null) {
                intent.setextrasclassloader(getclassloader());
                intent.preparetoenterprocess();
            }
            return intent;
        } catch (remoteexception e) {
            throw e.rethrowfromsystemserver();
        }
    }

registerreceiverinternal调用了ams的registerreceiver方法

public intent registerreceiver(iapplicationthread caller, string callerpackage,
            iintentreceiver receiver, intentfilter filter, string permission, int userid,
            int flags) {
        //...
        synchronized (this) {
            //...
            broadcastfilter bf = new broadcastfilter(filter, rl, callerpackage,
                    permission, callinguid, userid, instantapp, visibletoinstantapps);
            rl.add(bf);
            if (!bf.debugcheck()) {
                slog.w(tag, "==> for dynamic broadcast");
            }
            mreceiverresolver.addfilter(bf);
            //...
            return sticky;
        }
    }

广播的发送和接收过程

广播的发送是通过contextwrapper的sendbroadcast方法实现的

public void sendbroadcast(intent intent) {
        mbase.sendbroadcast(intent);
    }

sendbroadcast调用了contextimpl中的sendbroadcast方法

public void sendbroadcast(intent intent) {
        warnifcallingfromsystemprocess();
        string resolvedtype = intent.resolvetypeifneeded(getcontentresolver());
        try {
            intent.preparetoleaveprocess(this);
            activitymanager.getservice().broadcastintent(
                    mmainthread.getapplicationthread(), intent, resolvedtype, null,
                    activity.result_ok, null, null, null, appopsmanager.op_none, null, false, false,
                    getuserid());
        } catch (remoteexception e) {
            throw e.rethrowfromsystemserver();
        }
    }

sendbroadcast调用了ams的broadcastintent方法

public final int broadcastintent(iapplicationthread caller,
            intent intent, string resolvedtype, iintentreceiver resultto,
            int resultcode, string resultdata, bundle resultextras,
            string[] requiredpermissions, int appop, bundle boptions,
            boolean serialized, boolean sticky, int userid) {
        enforcenotisolatedcaller("broadcastintent");
        synchronized(this) {
            intent = verifybroadcastlocked(intent);

            final processrecord callerapp = getrecordforapplocked(caller);
            final int callingpid = binder.getcallingpid();
            final int callinguid = binder.getcallinguid();
            final long origid = binder.clearcallingidentity();
            int res = broadcastintentlocked(callerapp,
                    callerapp != null ? callerapp.info.packagename : null,
                    intent, resolvedtype, resultto, resultcode, resultdata, resultextras,
                    requiredpermissions, appop, boptions, serialized, sticky,
                    callingpid, callinguid, userid);
            binder.restorecallingidentity(origid);
            return res;
        }
    }

broadcastintent调用broadcastintentlocked方法

final int broadcastintentlocked(processrecord callerapp,
            string callerpackage, intent intent, string resolvedtype,
            iintentreceiver resultto, int resultcode, string resultdata,
            bundle resultextras, string[] requiredpermissions, int appop, bundle boptions,
            boolean ordered, boolean sticky, int callingpid, int callinguid, int userid) {
                //...
                queue.enqueueorderedbroadcastlocked(r);
                queue.schedulebroadcastslocked();
                //...
}

broadcastintentlocked调用了broadcastqueue的enqueueorderedbroadcastlocked将广播添加到队列中,通过broadcastqueue的schedulebroadcastslocked来处理队列中的广播。

public void schedulebroadcastslocked() {
        if (debug_broadcast) slog.v(tag_broadcast, "schedule broadcasts ["
                + mqueuename + "]: current="
                + mbroadcastsscheduled);

        if (mbroadcastsscheduled) {
            return;
        }
        mhandler.sendmessage(mhandler.obtainmessage(broadcast_intent_msg, this));
        mbroadcastsscheduled = true;
    }

在schedulebroadcastslocked方法中,通过handler发送了一个broadcast_intent_msg的消息

public void handlemessage(message msg) {
            switch (msg.what) {
                case broadcast_intent_msg: {
                    if (debug_broadcast) slog.v(
                            tag_broadcast, "received broadcast_intent_msg");
                    processnextbroadcast(true);
                } break;
                case broadcast_timeout_msg: {
                    synchronized (mservice) {
                        broadcasttimeoutlocked(true);
                    }
                } break;
            }
        }

在handler的handlemessage方法中处理消息,调用了processnextbroadcast方法

final void processnextbroadcast(boolean frommsg) {
        //...
        delivertoregisteredreceiverlocked(r, filter, r.ordered, recidx);
        //...
    }

processnextbroadcast方法调用delivertoregisteredreceiverlocked

private void delivertoregisteredreceiverlocked(broadcastrecord r,
            broadcastfilter filter, boolean ordered, int index) {
        //...
        performreceivelocked(filter.receiverlist.app, filter.receiverlist.receiver,
                        new intent(r.intent), r.resultcode, r.resultdata,
                        r.resultextras, r.ordered, r.initialsticky, r.userid);
        //...
    }

delivertoregisteredreceiverlocked调用performreceivelocked

void performreceivelocked(processrecord app, iintentreceiver receiver,
            intent intent, int resultcode, string data, bundle extras,
            boolean ordered, boolean sticky, int sendinguser) throws remoteexception {
        // send the intent to the receiver asynchronously using one-way binder calls.
        if (app != null) {
            if (app.thread != null) {
                // if we have an app thread, do the call through that so it is
                // correctly ordered with other one-way calls.
                try {
                    app.thread.scheduleregisteredreceiver(receiver, intent, resultcode,
                            data, extras, ordered, sticky, sendinguser, app.repprocstate);
                // todo: uncomment this when (b/28322359) is fixed and we aren't getting
                // deadobjectexception when the process isn't actually dead.
                //} catch (deadobjectexception ex) {
                // failed to call into the process.  it's dying so just let it die and move on.
                //    throw ex;
                } catch (remoteexception ex) {
                    // failed to call into the process. it's either dying or wedged. kill it gently.
                    synchronized (mservice) {
                        slog.w(tag, "can't deliver broadcast to " + app.processname
                                + " (pid " + app.pid + "). crashing it.");
                        app.schedulecrash("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                // application has died. receiver doesn't exist.
                throw new remoteexception("app.thread must not be null");
            }
        } else {
            receiver.performreceive(intent, resultcode, data, extras, ordered,
                    sticky, sendinguser);
        }
    }

performreceivelocked调用applicationthread的scheduleregisteredreceiver方法

public void scheduleregisteredreceiver(iintentreceiver receiver, intent intent,
                int resultcode, string datastr, bundle extras, boolean ordered,
                boolean sticky, int sendinguser, int processstate) throws remoteexception {
            updateprocessstate(processstate, false);
            receiver.performreceive(intent, resultcode, datastr, extras, ordered,
                    sticky, sendinguser);
        }

scheduleregisteredreceiver里调用loadedapk的内部类receiverdispatcher中的performreceive方法

public void performreceive(intent intent, int resultcode, string data, bundle extras, boolean ordered, boolean sticky, int sendinguser) {
                loadedapk.receiverdispatcher rd;
                if (intent == null) {
                    log.wtf("loadedapk", "null intent received");
                    rd = null;
                } else {
                    rd = (loadedapk.receiverdispatcher)this.mdispatcher.get();
                }

                if (rd != null) {
                    rd.performreceive(intent, resultcode, data, extras, ordered, sticky, sendinguser);
                } else {
                    iactivitymanager mgr = activitymanagernative.getdefault();

                    try {
                        if (extras != null) {
                            extras.setallowfds(false);
                        }

                        mgr.finishreceiver(this, resultcode, data, extras, false, intent.getflags());
                    } catch (remoteexception var11) {
                        throw var11.rethrowfromsystemserver();
                    }
                }

            }

performreceive调用performreceive的重载

public void performreceive(intent intent, int resultcode, string data, bundle extras, boolean ordered, boolean sticky, int sendinguser) {
            loadedapk.receiverdispatcher.args args = new loadedapk.receiverdispatcher.args(intent, resultcode, data, extras, ordered, sticky, sendinguser);
            if (intent == null) {
                log.wtf("loadedapk", "null intent received");
            }

            if ((intent == null || !this.mactivitythread.post(args)) && this.mregistered && ordered) {
                iactivitymanager mgr = activitymanagernative.getdefault();
                args.sendfinished(mgr);
            }

        }

performreceive调用activitythread的内部类handler的post方法,将args发送出去,args是一个runnable接口,在handler处理消息时,会回调args的run方法

public void run() {
                //...
                receiver.onreceive(receiverdispatcher.this.mcontext, intent);
                //...
            }

在run中回调receiver的onreceiver方法

广播注册的时序图

broadcast_register.png

广播发送及接收的时序图

broadcast_post_receive.png

contentprovider的工作过程

当contentprovider所在的进程启动时,contentprovider会同时启动并被发布到ams中,这个时候contentprovider的oncreate要先于application的oncreate执行。

应用启动时的入口为activitythread的main方法

public static void main(string[] args) {
        //...
        looper.preparemainlooper();

        activitythread thread = new activitythread();
        thread.attach(false);

        if (smainthreadhandler == null) {
            smainthreadhandler = thread.gethandler();
        }

        if (false) {
            looper.mylooper().setmessagelogging(new
                    logprinter(log.debug, "activitythread"));
        }

        // end of event activitythreadmain.
        trace.traceend(trace.trace_tag_activity_manager);
        looper.loop();

        throw new runtimeexception("main thread loop unexpectedly exited");
    }

在main方法中,会创建activitythread的实例,并调用attach方法,然后调用looper.loop方法。这里主要分析attach方法。

private void attach(boolean system) {
        //...
        final iactivitymanager mgr = activitymanager.getservice();
            try {
                mgr.attachapplication(mappthread);
            } catch (remoteexception ex) {
                throw ex.rethrowfromsystemserver();
            }
        //...   
    }

在attach中,调用ams的attachapplication方法

public final void attachapplication(iapplicationthread thread) {
        synchronized (this) {
            int callingpid = binder.getcallingpid();
            final long origid = binder.clearcallingidentity();
            attachapplicationlocked(thread, callingpid);
            binder.restorecallingidentity(origid);
        }
    }

attachapplication调用attachapplicationlocked方法

private final boolean attachapplicationlocked(iapplicationthread thread,
            int pid) {
            //...
            thread.bindapplication(processname, appinfo, providers,
                        app.instr.mclass,
                        profilerinfo, app.instr.marguments,
                        app.instr.mwatcher,
                        app.instr.muiautomationconnection, testmode,
                        mbindertransactiontrackingenabled, enabletrackallocation,
                        isrestrictedbackupmode || !normalmode, app.persistent,
                        new configuration(getglobalconfiguration()), app.compat,
                        getcommonserviceslocked(app.isolated),
                        mcoresettingsobserver.getcoresettingslocked(),
                        buildserial);
            //...
    }

attachapplicationlocked调用applicationthread的bindapplication方法

public final void bindapplication(string processname, applicationinfo appinfo,
                list<providerinfo> providers, componentname instrumentationname,
                profilerinfo profilerinfo, bundle instrumentationargs,
                iinstrumentationwatcher instrumentationwatcher,
                iuiautomationconnection instrumentationuiconnection, int debugmode,
                boolean enablebindertracking, boolean trackallocation,
                boolean isrestrictedbackupmode, boolean persistent, configuration config,
                compatibilityinfo compatinfo, map services, bundle coresettings,
                string buildserial) {

            if (services != null) {
                // setup the service cache in the servicemanager
                servicemanager.initservicecache(services);
            }

            setcoresettings(coresettings);

            appbinddata data = new appbinddata();
            data.processname = processname;
            data.appinfo = appinfo;
            data.providers = providers;
            data.instrumentationname = instrumentationname;
            data.instrumentationargs = instrumentationargs;
            data.instrumentationwatcher = instrumentationwatcher;
            data.instrumentationuiautomationconnection = instrumentationuiconnection;
            data.debugmode = debugmode;
            data.enablebindertracking = enablebindertracking;
            data.trackallocation = trackallocation;
            data.restrictedbackupmode = isrestrictedbackupmode;
            data.persistent = persistent;
            data.config = config;
            data.compatinfo = compatinfo;
            data.initprofilerinfo = profilerinfo;
            data.buildserial = buildserial;
            sendmessage(h.bind_application, data);
        }

bindapplication发送消息bind_application给handler

public void handlemessage(message msg) {
            if (debug_messages) slog.v(tag, ">>> handling: " + codetostring(msg.what));
            switch (msg.what) {
                case bind_application:
                    trace.tracebegin(trace.trace_tag_activity_manager, "bindapplication");
                    appbinddata data = (appbinddata)msg.obj;
                    handlebindapplication(data);
                    trace.traceend(trace.trace_tag_activity_manager);
                    break;
                //...
            }
}

handlemessage中调用activitythread中的handlebindapplication方法

private void handlebindapplication(appbinddata data) {
            //...
            app = data.info.makeapplication(data.restrictedbackupmode, null);
            minitialapplication = app;
            if (!data.restrictedbackupmode) {
                if (!arrayutils.isempty(data.providers)) {
                    installcontentproviders(app, data.providers);
                    // for process that contains content providers, we want to
                    // ensure that the jit is enabled "at some point".
                    mh.sendemptymessagedelayed(h.enable_jit, 10*1000);
                }
            }
            //...
            minstrumentation.callapplicationoncreate(app);
            //...
}

handlebindapplication中创建了application实例和contentprovider,并且application的oncreate回调在contentprovider之后。

下面来看installcontentproviders方法

private void installcontentproviders(
            context context, list<providerinfo> providers) {
        final arraylist<contentproviderholder> results = new arraylist<>();

        for (providerinfo cpi : providers) {
            if (debug_provider) {
                stringbuilder buf = new stringbuilder(128);
                buf.append("pub ");
                buf.append(cpi.authority);
                buf.append(": ");
                buf.append(cpi.name);
                log.i(tag, buf.tostring());
            }
            //1
            contentproviderholder cph = installprovider(context, null, cpi,
                    false /*noisy*/, true /*noreleaseneeded*/, true /*stable*/);
            if (cph != null) {
                cph.noreleaseneeded = true;
                results.add(cph);
            }
        }

        try {
            //2
            activitymanager.getservice().publishcontentproviders(
                getapplicationthread(), results);
        } catch (remoteexception ex) {
            throw ex.rethrowfromsystemserver();
        }
    }

在注释1处调用installprovider方法。注释2处调用ams的publishcontentproviders方法

private contentproviderholder installprovider(context context,
            contentproviderholder holder, providerinfo info,
            boolean noisy, boolean noreleaseneeded, boolean stable) {
                //...
                localprovider = (contentprovider)cl.
                    loadclass(info.name).newinstance();
                provider = localprovider.geticontentprovider();
                if (provider == null) {
                    slog.e(tag, "failed to instantiate class " +
                          info.name + " from sourcedir " +
                          info.applicationinfo.sourcedir);
                    return null;
                }
                if (debug_provider) slog.v(
                    tag, "instantiating local provider " + info.name);
                // xxx need to create the correct context for this provider.
                localprovider.attachinfo(c, info);
                //...
}

在installprovider创建了provider,并调用了attachinfo方法

private void attachinfo(context context, providerinfo info, boolean testing) {
        mnoperms = testing;

        /*
         * only allow it to be set once, so after the content service gives
         * this to us clients can't change it.
         */
        if (mcontext == null) {
            mcontext = context;
            if (context != null) {
                mtransport.mappopsmanager = (appopsmanager) context.getsystemservice(
                        context.app_ops_service);
            }
            mmyuid = process.myuid();
            if (info != null) {
                setreadpermission(info.readpermission);
                setwritepermission(info.writepermission);
                setpathpermissions(info.pathpermissions);
                mexported = info.exported;
                msingleuser = (info.flags & providerinfo.flag_single_user) != 0;
                setauthorities(info.authority);
            }
            contentprovider.this.oncreate();
        }
    }

在attchinfo中调用了oncreate方法

再看ams的publishcontentproviders方法

public final void publishcontentproviders(iapplicationthread caller,
            list<contentproviderholder> providers) {
                //...
                componentname comp = new componentname(dst.info.packagename, dst.info.name);
                    mprovidermap.putproviderbyclass(comp, dst);
                    string names[] = dst.info.authority.split(";");
                    for (int j = 0; j < names.length; j++) {
                        mprovidermap.putproviderbyname(names[j], dst);
                    }
                //...
                if (wasinlaunchingproviders) {
                        mhandler.removemessages(content_provider_publish_timeout_msg, r);
                    }
                //...
    }

在publishcontentproviders方法中,主要是将provider信息保存到map中,移除content_provider_publish_timeout_msg消息。因为在ams的attachapplicationlocked方法中发送了一个content_provider_publish_timeout_msg消息,以便在超时的时候作出相应的处理。

contentprovider的启动时序图

contentprovider_start.png

访问contentprovider需要通过contentresolver,contentresolver是一个抽象类,通过context获取到的contentresolver,其实是contextimpl中的内部类applicationcontentresolver的一个实例。当contentprovider所在进程未启动时,第一次访问它就会触发contentprovider的创建,contentprovider的进程也会启动。通过contentprovider的增删改查的任何一个方法都会触发contentprovider的启动。这里选择query方法来分析。

contentprovider的使用方法一般是如下这样:

context.getcontentresolver().query()

context的实现类是contextwrapper.来看contextwrapper的getcontentresolver方法

public contentresolver getcontentresolver() {
        return mbase.getcontentresolver();
    }

getcontentresolver调用contextimpl的getcontentresolver方法

public contentresolver getcontentresolver() {
        return mcontentresolver;
    }

mcontentresolver是在contextimpl的构造函数中初始化的

private contextimpl(@nullable contextimpl container, @nonnull activitythread mainthread,
            @nonnull loadedapk packageinfo, @nullable string splitname,
            @nullable ibinder activitytoken, @nullable userhandle user, int flags,
            @nullable classloader classloader) {
            //...
        mcontentresolver = new applicationcontentresolver(this, mainthread, user);
            //...
    }

applicationcontentresolver是contextimpl的内部类。实例化contentresolver后,调用query方法

public final @nullable cursor query(final @requirespermission.read @nonnull uri uri,
            @nullable string[] projection, @nullable bundle queryargs,
            @nullable cancellationsignal cancellationsignal) {
        //...
        icontentprovider unstableprovider = acquireunstableprovider(uri);
        //...
    }

在query方法里,先通过acquireunstableprovider获取contentprovider

public final icontentprovider acquireunstableprovider(uri uri) {
        if (!scheme_content.equals(uri.getscheme())) {
            return null;
        }
        string auth = uri.getauthority();
        if (auth != null) {
            return acquireunstableprovider(mcontext, uri.getauthority());
        }
        return null;
    }

acquireunstableprovider会调用它的重载方法acquireunstableprovider

protected icontentprovider acquireunstableprovider(context c, string auth) {
            return this.mmainthread.acquireprovider(c, contentprovider.getauthoritywithoutuserid(auth), this.resolveuseridfromauthority(auth), false);
        }

acquireunstableprovider方法会调用activitythread的acquireprovider方法

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

        // there is a possible race here.  another thread may try to acquire
        // the same provider at the same time.  when this happens, we want to ensure
        // that the first one wins.
        // note that we cannot hold the lock while acquiring and installing the
        // provider since it might take a long time to run and it could also potentially
        // be re-entrant in the case where the provider is in the same process.
        contentproviderholder holder = null;
        try {
            holder = activitymanager.getservice().getcontentprovider(
                    getapplicationthread(), auth, userid, stable);
        } catch (remoteexception ex) {
            throw ex.rethrowfromsystemserver();
        }
        if (holder == null) {
            slog.e(tag, "failed to find provider info for " + auth);
            return null;
        }

        // install provider will increment the reference count for us, and break
        // any ties in the race.
        holder = installprovider(c, holder, holder.info,
                true /*noisy*/, holder.noreleaseneeded, stable);
        return holder.provider;
    }

如果有缓存过contentprovider,则直接获取返回。如果没有缓存,则通过ams的getcontentprovider方法获取

public final contentproviderholder getcontentprovider(
            iapplicationthread caller, string name, int userid, boolean stable) {
        enforcenotisolatedcaller("getcontentprovider");
        if (caller == null) {
            string msg = "null iapplicationthread when getting content provider "
                    + name;
            slog.w(tag, msg);
            throw new securityexception(msg);
        }
        // the incoming user check is now handled in checkcontentproviderpermissionlocked() to deal
        // with cross-user grant.
        return getcontentproviderimpl(caller, name, null, stable, userid);
    }

contentproviderholder调用getcontentproviderimpl方法获取contentresoverholder

获取到provider后,就会调用contentprovider的query方法,这个方法是我们自定义contentprovider时需要实现的。代码就切换到了我们定义的contentprovider。

contentprovider的query时序图

contentprovider_query.png

您可能感兴趣的文章:

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

◎已有 0 人评论

Copyright © 2020  萬仟网 保留所有权利. 粤ICP备17035492号-1
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com