DivestOS/Patches/LineageOS-18.1/android_frameworks_base/0015-Bluetooth_Timeout.patch
2022-03-15 01:27:08 -04: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 0ac089362b92..d7e3e8f13acd 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14474,6 +14474,12 @@ public final class Settings {
public static final String NR_NSA_TRACKING_SCREEN_OFF_MODE =
"nr_nsa_tracking_screen_off_mode";
+ /**
+ * The amount of time in milliseconds before bluetooth is turned off
+ * @hide
+ */
+ public static final String BLUETOOTH_OFF_TIMEOUT = "bluetooth_off_timeout";
+
/**
* Whether to automatically reboot the device after a user defined timeout
*
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 9ce7cf27f9ff..9598faa3a667 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -21,6 +21,7 @@ import static android.os.UserHandle.USER_SYSTEM;
import android.Manifest;
import android.app.ActivityManager;
+import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.bluetooth.BluetoothAdapter;
@@ -512,6 +513,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);
}
/**