启动startService()分析(3)

Android  Java  2018年7月17日 pm8:13发布3个月前更新 城堡大人
110 1 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

 历史上的今天

  1. 2024: git log命令参数部分记录(0条评论)
  2. 2023: Android 中Bn和Bp介绍(0条评论)
  3. 2021: Dialog的简单使用(0条评论)
  4. 2021: 穆旦:冥想(0条评论)
  5. 2020: [摘]SeekBar的thumbOffset属性(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

1 条评论

  • Yu
    Yu 管理员

    太久了,略过吧

    回复

随机推荐

Android广播在子线程中运行

前言Android中,为了不让主线程阻塞,广播接收器在一些耗时或频繁的任务,可以考虑让其在子线程中运行,当需要刷新UI是才运行在主线程。。记录于此方便自己查阅。正文隐藏内容!付费阅读后才能查看!¥1 ¥3多个隐藏块只需支付一次付费阅读

[摘]Android IO流读写文件实例2

一、超类:字节流: InputStream(读入流) OutputStream(写出流)字符流: Reader(字符 读入流) Writer (字符写出流)二、文件操作流字节流: FileInputStream ,FileOutputStream字符流: FileReader, File...

[摘]System.exit(0)和System.exit(1)区别

原作者解释得很清晰明,因此摘抄于此。关于System.exit(status)System.exit(status)源码说明如下:System.java/** * Terminates the currently running Java Virtual Machine. The * ...

CarAudioManager方法简介

前言参考别人文章,看Android中车载部分CarAudioManager类中部分方法的介绍。正文简单记录一下CarAudioManager中方法的说明。packages\services\Car\car-lib\src\android\car\media\CarAudioManager....

麦芒:生活与危机

梦见的还是十年前的危机生活,却仍然是眼前的生活两种因素似被姻缘强拧在一起我记得,一个冬夜危机宛如积雪休闲的火山正对着度蜜月假的一对夫妻旅馆二层房间敞开的窗口不知是为了让屋内的人向外眺望还是让屋外的火山朝里窥视哎,没有马车驰过的空旷街道就像被声音遗弃的微潮的黎明让我替你说出...

Kotlin中的特殊函数简介

前言简单记录一下Kotlin中的run()、apply()、let()、also()和with()等特殊的函数,方便自己查阅。正文run()@kotlin.internal.InlineOnlypublic inline fun <T, R> T.run(block: T....