SystemServer研究报告

本文详细解读了Android SystemServer启动过程,包括SystemServer的启动机制、ActivityManagerService与全局Context的创建以及客户进程如何使用提供的服务。重点分析了跨进程服务交互的原理和流程,包括文件描述符的传递和Binder机制的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.SystemServer的启动

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

1.SystemServer.main

----->System.loadLibrary("android_servers");
----->init1(args);
也就是说加载了 android_servers库,然后运行native的函数 init1init1 对应的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对象是 ServerThreadLooper
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 的抽象方法
ContextImplServiceFetcher 类提供了两个函数,一个是 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
IWallpaperManagerandroid.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 ,即提供从 IBinderIInterface 的转换,根据 IBinder提供的queryLocalInterface 接口查询是否实现了指定的 Interface,如果实现了,那么就返回它自身,否则就返回一个 Proxy实例,并持有这个IBinder实例。整个过程与 native的实现是一样的。Stub对应 BnInterfaceProxy 对应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。我们可以清楚的看到它使用 mRemotetransact 方法发送 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);
cbIWallpaperManagerCallback 类型
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类型,
由此,我们在 kernelbinder.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();//之所以在 AThreadnew 这个实例就是为了让 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








 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值