启动startService()分析(2)

源码分析  2018年7月17日 pm8:09发布3个月前更新 城堡大人
96 0 0

接上一篇《Android 6.0 启动startService()源码分析(1)》,依旧分析startService()启动过程。由于篇幅过长,分开记录,便于阅读。

10.4 ActivityManagerProxy.attachApplication

在上一篇中的代码中

 【获取的又是ActivityManagerProxy对象】
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread); 【 10.4 ActivityManagerProxy.attachApplication 】但最终还是跑到了ActivityManagerService中attachApplication中
            } catch (RemoteException ex) {
                // Ignore
            }

根据上一篇分析

ActivityManagerNative.getDefault()获取的就是ActivityManagerProxy对象(过程可以看上一篇中的分析,此处省略)

我们看ActivityManagerProxy.attachApplication()

    public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app.asBinder());
        【mRemote 就是Binder  此处发送ATTACH_APPLICATION_TRANSACTION出去,然后在ActivityManagerNative的onTransact】
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

经过mRemote.transac后,ATTACH_APPLICATION_TRANSACTION有传送到ActivityManagerNative的onTransact()中

ActivityManagerNative.onTransact()

    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        ......
        case ATTACH_APPLICATION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IApplicationThread app = ApplicationThreadNative.asInterface(
                    data.readStrongBinder());
            if (app != null) {
                【这里最终调用的是 10.5 ActivityManagerService.attachApplication() 】
                attachApplication(app);
            }
            reply.writeNoException();
            return true;
        }
        .....
}
10.5 ActivityManagerService.attachApplication()
    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            【10.6 ActivityManagerService.attachApplicationLocked】
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
10.6 ActivityManagerService.attachApplicationLocked
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }

        if (app == null) {
            Slog.w(TAG, "No pending application record for pid " + pid
                    + " (IApplicationThread " + thread + "); dropping process");
            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
            if (pid > 0 && pid != MY_PID) {
                Process.killProcessQuiet(pid);
                //TODO: killProcessGroup(app.info.uid, pid);
            } else {
                try {
                    thread.scheduleExit();
                } catch (Exception e) {
                    // Ignore exceptions.
                }
            }
            return false;
        }

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {
            handleAppDiedLocked(app, true, true);
        }
        ......
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
                 【10.7 mServices.attachApplicationLocked 】
                didSomething |= mServices.attachApplicationLocked(app, processName);
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

      ......

        return true;
    }
10.7 ActiveServices.attachApplicationLocked
    boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        // Collect any services that are waiting for this process to come up.
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }

                    mPendingServices.remove(i);
                    i--;
                    【添加包名】
                    proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
                            mAm.mProcessStats);
		    【10.8 ActiveServices.realStartServiceLocked() 】
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception in new application when starting service "
                        + sr.shortName, e);
                throw e;
            }
        }
        // Also, if there are any services that are waiting to restart and
        // would run in this process, now is a good time to start them.  It would
        // be weird to bring up the process but arbitrarily not let the services
        // run at this point just because their restart time hasn't come up.
        if (mRestartingServices.size() > 0) {
            ServiceRecord sr = null;
            for (int i=0; i<mRestartingServices.size(); i++) {
                sr = mRestartingServices.get(i);
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                        || !processName.equals(sr.processName))) {
                    continue;
                }
                mAm.mHandler.removeCallbacks(sr.restarter);
                mAm.mHandler.post(sr.restarter);
            }
        }
        return didSomething;
    }
10.8 ActiveServices.realStartServiceLocked()
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (DEBUG_MU)
            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                    + ", ProcessRecord.uid = " + app.uid);
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        【10.9 ActiveServices.bumpServiceExecutingLocked 发送SERVICE_TIMEOUT_MSG用来判断是否ANR】
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        【这是服务的首次启动流程,先执行scheduleCreateService,其实到了本地端就是实例化服务类,然后调用了其onCreate方法 】
        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.ensurePackageDexOpt(r.serviceInfo.packageName);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            【执行onCreate()方法 10.10 ActivityThread.scheduleCreateService】
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);

                // Cleanup.
                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                }

                // Retry.
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null));
        }
        【11. 0 服务进入onStartCommand()】
        sendServiceArgsLocked(r, execInFg, true);

        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        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 (from start): " + r);
                stopServiceLocked(r);
            }
        }
    }
10.9 ActiveServices.bumpServiceExecutingLocked 发送SERVICE_TIMEOUT_MSG用来判断是否ANR

没写完,由于最近忙,没有大块时间,后续补上,不好意思

2018月6月11日写,先发出来。

 历史上的今天

  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、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

Android初始化第三方app权限

前言定制项目时要跟第三方应用合作,随着Android权限的收紧,需要APP主动申请需要的权限并让用户选择,但车机项目提醒权限申请这个弹框比较不友好,因此被客户要正文我只是Android系统应用测试开机时启动一个服务,添加需要申请权限的包名。不一定有效,个人笔记,只供参考AskP...

[摘]Android判断顶部Activity的包名等

前言本文摘抄,具体来源看末尾连接,记录于此。好记性不如烂笔头。小结在实际中,发现使用[获取顶层Activity]的第一个方式存在问题,偶尔获取的顶层activity是错误的。正文判断当前是不是桌面 public static boolean isHome(Context con...

重写TextView的setText出现异常问题

前言TextView重写setText(CharSequence text, BufferType type) 时出现如下异常日志(截取部分日志):java.lang.NullPointerException: Attempt to invoke interface method 'int j...

茅盾:白杨礼赞

白杨树实在是不平凡的,我赞美白杨树!当汽车在望不到边际的高原上奔驰,扑入你的视野的,是黄绿错综的一条大毡子;黄的,那是土,未开垦的处女土,几十万年前由伟大的自然力所堆积成功的黄土高原的外壳;绿的呢,是人类劳力战胜自然的成果,是麦田,和风吹送,翻起了一轮一轮的绿波——,这时你会真心佩服昔人所造的两个...

常见的文件头或文件尾十六进制表示

前言最近在加载图片时,由于需要对不同图片使用不同的加载方式,因此需要通过判断图片的类型进行条用不同的接口。因此摘抄于此,以便查阅。正文下面的文件头或文件尾都是用十六进制表示的。JPEG (jpg)文件头:FFD8FF文件尾:FFD9PNG (png)文件头:89504E47文件尾...

新井一二三:图书馆的恋人

我14岁那年,为了准备翌年的高中入学考试,除了上课以外,很多时间都在图书馆里温习。尤其放了暑假,每天一大早就到图书馆门口排队,以便获得里头较安静的座位。有个男同学叫T,每天也一定来图书馆。有时候,我早晨起得晚,差一点就没赶上9点钟图书馆开门的时间。每逢此时T都帮我占个座位。我们邻座学习到中午,一起...