Android O startForegroundService(前台服务)流程分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lylddingHFFW/article/details/80366791

本文主要分析Android O startForegroundService(前台服务)的流程,以及出现Context.startForegroundService() did not then call Service.startForeground()null notification 的原因。

startForegroundService使用方式:https://blog.csdn.net/lylddinghffw/article/details/78219327

第一步: 在应用中启动startForegroundService将会调用ContextImpl中的startForegroundService,接着直接调用startServiceCommon

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

在startServiceCommon中得到AMS代理并启动startService,其中requireForeground为true

 private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        if (cn != null) {
            if (cn.getPackageName().equals("!")) {
                throw new SecurityException(
                        "Not allowed to start service " + service
                        + " without permission " + cn.getClassName());
            } else if (cn.getPackageName().equals("!!")) {
                throw new SecurityException(
                        "Unable to start service " + service
                        + ": " + cn.getClassName());
            } else if (cn.getPackageName().equals("?")) {
                throw new IllegalStateException(
                        "Not allowed to start service " + service + ": " + cn.getClassName());
            }
        }
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

AMS的startService调用ActivityServices中的startServiceLocked

 @Override
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 {
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

设置一些参数,只列出后边使用到的fgRequired = true r.startRequested = true addToStarting = false,最后调用startServiceInnerLocked

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {
    if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
            + " type=" + resolvedType + " args=" + service.getExtras());

    .....

    r.startRequested = true;
    r.delayedStop = false;
    //值为传进来的,true
    r.fgRequired = fgRequired;

    .....

    boolean addToStarting = false;
    //fgRequired 为ture, 直接调到else
    if (!callerFg && !fgRequired && r.app == null
            && mAm.mUserController.hasStartedUserState(r.userId)) {
        ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
        if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
            ....
            addToStarting = true;
        } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
            ......
            addToStarting = true;

        }
    } else if (DEBUG_DELAYED_STARTS) {
       .....
    }
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}

调用bringUpServiceLocked创建并启动Service,修改addToStarting为 true。而startRequested 为true。

 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    ServiceState stracker = r.getTracker();
    if (stracker != null) {
        stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
    }
    r.callStart = false;
    synchronized (r.stats.getBatteryStats()) {
        r.stats.startRunningLocked();
    }
    //创建并启动Service,并修改addToStarting = true, 启动成功返回空。
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    if (error != null) {
        return new ComponentName("!!", error);
    }

    if (r.startRequested && addToStarting) {
        boolean first = smap.mStartingBackground.size() == 0;
        smap.mStartingBackground.add(r);
        r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
        if (DEBUG_DELAYED_SERVICE) {
            RuntimeException here = new RuntimeException("here");
            here.fillInStackTrace();
            Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
        } else if (DEBUG_DELAYED_STARTS) {
            Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
        }
        if (first) {
            smap.rescheduleDelayedStartsLocked();
        }
    } else if (callerFg || r.fgRequired) {
        smap.ensureNotStartingBackgroundLocked(r);
    }

    return r.name;
}

调用realStartServiceLocked创建service

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
    //Slog.i(TAG, "Bring up service:");
    //r.dump("  ");

    // 此时r.app 为null
    if (r.app != null && r.app.thread != null) {
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }

    ......


    // Service is now being launched, its package can't be stopped.
        if (app != null && app.thread != null) {
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, 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.shortName, e);
            }

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

    return null;
}

app.thread.scheduleCreateService发送创建service的msg, r.postNotification() 发送服务正在后台运行的通知。发送timeout 5s msg sendServiceArgsLocked(r, execInFg, true);

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

    r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

    final boolean newService = app.services.add(r);
    bumpServiceExecutingLocked(r, execInFg, "create");
    if (ActivityManagerService.PROCESS_ACTIVE_LOG)
            Log.d(ActivityManagerService.PROCESS_ACTIVE_TAG,
            "realStartServiceLocked app:" + app);
    mAm.onServiceProcessActive(app);
    mAm.updateLruProcessLocked(app, false, null);
    updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
    mAm.updateOomAdjLocked();

    boolean created = false;
    try {
        if (LOG_SERVICE_START_STOP) {
            String nameTerm;
            int lastPeriod = r.shortName.lastIndexOf('.');
            nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
            EventLogTags.writeAmCreateService(
                    r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
        }
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startLaunchedLocked();
        }
        mAm.notifyPackageUse(r.serviceInfo.packageName,
                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        //发送msg 创建service。
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        //发送服务正在后台运行的通知
        r.postNotification();
        created = true;
    } 
    ........


    //发送timeout 5s msg
    sendServiceArgsLocked(r, execInFg, true);

    ......
}

首先看创建service的流程:发送创建service的message (CREATE_SERVICE)

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

接收并处理message

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

通过反射创建service实例对象,并初始化一些参数,调用熟悉的onCreate()。

 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 {
        //通过反射创建service实例对象。
        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());
        //调用熟悉的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);
        }
    }
}

