SystemServer研究报告

.SystemServer的启动

SystemServer 是由 Zygote 启动的进程,它运行 java 代码,在该进程中启动其他的 Java 层服务。 SystemServer 首先从 SystemServer.main 开始
[java code]

1.SystemServer.main

----->System.loadLibrary("android_servers");
----->init1(args);
也就是说加载了 android_servers 库,然后运行 native 的函数 init1 init1 对应的 native 函数是定义在 frameworks/base/services/jni/com_android_server_SystemServer.cpp 文件中的 android_server_SystemServer_init1 ,它调用了 system_init 函数,这个函数定义在 frameworks/base/cmds/system_server/library/system_init.cpp 文件中,从这个文件所在目录中的 Android.mk ,它编译所在模块是 libsystem_server ,该函数定义如下:
extern "C" status_t system_init()
{
    LOGI("Entered system_init()");

    sp<ProcessState> proc(ProcessState::self());

    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p\n", sm.get());

    sp<GrimReaper> grim = new GrimReaper();
    sm->asBinder()->linkToDeath(grim, grim.get(), 0);

    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsurfaceflinger", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the SurfaceFlinger
        SurfaceFlinger::instantiate();//SurfaceFlinger 继承自 BinderService ,它的 instantiate 函数就是把一个 SurfaceFlinger 实例加入到 ServiceManager 中,也就是说它是在当前进程中提供服务,而并没有启动新的进程, BinderService::publishAndJoinThreadPool 则是在一个新的进程上单独运行 SurfaceFlinger ,并运行了用于获取 Binder 消息的线程
    }

    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }

    // And now start the Android runtime.  We have to do this bit
    // of nastiness because the Android runtime initialization requires
    // some of the core system services to already be started.
    // All other servers should just start the Android runtime at
    // the beginning of their processes's main(), before calling
    // the init function.
    LOGI("System server: starting Android runtime.\n");
    AndroidRuntime* runtime = AndroidRuntime::getRuntime();

    LOGI("System server: starting Android services.\n");
    JNIEnv* env = runtime->getJNIEnv();
    if (env == NULL) {
        return UNKNOWN_ERROR;
    }
    jclass clazz = env->FindClass("com/android/server/SystemServer");
    if (clazz == NULL) {
        return UNKNOWN_ERROR;
    }
    jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
    if (methodId == NULL) {
        return UNKNOWN_ERROR;
    }
    // 运行 java 层代码 com.android.server.SystemServer.init2 函数
    env->CallStaticVoidMethod(clazz, methodId);

    LOGI("System server: entering thread pool.\n");
    // 启动接收和发送 Binder 消息的线程
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    LOGI("System server: exiting thread pool.\n");

    return NO_ERROR;
}
SystemServer.init2 函数启动了一个新的线程 ServerThread ,在它的 run 函数中启动了 java 层的各种服务

.ActivityManagerService与全局Context

ServerThread 线程中启动的众多 Java 服务中,我们首先需要关注的是 ActivityManagerService ,因为它生成了全局的 Context
frameworks/base/services/java/com/android/server/SystemServer.java
            context = ActivityManagerService.main(factoryTest);

1.ActivityManagerService.main

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
    public static final Context main(int factoryTest) {
        AThread thr = new AThread();
        thr.start();

        synchronized (thr) {
            while (thr.mService == null) {
                try {
                    thr.wait();
                } catch (InterruptedException e) {
                }
            }
        }

        ActivityManagerService m = thr.mService;
        mSelf = m;
        ActivityThread at = ActivityThread.systemMain();
        mSystemThread = at;
        Context context = at.getSystemContext();
        context.setTheme(android.R.style.Theme_Holo);
        m.mContext = context;
        m.mFactoryTest = factoryTest;
        m.mMainStack = new ActivityStack(m, context, true);
       
        m.mBatteryStatsService.publish(context);
        m.mUsageStatsService.publish(context);
       
        synchronized (thr) {
            thr.mReady = true;
            thr.notifyAll();
        }

        m.startRunning(null, null, null, null);
       
        return context;
    }
AThread 定义如下:
static class AThread extends Thread {
        ActivityManagerService mService;
        boolean mReady = false;

