一.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
接口进行交互通信
它们之间的关系如下图所示