안 드 로 이 드 자바 층 ServiceManager

13299 단어 AndroidFramework
개술
ServiceManager 는 Android 프로 세 스 간 통신 binder 체제 의 중요 한 역할 로 native 층 에서 실 행 됩 니 다.c+언어 로 실 행 됩 니 다.모든 Service 가 사용 되 기 전에 음악 을 재생 하 는 MediaService,예 를 들 어 activity 를 관리 하 는 Activity Manager Service 는 SM 에 등록 해 야 합 니 다.같은 시간 에 클 라 이언 트 가 특정한 서 비 스 를 사용 할 때서비스 관리자 에 게 이 서비스 가 등록 되 었 는 지 확인 해 야 한다.
ServiceManager 역할
1.Binder driver 와 통신 하고 순환 을 유지 하 며 커 널 binder driver 를 계속 읽 습 니 다.서비스 에 대한 작업 요청 이 있 는 지 계속 읽 어 보 는 것 입 니 다.
2.svclist 목록 을 유지 하여 service 정 보 를 저장 합 니 다.
3.클 라 이언 트 에 Service 를 제공 하 는 대리,즉 BinderProxy 입 니 다.
연장:클 라 이언 트 가 서비스 관리자 에 게 서 비 스 를 찾 고 BinderProxy 를 가 져 오 며 BinderProxy 를 통 해 서비스 단 과 의 통신 을 실현 합 니 다.
4.서비스 등록 서비스 제공
사실은 ServiceManager 는 하나의 경로 와 같다.먼저,Service 는 자신 을 ServiceManager 에 등록 하고 호출 자(클 라 이언 트)는 ServiceManager 를 통 해 서 비 스 를 조회 한다.
    그것 의 실현 은 서비스manager.c。자바 의 ServiceManager.자바 는 서비스 에 불과 합 니 다.manager.c 의 패키지.여기,우 리 는 service 에 대해 토론 하지 않 습 니 다.manager.c 가 어떻게 Binder driver 와 아래로 통신 하 는 지,service 의 구체 적 인 논 리 를 등록 하고 찾 는 것 도 토론 하지 않 습 니 다.자바 차원,즉 안 드 로 이 드 프레임 워 크 차원 에서 ServceManager.자바 서 비 스 를 어떻게 사용 하 는 지 논의 하 는 것 이다.
   ServiceManager.java 의 원본 코드 는 매우 간단 합 니 다.다음 과 같 습 니 다.
public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;
    private static HashMap sCache = new HashMap();

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

    /**
     * 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 null if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     */
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * to access this service
     */
    public static void addService(String name, IBinder service, boolean allowIsolated) {
        try {
            getIServiceManager().addService(name, service, allowIsolated);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
    
    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Non-blocking.
     */
    public static IBinder checkService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().checkService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in checkService", e);
            return null;
        }
    }

    /**
     * Return a list of all currently running services.
     * @return an array of all currently running services, or null in
     * case of an exception
     */
    public static String[] listServices() {
        try {
            return getIServiceManager().listServices();
        } catch (RemoteException e) {
            Log.e(TAG, "error in listServices", e);
            return null;
        }
    }

    /**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     * 
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache(Map cache) {
        if (sCache.size() != 0) {
            throw new IllegalStateException("setServiceCache may only be called once");
        }
        sCache.putAll(cache);
    }
}

1、 addService() , native 2、 getService() , native 3、 Map      getService() native Binder, Stub.asInterface() BinderProxy, BinderProxy 。 , AIDL Service , 。 native , addService() getService() native native 。 native : Android Framework ( ) ServiceManager Native Android Framework ( ) ServiceManager Native App Android SystemServer , getSystemService() , ServiceFetcher.createService() XXManager,XXManager BinderProxy, , XXManager BinderProxy 。 ServiceManager.getService() , 。 ActivityManager,ActivityManager , BinderProxy , :

    @Deprecated
    public List getRunningTasks(int maxNum)
            throws SecurityException {
        try {
            return ActivityManagerNative.getDefault().getTasks(maxNum, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
Activity Manager Native.getDefault().getTasks()방법 을 호출 하여 Activity Manager Native.getDefault()를 되 돌려 주 는 것 을 볼 수 있 습 니 다.
BinderProxy,따라 들 어가 보 겠 습 니 다.
ActivityManagerNative.getDefault()
/**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

getDefault()가 무엇 인지 보 세 요:
private static final Singleton gDefault = new Singleton() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

아니 나 다 를 까 ServiceManager 에서 가 져 온 IBinder 를 BinderProxy 로 전환 했다.
XXManager,BluetoothManager 를 다시 보 세 요.그 중 하 나 는 논리 적 인 방법 이 있 습 니 다.getConnected Sevices()는 다음 과 같 습 니 다.
public List getConnectedDevices(int profile) {
        if (DBG) Log.d(TAG,"getConnectedDevices");
        if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
            throw new IllegalArgumentException("Profile not supported: " + profile);
        }

        List connectedDevices = new ArrayList();

        try {
            IBluetoothManager managerService = mAdapter.getBluetoothManager();
            IBluetoothGatt iGatt = managerService.getBluetoothGatt();
            if (iGatt == null) return connectedDevices;

            connectedDevices = iGatt.getDevicesMatchingConnectionStates(
                new int[] { BluetoothProfile.STATE_CONNECTED });
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
        }

        return connectedDevices;
    }

mAdapter 를 통 해 IBluetoothManager 인 터 페 이 스 를 얻 을 수 있 습 니 다.즉,BinderProxy 입 니 다.BluetoothAdapter 를 따라 갑 니 다.
/*package*/ IBluetoothManager getBluetoothManager() {
            return mManagerService;
    }

