(Service)服务启动流程分析(Android 10.0)
(Service)服务启动流程分析,AMS内保活服务 (Android 10.0)
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/IActivityManager.java
frameworks/base/core/java/android/app/ActivityThread.java
启动服务有两种方式startServie或者bindService,目前分析startServie的流程
1.Activity.java
-->startService(Intent service)
2.ContextWrapper.java
-->startService(Intent service)
3.ContextImpl.java
-->startServiceCommon(...)
4.IActivityManager.java
-->startService(...)
4.ActivityManagerService.java
-->startService(...)
5.ActiveServices.java
-->startServiceLocked(...)
-->startServiceInnerLocked(...)
-->bringUpServiceLocked(...) bringup(抚养)
-->realStartServiceLocked(...)
6.ActivityThread.java
-->scheduleCreateService(...) -->sendMessage(H.CREATE_SERVICE, s) --> handleCreateService((CreateServiceData)msg.obj);
handleCreateService(...)函数执行了service.onCreate(),让服务onCreate,
之后回调ActivityManagerService.java 中的serviceDoneExecuting(...)
回调ActiveServices.java
-->serviceDoneExecutingLocked(...)
android8.0Service启动流程
具体函数解析:
流程4:ActivityManagerService.java
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
synchronized(this) {
//调用者的pid和uid
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
//重点是这里 mServices是ActiveServices的对象
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
流程5:startServiceLocked.java
5.1 startServiceLocked(...);
startServiceLocked函数中几个比较重要的参数:
service:Intent类型,包含运行的Service信息
requireForeground:是否需要前台运行,前面传的是false
callingPackage:调用该方法的包名
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
final int userId, boolean allowBackgroundActivityStarts)
throws TransactionTooLargeException {
.....
// If this is a direct-to-foreground start, make sure it is allowed as per the app op.
//如果是前台服务,可以直接运行
boolean forceSilentAbort = false;
if (fgRequired) {
final int mode = mAm.mAppOpsService.checkOperation(
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
case AppOpsManager.MODE_DEFAULT:
// All okay.
break;
case AppOpsManager.MODE_IGNORED:
// Not allowed, fall back to normal start service, failing siliently
// if background check restricts that.
Slog.w(TAG, "startForegroundService not allowed due to app op: service "
+ service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
fgRequired = false;
forceSilentAbort = true;
break;
default:
return new ComponentName("!!", "foreground not allowed as per app op");
}
}
// If this isn't a direct-to-foreground start, check our ability to kick off an
// arbitrary service
//不是前台服务,后台服务启动,需要检查它是否能启动
if (forcedStandby || (!r.startRequested && !fgRequired)) {
// Before going further -- if this app is not allowed to start services in the
// background, then at this point we aren't going to let it period.
//这里重点 allowed = APP_START_MODE_NORMAL 就可以启动,反之出现报错异常
final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage + " startFg?=" + fgRequired);
if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
// In this case we are silently disabling the app, to disrupt as
// little as possible existing apps.
return null;
}
if (forcedStandby) {
// This is an O+ app, but we might be here because the user has placed
// it under strict background restrictions. Don't punish the app if it's
// trying to do the right thing but we're denying it for that reason.
if (fgRequired) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.v(TAG, "Silently dropping foreground service launch due to FAS");
}
return null;
}
}
// This app knows it is in the new model where this operation is not
// allowed, so tell it what has happened.
UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(r.appInfo.uid);
return new ComponentName("?", "app is in background uid " + uidRec);
......
}
}
//通过上面检查,执行startServiceInnerLocked
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
5.1.1 ActivityManagerService.java - >getAppStartModeLocked(...)
int getAppStartModeLocked(int uid, String packageName, int packageTargetSdk,
int callingPid, boolean alwaysRestrict, boolean disabledOnly, boolean forcedStandby) {
UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg="
+ packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle="
+ (uidRec != null ? uidRec.idle : false));
if (uidRec == null || alwaysRestrict || forcedStandby || uidRec.idle) {
boolean ephemeral;
if (uidRec == null) {
ephemeral = getPackageManagerInternalLocked().isPackageEphemeral(
UserHandle.getUserId(uid), packageName);
} else {
ephemeral = uidRec.ephemeral;
}
if (ephemeral) {
// We are hard-core about ephemeral apps not running in the background.
return ActivityManager.APP_START_MODE_DISABLED;
} else {
if (disabledOnly) {
// The caller is only interested in whether app starts are completely
// disabled for the given package (that is, it is an instant app). So
// we don't need to go further, which is all just seeing if we should
// apply a "delayed" mode for a regular app.
return ActivityManager.APP_START_MODE_NORMAL;
}
//这里是重点 alwaysRestrict(始终严格),判断startMode
final int startMode = (alwaysRestrict)
? appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk)//判断app在后台是否受限制
: appServicesRestrictedInBackgroundLocked(uid, packageName,
packageTargetSdk);//判断Service在后台是否受限制
if (DEBUG_BACKGROUND_CHECK) {
Slog.d(TAG, "checkAllowBackground: uid=" + uid
+ " pkg=" + packageName + " startMode=" + startMode
+ " onwhitelist=" + isOnDeviceIdleWhitelistLocked(uid, false)
+ " onwhitelist(ei)=" + isOnDeviceIdleWhitelistLocked(uid, true));
}
if (startMode == ActivityManager.APP_START_MODE_DELAYED) {
// This is an old app that has been forced into a "compatible as possible"
// mode of background check. To increase compatibility, we will allow other
// foreground apps to cause its services to start.
if (callingPid >= 0) {
ProcessRecord proc;
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(callingPid);
}
if (proc != null &&
!ActivityManager.isProcStateBackground(proc.getCurProcState())) {
// Whoever is instigating this is in the foreground, so we will allow it
// to go through.
return ActivityManager.APP_START_MODE_NORMAL;
}
}
}
return startMode;
}
}
return ActivityManager.APP_START_MODE_NORMAL;
}
UidRecord为null,则说明整个APP没有被启动,那么就一定属于后台启动Service,如果UidRecord非null,则要判断应用是否属于后台应用
uidRec.idle为false,即应用在前台。返回ActivityManager.APP_START_MODE_NORMAL,即前台应用不限制启动后台Service;
uidRec.idle为true,即应用在后台如alwaysRestrict为true,则判断app在后台是否受限制;如为false,则判断Service在后台是否受限制
appServicesRestrictedInBackgroundLocked中做了3个判断:
int appServicesRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
// Persistent app?
if (mPackageManagerInt.isPackagePersistent(packageName)) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName
+ " is persistent; not restricted in background");
}
return ActivityManager.APP_START_MODE_NORMAL;
}
// Non-persistent but background whitelisted?
if (uidOnBackgroundWhitelist(uid)) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName
+ " on background whitelist; not restricted in background");
}
return ActivityManager.APP_START_MODE_NORMAL;
}
// Is this app on the battery whitelist?
if (isOnDeviceIdleWhitelistLocked(uid, /*allowExceptIdleToo=*/ false)) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName
+ " on idle whitelist; not restricted in background");
}
return ActivityManager.APP_START_MODE_NORMAL;
}
// None of the service-policy criteria apply, so we apply the common criteria
return appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk);
}
persistent应用不受限制;
- 处于后台白名单中的uid不受限制
- 此白名单中只有一个uid:BLUETOOTH_UID,即蓝牙应用com.android.bluetooth;
注:uid为system的应用可以调用AMS.backgroundWhitelistUid将某一应用加入到此白名单中。 - 处于耗电白名单的应用不受限制此白名单定义在/data/system/deviceidle.xml文件中,由电量管理ServiceDeviceIdleController管理,此Service启动时会从此文件中读取配置。同样,此名单可被动态添加,在开发时,我们可以通过命令将应用添加到耗电白名单中:adb shell dumpsys deviceidle whitelist +package_name
如以上条件均不满足,继续调用appRestrictedInBackgroundLocked方法。这个方法逻辑很简单,target>=26的应用均受限制
Android10.0 startService启动过程
Android O实现限制自启&&限制后台&&杀活方案
frameworks/base/core/java/android/app/ActivityManager.java
一个应用是否可以后台执行(Background Execution),
与 ActivityManagerService 的 getAppStartModeLocked() 方法返回结果相关。返回结果在 ActivityManager 中定义。
/** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: normal free-to-run operation. 正常自由运行操作*/
public static final int APP_START_MODE_NORMAL = 0;
/** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: delay running until later. 将运行延迟到稍后*/
public static final int APP_START_MODE_DELAYED = 1;
/** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: delay running until later, with
rigid errors (throwing exception). */
public static final int APP_START_MODE_DELAYED_RIGID = 2;
/** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: disable/cancel pending 禁用/取消
launches; this is the mode for ephemeral apps. */
public static final int APP_START_MODE_DISABLED = 3;
5.2 startServiceInnerLocked
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
}
5.3 bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// 1.如果此Service已经被启动,直接调用onStartCommand
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
...
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
// 2.Service所属进程已经启动
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
//真正启动Service
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
....
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
// 3.如果Service所属进程尚未启动,则先启动进程
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;
}
}
if (r.fgRequired) {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
+ " for fg-service launch");
}
mAm.tempWhitelistUidLocked(r.appInfo.uid,
SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (in bring up): " + r);
stopServiceLocked(r);
}
}
return null;
}
Android 6.0的源码剖析startService启动过程
8.0服务详解
Servcie ANR
对于Servcie ANR 流程,三步走,埋炸弹,拆炸弹,引爆炸弹
埋炸弹 ActiveServices.java
bringDownServiceLocked(ServiceRecord r){
.........
if (r.app != null && !r.packageName.contains("com.android.xxxx")) {
//埋炸弹 发送SERVICE_FOREGROUND_CRASH_MSG
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
msg.obj = r.app;
msg.getData().putCharSequence(
ActivityManagerService.SERVICE_RECORD_KEY, r.toString());
mAm.mHandler.sendMessage(msg);
}
}
拆炸弹 ActivityThread.java
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.
......
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);
}
}
}
拆炸弹-->ActiveServices.java
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
boolean finishing) {
if (r.executeNesting <= 0) {
if (r.app != null) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"Nesting at 0 of " + r.shortInstanceName);
r.app.execServicesFg = false;
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
"No more executingServices of " + r.shortInstanceName);
//拆炸弹动作
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
} else if (r.executeFg) {
// Need to re-evaluate whether the app still needs to be in the foreground.
for (int i=r.app.executingServices.size()-1; i>=0; i--) {
if (r.app.executingServices.valueAt(i).executeFg) {
r.app.execServicesFg = true;
break;
}
}
}
.......
}
引爆炸弹-->ActivityManagerService.java ::MainHandler
final class MainHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case SERVICE_TIMEOUT_MSG: {
......
mServices.serviceTimeout((ProcessRecord)msg.obj);
} break;
}
}
}
引爆炸弹-->ActiveServices.java
void serviceTimeout(ProcessRecord proc) {
String anrMessage = null;
synchronized(mAm) {
if (proc.isDebugging()) {
// The app's being debugged, ignore timeout.
return;
}
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
......
if (anrMessage != null) {
//当存在timeout的service,则执行appNotResponding
proc.appNotResponding(null, null, null, null, false, anrMessage);
}
}
//不让服务停止
stopServiceLocked(ServiceRecord service){
}
Broadcast发送流程函数(Android 10.0)
AMS.broadcastIntentLocked()
BroadcastQueue.scheduleBroadcastsLocked()
BroadcastQueue.deliverToRegisteredReceiverLocked()
LoadedApk.performReceive()