\#Android 6.0 의 Bluetooth Enable 프로 세 스 분석

26856 단어 Bluetooth
Android 6.0 블 루 투 스 Enable 프로 세 스 분석
최근 에 블 루 투 스 모듈 코드 를 분석 하기 시 작 했 습 니 다.여기 서 기록 하 겠 습 니 다.본 고 는 주로 Android 6.0 코드 를 바탕 으로 하 는 블 루 투 스 시스템 서 비 스 를 바탕 으로 절차 분석 을 할 수 있 습 니 다.jni 이하 의 절차 인터넷 에 많은 글 이 명확 하 게 쓰 여 있 기 때문에 본 고 는 package 와 framework 층 의 흐름 만 분석 하고 관련 된 주요 유형 은 다음 과 같 습 니 다.
  • framework/base/core/java/android/bluetooth/BluetoothAdapter.java
  • framework/base/services/core/java/com/android/server/BluetoothService.java
  • framework/base/services/java/com/android/server/SystemServer.java -
  • packages/apps/Bluetooth/src/com/android/bluetooth/adapterService.java-
  • packages/apps/Bluetooth/src/com/android/bluetooth/adapterState.java-

  • 블 루 투 스 활성화
    Android 의 블 루 투 스 Enable 은 BluetoothAdapter 에서 제공 합 니 다.BluetoothAdapter.enable()을 호출 하면 블 루 투 스 를 시작 할 수 있 습 니 다.이 과정 을 분석 하 겠 습 니 다.
    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
        public boolean enable() {
            int state = STATE_OFF;
            if (isEnabled() == true){
                if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
                return true;
            }
            //Use service interface to get the exact state
            if (mService != null) {
                try {
                   state = mService.getState();
                } catch (RemoteException e) {Log.e(TAG, "", e);}
            }
    
            if (state == BluetoothAdapter.STATE_BLE_ON) {
                    Log.e(TAG, "BT is in BLE_ON State");
                    notifyUserAction(true);
                    return true;
            }
            Log.d(TAG, ":  bt enable current package name : "+ActivityThread.currentPackageName());
            AppOpsManager appOps = (AppOpsManager)((ActivityThread.currentApplication()).getApplicationContext()).getSystemService(Context.APP_OPS_SERVICE);
            if (appOps.noteOp(AppOpsManager.OP_BLUETOOTH_ON_OFF) != AppOpsManager.MODE_ALLOWED) {
               Log.d(TAG, ": bt enable");
               return false;
            }
    
            try {
                if (DBG) Log.d(TAG, "enable");
                return mManagerService.enable();
            } catch (RemoteException e) {Log.e(TAG, "", e);}
            return false;
        }
    

    mManager Service.enable()함수 에 중점 을 두 고 mManager Service 는 IBluetoothManager 유형,즉 btAdapter 의 proxy 입 니 다.왜 이렇게 말 합 니까?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;
        }
    
        /**
         * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
         */
        BluetoothAdapter(IBluetoothManager managerService) {
    
            if (managerService == null) {
                throw new IllegalArgumentException("bluetooth manager service is null");
            }
            try {
                mService = managerService.registerAdapter(mManagerCallback);
            } catch (RemoteException e) {Log.e(TAG, "", e);}
            mManagerService = managerService;
            mLeScanClients = new HashMap();
            mToken = new Binder();
        }

    ServiceManager 를 통 해 시스템 서 비 스 를 받 은 후 IBluetoothManager 인터페이스 로 전환 하여 mManager Service 를 BLUETOOTH 로 만 들 었 습 니 다.MANAGER_서비스 대행.블 루 투 스MANAGER_SERVICE 의 오픈,SystemServer.java 클래스 보기
    mSystemServiceManager.startService(BluetoothService.class);

    Bluetooth Service.java 의 구조 함 수 를 계속 보 세 요.
    public BluetoothService(Context context) {
            super(context);
            mBluetoothManagerService = new BluetoothManagerService(context);
        }

    구조 함수 에서 new Bluetooth Manager Service 류 의 인 스 턴 스 를 볼 수 있 습 니 다.onStart 함 수 를 계속 보 세 요.
    public void onStart() {
            Log.d(TAG, "onStart: publishing BluetoothManagerService");
            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService);
        }

    이로써 이 서비스의 오픈 분석 이 완료 되면 원래 BLUETOOTH 를 알 수 있 습 니 다.MANAGER_서비스 란 블 루 투 스 관리자 서비스 클래스 다.최초의 메 인 으로 돌아 가 현재 enable 은 Bluetooth Manager Service.java 의 enable()로 호출 되 었 습 니 다.
    public boolean enable() {
            ……
            /// @}
            synchronized(mReceiver) {
                mQuietEnableExternal = false;
                mEnableExternal = true;
                // waive WRITE_SECURE_SETTINGS permission check
                sendEnableMsg(false);
            }
            if (DBG) Log.d(TAG, "enable returning");
            return true;
        }

    sendEnableMsg 계속 보기
    private void sendEnableMsg(boolean quietMode) {
            mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
                                 quietMode ? 1 : 0, 0));
        }

    여기 서 Handler 메 시 지 를 보 내 고 이 메 시 지 를 처리 하 는 코드 를 계속 보 세 요.
    private class BluetoothHandler extends Handler {
            public BluetoothHandler(Looper looper) {
                super(looper);
            }
    
            @Override
            public void handleMessage(Message msg) {
                if (DBG) Log.d (TAG, "Message: " + msg.what);
                switch (msg.what) {
                ……
                case MESSAGE_ENABLE:
                        if (DBG) {
                            Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
                        }
                        mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                        mEnable = true;
                        handleEnable(msg.arg1 == 1);
                        break;
                        ……                   

    handle Enable 계속 보기()
    private void handleEnable(boolean quietMode) {
            mQuietEnable = quietMode;
    
            synchronized(mConnection) {
                if (DBG) Log.d(TAG, "handleEnable: mBluetooth = " + mBluetooth +
                        ", mBinding = " + mBinding + "quietMode = " + quietMode);
                if ((mBluetooth == null) && (!mBinding)) {
                    if (DBG) Log.d(TAG, "Bind AdapterService");
                    //Start bind timeout and bind
                    Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
                    mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
                    mConnection.setGetNameAddressOnly(false);
                    Intent i = new Intent(IBluetooth.class.getName());
                    if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                            UserHandle.CURRENT)) {
                        mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
                        Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
                    } else {
                        mBinding = true;
                    }
                } else if (mBluetooth != null) {
                    if (mConnection.isGetNameAddressOnly()) {
                        // if GetNameAddressOnly is set, we can clear this flag,
                        // so the service won't be unbind
                        // after name and address are saved
                        mConnection.setGetNameAddressOnly(false);
                        //Register callback object
                        try {
                            mBluetooth.registerCallback(mBluetoothCallback);
                        } catch (RemoteException re) {
                            Log.e(TAG, "Unable to register BluetoothCallback",re);
                        }
                        //Inform BluetoothAdapter instances that service is up
                        sendBluetoothServiceUpCallback();
                    }
    
                    //Enable bluetooth
                    try {
                        if (!mQuietEnable) {
                            if(!mBluetooth.enable()) {
                                Log.e(TAG,"IBluetooth.enable() returned false");
                            }
                        }
                        else {
                            if(!mBluetooth.enableNoAutoConnect()) {
                                Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
                            }
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG,"Unable to call enable()",e);
                    }
                }
            }
        }

    한 바퀴 돌 았 습 니 다.마지막 으로 mBluetooth.enable()을 호출 했 습 니 다.BluetoothAdapter 안에 mService 가 있 었 고 mService 는 registerAdapter()가 돌아 온 mBluetooth 입 니 다!
    public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
            if (callback == null) {
                Log.w(TAG, "Callback is null in registerAdapter");
                return null;
            }
            Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
            msg.obj = callback;
            mHandler.sendMessage(msg);
            synchronized(mConnection) {
                return mBluetooth;
            }
        }

    그러나 주의해 야 할 것 은 BluetoothAdapter 류 의 mService 의 할당 값 은 이곳 의 bindService 이전 이 고 다른 API 의 실현 은 모두 mService 를 직접 사용 하기 때문에 사실은 bindService 는 Bluetooth Manager Service.자바 의 또 다른 케이스(MESSAGEGET_NAME_AND_ADDRESS)에서 호출 된 이 mBluetooth 는 블 루 투 스 앱 의 AdapterService 입 니 다.
    public synchronized boolean enable(boolean quietMode) {
             enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
    
             debugLog("enable() - Enable called with quiet mode status =  " + mQuietmode);
             mQuietmode = quietMode;
             Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON);
             mAdapterStateMachine.sendMessage(m);
             return true;
         }

    여기 에는 StateMachine 을 사 용 했 습 니 다.여기 서 상태 기 를 펼 치지 않 는 용법 을 사 용 했 습 니 다.쉽게 말 하면 하나의 상태 기 는 여러 상 태 를 포함 하고 서로 다른 상태 에서 같은 메 시 지 를 서로 다른 처리 로 처리 하 며 초기 상 태 를 직접 보고 이 메 시 지 를 처리 하 는 곳 입 니 다.
    public boolean processMessage(Message msg) {
                AdapterService adapterService = mAdapterService;
                if (adapterService == null) {
                    errorLog("Received message in OffState after cleanup: " + msg.what);
                    return false;
                }
    
                debugLog("Current state: OFF, message: " + msg.what);
    
                switch(msg.what) {
                   case BLE_TURN_ON:
                   //
                       notifyAdapterStateChange(BluetoothAdapter.STATE_BLE_TURNING_ON);
                       mPendingCommandState.setBleTurningOn(true);
                       transitionTo(mPendingCommandState);
                       sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
                       adapterService.BleOnProcessStart();
                       break;
                       ……
                }
                return true;
            }
        }

    AdapterState 상태 기 는 mPendingCommandState 에 들 어가 mPendingCommandState.setBleTurning On(true)을 엽 니 다.주의해 야 할 것 은 여기 가 true 로 설 정 된 후에 만 processProfile ServiceState Changed 함수 에서 BLE 를 보 낼 수 있 습 니 다.STARTED 메시지,JNI 함수 enableNative 함 수 를 호출 합 니 다.
    private void processProfileServiceStateChanged(String serviceName, int state) {
            boolean doUpdate=false;
            boolean isBleTurningOn;
            boolean isBleTurningOff;
            boolean isTurningOn;
            boolean isTurningOff;
    
            synchronized (mProfileServicesState) {
                Integer prevState = mProfileServicesState.get(serviceName);
                if (prevState != null && prevState != state) {
                    mProfileServicesState.put(serviceName,state);
                    doUpdate=true;
                }
            }
            debugLog("onProfileServiceStateChange() serviceName=" + serviceName
                    + ", state = " + state + ", doUpdate = " + doUpdate);
    
            if (!doUpdate) {
                return;
            }
    
            synchronized (mAdapterStateMachine) {
                isTurningOff = mAdapterStateMachine.isTurningOff();
                isTurningOn = mAdapterStateMachine.isTurningOn();
                isBleTurningOn = mAdapterStateMachine.isBleTurningOn();
                isBleTurningOff = mAdapterStateMachine.isBleTurningOff();
            }
    
            debugLog("processProfileServiceStateChanged() - serviceName=" + serviceName +
                     " isTurningOn=" + isTurningOn + " isTurningOff=" + isTurningOff +
                     " isBleTurningOn=" + isBleTurningOn + " isBleTurningOff=" + isBleTurningOff);
    
            if (isBleTurningOn) {
                if (serviceName.equals("com.android.bluetooth.gatt.GattService")) {
                    debugLog("GattService is started");
                    mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED));
                    return;
                }            

    분명히 이때 AdapterState 는 PendingCommandState 에 있 습 니 다.processMessage 함수 Public boolean processMessage(Message msg){를 보십시오.
            boolean isTurningOn= isTurningOn();
            boolean isTurningOff = isTurningOff();
            boolean isBleTurningOn = isBleTurningOn();
            boolean isBleTurningOff = isBleTurningOff();
    
            AdapterService adapterService = mAdapterService;
            AdapterProperties adapterProperties = mAdapterProperties;
            if ((adapterService == null) || (adapterProperties == null)) {
                errorLog("Received message in PendingCommandState after cleanup: " + msg.what);
                return false;
            }
    
            debugLog("Current state: PENDING_COMMAND, message: " + msg.what);
    
            switch (msg.what) {
                ……
                case BLE_STARTED:
                    //Remove start timeout
                    removeMessages(BLE_START_TIMEOUT);
    
                    //Enable
                    boolean isGuest = UserManager.get(mAdapterService).isGuestUser();
                    if (!adapterService.enableNative(isGuest)) {
                        errorLog("Error while turning Bluetooth on");
                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
                        transitionTo(mOffState);
                    } else {
                        sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
                    }
                    break;               
                 ……
    

    이로써 상층 부 는 마침내 jni 층 으로 호출 되 었 고,enableNative 는 jni 에 등 록 된 native 함수 이다.계속 보 세 요.BleOnProcessStart.
    void BleOnProcessStart() {
            debugLog("BleOnProcessStart()");
            Class[] supportedProfileServices = Config.getSupportedProfiles();
            //Initialize data objects
            debugLog("supportedProfileServices.length = " + supportedProfileServices.length);
            for (int i=0; i < supportedProfileServices.length;i++) {
                debugLog("supportedProfileServices[" + i + "]: " + supportedProfileServices[i].getName());
                mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);
            }
            mRemoteDevices = new RemoteDevices(this);
            mAdapterProperties.init(mRemoteDevices);
    
            debugLog("BleOnProcessStart() - Make Bond State Machine");
            mBondStateMachine = BondStateMachine.make(mPowerManager, this, mAdapterProperties, mRemoteDevices);
    
            mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
            setAdapterService(this);
            //Start Gatt service
            setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
        }
    

    이로써 장치 가 지원 하 는 프로필 서비스 가 모두 시작 되 었 음 을 알 수 있다.

    좋은 웹페이지 즐겨찾기