Loading service/Android.bp +5 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ filegroup { name: "services.bluetooth-sources", srcs: [ "java/**/*.java", ":statslog-bluetooth-java-gen", ], visibility: [ "//frameworks/base/services", Loading Loading @@ -60,6 +61,7 @@ java_library { "framework-annotations-lib", "framework-bluetooth-pre-jarjar", "app-compat-annotations", "framework-statsd.stubs.module_lib", ], static_libs: [ Loading @@ -69,6 +71,9 @@ java_library { "bluetooth-manager-service-proto-java-gen", "bluetooth-proto-enums-java-gen", "bluetooth-nano-protos", "bluetooth-protos-lite", "libprotobuf-java-lite", "bluetooth-proto-enums-java-gen", ], apex_available: [ Loading service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java +77 −36 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ import android.database.ContentObserver; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; import com.android.bluetooth.BluetoothStatsLog; import com.android.internal.annotations.VisibleForTesting; /** Loading Loading @@ -68,6 +70,19 @@ public class BluetoothAirplaneModeListener { @VisibleForTesting static final int MAX_TOAST_COUNT = 10; // 10 times /* Tracks the bluetooth state before entering airplane mode*/ private boolean mIsBluetoothOnBeforeApmToggle = false; /* Tracks the bluetooth state after entering airplane mode*/ private boolean mIsBluetoothOnAfterApmToggle = false; /* Tracks whether user toggled bluetooth in airplane mode */ private boolean mUserToggledBluetoothDuringApm = false; /* Tracks whether user toggled bluetooth in airplane mode within one minute */ private boolean mUserToggledBluetoothDuringApmWithinMinute = false; /* Tracks whether media profile was connected before entering airplane mode */ private boolean mIsMediaProfileConnectedBeforeApmToggle = false; /* Tracks when airplane mode has been enabled */ private long mApmEnabledTime = 0; private final BluetoothManagerService mBluetoothManager; private final BluetoothAirplaneModeHandler mHandler; private final Context mContext; Loading Loading @@ -138,7 +153,15 @@ public class BluetoothAirplaneModeListener { @VisibleForTesting @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) void handleAirplaneModeChange() { if (shouldSkipAirplaneModeChange()) { if (mAirplaneHelper == null) { return; } if (mAirplaneHelper.isAirplaneModeOn()) { mApmEnabledTime = SystemClock.elapsedRealtime(); mIsBluetoothOnBeforeApmToggle = mAirplaneHelper.isBluetoothOn(); mIsBluetoothOnAfterApmToggle = shouldSkipAirplaneModeChange(); mIsMediaProfileConnectedBeforeApmToggle = mAirplaneHelper.isMediaProfileConnected(); if (mIsBluetoothOnAfterApmToggle) { Log.i(TAG, "Ignore airplane mode change"); // Airplane mode enabled when Bluetooth is being used for audio/headering aid. // Bluetooth is not disabled in such case, only state is changed to Loading @@ -156,9 +179,11 @@ public class BluetoothAirplaneModeListener { "bluetooth_and_wifi_stays_on_message", APM_WIFI_BT_NOTIFICATION); } catch (Exception e) { Log.e(TAG, "APM enhancement BT and Wi-Fi stays on notification not shown"); Log.e(TAG, "APM enhancement BT and Wi-Fi stays on notification not shown"); } } else if (!isWifiEnabledOnApm() && isFirstTimeNotification(APM_BT_NOTIFICATION)) { } else if (!isWifiEnabledOnApm() && isFirstTimeNotification( APM_BT_NOTIFICATION)) { try { sendApmNotification("bluetooth_stays_on_title", "bluetooth_stays_on_message", Loading @@ -170,29 +195,35 @@ public class BluetoothAirplaneModeListener { } return; } if (mAirplaneHelper != null) { mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager); } else { BluetoothStatsLog.write(BluetoothStatsLog.AIRPLANE_MODE_SESSION_REPORTED, BluetoothStatsLog.AIRPLANE_MODE_SESSION_REPORTED__PACKAGE_NAME__BLUETOOTH, mIsBluetoothOnBeforeApmToggle, mIsBluetoothOnAfterApmToggle, mAirplaneHelper.isBluetoothOn(), isBluetoothToggledOnApm(), mUserToggledBluetoothDuringApm, mUserToggledBluetoothDuringApmWithinMinute, mIsMediaProfileConnectedBeforeApmToggle); mUserToggledBluetoothDuringApm = false; mUserToggledBluetoothDuringApmWithinMinute = false; } mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager); } @VisibleForTesting boolean shouldSkipAirplaneModeChange() { if (mAirplaneHelper == null) { return false; } 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.isAirplaneModeOn() && mAirplaneHelper.isMediaProfileConnected()) { return true; } // APM feature enabled and user has used the feature by changing BT state in APM // BT will only remain on in APM based on user's last action in APM if (apmEnhancementUsed && mAirplaneHelper.isBluetoothOn() && mAirplaneHelper.isAirplaneModeOn() && mAirplaneHelper.isBluetoothOnAPM()) { return true; } Loading @@ -200,7 +231,6 @@ public class BluetoothAirplaneModeListener { // BT will only remain on in APM if the default value is set to on if (isApmEnhancementEnabled() && !isBluetoothToggledOnApm() && mAirplaneHelper.isBluetoothOn() && mAirplaneHelper.isAirplaneModeOn() && mAirplaneHelper.isBluetoothOnAPM()) { return true; } Loading Loading @@ -245,4 +275,15 @@ public class BluetoothAirplaneModeListener { mAirplaneHelper.setSettingsSecureInt(notificationState, NOTIFICATION_SHOWN); } /** * Helper method to update whether user toggled Bluetooth in airplane mode */ public void updateBluetoothToggledTime() { if (!mUserToggledBluetoothDuringApm) { mUserToggledBluetoothDuringApmWithinMinute = SystemClock.elapsedRealtime() - mApmEnabledTime < 60000; } mUserToggledBluetoothDuringApm = true; } } service/java/com/android/server/bluetooth/BluetoothManagerService.java +23 −17 Original line number Diff line number Diff line Loading @@ -1359,7 +1359,9 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; if (isAirplaneModeOn() && isApmEnhancementOn()) { if (isAirplaneModeOn()) { mBluetoothAirplaneModeListener.updateBluetoothToggledTime(); if (isApmEnhancementOn()) { setSettingsSecureInt(BLUETOOTH_APM_STATE, BLUETOOTH_ON_APM); setSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, USED); if (isFirstTimeNotification(APM_BT_ENABLED_NOTIFICATION)) { Loading @@ -1376,6 +1378,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } } } } // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); Loading Loading @@ -1416,10 +1419,13 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } synchronized (mReceiver) { if (isAirplaneModeOn() && isApmEnhancementOn()) { if (isAirplaneModeOn()) { mBluetoothAirplaneModeListener.updateBluetoothToggledTime(); if (isApmEnhancementOn()) { setSettingsSecureInt(BLUETOOTH_APM_STATE, BLUETOOTH_OFF_APM); setSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, USED); } } if (persist) { persistBluetoothSetting(BLUETOOTH_OFF); Loading service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java +0 −3 Original line number Diff line number Diff line Loading @@ -84,9 +84,6 @@ public class BluetoothAirplaneModeListenerTest { Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); when(mHelper.isMediaProfileConnected()).thenReturn(true); Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); when(mHelper.isAirplaneModeOn()).thenReturn(true); Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); } Loading Loading
service/Android.bp +5 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ filegroup { name: "services.bluetooth-sources", srcs: [ "java/**/*.java", ":statslog-bluetooth-java-gen", ], visibility: [ "//frameworks/base/services", Loading Loading @@ -60,6 +61,7 @@ java_library { "framework-annotations-lib", "framework-bluetooth-pre-jarjar", "app-compat-annotations", "framework-statsd.stubs.module_lib", ], static_libs: [ Loading @@ -69,6 +71,9 @@ java_library { "bluetooth-manager-service-proto-java-gen", "bluetooth-proto-enums-java-gen", "bluetooth-nano-protos", "bluetooth-protos-lite", "libprotobuf-java-lite", "bluetooth-proto-enums-java-gen", ], apex_available: [ Loading
service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java +77 −36 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ import android.database.ContentObserver; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; import com.android.bluetooth.BluetoothStatsLog; import com.android.internal.annotations.VisibleForTesting; /** Loading Loading @@ -68,6 +70,19 @@ public class BluetoothAirplaneModeListener { @VisibleForTesting static final int MAX_TOAST_COUNT = 10; // 10 times /* Tracks the bluetooth state before entering airplane mode*/ private boolean mIsBluetoothOnBeforeApmToggle = false; /* Tracks the bluetooth state after entering airplane mode*/ private boolean mIsBluetoothOnAfterApmToggle = false; /* Tracks whether user toggled bluetooth in airplane mode */ private boolean mUserToggledBluetoothDuringApm = false; /* Tracks whether user toggled bluetooth in airplane mode within one minute */ private boolean mUserToggledBluetoothDuringApmWithinMinute = false; /* Tracks whether media profile was connected before entering airplane mode */ private boolean mIsMediaProfileConnectedBeforeApmToggle = false; /* Tracks when airplane mode has been enabled */ private long mApmEnabledTime = 0; private final BluetoothManagerService mBluetoothManager; private final BluetoothAirplaneModeHandler mHandler; private final Context mContext; Loading Loading @@ -138,7 +153,15 @@ public class BluetoothAirplaneModeListener { @VisibleForTesting @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) void handleAirplaneModeChange() { if (shouldSkipAirplaneModeChange()) { if (mAirplaneHelper == null) { return; } if (mAirplaneHelper.isAirplaneModeOn()) { mApmEnabledTime = SystemClock.elapsedRealtime(); mIsBluetoothOnBeforeApmToggle = mAirplaneHelper.isBluetoothOn(); mIsBluetoothOnAfterApmToggle = shouldSkipAirplaneModeChange(); mIsMediaProfileConnectedBeforeApmToggle = mAirplaneHelper.isMediaProfileConnected(); if (mIsBluetoothOnAfterApmToggle) { Log.i(TAG, "Ignore airplane mode change"); // Airplane mode enabled when Bluetooth is being used for audio/headering aid. // Bluetooth is not disabled in such case, only state is changed to Loading @@ -156,9 +179,11 @@ public class BluetoothAirplaneModeListener { "bluetooth_and_wifi_stays_on_message", APM_WIFI_BT_NOTIFICATION); } catch (Exception e) { Log.e(TAG, "APM enhancement BT and Wi-Fi stays on notification not shown"); Log.e(TAG, "APM enhancement BT and Wi-Fi stays on notification not shown"); } } else if (!isWifiEnabledOnApm() && isFirstTimeNotification(APM_BT_NOTIFICATION)) { } else if (!isWifiEnabledOnApm() && isFirstTimeNotification( APM_BT_NOTIFICATION)) { try { sendApmNotification("bluetooth_stays_on_title", "bluetooth_stays_on_message", Loading @@ -170,29 +195,35 @@ public class BluetoothAirplaneModeListener { } return; } if (mAirplaneHelper != null) { mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager); } else { BluetoothStatsLog.write(BluetoothStatsLog.AIRPLANE_MODE_SESSION_REPORTED, BluetoothStatsLog.AIRPLANE_MODE_SESSION_REPORTED__PACKAGE_NAME__BLUETOOTH, mIsBluetoothOnBeforeApmToggle, mIsBluetoothOnAfterApmToggle, mAirplaneHelper.isBluetoothOn(), isBluetoothToggledOnApm(), mUserToggledBluetoothDuringApm, mUserToggledBluetoothDuringApmWithinMinute, mIsMediaProfileConnectedBeforeApmToggle); mUserToggledBluetoothDuringApm = false; mUserToggledBluetoothDuringApmWithinMinute = false; } mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager); } @VisibleForTesting boolean shouldSkipAirplaneModeChange() { if (mAirplaneHelper == null) { return false; } 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.isAirplaneModeOn() && mAirplaneHelper.isMediaProfileConnected()) { return true; } // APM feature enabled and user has used the feature by changing BT state in APM // BT will only remain on in APM based on user's last action in APM if (apmEnhancementUsed && mAirplaneHelper.isBluetoothOn() && mAirplaneHelper.isAirplaneModeOn() && mAirplaneHelper.isBluetoothOnAPM()) { return true; } Loading @@ -200,7 +231,6 @@ public class BluetoothAirplaneModeListener { // BT will only remain on in APM if the default value is set to on if (isApmEnhancementEnabled() && !isBluetoothToggledOnApm() && mAirplaneHelper.isBluetoothOn() && mAirplaneHelper.isAirplaneModeOn() && mAirplaneHelper.isBluetoothOnAPM()) { return true; } Loading Loading @@ -245,4 +275,15 @@ public class BluetoothAirplaneModeListener { mAirplaneHelper.setSettingsSecureInt(notificationState, NOTIFICATION_SHOWN); } /** * Helper method to update whether user toggled Bluetooth in airplane mode */ public void updateBluetoothToggledTime() { if (!mUserToggledBluetoothDuringApm) { mUserToggledBluetoothDuringApmWithinMinute = SystemClock.elapsedRealtime() - mApmEnabledTime < 60000; } mUserToggledBluetoothDuringApm = true; } }
service/java/com/android/server/bluetooth/BluetoothManagerService.java +23 −17 Original line number Diff line number Diff line Loading @@ -1359,7 +1359,9 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; if (isAirplaneModeOn() && isApmEnhancementOn()) { if (isAirplaneModeOn()) { mBluetoothAirplaneModeListener.updateBluetoothToggledTime(); if (isApmEnhancementOn()) { setSettingsSecureInt(BLUETOOTH_APM_STATE, BLUETOOTH_ON_APM); setSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, USED); if (isFirstTimeNotification(APM_BT_ENABLED_NOTIFICATION)) { Loading @@ -1376,6 +1378,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } } } } // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); Loading Loading @@ -1416,10 +1419,13 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } synchronized (mReceiver) { if (isAirplaneModeOn() && isApmEnhancementOn()) { if (isAirplaneModeOn()) { mBluetoothAirplaneModeListener.updateBluetoothToggledTime(); if (isApmEnhancementOn()) { setSettingsSecureInt(BLUETOOTH_APM_STATE, BLUETOOTH_OFF_APM); setSettingsSecureInt(APM_USER_TOGGLED_BLUETOOTH, USED); } } if (persist) { persistBluetoothSetting(BLUETOOTH_OFF); Loading
service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java +0 −3 Original line number Diff line number Diff line Loading @@ -84,9 +84,6 @@ public class BluetoothAirplaneModeListenerTest { Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); when(mHelper.isMediaProfileConnected()).thenReturn(true); Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); when(mHelper.isAirplaneModeOn()).thenReturn(true); Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange()); } Loading