Android 6.0 启动startService()源码分析(3)

极客导航  2018-07-17 20:13  阅读 101 次 评论 0 条


闲话少说,接上一篇《Android 6.0 启动startService()源码分析(2)

10.9 ActiveServices.bumpServiceExecutingLocked 发送SERVICE_TIMEOUT_MSG用来判断是否ANR
    private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
                + why + " of " + r + " in app " + r.app);
        else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
                + why + " of " + r.shortName);
        long now = SystemClock.uptimeMillis();
        【executeNesting 记录前台次数,第一次为0,fg是启动前台还是后台服务】
        if (r.executeNesting == 0) {
            r.executeFg = fg;
            ProcessStats.ServiceState stracker = r.getTracker();
            if (stracker != null) {
                stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
            }
            if (r.app != null) {
                r.app.executingServices.add(r);
                r.app.execServicesFg |= fg;
                if (r.app.executingServices.size() == 1) {
                    scheduleServiceTimeoutLocked(r.app); 【10.9.1 发送SERVICE_TIMEOUT_MSG】
                }
            }
        } else if (r.app != null && fg && !r.app.execServicesFg) {
            r.app.execServicesFg = true;
            scheduleServiceTimeoutLocked(r.app);
        }
        r.executeFg |= fg;
        r.executeNesting++;
        r.executingStart = now;
    }
10.9.1 发送SERVICE_TIMEOUT_MSG
    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
        if (proc.executingServices.size() == 0 || proc.thread == null) {
            return;
        }
        long now = SystemClock.uptimeMillis();
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
        【发送SERVICE_TIMEOUT_MSG消息】
        mAm.mHandler.sendMessageAtTime(msg,
                proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
    }

前台服务 SERVICE_TIMEOUT是20s

后台服务 SERVICE_BACKGROUND_TIMEOUT是200s

如果超过上面时间,没有移除SERVICE_TIMEOUT_MSG消息,就会弹出ANR消息。

10.10 ActivityThread.scheduleCreateService
app.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),app.repProcState);

其实调用的方法是ApplicationThreadProxy中的scheduleCreateService(),代码写在ApplicationThreadNative.java中

    public final void scheduleCreateService(IBinder token, ServiceInfo info,
            CompatibilityInfo compatInfo, int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        info.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        data.writeInt(processState);
        try {
           【是不是很熟悉,,,binder....然后到了ApplicationThreadNative的onTransact()】
            mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                    IBinder.FLAG_ONEWAY);
        } catch (TransactionTooLargeException e) {
            Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
            throw e;
        }
        data.recycle();
    }

mRemote.transact()这是不是很熟悉啊,,参考前面《Android 6.0 启动startService()源码分析(1)》中ActivityManagerProxy、ActivityManagerNative和ActivityManagerService的关系,这里省略

最后运行到了ApplicationThread.scheduleCreateService()

10.11 ApplicationThread.scheduleCreateService()

ApplicationThread是在ActivityThread.java中

     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;
            【发送CREATE_SERVICE消息】
            sendMessage(H.CREATE_SERVICE, s);
      }
    case CREATE_SERVICE:
              Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
              【handleCreateService】
              handleCreateService((CreateServiceData)msg.obj);
              Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              break;
    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();

        .....

        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,
                    ActivityManagerNative.getDefault());
            【service.onCreate()创建】
            service.onCreate();
            mServices.put(data.token, service);
            try {
                【10.12 这里调用的是ActivityManagerService.serviceDoneExecuting()此时出传入type=SERVICE_DONE_EXECUTING_ANON 】
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }
10.12 ActivityManagerService.serviceDoneExecuting()
    public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
                throw new IllegalArgumentException("Invalid service token");
            }
            【10.13 serviceDoneExecutingLocked】
            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
        }
    }
10.13 ActiveServices.serviceDoneExecutingLocked()

