From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Sun, 31 Jul 2022 11:19:33 +0300 Subject: [PATCH] Bluetooth auto turn off Co-authored-by: Pratyush --- core/java/android/provider/Settings.java | 6 ++ .../android/server/ext/BluetoothAutoOff.java | 69 +++++++++++++++++++ .../android/server/ext/SystemServerExt.java | 4 ++ 3 files changed, 79 insertions(+) create mode 100644 services/core/java/com/android/server/ext/BluetoothAutoOff.java diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 823177ed7b57..e12274516a55 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -17251,6 +17251,12 @@ public final class Settings { */ public static final String WIFI_OFF_TIMEOUT = "wifi_off_timeout"; + /** + * The amount of time in milliseconds before a disconnected Bluetooth adapter is turned off + * @hide + */ + public static final String BLUETOOTH_OFF_TIMEOUT = "bluetooth_off_timeout"; + /** * Settings migrated from Wear OS settings provider. * @hide diff --git a/services/core/java/com/android/server/ext/BluetoothAutoOff.java b/services/core/java/com/android/server/ext/BluetoothAutoOff.java new file mode 100644 index 000000000000..4e7dbc042f37 --- /dev/null +++ b/services/core/java/com/android/server/ext/BluetoothAutoOff.java @@ -0,0 +1,69 @@ +package com.android.server.ext; + +import android.annotation.Nullable; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.provider.Settings; +import android.util.Slog; + +class BluetoothAutoOff extends DelayedConditionalAction { + @Nullable + private final BluetoothAdapter adapter; + + BluetoothAutoOff(SystemServerExt sse) { + super(sse, sse.bgHandler); + adapter = sse.context.getSystemService(BluetoothManager.class).getAdapter(); + } + + @Override + protected boolean shouldScheduleAlarm() { + return isAdapterOnAndDisconnected(); + } + + @Override + protected void alarmTriggered() { + if (isAdapterOnAndDisconnected()) { + adapter.disable(); + } + } + + @Override + protected void registerStateListener() { + IntentFilter f = new IntentFilter(); + f.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + f.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); + + sse.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context broadcastContext, Intent intent) { + if (Build.isDebuggable()) { + Slog.d("BtAutoOff", "" + intent + ", extras " + intent.getExtras().deepCopy()); + } + update(); + } + }, f, handler); + } + + private boolean isAdapterOnAndDisconnected() { + if (adapter != null) { + int state = adapter.getLeStateSysApi(); // getState() converts BLE states into STATE_OFF + + if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) { + // getConnectionState() converts BLE states into STATE_DISCONNECTED + return adapter.getConnectionStateLeAware() == BluetoothAdapter.STATE_DISCONNECTED; + } + } + + return false; + } + + @Override + protected String getDelayGlobalSettingsKey() { + return Settings.Global.BLUETOOTH_OFF_TIMEOUT; + } +} diff --git a/services/core/java/com/android/server/ext/SystemServerExt.java b/services/core/java/com/android/server/ext/SystemServerExt.java index 66350e2b7f74..3c341ed25f4e 100644 --- a/services/core/java/com/android/server/ext/SystemServerExt.java +++ b/services/core/java/com/android/server/ext/SystemServerExt.java @@ -53,6 +53,10 @@ public final class SystemServerExt { if (packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI, 0)) { new WifiAutoOff(this); } + + if (packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH, 0)) { + new BluetoothAutoOff(this); + } } public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter, Handler handler) {