一.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
需要特别说明的是,客户进程也同样可以定义服务端,用于交给服务端进程进行回调通知状态转换,这是一种常用方法。
显然,在以后我们碰到客户端使用某种服务的时候,可以采用这种步骤对整个交互过程进行分析
四.ActivityManager与ActvityManagerService 的交互
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接口进行交互通信
它们之间的关系如下图所示
