jQuery鼠标指针特效

(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应用不受限制;

  1. 处于后台白名单中的uid不受限制
  2. 此白名单中只有一个uid:BLUETOOTH_UID,即蓝牙应用com.android.bluetooth;
    注:uid为system的应用可以调用AMS.backgroundWhitelistUid将某一应用加入到此白名单中。
  3. 处于耗电白名单的应用不受限制此白名单定义在/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);
        }
    }

ServiceANR

//不让服务停止
stopServiceLocked(ServiceRecord service){
    
}
Broadcast发送流程函数(Android 10.0)

AMS.broadcastIntentLocked()
BroadcastQueue.scheduleBroadcastsLocked()
BroadcastQueue.deliverToRegisteredReceiverLocked()
LoadedApk.performReceive()

posted @ 2024-03-24 17:35  僵小七  阅读(58)  评论(0编辑  收藏  举报