Android AMS源码分析之结合AIDL分析bindService

初识AMS(ActivityManagerService)

首先提到AMS(ActivityManagerService)我们先来了解一下Android系统的启动流程,以及AMS是什么时候创建的。
Android AMS源码分析之结合AIDL分析bindService_第1张图片
启动到SystemServer这时才会启动一些列的系统服务,其中包括
1.引导服务,例如 ActivityManagerService(AMS)、DeviceIdentifiersPolicyService、 UriGrantsManagerService等
2.核心服务,例如WebViewUpdateService、GpuService、BatteryService等
3.其他服务,例如TelecomLoaderService、AlarmManagerService等

源码分析

接下来我们来分析源码,今天的主要内容是结合之前的AIDL分析bindService,如果不了解AIDL通信可以看下我的这两篇文章AIDL的用法,AIDL原理分析。
下面我们看的源码都是基于Android10.0(29)版本的,AMS这块源码在Android25之后改动还是挺多的,这里需要大家注意一下。接下来我们开始分析源码。

开始我们先看一下下面这个流程图
Android AMS源码分析之结合AIDL分析bindService_第2张图片

然后我们开始看一个例子

    private void bindService() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.***.***","com.**.**.service.**Service"));

        bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected: ");
            myAidl = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myAidl = null;
        }
    };

我们在这里面进行一个bindService操作
我们会跳转到ContextWrapper类中的这个方法

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

这里调用mBase的bindService方法,这里的mBase是一个Context,Context是一个抽象类,他的具体实现方法都在ContextImpl这个类中。
所以执行

    @Override
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
                getUser());
    }

最终返回bindServiceCommon这个方法。这里面有个关键的代码块

            int res = ActivityManager.getService().bindIsolatedService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, instanceName, getOpPackageName(), user.getIdentifier());

首先看ActivityManager.getService()返回的是IActivityManagerSingleton.get()

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

IActivityManagerSingleton又是

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

再补充:

public abstract class Singleton<T> {
    @UnsupportedAppUsage
    private T mInstance;

    protected abstract T create();

    @UnsupportedAppUsage
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

这里的Singleton.get() 方法就是返回的泛型T的类型,也就是IActivityManager

这里的IActivityManager我们看到有没有觉得很眼熟,没错,他就是类似于我们常用的AIDL中的IMyAidlInterface接口,在Android25版本之前,这个接口都是由ActivityManagerNative.java类中的内部类ActivityManagerProxy来实现的,这时候是不是就更加眼熟了。但是在Android26以后,谷歌废弃了ActivityManagerNative这个类,IActivityManager这个接口的实现都更改到ActivityManagerService实现了,所以我们这里也需要到这个类里面找后续的实现。

我们可以轻松的在ActivityManagerService中轻松的找到bindIsolatedService方法的具体实现。
我们只关注几个关键的方法,接下来会走到ActiveServices中的bindServiceLocked()方法。
在这个方法中又会调用关键的bringUpServiceLocked()方法,
在这个方法中,系统会判断你的进程是否存在以及服务是否开启过并根据结果执行不同的操作,
这里我们只分析其中一种情况,剩下的感兴趣大家可以自己去分析源码

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

满足上面两个条件的时候执行mAm.startProcessLocked方法,这里面的方法涉及知识点过多,有兴趣可以自己看看主要是关于ProcessRecord和Zygote来完成一个进程的孵化工作。最终返回给我们里面app可以理解为创建的进程。

接下来我们返回上面继续走上面的流程,执行完成bringUpServiceLocked()方法之后,将继续向下执行requestServiceBindingLocked(),下面我们看看这个方法做了什么。
其中关键代码

            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.getReportedProcState());
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            }

在这里我们要知道r.app.thread,就是我们的ActivityThread这个类,之后我们走到这个方法scheduleBindService(),在ActivityThread里,

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }

注意看这个sendMessage,是不是很眼熟的样子,没错,他就是我们所谓的handler,所以我们可以快速的找到他后面执行的内容

                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

这样我们跳转到这个方法handleBindService(),继续看这里面的关键性代码

                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }

这又回到了ActivityManager.getService(),上文我们知道这个方法最终返回的就是ActivityManagerService,所以我们继续到AMS中,
接连跳转之后,我们会看到以下

try {
    c.conn.connected(r.name, service, false);
}

其中c是ConnectionRecord c ; conn是IServiceConnection conn;
又是熟悉的以字母“I”开头的,刚开始找他并不好找,这时候我们看ServiceConnection这正不是我们在写代码中创建的吗,他们两者是不是有什么关联,

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidl = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myAidl = null;
        }

    };

这样我们返回最开始bindService的时候,会发现确实有一个

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            String instanceName, Handler handler, Executor executor, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;
        ....
        if (mPackageInfo != null) {
            if (executor != null) {
                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
            } else {
                sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
            }

注意这个conn就是我们自己传进来的ServiceConnection啊,他又在这句话中产生了关联

if (executor != null) {
      sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
      sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}

下面我们看看他们是如何绑定的,经过一步步跳转我们会来到这个类LoadedApk
我们会在这里看到

 sd = new ServiceDispatcher(c, context, executor, flags);

return sd.getIServiceConnection();

注意什么这个c依旧是我们的ServiceConnection,sd再执行构造方法时把c赋值给了这个类的成员变量
mConnection,先记住这个点。
最终返回的 sd.getIServiceConnection()我们看看是什么

        IServiceConnection getIServiceConnection() {
            return mIServiceConnection;
        }
       private final ServiceDispatcher.InnerConnection mIServiceConnection;

       private static class InnerConnection extends IServiceConnection.Stub {
           @UnsupportedAppUsage
           final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

           InnerConnection(LoadedApk.ServiceDispatcher sd) {
               mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
           }

        public void connected(ComponentName name, IBinder service, boolean dead)
                    throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service, dead);
                }
            }
        }
        

在这里我们也找到了真正的
IServiceConnection.Stub,是不是又是很眼熟,还是那个stub类,所以我们这这也找到了上文提及的
conneced()方法
这里我们直接点进去就可以了
在这里我们也看到了

mConnection.onServiceConnected(name, service);
mConnection.onServiceDisconnected(name);

这不正是我们代码中所用到的方法吗,
这样我们整个流程就串通了,从一个bindService()操作到最终完成onServiceConnected()真的是跨越了"千山万水",大家可以回头再梳理一下这个流程。这样整个流程就讲述完成了!

大家如果对AMS还有什么问题的话欢迎关注我的微信公众号,我们来一起讨论学习,欢迎你的到来。

Android AMS源码分析之结合AIDL分析bindService_第3张图片

你可能感兴趣的:(java,Android,java,android,aidl)