2022-04-04 21:48:14 -04:00
|
|
|
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
|
2022-04-25 21:27:29 -04:00
|
|
|
index 87ed442b0f79..069ad604024b 100644
|
2022-04-04 21:48:14 -04:00
|
|
|
--- a/core/java/android/provider/Settings.java
|
|
|
|
+++ b/core/java/android/provider/Settings.java
|
|
|
|
@@ -16385,6 +16385,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 f5ff7a3d71a4..8123494599b6 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;
|
|
|
|
@@ -549,6 +550,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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|