Service源碼淺析一
Service源碼淺析二
Service源碼淺析三
Service源碼淺析四
咱們帶著這幾個(gè)問題繼續(xù)分析Service的代碼:
- binderDied和onServiceDisconnected是否會(huì)同時(shí)觸發(fā)?有先后順序嗎?
- Service AIDL進(jìn)程間通信服務(wù)端和客戶端分別運(yùn)行在哪個(gè)線程?
Stop Service
public abstract boolean stopService(Intent service);
ContextImpl
@Override
public boolean stopService(Intent service) {
warnIfCallingFromSystemProcess();
return stopServiceCommon(service, mUser);
}
private boolean stopServiceCommon(Intent service, UserHandle user) {
// // Keep this in sync with ActivityManagerLocal.stopSdkSandboxService
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
int res = ActivityManager.getService().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to stop service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
接下來就到了ActivityManagerService,它會(huì)調(diào)用ActiveServices中的方法stopServiceLocked,然后是bringDownServiceLocked,剩下的流程就和unbind Service中一樣了,執(zhí)行ActivityThread中的一些列操作。
linkToDeath
public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
throws RemoteException;
linkToDeath是IBinder方法,它接受一個(gè)DeathRecipient作為參數(shù)。
public interface DeathRecipient {
public void binderDied();
/**
* The function called when the process hosting an IBinder
* has gone away.
*
* This callback will be called from any binder thread like any other binder
* transaction. If the process receiving this notification is multithreaded
* then synchronization may be required because other threads may be executing
* at the same time.
*
* No locks are held in libbinder when {@link binderDied} is called.
*
* There is no need to call {@link unlinkToDeath} in the binderDied callback.
* The binder is already dead so {@link unlinkToDeath} is a no-op.
* It will be unlinked when the last local reference of that binder proxy is
* dropped.
*
* @param who The IBinder that has become invalid
*/
default void binderDied(@NonNull IBinder who) {
binderDied();
}
}
IBinder的實(shí)現(xiàn)類是Binder
/**
* Local implementation is a no-op.
*/
public void linkToDeath(@NonNull DeathRecipient recipient, int flags) {
}
Binder的linkToDeath方法實(shí)現(xiàn)也是空的,那它是在哪實(shí)現(xiàn)的呢?
其實(shí)它的實(shí)現(xiàn)類是BinderProxy,它是IBinder native類的Java層代理
public void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException {
linkToDeathNative(recipient, flags);
mDeathRecipients.add(recipient);
}
private native void linkToDeathNative(DeathRecipient recipient, int flags)
throws RemoteException;
linkToDeathNative是native方法,它的實(shí)現(xiàn)在哪呢?
native實(shí)現(xiàn)在
frameworks/platform_frameworks_base/core/jni/android_util_Binder.cpp
static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
jobject recipient, jint flags) // throws RemoteException
{
if (recipient == NULL) {
jniThrowNullPointerException(env, NULL);
return;
}
BinderProxyNativeData *nd = getBPNativeData(env, obj);
IBinder* target = nd->mObject.get();
LOG_DEATH_FREEZE("linkToDeath: binder=%p recipient=%p\n", target, recipient);
if (!target->localBinder()) {
sp<DeathRecipientList> list = nd->mOrgue;
sp<JavaDeathRecipient> jdr = sp<JavaDeathRecipient>::make(env, recipient, list);
status_t err = target->linkToDeath(jdr, NULL, flags);
if (err != NO_ERROR) {
// Failure adding the death recipient, so clear its reference
// now.
jdr->clearReference();
signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
}
}
}
target->linkToDeath最后追到
frameworks/native/libs/binder/BpBinder.cpp
status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
if (isRpcBinder()) {
if (rpcSession()->getMaxIncomingThreads() < 1) {
ALOGE("Cannot register a DeathRecipient without any incoming threads. Need to set max "
"incoming threads to a value greater than 0 before calling linkToDeath.");
return INVALID_OPERATION;
}
} else if constexpr (!kEnableKernelIpc) {
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
return INVALID_OPERATION;
} else {
if (ProcessState::self()->getThreadPoolMaxTotalThreadCount() == 0) {
ALOGW("Linking to death on %s but there are no threads (yet?) listening to incoming "
"transactions. See ProcessState::startThreadPool and "
"ProcessState::setThreadPoolMaxThreadCount. Generally you should setup the "
"binder "
"threadpool before other initialization steps.",
String8(getInterfaceDescriptor()).c_str());
}
}
Obituary ob;
ob.recipient = recipient;
ob.cookie = cookie;
ob.flags = flags;
LOG_ALWAYS_FATAL_IF(recipient == nullptr,
"linkToDeath(): recipient must be non-NULL");
{
RpcMutexUniqueLock _l(mLock);
if (!mObitsSent) {
if (!mObituaries) {
mObituaries = new Vector<Obituary>;
if (!mObituaries) {
return NO_MEMORY;
}
ALOGV("Requesting death notification: %p handle %d\n", this, binderHandle());
if (!isRpcBinder()) {
if constexpr (kEnableKernelIpc) {
getWeakRefs()->incWeak(this);
IPCThreadState* self = IPCThreadState::self();
self->requestDeathNotification(binderHandle(), this);
self->flushCommands();
}
}
}
ssize_t res = mObituaries->add(ob);
return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
}
}
return DEAD_OBJECT;
}
追到這里還是一臉懵,服務(wù)進(jìn)程掛了是怎么通知客戶端的?
其實(shí)它是通過binder驅(qū)動(dòng)直接通知客戶端的
+----------------+ +---------------+ +----------------+
| 服務(wù)端進(jìn)程死亡 | ----> | Binder驅(qū)動(dòng) | ----> | 客戶端進(jìn)程 |
+----------------+ +---------------+ +----------------+
|
v
+-----------------+
| 死亡通知工作項(xiàng) |
| (BINDER_WORK_ |
| DEAD_BINDER) |
+-----------------+
Binder驅(qū)動(dòng)可以感知服務(wù)端進(jìn)程死亡,然后回調(diào)客戶端注冊(cè)的Java層方法。
咱們?cè)诳碽indService時(shí)應(yīng)該注意到,傳入的ServiceConnection經(jīng)過LoadedApk包裝之后變成了ServiceDispatcher,服務(wù)綁定之后會(huì)通過doConnected觸發(fā)ServiceConnection#onServiceConnected
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);
}
}
}
這個(gè)方法中還藏了一步,它悄悄的給服務(wù)端注冊(cè)了另一個(gè)死亡監(jiān)聽DeathMonitor
private final class DeathMonitor implements IBinder.DeathRecipient
{
DeathMonitor(ComponentName name, IBinder service) {
mName = name;
mService = service;
}
public void binderDied() {
death(mName, mService);
}
final ComponentName mName;
final IBinder mService;
}
最后會(huì)通過主線程回調(diào)onServiceDisconnected,感覺太雞賊了。
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);
}
也就是說服務(wù)端進(jìn)程死亡之后,客戶自己注冊(cè)的死亡監(jiān)聽可以收到回調(diào),這里注冊(cè)的監(jiān)聽也可以收到回調(diào),所以咱們開頭的第一個(gè)問題就有答案了
- binderDied和onServiceDisconnected是否會(huì)同時(shí)觸發(fā)?有先后順序嗎?
不會(huì)同時(shí)觸發(fā),應(yīng)該是先在Binder線程觸發(fā)binderDied,再在主線程觸發(fā)onServiceDisconnected
- binderDied和onServiceDisconnected是否會(huì)同時(shí)觸發(fā)?有先后順序嗎?
目前咱們就剩下第2個(gè)問題了
- Service AIDL進(jìn)程間通信服務(wù)端和客戶端分別運(yùn)行在哪個(gè)線程?
先說答案,以客戶端調(diào)用服務(wù)端為例,客戶端側(cè)的邏輯運(yùn)行在客戶端側(cè)的調(diào)用進(jìn)程,服務(wù)端的邏輯運(yùn)行在Binder線程池的線程中,服務(wù)端調(diào)用客戶端同理。
- Service AIDL進(jìn)程間通信服務(wù)端和客戶端分別運(yùn)行在哪個(gè)線程?
這里涉及Binder通信的原理,可以參考[Binder 一]Binder淺析
咱們先來回顧一下AIDL進(jìn)程通信的步驟:
- 創(chuàng)建 .aidl 文件
咱們創(chuàng)建一個(gè)簡(jiǎn)單的AIDL文件
interface IRemoteService {
int getPid();
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
- 實(shí)現(xiàn)接口
private val binder = object : IRemoteService.Stub() {
override fun getPid(): Int {
return Process.myPid()
}
override fun basicTypes(
anInt: Int,
aLong: Long,
aBoolean: Boolean,
aFloat: Float,
aDouble: Double,
aString: String?
) {
}
}
- 向客戶端公開該接口
override fun onBind(intent: Intent?): IBinder {
return binder
}
客戶端綁定服務(wù)端成功之后會(huì)回調(diào)onServiceConnected,這個(gè)咱們?cè)谏弦黄呀?jīng)跟過流程了。
private val mConnection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// This is called when the connection with the service is
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = IRemoteService.Stub.asInterface(service)
}
override fun onServiceDisconnected(className: ComponentName) {
// This is called when the connection with the service is
// unexpectedly disconnected—that is, its process crashed.
mService = null
}
}
首先,咱們?cè)?build/generated/aidl_source_output_dir下找到編譯器為我們自動(dòng)生成的IRemoteService.java類文件。