        public AThread() {
            super("ActivityManager");
        }

        public void run() {
            Looper.prepare();

            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);

            ActivityManagerService m = new ActivityManagerService();

            synchronized (this) {
                mService = m;
                notifyAll();
            }

            synchronized (this) {
                while (!mReady) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }

            // For debug builds, log event loop stalls to dropbox for analysis.
            if (StrictMode.conditionallyEnableDebugLogging()) {
                Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
            }

            Looper.loop();
        }
    }
ActivityManagerService.main 中启动了一个 AThread 线程,并且等待它的 mService 变量被设置,
synchronized (thr) {
            while (thr.mService == null) {
                try {
                    thr.wait();
                } catch (InterruptedException e) {
                }
            }
        }
对应的在 AThread 线程中有:
ActivityManagerService m = new ActivityManagerService();

            synchronized (this) {
                mService = m;
                notifyAll();
            }
这里需要说明的有亮点:
1.synchronized 关键字,每个 java 对象都有一个唯一的 monitor ,这个关键字表示获取对象的 monitor
2.wait ,这个方法是 object 类的方法,表示当前线程进入等待,等待这个对象的 notify ,同时会释放这个对象的 monitor
3.notifyAll ,这个方法是 object 类的方法,表示通知所有等待这个对象的线程,退出等待状态
这就是说主线程和新创建的 AThread 线程在进行线程协作,主线程在启动 AThread 线程后,等待它创建 AcvitityManagerService 实例, AThread 线程在创建这个实例后通知主线程继续运行。同样的, AThread 线程会等待主线程设置 mReady 变量,主线程设置该变量后,通知 AThread 线程继续运行,进入消息循环。

2.ActivityThread.systemMain

ActivityManagerService 启动了 AThread 线程之后,会调用 ActivityThread.systemMain 函数,这个函数是运行在主线程的
---->ActivityThread at = ActivityThread.systemMain();
                                   ----->ActivityThread thread = new ActivityThread();
                                   ----->thread.attach(true);
ActivityThread 类其实并不是一个 Thread ,它并不从 Thread 继承,它甚至不创建消息队列,而是使用当前线程的消息队列,它有的是 Handler ,即消息处理能力,从其类成员中可以看到
    final Looper mLooper = Looper.myLooper();
    final H mH = new H();
Looper.myLooper 是直接从当前线程的 TLS 中获取 Looper 对象的,而 H 是继承自 Handler 。由于 ActivityThread.systemMain 函数是运行在 SystemServer.ServerThread.run 方法中,所以它获取的 Looper 对象是 ServerThread Looper
ActivityThread.attach
private void attach(boolean system) {
        sThreadLocal.set(this);// 从这里知道每个线程都有一个 ActivityThread 实例
        mSystemThread = system;// 运行在 SystemServer.ServerThread ActivityThread 实例是 System Thread
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process");
            try {
                mInstrumentation = new Instrumentation();
                ContextImpl context = new ContextImpl();// 创建 ContextImpl 实例
                context.init(getSystemContext().mPackageInfo, null, this);
                Application app = Instrumentation.newApplication(Application.class, context);
                mAllApplications.add(app);
                mInitialApplication = app;
                app.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }
        。。。。。
    }
由于在调用 attach 的时候传入的参数为 true ,所以我们看到创建了 ContextImpl 实例和 Instrumentation 实例,并创建了 Application 实例。
另外需要说明的是, attach 传入参数为 false 的情况如下:
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java 文件中方法
startProcessLocked 调用了如下的方法创建一个新的进程,并在该进程中运行 ActivityThread.main 方法
----->Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, app.info.targetSdkVersion, null);

3.ActivityThread.main

