Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16c08c08 authored by William Escande's avatar William Escande
Browse files

AirplaneListener: ask app for media profile state

Directly ask the app what profiles are connected.
This removes the need to store profiles and register listeners.

Bug: 271963349
Test: atest BluetoothAirplaneModeListenerTest
Change-Id: I4c31e5ca855fc2007cf6d9a35537eb8e0eb8e78e
parent 4a4b1ba2
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -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();
@@ -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}.
+1 −1
Original line number Diff line number Diff line
@@ -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()) {
+19 −0
Original line number Diff line number Diff line
@@ -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
@@ -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()

@@ -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
        }
    }
}
+5 −6
Original line number Diff line number Diff line
@@ -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.
@@ -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
+8 −8
Original line number Diff line number Diff line
@@ -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;
@@ -215,8 +213,6 @@ class BluetoothManagerService {

    private List<Integer> mSupportedProfileList = new ArrayList<>();

    private BluetoothModeChangeHelper mBluetoothModeChangeHelper;

    private final BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;

    private BluetoothNotificationManager mBluetoothNotificationManager;
@@ -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 =
@@ -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