AIDL 调用过程详解

来源:互联网 发布:算法分析导论 编辑:程序博客网 时间:2024/05/21 16:58

目的:不同进程间的的IPC 通信

代码示例:

/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.car;import android.content.Intent;import android.car.ICarConnectionListener;/** @hide */interface ICar {    IBinder getCarService(in String serviceName) = 0;    int getCarConnectionType() = 1;}

声明了两个接口 getCarService 和getCarConnectionType

接口的实现在什么地方呢?

 * Copyright (C) 2015 The Android Open Source Projectpackage com.android.car;import android.car.Car;public class ICarImpl extends ICar.Stub {    public static final String INTERNAL_INPUT_SERVICE =  "internal_input";    // load jni for all services here    static {        System.loadLibrary("jni_car_service");    }    @GuardedBy("ICarImpl.class")    private static ICarImpl sInstance = null;    private final Context mContext;    private final VehicleHal mHal;    private final CarPowerManagementService mCarPowerManagementService;    private final CarPackageManagerService mCarPackageManagerService;    private final CarInputService mCarInputService;    private final CarSensorService mCarSensorService;    private final CarInfoService mCarInfoService;    private final CarAudioService mCarAudioService;    private final CarProjectionService mCarProjectionService;    private final CarCameraService mCarCameraService;    private final CarHvacService mCarHvacService;    private final CarRadioService mCarRadioService;    private final CarNightService mCarNightService;    private final AppContextService mAppContextService;    private final GarageModeService mGarageModeService;    private final CarNavigationService mCarNavigationService;    private final InstrumentClusterService mInstrumentClusterService;    /** Test only service. Populate it only when necessary. */    @GuardedBy("this")    private CarTestService mCarTestService;    private final CarServiceBase[] mAllServices;    public synchronized static ICarImpl getInstance(Context serviceContext) {        if (sInstance == null) {            sInstance = new ICarImpl(serviceContext);            sInstance.init();        }        return sInstance;    }    public synchronized static void releaseInstance() {        if (sInstance == null) {            return;        }        sInstance.release();        sInstance = null;    }    public ICarImpl(Context serviceContext) {        mContext = serviceContext;        mHal = VehicleHal.getInstance();        mCarPowerManagementService = new CarPowerManagementService(serviceContext);        mCarInputService = new CarInputService(serviceContext);        mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);        mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);        mCarInfoService = new CarInfoService(serviceContext);        mAppContextService = new AppContextService(serviceContext);        mCarSensorService = new CarSensorService(serviceContext);        mCarAudioService = new CarAudioService(serviceContext);        mCarHvacService = new CarHvacService(serviceContext);        mCarRadioService = new CarRadioService(serviceContext);        mCarCameraService = new CarCameraService(serviceContext);        mCarNightService = new CarNightService(serviceContext);        mCarPackageManagerService = new CarPackageManagerService(serviceContext);        mInstrumentClusterService = new InstrumentClusterService(serviceContext);        mCarNavigationService = new CarNavigationService(                serviceContext, mAppContextService, mInstrumentClusterService);        // Be careful with order. Service depending on other service should be inited later.        mAllServices = new CarServiceBase[] {                mCarPowerManagementService,                mCarPackageManagerService,                mCarInputService,                mGarageModeService,                mCarInfoService,                mAppContextService,                mCarSensorService,                mCarAudioService,                mCarHvacService,                mCarRadioService,                mCarCameraService,                mCarNightService,                mInstrumentClusterService,                mCarProjectionService,                mCarNavigationService,                };    }    private void init() {        for (CarServiceBase service: mAllServices) {            service.init();        }    }    private void release() {        // release done in opposite order from init        for (int i = mAllServices.length - 1; i >= 0; i--) {            mAllServices[i].release();        }        VehicleHal.releaseInstance();    }    /** Only for CarTestService */    void startMocking() {        reinitServices();    }    /** Only for CarTestService */    void stopMocking() {        reinitServices();    }    /** Reset all services when starting / stopping vehicle hal mocking */    private void reinitServices() {        for (int i = mAllServices.length - 1; i >= 0; i--) {            mAllServices[i].release();        }        for (CarServiceBase service: mAllServices) {            service.init();        }    }    @Override    public IBinder getCarService(String serviceName) {        switch (serviceName) {            case Car.AUDIO_SERVICE:                return mCarAudioService;            case Car.SENSOR_SERVICE:                return mCarSensorService;            case Car.INFO_SERVICE:                return mCarInfoService;            case Car.APP_CONTEXT_SERVICE:                return mAppContextService;            case Car.PACKAGE_SERVICE:                return mCarPackageManagerService;            case Car.CAMERA_SERVICE:                assertCameraPermission(mContext);                return mCarCameraService;            case Car.HVAC_SERVICE:                assertHvacPermission(mContext);                return mCarHvacService;            case Car.RADIO_SERVICE:                assertRadioPermission(mContext);                return mCarRadioService;            case Car.CAR_NAVIGATION_SERVICE:                assertNavigationManagerPermission(mContext);                return mCarNavigationService;            case Car.PROJECTION_SERVICE:                assertProjectionPermission(mContext);                return mCarProjectionService;            case Car.TEST_SERVICE: {                assertVehicleHalMockPermission(mContext);                synchronized (this) {                    if (mCarTestService == null) {                        mCarTestService = new CarTestService(mContext, this);                    }                    return mCarTestService;                }            }            default:                Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);                return null;        }    }    @Override    public int getCarConnectionType() {        if (!isInMocking()) {            return Car.CONNECTION_TYPE_EMBEDDED;        } else {            return Car.CONNECTION_TYPE_EMBEDDED_MOCKING;        }    }    public CarServiceBase getCarInternalService(String serviceName) {        switch (serviceName) {            case INTERNAL_INPUT_SERVICE:                return mCarInputService;            default:                Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" +                        serviceName);                return null;        }    }    /**     * Whether mocking underlying HAL or not.     * @return     */    public synchronized boolean isInMocking() {        if (mCarTestService == null) {            return false;        }        return mCarTestService.isInMocking();    }    public static void assertVehicleHalMockPermission(Context context) {        if (context.checkCallingOrSelfPermission(Car.PERMISSION_MOCK_VEHICLE_HAL)                != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission");        }    }    public static void assertCameraPermission(Context context) {        if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_CAMERA)                != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException(                    "requires " + Car.PERMISSION_CAR_CAMERA);        }    }    public static void assertNavigationManagerPermission(Context context) {        if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_NAVIGATION_MANAGER)                != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException(                    "requires " + Car.PERMISSION_CAR_NAVIGATION_MANAGER);        }    }    public static void assertHvacPermission(Context context) {        if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_HVAC)                != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException(                    "requires " + Car.PERMISSION_CAR_HVAC);        }    }    private static void assertRadioPermission(Context context) {        if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_RADIO)            != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException(                "requires permission " + Car.PERMISSION_CAR_RADIO);        }    }    public static void assertProjectionPermission(Context context) {        if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_PROJECTION)                != PackageManager.PERMISSION_GRANTED) {            throw new SecurityException(                    "requires " + Car.PERMISSION_CAR_PROJECTION);        }    }    void dump(PrintWriter writer) {        writer.println("*Dump all services*");        for (CarServiceBase service: mAllServices) {            service.dump(writer);        }        CarTestService testService = mCarTestService;        if (testService != null) {            testService.dump(writer);        }    }}

如何确认这个代码就是ICar 接口的实现呢?
ICarImpl extends ICar.Stub
ICarImpl 继承了服务器端ICar.Stub

现在需要如何使用这个接口呢?

 mService = ICar.Stub.asInterface(service);

*在连接Service的时候,服务端的Stub(Binder)以参数的形式传过来了–IBinder service,然后我们通过asInterface()方法获取它的实例对象。
我们从android对aidl文件自动生成的java类中可以看到asInterface()这个接口的实现,大概的意思就是:
如果客户端和服务端在同一个进程下,那么asInterface()将返回Stub对象本身,否则返回Stub.Proxy对象。
也就是说asInterface()返回的对象有两种可能(实际上有三种,还有一种是null),Stub和Stub.Proxy。它们有什么区别呢?
如果在同一个进程下的话,那么asInterface()将返回服务端的Stub对象本身,因为此时根本不需要跨进称通信,那么直接调用Stub对象的接口就可以了,返回的实现就是服务端的Stub实现,也就是根本没有跨进程通信;
如果不是同一个进程,那么asInterface()返回是Stub.Proxy对象,该对象持有着远程的Binder引用,因为现在需要跨进程通信,所以如果调用Stub.Proxy的接口的话,那么它们都将是IPC调用,它会通过调用transact方法去与服务端通信。
以上就是两者的区别。*

Created with Raphaël 2.1.0IPC CommunicationClientClientServerServerBinder
原创粉丝点击