DivestOS/Patches/LineageOS-19.1/android_frameworks_base/0015-Bluetooth_Timeout.patch
Tavi 44e57d0a5a
Picks
Signed-off-by: Tavi <tavi@divested.dev>
2024-02-07 19:38:52 -05:00

122 lines
5.3 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: pratyush <codelab@pratyush.dev>
Date: Thu, 1 Jul 2021 12:26:49 +0530
Subject: [PATCH] Bluetooth auto turn off
---
core/java/android/provider/Settings.java | 6 ++
.../server/BluetoothManagerService.java | 76 +++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5c7851d3fb41..8fb1272a5800 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16409,6 +16409,12 @@ public final class Settings {
* @hide
*/
public static final String SETTINGS_REBOOT_AFTER_TIMEOUT = "settings_reboot_after_timeout";
+
+ /**
+ * The amount of time in milliseconds before bluetooth is turned off
+ * @hide
+ */
+ public static final String BLUETOOTH_OFF_TIMEOUT = "bluetooth_off_timeout";
}
/**
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 8ceca50cbe72..8206a602e40e 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -29,6 +29,7 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
+import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -568,6 +569,81 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
Slog.w(TAG, "Unable to resolve SystemUI's UID.");
}
mSystemUiUid = systemUiUid;
+
+ /*
+ * System sends ACTION_STATE_CHANGED broadcast soon as any state
+ * changes. what it means in action is we don't have to take care if
+ * device reboot while BT has not been turned off automatically.
+ *
+ * A word of warning though it does not check if device as been
+ * unlocked or not what it means in real life is if you have sometime
+ * like tile ble tracker configured it will turn off BT. As result tile
+ * tracking will fail because of auto timeout. this behaviour can be
+ * changed with UserManager.isUnlocked()
+ * */
+ IntentFilter btFilter = new IntentFilter();
+ btFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ btFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
+ btFilter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+ context.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context broadcastContext, Intent intent) {
+ reconfigureBtTimeoutListener();
+ }
+ }, btFilter);
+
+ context.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.BLUETOOTH_OFF_TIMEOUT),
+ false,
+ new ContentObserver(new Handler(context.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ reconfigureBtTimeoutListener();
+ }
+ });
+ }
+
+ private static final AlarmManager.OnAlarmListener listener = () -> {
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (isBtOnAndDisconnected() && bluetoothAdapter != null) {
+ bluetoothAdapter.disable();
+ }
+ };
+
+ // If device is still connected cancel timeout for now and wait for disconnected signal
+ private void reconfigureBtTimeoutListener() {
+ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ if (isTimeoutEnabled(mContext) && isBtOnAndDisconnected()) {
+ final long timeout = SystemClock.elapsedRealtime() + btTimeoutDurationInMilli(mContext);
+ alarmManager.cancel(listener);
+ alarmManager.setExact(
+ AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ timeout,
+ "BT Idle Timeout",
+ listener,
+ new Handler(mContext.getMainLooper())
+ );
+ } else {
+ alarmManager.cancel(listener);
+ }
+ }
+
+ private static boolean isBtOnAndDisconnected() {
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ return bluetoothAdapter != null && bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON
+ && bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON &&
+ bluetoothAdapter.getConnectionState() == BluetoothAdapter.STATE_DISCONNECTED;
+ }
+
+ private static long btTimeoutDurationInMilli(Context context) {
+ return Settings.Global.getLong(context.getContentResolver(),
+ Settings.Global.BLUETOOTH_OFF_TIMEOUT, 0);
+ }
+
+ /** Zero is default and means disabled */
+ private static boolean isTimeoutEnabled(Context context) {
+ return 0 != btTimeoutDurationInMilli(context);
}
/**