\#Android 6.0 의 Bluetooth Enable 프로 세 스 분석
26856 단어 Bluetooth
최근 에 블 루 투 스 모듈 코드 를 분석 하기 시 작 했 습 니 다.여기 서 기록 하 겠 습 니 다.본 고 는 주로 Android 6.0 코드 를 바탕 으로 하 는 블 루 투 스 시스템 서 비 스 를 바탕 으로 절차 분석 을 할 수 있 습 니 다.jni 이하 의 절차 인터넷 에 많은 글 이 명확 하 게 쓰 여 있 기 때문에 본 고 는 package 와 framework 층 의 흐름 만 분석 하고 관련 된 주요 유형 은 다음 과 같 습 니 다.
블 루 투 스 활성화
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);
}
이로써 장치 가 지원 하 는 프로필 서비스 가 모두 시작 되 었 음 을 알 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Raspberry Pi를 Bluetooth 오디오 서버로 설정하기 위한 가장 빠른 설정 단계다음 내용을 참조하여 Raspberry Pi에 Ubuntu를 설치합니다. 처음 시작할 때 DHCP는 자동으로 개인 IP 주소를 부여하지만 이 주소는 지금까지 래스퍼리피에 부여된 것과 다르면 일일이 다시 작성~/.ss...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.