【Android 10 4つのコンポーネント】シリーズ--Serviceの「起動フロー」

64238 ワード

同前
ソース分析のコード量が大きいので、ほとんどのブログサイトの内容表示ページは狭く、表示された効果は非常に醜いです。だから、直接に「Thinking in Android」を見てこちらの文章を読んでください。この文章があなたのために、「Serviceの起動プロセス」を整理してくれることを願っています。
安徽省の核心的なソースコード
キークラス
パス
ContectImpl.java
frame eworks/base/core/java/android/ap/Contect Impl.java
ConttextWrapper.java
framweorks/base/core/java/android/content/Contect Wrapper.java
Contect The meWrapper.java
frame eworks/base/core/java/android/Conteext The meWrapper.java
Activity.java
fram eworks/base/core/java/android/ap/Activity.java
ActivityManager.java
fram eworks/base/core/java/android/ap/ActivityManager.java
ActivityManager Service.java
frame eworks/base/services/core/java/com/android/server/am/ActivityManager Service.java
Active Services.java
フレームワーク/base/services/core/java/com/android/server/am/Active Services.java
ActivityThread.java
fram eworks/base/core/java/android/ap/ActivityThread.javaServiceの起動プロセスは相対的にActivityの起動プロセスにとって簡単になりました。どのようにServiceを作成し、起動するか分かります。ソースの角度からServiceを研究したことがありますか?
〹Activity.startService()
まず知っています。Serviceを起動するには、ActivityでstartService()を通じて起動されるのが一般的です。
Intent intent = new Intent(MainActivity.this, xxxService.class);
startService(intent);
しかし、私たちはActivityのソースコードの中でstartService()方法を実現していません。どこで呼び出されましたか?見つけられないなら、私達はActivityの父の種類の中に探しに行きます。
// frameworks/base/core/java/android/app/Activity.java

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
		
}

// frameworks/base/core/java/android/view/ContextThemeWrapper.java

public class ContextThemeWrapper extends ContextWrapper {

}

// frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {

}
ActivityContextThemeWrapperクラスを継承し、ContextThemeWrapperContextWrapperクラスを継承し、ContextWrapperContextクラスを継承した。
ハConttextWrapper.startService()ContextWrapperにおいて、startService()方法が実装されている。
// frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {

    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }

    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

}
したがって、startService()方法は、ContextWrapperによって実現され、次いでmBase.startService()方法が呼び出され、mBaseオブジェクトはContextのサブクラスContextImplであるので、最終的にContextImplクラスに入るstartService()方法を呼び出す。
皱ConttextImpl.startService()
// frameworks/base/core/java/android/app/ContextImpl.java

class ContextImpl extends Context {

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

    private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            //    Binder         ActivityManagerService   startService()   
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                    getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier());
            ... ...

            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

}
〹ActivityManager.get Service()
// frameworks/base/core/java/android/app/ActivityManager.java

public class ActivityManager {

    @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

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

}
〹ActivityManagerService.startService()
次に、ActivityManagerServiceに実行されるstartService()方法について説明する。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

    final ActiveServices mServices;

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ... ...

        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                //    ActiveServices   startServiceLocked()   
                res = mServices.startServiceLocked(caller, service, resolvedType, callingPid,
                            callingUid, requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

}
癜Active Services.startServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

public final class ActiveServices {

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
                callingPackage, userId, false);
    }

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            final int userId, boolean allowBackgroundActivityStarts)
            throws TransactionTooLargeException {
        ... ...
		
		//    AndroidManifest.xml       Service   intent-filter       
        ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
        if (res == null) {
            return null;
        }
        ... ...

        ServiceRecord r = res.record;
        ... ...

        //    startServiceInnerLocked()   
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }

}
retrieveServiceLocked()方法によって、Serviceを構成するAndroidManifest.xmlファイルの関連コンテンツ情報を解析する。intent-filterServiceに関するコンテンツ情報を解析した後、解析の結果はintent-filter変数に保存されます。一方、res変数はres.recordタイプのオブジェクトであり、record変数はServiceLookupResultタイプのオブジェクトであり、ServiceRecordタイプのオブジェクトである。
癜Active Services.startServiceInner Locked()
Active ServicesのstartServiceLocked()メソッドは最後にServiceメソッドを呼び出しました。
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