在onCreate时候传入的type是SERVICE_DONE_EXECUTING_ANON,上面可以看到。

    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
        boolean inDestroying = mDestroyingServices.contains(r);
        if (r != null) {
            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
              .....
            } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
             ......
            }
            final long origId = Binder.clearCallingIdentity();
            //  10.14 type 都不符合上面条件,因此直接走这里serviceDoneExecutingLocked
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
            Binder.restoreCallingIdentity(origId);
        } else {
            Slog.w(TAG, "Done executing unknown service from pid "
                    + Binder.getCallingPid());
        }
    }
// 10.14 serviceDoneExecutingLocked
    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
            boolean finishing) {
        r.executeNesting--;
        if (r.executeNesting <= 0) {
            if (r.app != null) {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                        "Nesting at 0 of " + r.shortName);
                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.shortName);
                    【移除超时SERVICE_TIMEOUT_MSG消息,否则就会ANR】
                    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;
                        }
                    }
                }
        ......
        }
    }

如果没有移除超时消息SERVICE_TIMEOUT_MSG,就会ANR。

onCreate()执行完后,接着是前面提到的sendServiceArgsLocked(),我们继续

11. 0 sendServiceArgsLocked 服务进入onStartCommand()
  private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        final int N = r.pendingStarts.size();
        if (N == 0) {
            return;
        }

        while (r.pendingStarts.size() > 0) {
            Exception caughtException = null;
            ServiceRecord.StartItem si;
            try {
                si = r.pendingStarts.remove(0);
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Sending arguments to: "
                        + r + " " + r.intent + " args=" + si.intent);
                if (si.intent == null && N > 1) {
                    // If somehow we got a dummy null intent in the middle,
                    // then skip it.  DO NOT skip a null intent when it is
                    // the only one in the list -- this is to support the
                    // onStartCommand(null) case.
                    continue;
                }
                si.deliveredTime = SystemClock.uptimeMillis();
                r.deliveredStarts.add(si);
                si.deliveryCount++;
                if (si.neededGrants != null) {
                    mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
                            si.getUriPermissionsLocked());
                }
                【和 10.9 ActiveServices.bumpServiceExecutingLocked 发送SERVICE_TIMEOUT_MSG用来判断是否ANR,一样】
                bumpServiceExecutingLocked(r, execInFg, "start");
                if (!oomAdjusted) {
                    oomAdjusted = true;
                    mAm.updateOomAdjLocked(r.app);
                }
                int flags = 0;
                if (si.deliveryCount > 1) {
                    flags |= Service.START_FLAG_RETRY;
                }
                if (si.doneExecutingCount > 0) {
                    flags |= Service.START_FLAG_REDELIVERY;
                }
                【启动onStartCommand,这个和启动onCreate()的路径都一样,这里都不在重复】
                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
            } catch (TransactionTooLargeException e) {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large: intent="
                        + si.intent);
                caughtException = e;
            } catch (RemoteException e) {
                // Remote process gone...  we'll let the normal cleanup take care of this.
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
                caughtException = e;
            } catch (Exception e) {
                Slog.w(TAG, "Unexpected exception", e);
                caughtException = e;
            }

            if (caughtException != null) {
                // Keep nesting count correct
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                if (caughtException instanceof TransactionTooLargeException) {
                    throw (TransactionTooLargeException)caughtException;
                }
                break;
            }
        }
    }

启动onStartCommand()和onCreate()流程差不多,这个就不再重复。流程很长,细节部分都丢了。

总结

1、在流程中,我们看到了在ActivityThread.java中初始化了Looper.prepareMainLooper()和开启了Looper.loop()

2、前台服务20m没有执行完就会ANR,后台服务200s没有启动就ANR

历史上的今天:

本文地址: https://www.125la.com/527.html
关注我们:请关注一下我们站长微信:扫描二维码125啦读书导航的微信号,微信号:yudemi(十三少)
版权声明:本文为原创或转载文章,版权归原作者所有,欢迎分享本文,转载请保留出处!
第一个读书导航

发表评论


表情