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

Commit 5e29ffab authored by William Escande's avatar William Escande
Browse files

SystemServer: AutoOn: Airplane override

Suspend timer during Airplane time, only for legacy mode

Bug: 323060869
Bug: 316946334
Test: atest ServiceBluetoothRoboTest
Change-Id: Ie64f821a1a9f71f923876c6fd9ec2f81095ba931
parent e90d7a79
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import android.os.Looper
import android.provider.Settings
import androidx.annotation.VisibleForTesting
import com.android.modules.expresslog.Counter
import com.android.server.bluetooth.airplane.hasUserToggledApm as hasUserToggledApm
import com.android.server.bluetooth.airplane.isOn as isAirplaneModeOn
import com.android.server.bluetooth.satellite.isOn as isSatelliteModeOn
import java.time.LocalDateTime
import java.time.LocalTime
@@ -61,6 +63,13 @@ public fun resetAutoOnTimerForUser(
        Log.d(TAG, "Satellite prevent feature activation")
        return
    }
    if (isAirplaneModeOn) {
        if (!hasUserToggledApm(context)) {
            Log.d(TAG, "Airplane prevent feature activation")
            return
        }
        Log.d(TAG, "Airplane bypassed as airplane enhanced mode has been activated previously")
    }

    val receiver =
        object : BroadcastReceiver() {
+32 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import com.android.server.bluetooth.BluetoothAdapterState
import com.android.server.bluetooth.Log
import com.android.server.bluetooth.Timer
import com.android.server.bluetooth.USER_SETTINGS_KEY
import com.android.server.bluetooth.airplane.isOn as isAirplaneModeOn
import com.android.server.bluetooth.airplane.test.ModeListenerTest as AirplaneListener
import com.android.server.bluetooth.isUserEnabled
import com.android.server.bluetooth.isUserSupported
import com.android.server.bluetooth.notifyBluetoothOn
@@ -369,4 +371,34 @@ class AutoOnFeatureTest {
        expect.that(callback_count).isEqualTo(1)
        expectNoStorageTime()
    }

    @Test
    @kotlin.time.ExperimentalTime
    fun setupTimer_whenLegacyAirplaneIsOn_isNotSchedule() {
        val userCallback: () -> Context = { -> context }
        AirplaneListener.setupAirplaneModeToOn(resolver, looper, userCallback, false)
        assertThat(isAirplaneModeOn).isTrue()

        setupTimer()

        AirplaneListener.setupAirplaneModeToOff(resolver, looper)
        expect.that(timer).isNull()
        expect.that(callback_count).isEqualTo(0)
        expectNoStorageTime()
    }

    @Test
    @kotlin.time.ExperimentalTime
    fun setupTimer_whenApmAirplaneIsOn_isSchedule() {
        val userCallback: () -> Context = { -> context }
        AirplaneListener.setupAirplaneModeToOn(resolver, looper, userCallback, true)
        assertThat(isAirplaneModeOn).isTrue()

        setupTimer()

        AirplaneListener.setupAirplaneModeToOff(resolver, looper)
        expect.that(timer).isNotNull()
        expect.that(callback_count).isEqualTo(0)
        expectStorageTime()
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ private fun airplaneModeValueOverride(
        return currentAirplaneMode
    }
    // If "Airplane Enhancement Mode" is on and the user already used the feature …
    if (isApmEnhancementEnabled(resolver) && hasUserToggledApm(getUser)) {
    if (isApmEnhancementEnabled(resolver) && hasUserToggledApm(getUser())) {
        // … Staying on only depend on its last action in airplane mode
        if (isBluetoothOnAPM(getUser)) {
            Log.i(TAG, "Bluetooth stay on during airplane mode because of last user action")
@@ -299,7 +299,7 @@ private class AirplaneMetricSession(
            isBluetoothOnBeforeApmToggle,
            isBluetoothOnAfterApmToggle,
            isBluetoothOn,
            hasUserToggledApm(getUser),
            hasUserToggledApm(getUser()),
            userToggledBluetoothDuringApm,
            userToggledBluetoothDuringApmWithinMinute,
            isMediaProfileConnectedBeforeApmToggle,
@@ -344,8 +344,8 @@ private fun isWifiOnApm(resolver: ContentResolver, getUser: () -> Context) =
        Settings.Secure.getInt(getUser().contentResolver, WIFI_APM_STATE, 0) == 1

/** Airplane Enhancement Mode: Return true if this user already toggled (aka used) the feature */
private fun hasUserToggledApm(getUser: () -> Context) =
    Settings.Secure.getInt(getUser().contentResolver, APM_USER_TOGGLED_BLUETOOTH, 0) == 1
fun hasUserToggledApm(userContext: Context) =
    Settings.Secure.getInt(userContext.contentResolver, APM_USER_TOGGLED_BLUETOOTH, 0) == 1

/** Airplane Enhancement Mode: Return true if the bluetooth should stays on during airplane mode */
private fun isBluetoothOnAPM(getUser: () -> Context) =
+34 −0
Original line number Diff line number Diff line
@@ -56,6 +56,40 @@ import org.robolectric.shadows.ShadowToast
@RunWith(RobolectricTestRunner::class)
@kotlin.time.ExperimentalTime
class ModeListenerTest {
    companion object {
        internal fun setupAirplaneModeToOn(
            resolver: ContentResolver,
            looper: Looper,
            user: () -> Context,
            enableEnhancedMode: Boolean
        ) {
            enableSensitive(resolver, looper, Settings.Global.AIRPLANE_MODE_RADIOS)
            enableMode(resolver, looper, Settings.Global.AIRPLANE_MODE_ON)
            val mode: (m: Boolean) -> Unit = { _: Boolean -> }
            val notif: (m: String) -> Unit = { _: String -> }
            val media: () -> Boolean = { -> false }
            if (enableEnhancedMode) {
                Settings.Secure.putInt(resolver, APM_USER_TOGGLED_BLUETOOTH, 1)
            }

            initialize(
                looper,
                resolver,
                BluetoothAdapterState(),
                mode,
                notif,
                media,
                user,
                TimeSource.Monotonic,
            )
        }

        internal fun setupAirplaneModeToOff(resolver: ContentResolver, looper: Looper) {
            disableSensitive(resolver, looper, Settings.Global.AIRPLANE_MODE_RADIOS)
            disableMode(resolver, looper, Settings.Global.AIRPLANE_MODE_ON)
        }
    }

    private val looper: Looper = Looper.getMainLooper()
    private val state = BluetoothAdapterState()
    private val mContext = ApplicationProvider.getApplicationContext<Context>()
+6 −0
Original line number Diff line number Diff line
@@ -507,6 +507,10 @@ class BluetoothManagerService {
                // Clear registered LE apps to force shut-off
                clearBleApps();

                if (!AirplaneModeListener.hasUserToggledApm(mCurrentUserContext)) {
                    AutoOnFeature.pause();
                }

                // If state is BLE_ON make sure we trigger stopBle
                if (st == STATE_BLE_ON) {
                    mAdapterLock.readLock().lock();
@@ -535,6 +539,8 @@ class BluetoothManagerService {
                        mQuietEnableExternal,
                        BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
                        mContext.getPackageName());
            } else if (st != STATE_ON) {
                autoOnSetupTimer();
            }
        }
    }