public static void main(String[] args) {
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
在该方法中,创建了 Looper ,创建了 ActivityThread 实例,并调用了它的 attach 方法,从这一点,我们也确认了前面看到的每个线程都有一个 ActivityThread 实例,而所谓的系统线程是运行在 SystemServer.ServerThread 中的 ActivityThread 实例。

这里可以看出,在初始化 ActivityManagerService 的时候,生成了一个新的线程,并设置为系统线程,在使用 startProcess 创建新的进程的时候,进程的 main 函数会生成一个 ActivityThread ,但这个线程不是系统线程

4.ActivityManagerService.startRunning

前面把线程也启动了,消息队列和 Handler 也准备好了,这里显然是启动运行的,它使用了 Intent 启动,后面分析 Intent 的时候会进行分析。

.客户进程是如何使用SystemServer提供的服务的

1.ContextImpl类的创建

ActivityThread.attach 函数中调用了有如下的调用:
         ContextImpl context = new ContextImpl();
         context.init(getSystemContext().mPackageInfo, null, this);
其中 ActivityThread.getSystemContext 定义如下:
public ContextImpl getSystemContext() {
        synchronized (this) {
            if (mSystemContext == null) {
                ContextImpl context =
                    ContextImpl.createSystemContext(this);
                LoadedApk info = new LoadedApk(this, "android", context, null,
                        CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
                context.init(info, null, this);
                context.getResources().updateConfiguration(
                        getConfiguration(), getDisplayMetricsLocked(
                                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));
                mSystemContext = context;
                //Slog.i(TAG, "Created system resources " + context.getResources()
                //        + ": " + context.getResources().getConfiguration());
            }
        }
        return mSystemContext;
    }
在这个方法中我们看到 ContextImpl.createSystemContext 创建了一个 ContextImpl ActivityThread 把它作为 SystemContext ,这个 Context 最后被返回给 SystemServer 作为后续服务的 Context ,那么 Context 的主要功能是什么呢?

2.ContextImpl类的实现

frameworks/base/core/java/android/app/ContextImpl.java
Context 类是一个抽象类,从其注释中,我们可以看到一些说明:
/**
 * Interface to global information about an application environment.  This is
 * an abstract class whose implementation is provided by
 * the Android system.  It
 * allows access to application-specific resources and classes, as well as
 * up-calls for application-level operations such as launching activities,
 * broadcasting and receiving intents, etc.
 */
public abstract class Context
也就是说, Context 主要包含一些和应用程序相关的资源和类,提供了应用环境的全局信息。
ContextImpl 实现了 Context 的抽象方法
ContextImpl ServiceFetcher 类提供了两个函数,一个是 getService ,一个是 createService createService 用于创建 Service ,它是虚方法 , 需要实现, getService 是给外部函数调用用于获取 Service 的。在 ContextImpl 中定义了许多的 ServiceFetcher 静态实例,他们都通过 RegisterService 注册到 SYSTEM_SERVICE_MAP 这个静态变量中,当应用需要使用某个服务的时候,可以调用 Context 的相应 get 函数获取该服务。但是这里的服务,并非是 ServiceManager 中服务,它只是服务的客户端,服务运行在 SystemServer 进程中,他们运行在不同的进程,通过 Binder 通信
我们以 wallpager 为例,看看这个过程是如何实现的
ContextImpl.java
    private static ServiceFetcher WALLPAPER_FETCHER = new ServiceFetcher() {
            public Object createService(ContextImpl ctx) {
                return new WallpaperManager(ctx.getOuterContext(),
                        ctx.mMainThread.getHandler());
            }};
...
         registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
...
    private WallpaperManager getWallpaperManager() {
        return (WallpaperManager) WALLPAPER_FETCHER.getService(this);
    }
从这里我们看到创建 WallPaperManager 实例的时候, ContextImpl 实例中已经具有了创建该实例所需要的一切信息。
下面我们来看看得到 WallPaperManager 实例后,该实例是如何提供服务的
frameworks/base/core/java/android/app/WallpaperManager.java
/*package*/ WallpaperManager(Context context, Handler handler) {
        mContext = context;
        initGlobals(context.getMainLooper());
    }
    static void initGlobals(Looper looper) {
        synchronized (sSync) {
            if (sGlobals == null) {
                sGlobals = new Globals(looper);
            }
        }
          static class Globals extends IWallpaperManagerCallback.Stub {
        private IWallpaperManager mService;
        private Bitmap mWallpaper;
        private Bitmap mDefaultWallpaper;
       
        private static final int MSG_CLEAR_WALLPAPER = 1;
       
        private final Handler mHandler;
       
        Globals(Looper looper) {
            IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
            mService = IWallpaperManager.Stub.asInterface(b);
            mHandler = new Handler(looper) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case MSG_CLEAR_WALLPAPER:
                            synchronized (this) {
                                mWallpaper = null;
                                mDefaultWallpaper = null;
                            }
                            break;
                    }
                }
            };
        }
WallPaperManager 类从构造函数,一路调用到创建 Global 实例,在 Global 类的构造函数中首先通过 ServiceManager.getService 方法得到了 WallPaperService IBinder ,即客户端实例。从 native 角度看,它是一个 BpBinder ,它经过 IWallpaperManager.Stub.asInterface 转换后得到了 IWallpaperManager 实例,这是一个接口类从 android.os.IInterface 继承,从 Binder 的知识,我们知道这个接口定义了服务的接口,客户端和服务器端分别实现了这个接口。
我们来研究一下 IWallpaperManager 这个类
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/app/IWallpaperManager.java
public interface IWallpaperManager extends android.os.IInterface
public static abstract class Stub extends android.os.Binder implements android.app.IWallpaperManager
private static class Proxy implements android.app.IWallpaperManager
IWallpaperManager android.os.IInterface 继承而来,显然它是一个接口,它定义了一个内部类 Stub ,它从 android.os.Binder 继承,并实现了 android.app.IWallpaperManager 接口,也就是说 Stub 是一个 BBinder ,是一个服务器端;
同时,在 Stub 中还有一个 Proxy 类,它也实现了 android.app.IWallpaperManager 接口,它的构造函数的参数是 IBinder ,显然它是一个客户端。
android.app.IWallpaperManager.Stub 还提供了一个 asInterface 的函数,该函数的作用类似于 IInterface.h 中的 asInterface ,即提供从 IBinder IInterface 的转换,根据 IBinder 提供的 queryLocalInterface 接口查询是否实现了指定的 Interface ,如果实现了,那么就返回它自身,否则就返回一个 Proxy 实例,并持有这个 IBinder 实例。整个过程与 native 的实现是一样的。 Stub 对应 BnInterface Proxy 对应 BpInterface
public static android.app.IWallpaperManager asInterface(android.os.IBinder obj)
{
         if ((obj==null)) {
                   return null;
         }
         android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
         if (((iin!=null)&&(iin instanceof android.app.IWallpaperManager))) {
                   return ((android.app.IWallpaperManager)iin);
         }
         return new android.app.IWallpaperManager.Stub.Proxy(obj);
}
再来看 Globals 的构造函数,
mService = IWallpaperManager.Stub.asInterface(b);
b 是一个 BpBinder asInterface 之后,得到的实际上是一个 Proxy 实例,它持有这个 BpBinder ,同时这个 Proxy 实例实现了 IWallpaperManager 接口,所以在用户调用这个接口的某项服务的时候, Proxy 会使用它持有的 BpBinder 实例与服务器端通信获得服务
我们看看从客户端角度,是如何使用这个 Service 提供的服务的
WallpaperManager.java 中,我们可以看到调用 getWallpaper 的过程
static class Globals extends IWallpaperManagerCallback.Stub {
....
private Bitmap getCurrentWallpaperLocked() {
            try {
                Bundle params = new Bundle();
                ParcelFileDescriptor fd = mService.getWallpaper(this, params);
                if (fd != null) {
                    int width = params.getInt("width", 0);
                    int height = params.getInt("height", 0);

                    try {
                        BitmapFactory.Options options = new BitmapFactory.Options();
                        Bitmap bm = BitmapFactory.decodeFileDescriptor(
                                fd.getFileDescriptor(), null, options);
                        return generateBitmap(bm, width, height);
                    } catch (OutOfMemoryError e) {
                        Log.w(TAG, "Can't decode file", e);
                    } finally {
                        try {
                            fd.close();
                        } catch (IOException e) {
                            // Ignore
                        }
                    }
                }
            } catch (RemoteException e) {
                // Ignore
            }
            return null;
        }
.....
}
这个方法是属于 Globals 的,所以其中的 this ,是一个 Globals 实例,
         ParcelFileDescriptor fd = mService.getWallpaper(this, params);
getWallpaper 的参数需要一个 IWallpaperManagerCallback 类型匹配的,从 Globals 实例的定义我们知道它继承自 IWallpaperManagerCallback.Stub ,这与调用的参数是匹配的。
下面我们看看在 IWallPaperManager.java 中, getWallPaper 是如何实现的
public android.os.ParcelFileDescriptor getWallpaper(android.app.IWallpaperManagerCallback cb, android.os.Bundle outParams) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.os.ParcelFileDescriptor _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_getWallpaper, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
if ((0!=_reply.readInt())) {
outParams.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
这个 getWallPaper 方法是 Proxy 中的一个方法,其功能应该是从服务器端获得 WallPaper 。我们可以清楚的看到它使用 mRemote transact 方法发送 data 参数,并返回 reply 结果,一如我们在 native 中使用的那样。这里比较特别的就是 data 参数使用 writeStrongBinder 把参数 cb 作为 Binder 写入,这个过程我们似曾相识,就是我们在 native 中注册服务的时候。
那么 IWallpaperManagerCallback 又是干什么的呢?我们还是需要从 IWallpaperManager.Stub.Proxy.getWallpaper 函数看起,
_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_getWallpaper, _data, _reply, 0);
cb IWallpaperManagerCallback 类型
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/app/IWallpaperManagerCallback.java
这个接口文件的布局与 IWallpaperManager.java 是相似的,也有一个 Stub ,一个 Proxy ,分别表示服务器端和客户端,这个接口提供的功能也比较简单,就是提供了 onWallpaperChanged 方法。
这里的 cb ,显然就是 Globals 实例,由于它从 Binder 继承,它同时也是一个服务器端, asBinder 将得到 BBinder ,通过 Binder 的知识,我们知道 Binder 实例在作为参数进行传递的时候,其类型会被改写,这个 BBinder 将会变为 BpBinder
根据客户端的 transact 方法使用的 status Stub.TRANSACTION_getWallpaper ,我们马上就能找到 IWallpaperManager.Stub.onTransact 中的相应代码如下:
case TRANSACTION_getWallpaper:
{
data.enforceInterface(DESCRIPTOR);
android.app.IWallpaperManagerCallback _arg0;
_arg0 = android.app.IWallpaperManagerCallback.Stub.asInterface(data.readStrongBinder());
android.os.Bundle _arg1;
_arg1 = new android.os.Bundle();
android.os.ParcelFileDescriptor _result = this.getWallpaper(_arg0, _arg1);
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
if ((_arg1!=null)) {
reply.writeInt(1);
_arg1.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
其中 _arg0 = android.app.IWallpaperManagerCallback.Stub.asInterface(data.readStrongBinder()); 这里得到的 Binder 已经是一个 BpBinder ,即经过转换后得到的是一个 android.app.IWallpaperManagerCallback.Stub.Proxy 实例
android.os.ParcelFileDescriptor _result = this.getWallpaper(_arg0, _arg1); 这里的 this 是什么类型的实例呢,也就是提供服务的类是什么呢,它是 WallpaperManagerService 实例,该类定义在
frameworks/base/services/java/com/android/server/WallpaperManagerService.java
class WallpaperManagerService extends IWallpaperManager.Stub
从类定义中,我们知道它是一个服务端
SystemServer.java 中,我们可以看到它是如何注册称为服务的
                wallpaper = new WallpaperManagerService(context);
                ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
该类的 getWallpaper 方法如下,它把 cb 注册到一个列表中
public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
            Bundle outParams) {
        synchronized (mLock) {
            try {
                if (outParams != null) {
                    outParams.putInt("width", mWidth);
                    outParams.putInt("height", mHeight);
                }
                mCallbacks.register(cb);
                File f = WALLPAPER_FILE;
                if (!f.exists()) {
                    return null;
                }
                return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
            } catch (FileNotFoundException e) {
                /* Shouldn't happen as we check to see if the file exists */
                Slog.w(TAG, "Error getting wallpaper", e);
            }
            return null;
        }
    }
在发生变化的时候,会产生回调
private void notifyCallbacksLocked() {
        final int n = mCallbacks.beginBroadcast();
        for (int i = 0; i < n; i++) {
            try {
                mCallbacks.getBroadcastItem(i).onWallpaperChanged();
            } catch (RemoteException e) {

                // The RemoteCallbackList will take care of removing
                // the dead object for us.
            }
        }
        mCallbacks.finishBroadcast();
        final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
        mContext.sendBroadcast(intent);
    }
这里的 mCallbacks.getBroadcastItem(i).onWallpaperChanged(); 显然 mCallbacks.getBroadcastItem(i) 得到的就是一个 Proxy 实例,调用这个 Proxy 实例的 onWallpaperChanged 方法,将与其服务器端进行通信,其服务器端就是 Globals 实例。显然,这是一个跨进程的回调。
至此,我们对于 WallpaperService 的分析结束,总体来说,在 Context 中,通过 getWallpaperManager 的形式,得到了 WallPaperService 的客户端,然后与 WallPaperService 进行通信。

3.Binder传递Fd的问题

顺带有一个奇怪的问题,在上述的 IWallpaperManager.java 中的服务器端代码中,
android.os.ParcelFileDescriptor _result = this.getWallpaper(_arg0, _arg1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
这里的 this 就是 WallpaperService ,它的 getWallpaper 方法
return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
ParcelFileDescriptor 类是对文件描述符的封装。也就是说这返回了一个文件描述符
奇怪的地方在于, reply 就是返回给客户端的值,但是它里面包括的却是在服务器端进程得到的 fd ,我们知道不同进程上的 fd 是不同的,它们代表了不同的文件。这样看来不是很奇怪么?我们来看 result.writeToParcel 这个函数。
ParcelFileDescriptor.writeToParcel 函数
    public void writeToParcel(Parcel out, int flags) {
        out.writeFileDescriptor(mFileDescriptor);
        if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
            try {
                close();
            } catch (IOException e) {
                // Empty
            }
        }
    }
Parcel.writeFileDescriptor 函数是一个 native 函数,它对应 frameworks/base/core/jni/android_util_Binder.cpp 文件中的 android_os_Parcel_writeFileDescriptor 函数
static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
{
    Parcel* parcel = parcelForJavaObject(env, clazz);
    if (parcel != NULL) {
        const status_t err =
                parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}
frameworks/base/libs/binder/Parcel.cpp 中的
status_t Parcel::writeDupFileDescriptor(int fd)
{
    return writeFileDescriptor(dup(fd), true /*takeOwnership*/);
}
status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
{
    flat_binder_object obj;
    obj.type = BINDER_TYPE_FD;
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    obj.handle = fd;
    obj.cookie = (void*) (takeOwnership ? 1 : 0);
    return writeObject(obj, true);
}
至此,我们看出来点眉目了,这里在序列化 FileDescriptor 的时候,使用了 BINDER_TYPE_FD 类型,我们在分析 binder 的时候,在进程间传递 binder 的时候,也会使用 binder 类型,
由此,我们在 kernel binder.c 中的 binder_transaction 函数中,找到如下的代码:
case BINDER_TYPE_FD: {
            int target_fd;
            struct file *file;

            if (reply) {
                if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
                    binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
                        proc->pid, thread->pid, fp->handle);
                    return_error = BR_FAILED_REPLY;
                    goto err_fd_not_allowed;
                }
            } else if (!target_node->accept_fds) {
                binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
                    proc->pid, thread->pid, fp->handle);
                return_error = BR_FAILED_REPLY;
                goto err_fd_not_allowed;
            }

            file = fget(fp->handle);
            if (file == NULL) {
                binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
                    proc->pid, thread->pid, fp->handle);
                return_error = BR_FAILED_REPLY;
                goto err_fget_failed;
            }
            target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);// 这里从 target_proc ,也就是我们的目标进程中得到一个 fd
            if (target_fd < 0) {
                fput(file);
#ifdef BINDER_MONITOR
                binder_user_error("binder: %d:%d no unused fd available, %d\n",
                    proc->pid, thread->pid, target_fd);
#endif
                return_error = BR_FAILED_REPLY;
                goto err_get_unused_fd_failed;
            }
            task_fd_install(target_proc, target_fd, file);// 把新得到的 fd 与指定的 file 关联起来
            binder_debug(BINDER_DEBUG_TRANSACTION,
                     "        fd %ld -> %d\n", fp->handle, target_fd);
            /* TODO: fput? */
            fp->handle = target_fd;// 把新的 fd 设置给 handle
        } break;
