zoukankan      html  css  js  c++  java
  • Android 8 蓝牙 连接过程

    
    
    packagesappsSettingssrccomandroidsettingsluetoothBluetoothPairingDetail.java
    	@Override
        void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
            disableScanning();
            super.onDevicePreferenceClick(btPreference);
        }   
    	
    packagesappsSettingssrccomandroidsettingsluetoothDeviceListPreferenceFragment.java
        void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
            btPreference.onClicked();
        }
    	
    	
    packagesappsSettingssrccomandroidsettingsluetoothBluetoothDevicePreference.java
        void onClicked() {
            Context context = getContext();
    		// 获取连接状态
            int bondState = mCachedDevice.getBondState();
    
            final MetricsFeatureProvider metricsFeatureProvider =
                    FeatureFactory.getFactory(context).getMetricsFeatureProvider();
    		// 已经连接
            if (mCachedDevice.isConnected()) {
    			// 断开连接
                metricsFeatureProvider.action(context,
                        MetricsEvent.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
                askDisconnect();
    			// 以前连接过,不需要再配对,直接进行连接
            } else if (bondState == BluetoothDevice.BOND_BONDED) {
                metricsFeatureProvider.action(context,
                        MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT);
                mCachedDevice.connect(true);
    			// 没连接过,进行配对,需要连接的双方都同意之后才能连接
            } else if (bondState == BluetoothDevice.BOND_NONE) {
                metricsFeatureProvider.action(context,
                        MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
                if (!mCachedDevice.hasHumanReadableName()) {
                    metricsFeatureProvider.action(context,
                            MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
                }
                pair();
            }
        }
    	
    	
    1. 已经连接过的设备,直接断开
    	    // Show disconnect confirmation dialog for a device.
        private void askDisconnect() {
            Context context = getContext();
            String name = mCachedDevice.getName();
            if (TextUtils.isEmpty(name)) {
                name = context.getString(R.string.bluetooth_device);
            }
            String message = context.getString(R.string.bluetooth_disconnect_all_profiles, name);
            String title = context.getString(R.string.bluetooth_disconnect_title);
    		// 对话框的listener
            DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    mCachedDevice.disconnect();
                }
            };
    		// 显示断开对话框
            mDisconnectDialog = Utils.showDisconnectDialog(context,
                    mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
        }
    	
    2. 匹配过的设别,进行连接
    	frameworksasepackagesSettingsLibsrccomandroidsettingslibluetoothCachedBluetoothDevice.java
    	    public void connect(boolean connectAllProfiles) {
            // 是否配对过
    		if (!ensurePaired()) {
                return;
            }
    
            mConnectAttempted = SystemClock.elapsedRealtime();
            connectWithoutResettingTimer(connectAllProfiles);
        }
    	
    	    private void connectWithoutResettingTimer(boolean connectAllProfiles) {
            // Try to initialize the profiles if they were not.
            if (mProfiles.isEmpty()) {
                // if mProfiles is empty, then do not invoke updateProfiles. This causes a race
                // condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated
                // from bluetooth stack but ACTION.uuid is not sent yet.
                // Eventually ACTION.uuid will be received which shall trigger the connection of the
                // various profiles
                // If UUIDs are not available yet, connect will be happen
                // upon arrival of the ACTION_UUID intent.
                Log.d(TAG, "No profiles. Maybe we will connect later");
                return;
            }
    
            // Reset the only-show-one-error-dialog tracking variable
            mIsConnectingErrorPossible = true;
    
            int preferredProfiles = 0;
            for (LocalBluetoothProfile profile : mProfiles) {
                // connectAllProfile传进来的是true
                if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
                    if (profile.isPreferred(mDevice)) {
                        ++preferredProfiles;
                        connectInt(profile);                        // 连接对应的profile
                    }
                }
            }
            if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles);
    
            if (preferredProfiles == 0) {
                connectAutoConnectableProfiles();
            }
        }
    
        private void connectAutoConnectableProfiles() {
            if (!ensurePaired()) {
                return;
            }
            // Reset the only-show-one-error-dialog tracking variable
            mIsConnectingErrorPossible = true;
    
            for (LocalBluetoothProfile profile : mProfiles) {
                if (profile.isAutoConnectable()) {
                    profile.setPreferred(mDevice, true);
                    connectInt(profile);
                }
            }
        }
    	
    3. 没有配对的设备,先进行配对
    	   private void pair() {
            if (!mCachedDevice.startPairing()) {
                Utils.showError(getContext(), mCachedDevice.getName(),
                        R.string.bluetooth_pairing_error_message);
            }
        }
    	
    	frameworksasepackagesSettingsLibsrccomandroidsettingslibluetoothCachedBluetoothDevice.java
    	   public boolean startPairing() {
            // Pairing is unreliable while scanning, so cancel discovery
            // 配对的时候,关闭扫描
    		if (mLocalAdapter.isDiscovering()) {
                mLocalAdapter.cancelDiscovery();
            }
    
            if (!mDevice.createBond()) {
                return false;
            }
    
            return true;
        }
    	
    	frameworksasecorejavaandroidluetoothBluetoothDevice.java
    	    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
        public boolean createBond() {
            final IBluetooth service = sService;
            if (service == null) {
                Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
                return false;
            }
            try {
                Log.i(TAG, "createBond() for device " + getAddress()
                        + " called by pid: " + Process.myPid()
                        + " tid: " + Process.myTid());
                return service.createBond(this, TRANSPORT_AUTO);
            } catch (RemoteException e) {
                Log.e(TAG, "", e);
            }
            return false;
        }
    	
    	packagesappsBluetoothsrccomandroidluetoothtserviceAdapterService.java
    	    private static class AdapterServiceBinder extends IBluetooth.Stub {
    	        public boolean createBond(BluetoothDevice device, int transport) {
                if (!Utils.checkCallerAllowManagedProfiles(mService)) {
                    Log.w(TAG, "createBond() - Not allowed for non-active user");
                    return false;
                }
    
                AdapterService service = getService();
                if (service == null) return false;
                return service.createBond(device, transport, null);		// bond
            }
    		
    		
    		// 建立bond
    	     boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                "Need BLUETOOTH ADMIN permission");
            DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
            if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
                return false;
            }
    		// 在多播的时候不要进行bond,不明白这个multicast是什么意思
            // Multicast: Do not allow bonding while multcast
            A2dpService a2dpService = A2dpService.getA2dpService();
            if (a2dpService != null &&
                a2dpService.isMulticastFeatureEnabled() &&
                a2dpService.isMulticastOngoing(null)) {
                Log.i(TAG,"A2dp Multicast is ongoing, ignore bonding");
                return false;
            }
    
            mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
    
            // Pairing is unreliable while scanning, so cancel discovery
            // Note, remove this when native stack improves
            if (!mAdapterProperties.isDiscovering()) {
                Log.i(TAG,"discovery not active, no need to send cancelDiscovery");
            } else {
                cancelDiscoveryNative();
            }
    		// 或去状态机的消息
            Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
            msg.obj = device;
            msg.arg1 = transport;
    
            if (oobData != null) {
                Bundle oobDataBundle = new Bundle();
                oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
                msg.setData(oobDataBundle);
            }
    		// 发送消息给状态机
            mBondStateMachine.sendMessage(msg);
            return true;
        }
    		
    packagesappsBluetoothsrccomandroidluetoothtserviceBondStateMachine.java
       private class StableState extends State {
            @Override
            public void enter() {
                infoLog("StableState(): Entering Off State");
            }
    
            @Override
            public synchronized boolean processMessage(Message msg) {
    
                BluetoothDevice dev = (BluetoothDevice)msg.obj;
    
                switch(msg.what) {
    
                  case CREATE_BOND:
                      OobData oobData = null;
                      if (msg.getData() != null)
                          oobData = msg.getData().getParcelable(OOBDATA);
    
                      createBond(dev, msg.arg1, oobData, true);
                      break;
                  case REMOVE_BOND:
                      removeBond(dev, true);
                      break;
                  case BONDING_STATE_CHANGE:
                    int newState = msg.arg1;
                    /* if incoming pairing, transition to pending state */
                    if (newState == BluetoothDevice.BOND_BONDING)
                    {
                        if(!mDevices.contains(dev)) {
                            mDevices.add(dev);
                        }
                        sendIntent(dev, newState, 0);
                        transitionTo(mPendingCommandState);
                    }
                    else if (newState == BluetoothDevice.BOND_NONE)
                    {
                        /* if the link key was deleted by the stack */
                        sendIntent(dev, newState, 0);
                    }
                    else
                    {
                        Log.e(TAG, "In stable state, received invalid newState: " + newState);
                    }
                    break;
    
                  case CANCEL_BOND:
                  default:
                       Log.e(TAG, "Received unhandled state: " + msg.what);
                       return false;
                }
                return true;
            }
        }
    	
    
       private boolean createBond(BluetoothDevice dev, int transport, OobData oobData,
                                   boolean transition) {
            if(mAdapterService == null) return false;
            if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
                infoLog("Bond address is:" + dev);
                byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
                boolean result;
    			// 调用JNI
                if (oobData != null) {
                    result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
                } else {
                    result = mAdapterService.createBondNative(addr, transport);
                }
    
                if (!result) {
                    sendIntent(dev, BluetoothDevice.BOND_NONE,
                               BluetoothDevice.UNBOND_REASON_REMOVED);
                    return false;
                } else if (transition) {
                    transitionTo(mPendingCommandState);
                }
                return true;
            }
            return false;
        }
    
    

    Liu Tao

    2019-3-27

  • 相关阅读:
    Integer to English Words
    Word Ladder II
    Word Ladder
    Distinct Subsequences
    Interleaving String
    Scramble String
    【转】ROC和AUC介绍以及如何计算AUC
    Minimum Size Subarray Sum
    Minimum Window Substring
    Edit Distance
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/10608246.html
Copyright © 2011-2022 走看看