public final class ActiveServices {

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ... ...

        //    bringUpServiceLocked()   
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        ... ...

    }
}
癜Active Services.brigUpServiceLocked()startServiceInnerLocked()コール方法はさらに処理される。
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

public final class ActiveServices {

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        ... ...

        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);    //    app   
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    //    service        ,   realStartServiceLocked()   
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                }

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

        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
        ... ...

        return null;
    }

}
bringUpServiceLocked()方法は、まずbringUpServiceLocked()方式でappオブジェクトを取得し、getProcessRecordLocked()タイプのオブジェクトである。もしそれが空でなければ、ProcessRecordが実行するプロセスがすでに存在するということを示す。
Serviceが実行するプロセスは2つあります。
(1)一つはデフォルトで、ActivityでServiceを起動するプロセス、つまりどのプロセスでstartService()メソッドを呼び出しましたか?起動したserviceはどのプロセスで実行しますか?
(2)Serviceに別々のプロセスを実行すること。例えば、Android Manifestファイルには以下のような内容が配置されている。
//

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.documentsui">

    <application
        android:name=".DocumentsApplication"
        android:label="@string/app_label"
        android:icon="@drawable/app_icon"
        android:supportsRtl="true"
        android:allowBackup="true"
        android:backupAgent=".prefs.BackupAgent"
        android:fullBackupOnly="false">

        
        <service
            android:name=".services.FileOperationService"
            android:exported="false"
            android:process=":com.android.documentsui.services">
        service>

    application>
manifest>
この構成にはServiceの声明があります。この声明はserviceが単独で「xxx」プロセスで実行することを実現するために使われます。このようにするメリットはandroid:process="xxx"です。
前の方法に戻ると、変数アプリが空であれば、Serviceが実行するプロセスが起動されていないことを表し、 , service , 方法を呼び出して新しいプロセスを開始する。
appが空でない場合は、デフォルトでServiceを起動し、最終的にstartProcessLocked()方法に呼び出します。
皱Active Services.realStartServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

public final class ActiveServices {

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ... ...

        try {
            ... ...

            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState());
            ... ...

        }
        ... ...

    }

}
この方法では、appオブジェクトのrealStartServiceLocked()変数は、thread ApplicationThreadオブジェクトであり、Binder方法を呼び出した後、クライアントのscheduleCreateService()に入る。
皱ActivityThread.scheduleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    // ApplicationThread     Binder
    private class ApplicationThread extends IApplicationThread.Stub {

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

    }
    
}
ActivityThreadApplicationThread方法は、scheduleCreateService()を呼び出すことにより、Handlerがmsgメッセージを受信した後、sendMessage() msg 方法を呼び出して、さらなる処理を行う。
萼H.handleMessage()
// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    class H extends Handler {

        public void handleMessage(Message msg) {
            switch (msg.what) {

                case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                    handleCreateService((CreateServiceData)msg.obj);    //    handleCreateService()   
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

            }
        }

    }
}
癜ActivityThread.handleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread extends ClientTransactionHandler {

    private void handleCreateService(CreateServiceData data) {
        ... ...

        LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);
        } 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();    //    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);
            }
        }
    }

}
handleCreateService()クラスのActivityThread方法では、まずhandleCreateService()クラスを介してServiceをロードし、パラメータClassLoaderはこのdata.info.nameの名前を表し、Service方法はServiceのインスタンスを作成することである。次に、instantiateService()は、コンテキスト環境として使用される。 Context 方法は最後にhandleCreateService()を呼び出し、この方法が呼び出された後にservice onCreate() を呼び出す。
これでServiceの起動は分析済みで、このプロセスはActivityを起動するより簡単になりました。