接下来 看发送timeout 5s msg的流程

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
        .......
        // fgRequired = true 表示前台服务,fgWaiting默认值为false,当发送timeout msg 时修改为true。
        if (r.fgRequired && !r.fgWaiting) {
            //isForeground =  false 不在前台
            if (!r.isForeground) { 
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);
                }
                //发送 timeout msg
                scheduleServiceForegroundTransitionTimeoutLocked(r);
            } else {
                if (DEBUG_BACKGROUND_CHECK) {
                    Slog.i(TAG, "Service already foreground; no new timeout: " + r);
                }
                r.fgRequired = false;
            }
        }
        int flags = 0;
        if (si.deliveryCount > 1) {
            flags |= Service.START_FLAG_RETRY;
        }
        if (si.doneExecutingCount > 0) {
            flags |= Service.START_FLAG_REDELIVERY;
        }
        args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
    }

   ....
}

发送5s Timeout超时的Message,及报crash

void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
    if (r.app.executingServices.size() == 0 || r.app.thread == null) {
        return;
    }
    Message msg = mAm.mHandler.obtainMessage(
            ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
    msg.obj = r;
    r.fgWaiting = true;
    mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT);
}

AMS中接收并处理msg

 case SERVICE_FOREGROUND_TIMEOUT_MSG: {
            mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);

ActivityServices中停止服务并抛出异常”Context.startForegroundService() did not then call Service.startForeground(): “

void serviceForegroundTimeout(ServiceRecord r) {
    ProcessRecord app;
    synchronized (mAm) {
        if (!r.fgRequired || r.destroying) {
            return;
        }

        if (DEBUG_BACKGROUND_CHECK) {
            Slog.i(TAG, "Service foreground-required timeout for " + r);
        }
        app = r.app;
        r.fgWaiting = false;
        stopServiceLocked(r);
    }

    if (app != null) {
        mAm.mAppErrors.appNotResponding(app, null, null, false,
                "Context.startForegroundService() did not then call Service.startForeground(): "
                + r);
    }
}

第二步:在第一步中分析了在handleCreateService中会调用onCreate方法。在service的onCreate中调用手动添加的startForeground,接着直接调用setServiceForeground—->setServiceForegroundLocked

 public final void startForeground(int id, Notification notification) {
    try {
        mActivityManager.setServiceForeground(
                new ComponentName(this, mClassName), mToken, id,
                notification, 0);
    } catch (RemoteException ex) {
    }
}

找到保存的ServiceRecord,并调用setServiceForegroundInnerLocked

public void setServiceForegroundLocked(ComponentName className, IBinder token,
        int id, Notification notification, int flags) {
    final int userId = UserHandle.getCallingUserId();
    final long origId = Binder.clearCallingIdentity();
    try {
        ServiceRecord r = findServiceLocked(className, token, userId);
        if (r != null) {
            setServiceForegroundInnerLocked(r, id, notification, flags);
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

notification为空的时候会抛出”null notification”异常,并移除Timeout超时的Message。

 private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
        Notification notification, int flags) {
    if (id != 0) {

        if (notification == null) {
            throw new IllegalArgumentException("null notification");
        .....

        if (r.fgRequired) {
            if (DEBUG_SERVICE || DEBUG_BACKGROUND_CHECK) {
                Slog.i(TAG, "Service called startForeground() as required: " + r);
            }
            r.fgRequired = false;
            r.fgWaiting = false;
            //移除Timeout超时的Message
            mAm.mHandler.removeMessages(
                    ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
        }
        if (r.foregroundId != id) {
            cancelForegroundNotificationLocked(r);
            r.foregroundId = id;
        }
        notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
        r.foregroundNoti = notification;
        if (!r.isForeground) {
            final ServiceMap smap = getServiceMapLocked(r.userId);
            if (smap != null) {
                ActiveForegroundApp active = smap.mActiveForegroundApps.get(r.packageName);
                if (active == null) {
                    active = new ActiveForegroundApp();
                    active.mPackageName = r.packageName;
                    active.mUid = r.appInfo.uid;
                    active.mShownWhileScreenOn = mScreenOn;
                    if (r.app != null) {
                        active.mAppOnTop = active.mShownWhileTop =
                                r.app.uidRecord.curProcState
                                        <= ActivityManager.PROCESS_STATE_TOP;
                    }
                    active.mStartTime = active.mStartVisibleTime
                            = SystemClock.elapsedRealtime();
                    smap.mActiveForegroundApps.put(r.packageName, active);
                    requestUpdateActiveForegroundAppsLocked(smap, 0);
                }
                active.mNumActive++;
            }
            r.isForeground = true;
        }
        //发送服务正在后台运行的通知
        r.postNotification();
        if (r.app != null) {
            if (ActivityManagerService.PROCESS_ACTIVE_LOG)
                    Log.d(ActivityManagerService.PROCESS_ACTIVE_TAG,
                    "setServiceForegroundLocked app:" + r.app);
            mAm.onServiceProcessActive(r.app);
            updateServiceForegroundLocked(r.app, true);
        }
        getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
        mAm.notifyPackageUse(r.serviceInfo.packageName,
                             PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
    } 

    ......
}

总结:从分析来看startForegroundService中主要是通知创建service 并发送一个延迟5s的msg,5s后就会抛出异常。而在service创建之后会调用oncCreate中手动添加的startForeground,它的作用是添加notification避免 “null notification”,同时取消startForegroundService中发出的msg 避免异常“Context.startForegroundService() did not then call Service.startForeground()”。

原文链接:https://blog.csdn.net/lylddinghffw/article/details/80366791

欢迎指教。

猜你喜欢

转载自blog.csdn.net/lylddingHFFW/article/details/80366791
今日推荐