【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.java
〹Activity.startService()
まず知っています。Serviceを起動するには、Activityで
ハConttextWrapper.startService()
皱ConttextImpl.startService()
次に、
癜Active Services.startServiceInner Locked()
Active ServicesのstartServiceLocked()メソッドは最後に
Serviceが実行するプロセスは2つあります。
(1)一つはデフォルトで、ActivityでServiceを起動するプロセス、つまりどのプロセスでstartService()メソッドを呼び出しましたか?起動したserviceはどのプロセスで実行しますか?
(2)Serviceに別々のプロセスを実行すること。例えば、Android Manifestファイルには以下のような内容が配置されている。
前の方法に戻ると、変数アプリが空であれば、Serviceが実行するプロセスが起動されていないことを表し、
appが空でない場合は、デフォルトでServiceを起動し、最終的に
皱Active Services.realStartServiceLocked()
皱ActivityThread.scheduleCreateService()
萼H.handleMessage()
これでServiceの起動は分析済みで、このプロセスはActivityを起動するより簡単になりました。
ソース分析のコード量が大きいので、ほとんどのブログサイトの内容表示ページは狭く、表示された効果は非常に醜いです。だから、直接に「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.java
Service
の起動プロセスは相対的に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 {
}
Activity
はContextThemeWrapper
クラスを継承し、ContextThemeWrapper
はContextWrapper
クラスを継承し、ContextWrapper
はContext
クラスを継承した。ハ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-filter
のService
に関するコンテンツ情報を解析した後、解析の結果は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);
}
}
}
ActivityThread
のApplicationThread
方法は、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を起動するより簡単になりました。