mManager Service 를 되 돌려 줍 니 다.이 변 수 는 BluetoothAdapter 를 구성 할 때 들 어 옵 니 다.BluetoothAdapter 에 BluetoothAdapter 를 만 드 는 방법 getDefaultAdapter 가 포함 되 어 있 는 것 을 발 견 했 습 니 다.다음 과 같 습 니 다.
public static synchronized BluetoothAdapter getDefaultAdapter() {
        if (sAdapter == null) {
            IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
            if (b != null) {
                IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
                sAdapter = new BluetoothAdapter(managerService);
            } else {
                Log.e(TAG, "Bluetooth binder is null");
            }
        }
        return sAdapter;
    }

이 를 통 해 알 수 있 듯 이 ServiceManager.getService()를 통 해 IBinder 를 얻 고 adInterface(b)방법 을 통 해 BinderProxy 로 전환 할 수 있 습 니 다.
물론 모든 XXManager 가 원 격 서 비 스 를 필요 로 하 는 것 은 아니다.일부 XXManager 의 업무 방법 은 ContentProvider 를 통 해 이 루어 진다.
이 를 통 해 저 희 는 XXManager 에 포 함 된 BinderProxy 는 ServiceManager.getService()에서 얻 고 asInterface()를 통 해 얻 은 것 임 을 검 증 했 습 니 다.
시스템 서버 엔 드
다음 에 저 희 는 등록 서비스 가 ServiceManager.addService()를 통 해 이 루어 졌 다 는 것 을 검증 하 겠 습 니 다.지난 글 에서 Android SystemServer 를 분석 한 결과 각 XX Manager Service 는 SystemServer.자바 의 정적 코드 블록 을 통 해 onStart()를 만 들 고 호출 하 는 방법 으로 시작 되 었 습 니 다.ServiceManager.addService()와 연락 이 없 는 것 처럼 보 입 니 다.급 하지 않 습 니 다.SystemServer.startOtherService()방법 에 다음 코드 가 존재 하 는 것 을 볼 수 있 습 니 다.
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);

ServiceManager.addService()를 통 해 native 에 서 비 스 를 등록 하 는 것 을 발견 할 수 있 습 니 다.
또한 AMS 에서 핵심 Service 를 등록 하 는 코드 도 발견 할 수 있 습 니 다.
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));

등록 서비스 라 고 하 는데 사실은 IBinder 를 등록 하 는 것 입 니 다.이 IBinder 는 자신의 신분 을 표시 합 니 다.우 리 는 addService()의 두 번 째 매개 변 수 는 모두 Binder 입 니 다.예 를 들 어 VibratorService:
public class VibratorService extends IVibratorService.Stub
        implements InputManager.InputDeviceListener {
....

예 를 들 어 TelephonyRegistry:
class TelephonyRegistry extends ITelephonyRegistry.Stub {
    private static final String TAG = "TelephonyRegistry";
.....

또한 XXManager Service 의 부모 클래스 SystemService 에서 도 ServiceManager 에 등록 하 는 방법 을 제공 했다.
    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }

좋은 웹페이지 즐겨찾기