一、Service 开启和停止
二、Service 执行耗时工作
三、IPC常用方式
四、AIDL(一)同一应用中使用AIDL及原理
五、AIDL(二)不同应用中使用、自定义数据类型及定向Tag
六、AIDL(三)实现回调
七、AIDL(四)获取服务及绑定和Binder传递流程
AIDL(四)获取服务及绑定和Binder传递流程
7.1 获取系统服务
7.1.1 从简单例子 BatteryManager 开始
BatteryManager batteryManager = (BatteryManager) getSystemService(Context.BATTERY_SERVICE);
Log.d(TAG, "Battery is charging: "+String.valueOf(batteryManager.isCharging()));
调用Context
的getSystemService(Context.BATTERY_SERVICE)
方法,最终获取BatteryManager
,拿到BatteryManager
引用后,就可以调用相应的方法,获取电池的相关状态了。我们继续沿着调用分析:
代码1
frameworks\base\core\java\android\app\ContextImpl.java
@Override
public Object getSystemService(String name) {
if (vmIncorrectContextUseEnabled()) {
// Check incorrect Context usage.
if (WINDOW_SERVICE.equals(name) && !isUiContext()) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
+ " from a non-visual Context:" + getOuterContext();
final String message = "WindowManager should be accessed from Activity or other "
+ "visual Context. Use an Activity or a Context created with "
+ "Context#createWindowContext(int, Bundle), which are adjusted to "
+ "the configuration and visual bounds of an area on screen.";
final Exception exception = new IllegalAccessException(errorMessage);
StrictMode.onIncorrectContextUsed(message, exception);
Log.e(TAG, errorMessage + " " + message, exception);
}
}
return SystemServiceRegistry.getSystemService(this, name);
}
最后调用SystemServiceRegistry.getSystemService
代码2
frameworks\base\core\java\android\app\SystemServiceRegistry.java
/**
* Gets a system service from a given context.
* @hide
*/
public static Object getSystemService(ContextImpl ctx, String name) {
if (name == null) {
return null;
}
final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); // 从 map 中获取键值
if (fetcher == null) {
if (sEnableServiceNotFoundWtf) {
Slog.wtf(TAG, "Unknown manager requested: " + name);
}
return null;
}
final Object ret = fetcher.getService(ctx);
if (sEnableServiceNotFoundWtf && ret == null) {
// Some services do return null in certain situations, so don't do WTF for them.
switch (name) {
case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
case Context.APP_PREDICTION_SERVICE:
case Context.INCREMENTAL_SERVICE:
case Context.ETHERNET_SERVICE:
case Context.CONTEXTHUB_SERVICE:
case Context.VIRTUALIZATION_SERVICE:
case Context.VIRTUAL_DEVICE_SERVICE:
return null;
}
Slog.wtf(TAG, "Manager wrapper not available: " + name);
return null;
}
return ret;
}
那SYSTEM_SERVICE_FETCHERS
是从哪里来的呢?继续分析,发现在SystemServiceRegistry
静态代码块中,有着注册服务的代码,如下:
代码3
frameworks\base\core\java\android\app\SystemServiceRegistry.java
static {
//CHECKSTYLE:OFF IndentationCheck
registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
new CachedServiceFetcher<AccessibilityManager>() {
@Override
public AccessibilityManager createService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}});
registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
new CachedServiceFetcher<CaptioningManager>() {
@Override
public CaptioningManager createService(ContextImpl ctx) {
return new CaptioningManager(ctx);
}});
......
registerService(Context.BATTERY_SERVICE, BatteryManager.class,
new CachedServiceFetcher<BatteryManager>() {
@Override
public BatteryManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBatteryStats stats = IBatteryStats.Stub.asInterface(
ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME));
IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub
.asInterface(ServiceManager.getServiceOrThrow("batteryproperties"));
return new BatteryManager(ctx, stats, registrar);
}});
......
}
里面注册了各种服务,看到我们的目标BatteryManager
,创建BatteryManager
时,获取了IBatteryStats
和IBatteryPropertiesRegistrar
两个Proxy Binder
,我们示例代码batteryManager.isCharging()
其实调用的就是IBatteryStats
中的isCharging
,IBatteryStats.aidl
路径为:frameworks\base\core\java\com\android\internal\app\IBatteryStats.aidl
。
通过上面的分析可以知道,IBatteryStats
是客户端的Proxy Binder
,客户端调用其提供的方法,实现相应的功能。这次通信中,客户端是当前使用BatteryManager
的进程,服务端为提供ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME) Binder
的进程。那么,IBatteryStats.Stub.asInterface(android.os.IBinder obj)
中 IBinder
如何得来?
7.1.2 asInterface中IBinder
ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME)
获取IBinder
,代码如下:
代码4
frameworks\base\core\java\android\os\ServiceManager.java
/**
* Returns a reference to a service with the given name, or throws
* {@link ServiceNotFoundException} if none is found.
*
* @hide
*/
public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
final IBinder binder = getService(name);
if (binder != null) {
return binder;
} else {
throw new ServiceNotFoundException(name);
}
}
/**
* Returns a reference to a service with the given name.
*
* @param name the name of the service to get
* @return a reference to the service, or <code>null</code> if the service doesn't exist
* @hide
*/
@UnsupportedAppUsage
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return Binder.allowBlocking(rawGetService(name));
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
private static IBinder rawGetService(String name) throws RemoteException {
......
final IBinder binder = getIServiceManager().getService(name);
......
return binder;
}
@UnsupportedAppUsage
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
又是典型的Binder
使用场景,sServiceManager
是ServiceManager
提供的Proxy Binder
,通过该接口中getService
获取目标服务的Binder
引用。BinderInternal.getContextObject()
是获取ServiceManager Binder
需要的Binder
。
Client
需要从ServiceManager
获取电池服务的IBinder
,而Client
本身需要和ServiceManager
通信,要通信就需要IBinder
。BinderInternal.getContextObject())
就是为了获取ServiceManager
的IBinder
,该方法从Binder
驱动获取了IBinder
引用。
7.1.3 注册服务
ServiceManager
是如何找到BatteryStatsService
服务的呢?Android
启动后,会开启system_server
进程,该进程会开启很多系统服务,比如:BattertService、AWS、WMS
等,因为BatteryStatsService
会随着ActivityManagerService
一起启动,在ActivityManagerService
的start
函数中:
代码5
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
private void start() {
mBatteryStatsService.publish(); // 注释1
mAppOpsService.publish();
mProcessStats.publish();
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, mInternal);
LocalManagerRegistry.addManager(ActivityManagerLocal.class,
(ActivityManagerLocal) mInternal);
mActivityTaskManager.onActivityManagerInternalAdded();
mPendingIntentController.onActivityManagerInternalAdded();
mAppProfiler.onActivityManagerInternalAdded();
CriticalEventLog.init();
}
注释1中,BatteryStatsService
将自己发布,发布的代码如下:
代码6
frameworks\base\services\core\java\com\android\server\am\BatteryStatsService.java
public void publish() {
LocalServices.addService(BatteryStatsInternal.class, new LocalService());
ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); // 注释1
}
上述注释1代码中,调用ServiceManager
的addService
将服务添加到ServiceManager
里。
7.1.4 总结
图中,Client
、ServiceManager
、SystemServer
和BatteryStatsService
分别运行于四个不同进程,Client
、ServiceManager
、SystemServer
和BatteryStatsService
之间通过Binder
进行通信。
- 在
SystemServer
中启动和发布BatteryStatsService
,使其运行并注册至ServiceManager
中; SystemServer
通过BinderInternal.getContextObject()
向ServiceManager
注册服务IBinder ISErviceManager
;Client
通过BatteryStatsService
向Client
注册IBatteryStats
服务;Client
拿到服务后,通过调用具体函数使用服务提供的具体功能;
7.2 客户端获取服务端Binder
流程
7.2.1 Service 的绑定流程
上面我们都知道,系统服务会注册到ServiceManager
里供后来者查询使用。那,我们自己自定义的服务是如何获得的呢?
一个典型的绑定服务流程中,服务端代码如下:
代码7
com.ieening.server.StudentService
public class StudentService extends Service {
......
public StudentService() {
}
private final IStudentInfo.Stub studentInfoBinder = new IStudentInfo.Stub() { // 注释1
@Override
public Student getStudentInfo() {
return student;
}
@Override
public void register(ScoreChangedCallback callback) {
remoteCallback = callback;
}
};
......
@Override
public IBinder onBind(Intent intent) { // 注释2
return studentInfoBinder;
}
}
客户端代码如下:
代码8
com.ieening.androidipccallback.MainActivity
public class MainActivity extends AppCompatActivity {
......
private IStudentInfo studentServiceRemoteBinder = null;
......
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
studentServiceRemoteBinder = IStudentInfo.Stub.asInterface(service); // 注释3
try {
studentServiceRemoteBinder.register(new ScoreChangedCallback.Stub() {
@Override
public void onCallback(Student student) {
//在子线程中创建一个消息对象
Message studentInfoMessage = new Message();
studentInfoMessage.what = 1;
Bundle bundle = new Bundle();
bundle.putParcelable("student", student);
studentInfoMessage.setData(bundle);
//将该消息放入主线程的消息队列中
studentInfoHandler.sendMessage(studentInfoMessage);
}
});
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
studentServiceRemoteBinder = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setBindUnbindButtonOnClickListener();
binding.getStudentInfoButton.setOnClickListener(v -> {
try {
binding.studentInfoEditText.setText(studentServiceRemoteBinder.getStudentInfo().toString()); // 注释4
} catch (RemoteException e) {
throw new RuntimeException(e);
}
});
}
private void setBindUnbindButtonOnClickListener() {
binding.bindStudentServiceButton.setOnClickListener(v -> {
Intent bindIntent = new Intent(this, StudentService.class);
boolean bindResult = bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
if (bindResult) {
binding.bindStudentServiceButton.setEnabled(false);
binding.unbindStudentServiceButton.setEnabled(true);
binding.getStudentInfoButton.setEnabled(true);
Toast.makeText(this, "bind student service success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "bind student service failed", Toast.LENGTH_SHORT).show();
}
});
binding.unbindStudentServiceButton.setOnClickListener(v -> {
unbindService(serviceConnection);
binding.bindStudentServiceButton.setEnabled(true);
binding.unbindStudentServiceButton.setEnabled(false);
binding.getStudentInfoButton.setEnabled(false);
});
}
......
}
客户端和服务端代码中,上述的流程,大致如下:
- 注释1:
Service
构造Binder
对象; - 注释2:在
onBind
函数中,将Binder
传递出去; - 注释3:客户端在绑定
Service
成功后,会收到服务端传递过来的IBInder service
; - 注释4:通过传递过来的
IBinder
获取关联的接口与服务端通信;
所以,在服务端,我们在Service
中,定义了业务逻辑(服务端),并开放了接口,然后通过Service
的绑定功能将IBinder
传递给客户端。这样的逻辑和系统服务的逻辑是一样的,核心是IBInder
的传递。
7.2.2 传递IBinder
7.2.2.1 bindServiceCommon
在ContextImpl
中运行bindService
,最终会调用bindServiceCommon
函数。如下代码所示,在bindServiceCommon
内会将conn
封装在ServiceDispatcher
内。
代码9
frameworks\base\core\java\android\app\ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, long flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser and
// ActivityManagerLocal.bindSdkSandboxService
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (handler != null && executor != null) {
throw new IllegalArgumentException("Handler and Executor both supplied");
}
if (mPackageInfo != null) {
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); // 注释1
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
} else {
throw new RuntimeException("Not supported in system context");
}
......
}
注释1中,在ServiceDispatcher
内,持有InnerConnection
,而InnerConnection
继承自IServiceConnection.Stub
,可以跨进程调用,换句话说,客户端进程内,留下了一个IServiceConnection.Stub
的桩,而且可以跨进程调用。在IServiceConnection.Stub
内connected
函数,最终会调用ServiceConnection
的onServiceDisconnected
和onServiceConnected
函数。
代码10
frameworks\base\core\java\android\app\LoadedApk.java
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
Context context, Handler handler, Executor executor, long flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
if (executor != null) {
sd = new ServiceDispatcher(c, context, executor, flags);
} else {
sd = new ServiceDispatcher(c, context, handler, flags);
}
if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler, executor);
}
return sd.getIServiceConnection();
}
}
......
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private final ServiceConnection mConnection;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final Context mContext;
private final Handler mActivityThread;
private final Executor mActivityExecutor;
private final ServiceConnectionLeaked mLocation;
private final long mFlags;
private RuntimeException mUnbindLocation;
private boolean mForgotten;
private static class ConnectionInfo {
IBinder binder;
IBinder.DeathRecipient deathMonitor;
}
private static class InnerConnection extends IServiceConnection.Stub {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
= new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
......
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
......
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
if (mForgotten) {
// We unbound before receiving the connection; ignore
// any connection received.
return;
}
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
if (service != null) {
// A new service is being connected... set it all up.
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
service.linkToDeath(info.deathMonitor, 0);
mActiveConnections.put(name, info);
} catch (RemoteException e) {
// This service was dead before we got it... just
// don't do anything with it.
mActiveConnections.remove(name);
return;
}
} else {
// The named service is being disconnected... clean up.
mActiveConnections.remove(name);
}
if (old != null) {
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
}
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
} else {
// If there is a new viable service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
}
public void doDeath(ComponentName name, IBinder service) {
synchronized (this) {
ConnectionInfo old = mActiveConnections.get(name);
if (old == null || old.binder != service) {
// Death for someone different than who we last
// reported... just ignore it.
return;
}
mActiveConnections.remove(name);
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
mConnection.onServiceDisconnected(name);
}
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
......
}
7.2.2.2 返回服务端IBinder
引用
在ContextImpl.bindServiceCommon
函数内调用ActivityManager.getService().bindServiceInstance
函数。
代码11
frameworks\base\core\java\android\app\ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, long flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
......
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
int res = ActivityManager.getService().bindServiceInstance(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
其中ActivityManager.getService()
获取IActivityManager.Stub Binder
,ActivityServiceManager
继承了IActivityManager.Stub
类,所以,这里有一个IPC
通信,最终调用ActivityServiceManager.bindServiceInstance
函数。
代码12
frameworks\base\core\java\android\app\ActivityManager.java
@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
......
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
在bindServiceInstance
函数内,最后调用ActiveServices.bindServiceLocked
函数。在函数ActiveServices.bindServiceLocked
内,调用ActiveServices.requestServiceBindingLocked
函数,requestServiceBindingLocked
代码如下:
代码13
frameworks\base\services\core\java\com\android\server\am\ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.getThread() == null) {
// If service is not currently running, can't yet bind.
return false;
}
if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
+ " rebind=" + rebind);
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind", OOM_ADJ_REASON_BIND_SERVICE);
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestServiceBinding="
+ i.intent.getIntent() + ". bindSeq=" + mBindServiceSeqCounter);
}
// 注释1
r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.mState.getReportedProcState(), mBindServiceSeqCounter++);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
// Keep the executeNesting count accurate.
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying, false,
OOM_ADJ_REASON_UNBIND_SERVICE);
throw e;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying, false,
OOM_ADJ_REASON_UNBIND_SERVICE);
return false;
}
}
return true;
}
在注释1处,r.app.getThread()
是ApplicationThread
,ApplicationThread
继承了IApplicationThread.Stub
,所以,r.app.getThread().scheduleBindService
调用的是ActivityThread.ApplicationThread.scheduleBindService
函数。
代码14
frameworks\base\core\java\android\app\ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
......
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState, long bindSeq) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
s.bindSeq = bindSeq;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
....
}
......
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
......
case BIND_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind: "
+ String.valueOf(msg.obj));
}
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
......
}
......
}
......
private void handleBindService(BindServiceData data) {
CreateServiceData createData = mServicesData.get(data.token);
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent); // 注释1
ActivityManager.getService().publishService( // 注释2
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
......
}
注释1中调用服务端的onBind
函数,并返回服务端的IBinder
引用。
7.2.2.3 发布服务端BInder
在调用onBind
后返回服务端IBinder
随后调用ActivityManager.getService().publishService(data.token, data.intent, binder)
,委托AWS
发布IBinder
,代码如下:
代码15
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
mServices.publishServiceLocked
调用ActiveServices
中publishServiceLocked
函数。最终在注释1中调用c.conn.connected(clientSideComponentName, service, false)
完成服务绑定。
代码16
frameworks\base\services\core\java\com\android\server\am\ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
+ " " + intent + ": " + service);
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Published intent: " + intent);
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
// If what the client try to start/connect was an alias, then we need to
// pass the alias component name instead to the client.
final ComponentName clientSideComponentName =
c.aliasComponent != null ? c.aliasComponent : r.name;
try {
c.conn.connected(clientSideComponentName, service, false); // 注释1
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false,
OOM_ADJ_REASON_EXECUTING_SERVICE);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
7.2.2.5 总结
7.2.3 Binder序列化
我们知道,服务端返回的是IBinder
,但是客户端接收到的IBinder
却是BinderProxy
,这是怎么一回事呢?
IBinder
支持进程间传递,但是却没有实现Parcelable
接口,那它是如何支持序列化的呢?
7.2.3.1 IBinder如何序列化
分析Parcel.java
发现,Parcel
除了基本数据类型,还有writeStrongBinder
和readStrongBinder
。
代码17
frameworks\base\core\java\android\os\Parcel.java
/**
* Write an integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeInt(int val) {
int err = nativeWriteInt(mNativePtr, val);
if (err != OK) {
nativeSignalExceptionForError(err);
}
}
......
/**
* Write an object into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
......
/**
* Read an integer value from the parcel at the current dataPosition().
*/
public final int readInt() {
return nativeReadInt(mNativePtr);
}
......
/**
* Read an object from the parcel at the current dataPosition().
*/
public final IBinder readStrongBinder() {
final IBinder result = nativeReadStrongBinder(mNativePtr);
// If it's a reply from a method with @PropagateAllowBlocking, then inherit allow-blocking
// from the object that returned it.
if (result != null && hasFlags(
FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT | FLAG_PROPAGATE_ALLOW_BLOCKING)) {
Binder.allowBlocking(result);
}
return result;
}
所以说,虽然没有实现Parcelable
,但是Parcel
内支持了IBinder
,接着看其native
方法。
代码18
frameworks\base\core\jni\android_os_Parcel.cpp
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
7.2.3.2 writeStrongBinder
代码19
frameworks\native\libs\binder\Parcel.cpp
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flattenBinder(val); // 注释1
}
status_t Parcel::flattenBinder(const sp<IBinder>& binder) {
BBinder* local = nullptr;
if (binder) local = binder->localBinder();
if (local) local->setParceled();
......
#ifdef BINDER_WITH_KERNEL_IPC
flat_binder_object obj;
int schedBits = 0;
if (!IPCThreadState::self()->backgroundSchedulingDisabled()) {
schedBits = schedPolicyMask(SCHED_NORMAL, 19);
}
if (binder != nullptr) {
if (!local) { // 注释2
BpBinder *proxy = binder->remoteBinder();
if (proxy == nullptr) {
ALOGE("null proxy");
} else {
if (proxy->isRpcBinder()) {
ALOGE("Sending a socket binder over kernel binder is prohibited");
return INVALID_OPERATION;
}
}
const int32_t handle = proxy ? proxy->getPrivateAccessor().binderHandle() : 0;
obj.hdr.type = BINDER_TYPE_HANDLE; // 注释3
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.flags = 0;
obj.handle = handle;
obj.cookie = 0;
} else {
int policy = local->getMinSchedulerPolicy();
int priority = local->getMinSchedulerPriority();
if (policy != 0 || priority != 0) {
// override value, since it is set explicitly
schedBits = schedPolicyMask(policy, priority);
}
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (local->isRequestingSid()) {
obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
}
if (local->isInheritRt()) {
obj.flags |= FLAT_BINDER_FLAG_INHERIT_RT;
}
obj.hdr.type = BINDER_TYPE_BINDER; // 注释4
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
......
}
obj.flags |= schedBits;
status_t status = writeObject(obj, false);
if (status != OK) return status;
return finishFlattenBinder(binder);
#else // BINDER_WITH_KERNEL_IPC
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
}
- 注释1:在
Parcel::writeStrongBinder
内,随后调用flattenBinder
函数; - 注释2:如果不是本地
Binder
; - 注释3:标记
type
为BINDER_TYPE_HANDLE
(非本地Binder
); - 注释4:为本地
Binder
,标记为BINDER_TYPE_BINDER
;
7.2.3.2 readStrongBinder
代码20
frameworks\native\libs\binder\Parcel.cpp
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
status_t status = readNullableStrongBinder(val);
if (status == OK && !val->get()) {
ALOGW("Expecting binder but got null!");
status = UNEXPECTED_NULL;
}
return status;
}
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
return unflattenBinder(val); // 注释1
}
status_t Parcel::unflattenBinder(sp<IBinder>* out) const
{
if (const auto* rpcFields = maybeRpcFields()) {
int32_t isPresent;
status_t status = readInt32(&isPresent);
if (status != OK) return status;
sp<IBinder> binder;
if (isPresent & 1) {
uint64_t addr;
if (status_t status = readUint64(&addr); status != OK) return status;
if (status_t status =
rpcFields->mSession->state()->onBinderEntering(rpcFields->mSession, addr,
&binder);
status != OK)
return status;
if (status_t status =
rpcFields->mSession->state()->flushExcessBinderRefs(rpcFields->mSession,
addr, binder);
status != OK)
return status;
}
return finishUnflattenBinder(binder, out);
}
#ifdef BINDER_WITH_KERNEL_IPC
const flat_binder_object* flat = readObject(false);
if (flat) {
switch (flat->hdr.type) { // 注释2
case BINDER_TYPE_BINDER: { // 注释3
sp<IBinder> binder =
sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie));
return finishUnflattenBinder(binder, out);
}
case BINDER_TYPE_HANDLE: { // 注释4
sp<IBinder> binder =
ProcessState::self()->getStrongProxyForHandle(flat->handle);
return finishUnflattenBinder(binder, out);
}
}
}
return BAD_TYPE;
#else // BINDER_WITH_KERNEL_IPC
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
}
- 注释1:最终调用
unflattenBinder
函数; - 注释2:判断是否是本地
Binder
- 注释3:本地
Binder
; - 注释4:非本地
Binder
转换为Proxy
对象,在Java
层对应BinderProxy
类型;
所以,综上所述,IBinder
跨进程传递时:如果客户端、服务端同一进程,则服务端返回的IBinder
为当前引用,如果客户端、服务端处在不同进程,则服务端回传的IBinder
为BinderProxy
。