從上圖中可以看到asInterface是Stub的方法
/**
* Cast an IBinder object into an com.example.serverdemo.IRemoteService interface,
* generating a proxy if needed.
*/
public static com.example.serverdemo.IRemoteService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.serverdemo.IRemoteService))) {
return ((com.example.serverdemo.IRemoteService)iin);
}
return new com.example.serverdemo.IRemoteService.Stub.Proxy(obj);
}
該方法會(huì)返回服務(wù)端的接口對(duì)象,如果客戶端和服務(wù)端在同一個(gè)進(jìn)程,則返回Stub對(duì)象本身,如果不在同一進(jìn)程,則返回Proxy對(duì)象。
/**
* Use information supplied to {@link #attachInterface attachInterface()}
* to return the associated {@link IInterface} if it matches the requested
* descriptor.
*/
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
可以看到queryLocalInterface返回的是attachInterface中的接口,attachInterface是在Stub構(gòu)造方法中調(diào)用的。
public static abstract class Stub extends android.os.Binder implements com.example.serverdemo.IRemoteService
{
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
}
跨進(jìn)程情況下返回的是Proxy對(duì)象,
private static class Proxy implements com.example.serverdemo.IRemoteService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
}
Proxy實(shí)現(xiàn)了IRemoteService,并持有服務(wù)端傳過來的IBinder對(duì)象,并通過這個(gè)對(duì)象調(diào)用對(duì)應(yīng)的方法
@Override public int getPid() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
以調(diào)用getPid方法為例,會(huì)觸發(fā)mRemote.transact,這里發(fā)生了進(jìn)程通信,從客戶端進(jìn)程進(jìn)入服務(wù)端進(jìn)程,方法transact的實(shí)現(xiàn)在Binder類中,接下來都是在服務(wù)端進(jìn)程發(fā)生的。
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
會(huì)調(diào)用到服務(wù)端Stub對(duì)象的onTransact方法。
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
data.enforceInterface(descriptor);
}
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
}
switch (code)
{
case TRANSACTION_getPid:
{
int _result = this.getPid();
reply.writeNoException();
reply.writeInt(_result);
break;
}
case TRANSACTION_basicTypes:
{
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
break;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
return true;
}
然后會(huì)觸發(fā)自定義Binder對(duì)象的getPid方法,并返回結(jié)果,這個(gè)大體流程就走下來了,但是mRemote.transact是怎么調(diào)到服務(wù)端進(jìn)程的,這塊還得深究,本篇文章到此結(jié)束。
參考: