七、AIDL(四)获取服务及绑定和Binder传递流程

一、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()));

调用ContextgetSystemService(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时,获取了IBatteryStatsIBatteryPropertiesRegistrar两个Proxy Binder,我们示例代码batteryManager.isCharging()其实调用的就是IBatteryStats中的isChargingIBatteryStats.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使用场景,sServiceManagerServiceManager提供的Proxy Binder,通过该接口中getService获取目标服务的Binder引用。BinderInternal.getContextObject()是获取ServiceManager Binder需要的Binder

Client需要从ServiceManager获取电池服务的IBinder,而Client本身需要和ServiceManager通信,要通信就需要IBinderBinderInternal.getContextObject())就是为了获取ServiceManagerIBinder,该方法从Binder驱动获取了IBinder引用。

7.1.3 注册服务

ServiceManager是如何找到BatteryStatsService服务的呢?Android启动后,会开启system_server进程,该进程会开启很多系统服务,比如:BattertService、AWS、WMS等,因为BatteryStatsService会随着ActivityManagerService一起启动,在ActivityManagerServicestart函数中:

代码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代码中,调用ServiceManageraddService将服务添加到ServiceManager里。

7.1.4 总结

get_system_service

图中,ClientServiceManagerSystemServerBatteryStatsService分别运行于四个不同进程,ClientServiceManagerSystemServerBatteryStatsService之间通过Binder进行通信。

  1. SystemServer中启动和发布BatteryStatsService,使其运行并注册至ServiceManager中;
  2. SystemServer通过BinderInternal.getContextObject()ServiceManager注册服务IBinder ISErviceManager
  3. Client通过BatteryStatsServiceClient注册IBatteryStats服务;
  4. 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. 注释1:Service构造Binder对象;
  2. 注释2:在onBind函数中,将Binder传递出去;
  3. 注释3:客户端在绑定Service成功后,会收到服务端传递过来的IBInder service
  4. 注释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.Stubconnected函数,最终会调用ServiceConnectiononServiceDisconnectedonServiceConnected函数。

代码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 BinderActivityServiceManager继承了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()ApplicationThreadApplicationThread继承了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调用ActiveServicespublishServiceLocked函数。最终在注释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 总结

self Service Binder

7.2.3 Binder序列化

我们知道,服务端返回的是IBinder,但是客户端接收到的IBinder却是BinderProxy,这是怎么一回事呢?

IBinder支持进程间传递,但是却没有实现Parcelable接口,那它是如何支持序列化的呢?

7.2.3.1 IBinder如何序列化

分析Parcel.java发现,Parcel除了基本数据类型,还有writeStrongBinderreadStrongBinder

代码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. 注释1:在Parcel::writeStrongBinder内,随后调用flattenBinder函数;
  2. 注释2:如果不是本地Binder
  3. 注释3:标记typeBINDER_TYPE_HANDLE(非本地Binder);
  4. 注释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. 注释1:最终调用unflattenBinder函数;
  2. 注释2:判断是否是本地Binder
  3. 注释3:本地Binder
  4. 注释4:非本地Binder转换为Proxy对象,在Java层对应BinderProxy类型;

所以,综上所述,IBinder跨进程传递时:如果客户端、服务端同一进程,则服务端返回的IBinder为当前引用,如果客户端、服务端处在不同进程,则服务端回传的IBinderBinderProxy

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值