原来在 kernel 中在目标进程中打开了这个文件,最后返回给我们的文件描述符就是这个 fd 了,我们的疑问也得到了解答,原来不仅 binder 会被转换,文件描述符也会被转换,在以后的分析中,我们多次会碰到文件描述符被转换的情况。

.分析客户进程与其服务交互的一般步骤

我们重新回顾一下分析 WallPaper 的过程
首先,我们从 ContextImpl 中得到了 WallPaperManager 类,它实际上是对 WallPaper 服务的客户端的封装
其次,我们从 WallPaperManager 中得到了它的服务实现的接口 IWallpaperManager ,继而找到了它的服务器端必定是实现了 IWallpaperManager.Stub 的类,它的客户端必定是通过 asInterface 转换后的 IWallpaperManager 实例,其中参数 Binder 来自于 ServerManager.getService
再次,我们在 SystemServer 中找到了注册称为服务的 WallpaperManagerService 类,它继承自 IWallpaperManager.Stub
需要特别说明的是,客户进程也同样可以定义服务端,用于交给服务端进程进行回调通知状态转换,这是一种常用方法。
显然,在以后我们碰到客户端使用某种服务的时候,可以采用这种步骤对整个交互过程进行分析

.ActivityManagerActvityManagerService 的交互

1.ActivityManagerService.AThread

AThread 中创建了 ActivityManagerService 实例之后,该线程进入到消息循环中, ActivityManagerService 实例继承自 ActivityManagerNative ,它有一个 Handler 实例, Handler 类的构造函数中直接获取了当前线程的 Looper 作为其默认的消息队列,也就是说 ActivityManagerService 与当前线程 AThread 的消息队列绑定了,也就是说 ActvityManagerService 是通过 AThread 线程提供服务的。
----->AThread thr = new AThread();
                                      ----->run()
                                                  ActivityManagerService m = new ActivityManagerService();// 之所以在 AThread new 这个实例就是为了让 ActivityManagerService 实例中的 handler 与线程的 looper 绑定起来
        thr.start();

那么客户端是如何使用 ActvityManagerService 的呢?
frameworks/base/core/java/android/app/ContextImpl.java
        registerService(ACTIVITY_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
                }});
同时在该文件中有如下的函数:
public Object getSystemService(String name) {
        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
        return fetcher == null ? null : fetcher.getService(this);
    }
也就是说通过 getSystemService("activity") 可以得到 ActivityManager 实例,那么这个实例又是如何与 ActivityManagerService 通信的呢
frameworks/base/core/java/android/app/ActivityManager.java
在这个文件中我们可以知道它实际上是个代理类,它的功能都是通过 ActivityManagerNative.getDefault() 完成的。
frameworks/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
看到这个类我们就知道它用于在服务器端提供服务,同时在该文件中,还定义了 ActivityManagerProxy 类,它是提供客户端功能的,但是实际上我们知道,它并不出现在代码中,而是通过 asInterface ,把从 getService 中得到的 IBinder 转换得到的。但是似乎这个 Proxy 类并没有使用过,而是通过 getDefault 方法获取客户端实例的,其代码如下:
ActivityManagerNative 类中有
static public IActivityManager getDefault() {
        return gDefault.get();
    }
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
显然这里通过 getDefault 得到的就是一个客户端 Binder
同时,我们也应该注意到在 ActivityManagerService 类的定义为
public final class ActivityManagerService extends ActivityManagerNative
也就是说它是一个服务器端代码,这与我们对与 Binder 的认识是一致的。这样,通过 ActivityManager 类封装了对 ActivityManagerService 类的客户端请求,通过 IActivityManager 接口进行交互通信
它们之间的关系如下图所示
graphic








 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值