Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +48 −0 Original line number Diff line number Diff line Loading @@ -5169,6 +5169,33 @@ public class AdapterService extends Service { return service.getOffloadedTransportDiscoveryDataScanSupported(); } @Override public void isMediaProfileConnected( AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(isMediaProfileConnected(source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission( allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private boolean isMediaProfileConnected(AttributionSource source) { AdapterService service = getService(); if (service == null || !Utils.checkConnectPermissionForDataDelivery( service, source, "AdapterService.isMediaProfileConnected")) { return false; } enforceBluetoothPrivilegedPermission(service); return service.isMediaProfileConnected(); } @Override public IBluetoothGatt getBluetoothGatt() { AdapterService service = getService(); Loading Loading @@ -6845,6 +6872,27 @@ public class AdapterService extends Service { } } boolean isMediaProfileConnected() { if (mA2dpService != null && mA2dpService.getConnectedDevices().size() > 0) { debugLog("isMediaProfileConnected. A2dp is connected"); return true; } else if (mHearingAidService != null && mHearingAidService.getConnectedDevices().size() > 0) { debugLog("isMediaProfileConnected. HearingAid is connected"); return true; } else if (mLeAudioService != null && mLeAudioService.getConnectedDevices().size() > 0) { debugLog("isMediaProfileConnected. LeAudio is connected"); return true; } else { debugLog( "isMediaProfileConnected: no Media connected." + (" A2dp=" + mA2dpService) + (" HearingAid=" + mHearingAidService) + (" LeAudio=" + mLeAudioService)); return false; } } /** * Notify GATT of a Bluetooth profile's connection state change for a given {@link * BluetoothProfile}. Loading android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +1 −1 Original line number Diff line number Diff line Loading @@ -359,7 +359,7 @@ public class HearingAidService extends ProfileService { return true; } List<BluetoothDevice> getConnectedDevices() { public List<BluetoothDevice> getConnectedDevices() { synchronized (mStateMachines) { List<BluetoothDevice> devices = new ArrayList<>(); for (HearingAidStateMachine sm : mStateMachines.values()) { Loading service/src/com/android/server/bluetooth/AdapterBinder.kt +19 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.bluetooth.IBluetoothCallback import android.content.AttributionSource import android.os.IBinder import android.os.RemoteException import android.util.Log import com.android.modules.utils.SynchronousResultReceiver import com.android.server.bluetooth.BluetoothManagerService.timeToLog import java.time.Duration Loading @@ -29,6 +30,7 @@ import java.util.concurrent.TimeoutException val SYNC_TIMEOUT = Duration.ofSeconds(3) class AdapterBinder(rawBinder: IBinder) { private val TAG = "AdapterBinder" val adapterBinder: IBluetooth = IBluetooth.Stub.asInterface(rawBinder) val createdAt = System.currentTimeMillis() Loading Loading @@ -116,4 +118,21 @@ class AdapterBinder(rawBinder: IBinder) { adapterBinder.unregAllGattClient(source, recv) recv.awaitResultNoInterrupt(SYNC_TIMEOUT).getValue(null) } fun isMediaProfileConnected(source: AttributionSource): Boolean { try { val recv: SynchronousResultReceiver<Boolean> = SynchronousResultReceiver.get() adapterBinder.isMediaProfileConnected(source, recv) return recv.awaitResultNoInterrupt(SYNC_TIMEOUT).getValue(false) } catch (ex: Exception) { when (ex) { is RemoteException, is TimeoutException -> { Log.e(TAG, "Error when calling isMediaProfileConnected", ex) } else -> throw ex } return false } } } service/src/com/android/server/bluetooth/BluetoothAirplaneModeListener.java +5 −6 Original line number Diff line number Diff line Loading @@ -184,8 +184,9 @@ class BluetoothAirplaneModeListener extends Handler { if (isAirplaneModeOn) { mApmEnabledTime = SystemClock.elapsedRealtime(); mIsBluetoothOnBeforeApmToggle = mAirplaneHelper.isBluetoothOn(); mIsBluetoothOnAfterApmToggle = shouldSkipAirplaneModeChange(); mIsMediaProfileConnectedBeforeApmToggle = mAirplaneHelper.isMediaProfileConnected(); mIsMediaProfileConnectedBeforeApmToggle = mBluetoothManager.isMediaProfileConnected(); mIsBluetoothOnAfterApmToggle = shouldSkipAirplaneModeChange(mIsMediaProfileConnectedBeforeApmToggle); if (mIsBluetoothOnAfterApmToggle) { Log.i(TAG, "Ignore airplane mode change"); // Airplane mode enabled when Bluetooth is being used for audio/hearing aid. Loading Loading @@ -244,14 +245,12 @@ class BluetoothAirplaneModeListener extends Handler { } @VisibleForTesting boolean shouldSkipAirplaneModeChange() { boolean shouldSkipAirplaneModeChange(boolean isMediaProfileConnected) { boolean apmEnhancementUsed = isApmEnhancementEnabled() && isBluetoothToggledOnApm(); // APM feature disabled or user has not used the feature yet by changing BT state in APM // BT will only remain on in APM when media profile is connected if (!apmEnhancementUsed && mAirplaneHelper.isBluetoothOn() && mAirplaneHelper.isMediaProfileConnected()) { if (!apmEnhancementUsed && mAirplaneHelper.isBluetoothOn() && isMediaProfileConnected) { return true; } // APM feature enabled and user has used the feature by changing BT state in APM Loading service/src/com/android/server/bluetooth/BluetoothManagerService.java +8 −8 Original line number Diff line number Diff line Loading @@ -24,9 +24,7 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF; import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_ENHANCEMENT; import static java.util.Objects.requireNonNull; import android.annotation.NonNull; Loading Loading @@ -215,8 +213,6 @@ class BluetoothManagerService { private List<Integer> mSupportedProfileList = new ArrayList<>(); private BluetoothModeChangeHelper mBluetoothModeChangeHelper; private final BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; private BluetoothNotificationManager mBluetoothNotificationManager; Loading Loading @@ -972,6 +968,13 @@ class BluetoothManagerService { return mIsHearingAidProfileSupported; } boolean isMediaProfileConnected() { if (mAdapter == null || !mState.oneOf(STATE_ON)) { return false; } return mAdapter.isMediaProfileConnected(mContext.getAttributionSource()); } // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = Loading Loading @@ -1459,10 +1462,7 @@ class BluetoothManagerService { mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS); } mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext); if (mBluetoothAirplaneModeListener != null) { mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } mBluetoothAirplaneModeListener.start(new BluetoothModeChangeHelper(mContext)); setApmEnhancementState(); } Loading Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +48 −0 Original line number Diff line number Diff line Loading @@ -5169,6 +5169,33 @@ public class AdapterService extends Service { return service.getOffloadedTransportDiscoveryDataScanSupported(); } @Override public void isMediaProfileConnected( AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(isMediaProfileConnected(source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission( allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private boolean isMediaProfileConnected(AttributionSource source) { AdapterService service = getService(); if (service == null || !Utils.checkConnectPermissionForDataDelivery( service, source, "AdapterService.isMediaProfileConnected")) { return false; } enforceBluetoothPrivilegedPermission(service); return service.isMediaProfileConnected(); } @Override public IBluetoothGatt getBluetoothGatt() { AdapterService service = getService(); Loading Loading @@ -6845,6 +6872,27 @@ public class AdapterService extends Service { } } boolean isMediaProfileConnected() { if (mA2dpService != null && mA2dpService.getConnectedDevices().size() > 0) { debugLog("isMediaProfileConnected. A2dp is connected"); return true; } else if (mHearingAidService != null && mHearingAidService.getConnectedDevices().size() > 0) { debugLog("isMediaProfileConnected. HearingAid is connected"); return true; } else if (mLeAudioService != null && mLeAudioService.getConnectedDevices().size() > 0) { debugLog("isMediaProfileConnected. LeAudio is connected"); return true; } else { debugLog( "isMediaProfileConnected: no Media connected." + (" A2dp=" + mA2dpService) + (" HearingAid=" + mHearingAidService) + (" LeAudio=" + mLeAudioService)); return false; } } /** * Notify GATT of a Bluetooth profile's connection state change for a given {@link * BluetoothProfile}. Loading
android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +1 −1 Original line number Diff line number Diff line Loading @@ -359,7 +359,7 @@ public class HearingAidService extends ProfileService { return true; } List<BluetoothDevice> getConnectedDevices() { public List<BluetoothDevice> getConnectedDevices() { synchronized (mStateMachines) { List<BluetoothDevice> devices = new ArrayList<>(); for (HearingAidStateMachine sm : mStateMachines.values()) { Loading
service/src/com/android/server/bluetooth/AdapterBinder.kt +19 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.bluetooth.IBluetoothCallback import android.content.AttributionSource import android.os.IBinder import android.os.RemoteException import android.util.Log import com.android.modules.utils.SynchronousResultReceiver import com.android.server.bluetooth.BluetoothManagerService.timeToLog import java.time.Duration Loading @@ -29,6 +30,7 @@ import java.util.concurrent.TimeoutException val SYNC_TIMEOUT = Duration.ofSeconds(3) class AdapterBinder(rawBinder: IBinder) { private val TAG = "AdapterBinder" val adapterBinder: IBluetooth = IBluetooth.Stub.asInterface(rawBinder) val createdAt = System.currentTimeMillis() Loading Loading @@ -116,4 +118,21 @@ class AdapterBinder(rawBinder: IBinder) { adapterBinder.unregAllGattClient(source, recv) recv.awaitResultNoInterrupt(SYNC_TIMEOUT).getValue(null) } fun isMediaProfileConnected(source: AttributionSource): Boolean { try { val recv: SynchronousResultReceiver<Boolean> = SynchronousResultReceiver.get() adapterBinder.isMediaProfileConnected(source, recv) return recv.awaitResultNoInterrupt(SYNC_TIMEOUT).getValue(false) } catch (ex: Exception) { when (ex) { is RemoteException, is TimeoutException -> { Log.e(TAG, "Error when calling isMediaProfileConnected", ex) } else -> throw ex } return false } } }
service/src/com/android/server/bluetooth/BluetoothAirplaneModeListener.java +5 −6 Original line number Diff line number Diff line Loading @@ -184,8 +184,9 @@ class BluetoothAirplaneModeListener extends Handler { if (isAirplaneModeOn) { mApmEnabledTime = SystemClock.elapsedRealtime(); mIsBluetoothOnBeforeApmToggle = mAirplaneHelper.isBluetoothOn(); mIsBluetoothOnAfterApmToggle = shouldSkipAirplaneModeChange(); mIsMediaProfileConnectedBeforeApmToggle = mAirplaneHelper.isMediaProfileConnected(); mIsMediaProfileConnectedBeforeApmToggle = mBluetoothManager.isMediaProfileConnected(); mIsBluetoothOnAfterApmToggle = shouldSkipAirplaneModeChange(mIsMediaProfileConnectedBeforeApmToggle); if (mIsBluetoothOnAfterApmToggle) { Log.i(TAG, "Ignore airplane mode change"); // Airplane mode enabled when Bluetooth is being used for audio/hearing aid. Loading Loading @@ -244,14 +245,12 @@ class BluetoothAirplaneModeListener extends Handler { } @VisibleForTesting boolean shouldSkipAirplaneModeChange() { boolean shouldSkipAirplaneModeChange(boolean isMediaProfileConnected) { boolean apmEnhancementUsed = isApmEnhancementEnabled() && isBluetoothToggledOnApm(); // APM feature disabled or user has not used the feature yet by changing BT state in APM // BT will only remain on in APM when media profile is connected if (!apmEnhancementUsed && mAirplaneHelper.isBluetoothOn() && mAirplaneHelper.isMediaProfileConnected()) { if (!apmEnhancementUsed && mAirplaneHelper.isBluetoothOn() && isMediaProfileConnected) { return true; } // APM feature enabled and user has used the feature by changing BT state in APM Loading
service/src/com/android/server/bluetooth/BluetoothManagerService.java +8 −8 Original line number Diff line number Diff line Loading @@ -24,9 +24,7 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF; import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static com.android.server.bluetooth.BluetoothAirplaneModeListener.APM_ENHANCEMENT; import static java.util.Objects.requireNonNull; import android.annotation.NonNull; Loading Loading @@ -215,8 +213,6 @@ class BluetoothManagerService { private List<Integer> mSupportedProfileList = new ArrayList<>(); private BluetoothModeChangeHelper mBluetoothModeChangeHelper; private final BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; private BluetoothNotificationManager mBluetoothNotificationManager; Loading Loading @@ -972,6 +968,13 @@ class BluetoothManagerService { return mIsHearingAidProfileSupported; } boolean isMediaProfileConnected() { if (mAdapter == null || !mState.oneOf(STATE_ON)) { return false; } return mAdapter.isMediaProfileConnected(mContext.getAttributionSource()); } // Monitor change of BLE scan only mode settings. private void registerForBleScanModeChange() { ContentObserver contentObserver = Loading Loading @@ -1459,10 +1462,7 @@ class BluetoothManagerService { mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS); } mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext); if (mBluetoothAirplaneModeListener != null) { mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } mBluetoothAirplaneModeListener.start(new BluetoothModeChangeHelper(mContext)); setApmEnhancementState(); } Loading