Toggle Notification

Fix per user context
Use translatable resource for channel name
Rework autoOn notification text
Create AutoOn action to turn feature off
Fix AutoOn notification linking to airplane mode help url

Bug: 323060869
Bug: 316946334
Fix: 324332031
Test: m Bluetooth | NotificationHelperService is not tested
Change-Id: I1dae21d96a537810c5a1d9ec70ec5346c07e069b
diff --git a/android/app/AndroidManifest.xml b/android/app/AndroidManifest.xml
index c87c771..c0548dd 100644
--- a/android/app/AndroidManifest.xml
+++ b/android/app/AndroidManifest.xml
@@ -110,6 +110,7 @@
              android:permission="android.permission.BLUETOOTH_PRIVILEGED">
             <intent-filter>
                 <action android:name="android.bluetooth.notification.action.SEND_TOGGLE_NOTIFICATION"/>
+                <action android:name="android.bluetooth.notification.action.AUTO_ON_USER_ACTION"/>
             </intent-filter>
         </service>
 
diff --git a/android/app/res/drawable/ic_bluetooth_settings.xml b/android/app/res/drawable/ic_bluetooth_settings.xml
new file mode 100644
index 0000000..00678fb
--- /dev/null
+++ b/android/app/res/drawable/ic_bluetooth_settings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M450,472.15L277.08,645.08Q268.77,653.38 256.19,653.58Q243.62,653.77 234.92,645.08Q226.23,636.38 226.23,624Q226.23,611.62 234.92,602.92L437.85,400L234.92,197.08Q226.62,188.77 226.42,176.19Q226.23,163.62 234.92,154.92Q243.62,146.23 256,146.23Q268.38,146.23 277.08,154.92L450,327.85L450,71.23Q450,54.77 461.04,44.62Q472.08,34.46 486.15,34.46Q493,34.46 499.42,37.08Q505.85,39.69 511.46,45.31L668.84,202.69Q674.46,208.31 676.77,214.54Q679.08,220.77 679.08,228Q679.08,235.23 676.77,241.46Q674.46,247.69 668.84,253.31L522.15,400L668.84,546.69Q674.46,552.31 676.77,558.54Q679.08,564.77 679.08,572Q679.08,579.23 676.77,585.46Q674.46,591.69 668.84,597.31L511.46,754.69Q505.85,760.31 499.42,762.92Q493,765.54 486.15,765.54Q472.08,765.54 461.04,755.38Q450,745.23 450,728.77L450,472.15ZM510,670.62L609.85,572L510,472.15L510,670.62ZM510,327.85L609.85,228L510,129.38L510,327.85ZM320,955.38Q305.31,955.38 294.96,945.04Q284.62,934.69 284.62,920Q284.62,905.31 294.96,894.96Q305.31,884.62 320,884.62Q334.69,884.62 345.04,894.96Q355.38,905.31 355.38,920Q355.38,934.69 345.04,945.04Q334.69,955.38 320,955.38ZM480,955.38Q465.31,955.38 454.96,945.04Q444.62,934.69 444.62,920Q444.62,905.31 454.96,894.96Q465.31,884.62 480,884.62Q494.69,884.62 505.04,894.96Q515.38,905.31 515.38,920Q515.38,934.69 505.04,945.04Q494.69,955.38 480,955.38ZM640,955.38Q625.31,955.38 614.96,945.04Q604.62,934.69 604.62,920Q604.62,905.31 614.96,894.96Q625.31,884.62 640,884.62Q654.69,884.62 665.04,894.96Q675.38,905.31 675.38,920Q675.38,934.69 665.04,945.04Q654.69,955.38 640,955.38Z" />
+</vector>
diff --git a/android/app/res/values/strings.xml b/android/app/res/values/strings.xml
index cd42305..fe34075 100644
--- a/android/app/res/values/strings.xml
+++ b/android/app/res/values/strings.xml
@@ -256,6 +256,8 @@
     <string name="bluetooth_stays_on_message">Your device remembers to keep Bluetooth on in airplane mode. Turn off Bluetooth if you don\'t want it to stay on.</string>
     <string name="bluetooth_and_wifi_stays_on_title">Wi-Fi and Bluetooth stay on</string>
     <string name="bluetooth_and_wifi_stays_on_message">Your device remembers to keep Wi-Fi and Bluetooth on in airplane mode. Turn off Wi-Fi and Bluetooth if you don\'t want them to stay on.</string>
-    <string name="bluetooth_enabled_auto_on_title">Bluetooth was restarted automatically</string>
-    <string name="bluetooth_enabled_auto_on_message">Bluetooth has been automatically re-enabled. To prevent Bluetooth from re-enabling automatically, go to Bluetooth settings.</string>
+    <string name="bluetooth_enabled_auto_on_title">Bluetooth has been automatically enabled</string>
+    <string name="bluetooth_enabled_auto_on_message">Automatic restart can be toggled in Bluetooth Settings.</string>
+    <string name="bluetooth_disable_auto_on">Turn off</string>
+    <string name="bluetooth_notification_group">Bluetooth automatic state change</string>
 </resources>
diff --git a/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java b/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java
index 481e161..07bb45e 100644
--- a/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java
+++ b/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java
@@ -23,7 +23,9 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Service;
+import android.bluetooth.BluetoothManager;
 import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.IBinder;
 import android.provider.Settings;
@@ -50,7 +52,17 @@
 
     private static final String NOTIFICATION_TAG = "com.android.bluetooth";
     private static final String NOTIFICATION_CHANNEL = "notification_toggle_channel";
-    private static final String NOTIFICATION_GROUP = "notification_toggle_group";
+    private static final int NOTIFICATION_GROUP = R.string.bluetooth_notification_group;
+
+    private static final String NOTIFICATION_ACTION =
+            "android.bluetooth.notification.action.SEND_TOGGLE_NOTIFICATION";
+    private static final String NOTIFICATION_EXTRA =
+            "android.bluetooth.notification.extra.NOTIFICATION_REASON";
+
+    private static final String AUTO_ON_USER_ACTION =
+            "android.bluetooth.notification.action.AUTO_ON_USER_ACTION";
+    private static final String AUTO_ON_USER_EXTRA =
+            "android.bluetooth.notification.extra.AUTO_ON_DISABLE";
 
     private static final Map<String, Pair<Integer /* titleId */, Integer /* messageId */>>
             NOTIFICATION_MAP =
@@ -79,8 +91,14 @@
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        sendToggleNotification(
-                intent.getStringExtra("android.bluetooth.notification.extra.NOTIFICATION_REASON"));
+        switch (intent.getAction()) {
+            case NOTIFICATION_ACTION -> {
+                sendToggleNotification(intent.getStringExtra(NOTIFICATION_EXTRA));
+            }
+            case AUTO_ON_USER_ACTION -> {
+                autoOnUserAction(intent.getBooleanExtra(AUTO_ON_USER_EXTRA, false));
+            }
+        }
         return Service.START_NOT_STICKY;
     }
 
@@ -102,16 +120,17 @@
 
         NotificationManager notificationManager =
                 requireNonNull(getSystemService(NotificationManager.class));
+        String tag = NOTIFICATION_TAG + "/" + notificationReason;
         for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
-            if (NOTIFICATION_TAG.equals(notification.getTag())) {
-                notificationManager.cancel(NOTIFICATION_TAG, notification.getId());
+            if (tag.equals(notification.getTag())) {
+                notificationManager.cancel(tag, notification.getId());
             }
         }
 
         notificationManager.createNotificationChannel(
                 new NotificationChannel(
                         NOTIFICATION_CHANNEL,
-                        NOTIFICATION_GROUP,
+                        getString(NOTIFICATION_GROUP),
                         NotificationManager.IMPORTANCE_HIGH));
 
         String title = getString(notificationContent.first);
@@ -127,7 +146,7 @@
                         .setStyle(new Notification.BigTextStyle().bigText(message))
                         .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth);
 
-        if (notificationReason != AUTO_ON_BT_ENABLED_NOTIFICATION) {
+        if (!notificationReason.equals(AUTO_ON_BT_ENABLED_NOTIFICATION)) {
             // Do not display airplane link when the notification is due to auto_on feature
             String helpLinkUrl = getString(R.string.config_apmLearnMoreLink);
             builder.setContentIntent(
@@ -138,14 +157,37 @@
                                     .setData(Uri.parse(helpLinkUrl))
                                     .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
                             PendingIntent.FLAG_IMMUTABLE));
+        } else {
+            Intent baseIntent =
+                    new Intent()
+                            .setAction(AUTO_ON_USER_ACTION)
+                            .setClass(this, NotificationHelperService.class);
+            PendingIntent disablePendingIntent =
+                    PendingIntent.getService(
+                            this,
+                            0,
+                            new Intent(baseIntent).putExtra(AUTO_ON_USER_EXTRA, true),
+                            PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
+            builder.addAction(
+                    new Notification.Action.Builder(
+                                    Icon.createWithResource(this, R.drawable.ic_bluetooth_settings),
+                                    getString(R.string.bluetooth_disable_auto_on),
+                                    disablePendingIntent)
+                            .build());
         }
 
         notificationManager.notify(
-                NOTIFICATION_TAG, SystemMessage.ID.NOTE_BT_APM_NOTIFICATION_VALUE, builder.build());
+                tag, SystemMessage.ID.NOTE_BT_APM_NOTIFICATION_VALUE, builder.build());
     }
 
     /** Return whether the notification has been shown */
     private boolean isFirstTimeNotification(String name) {
         return Settings.Secure.getInt(getContentResolver(), name, 0) == 0;
     }
+
+    private void autoOnUserAction(boolean disableAutoOn) {
+        if (disableAutoOn) {
+            getSystemService(BluetoothManager.class).getAdapter().setAutoOnEnabled(false);
+        }
+    }
 }
diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java
index c4aae21..13172e8 100644
--- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java
+++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java
@@ -437,7 +437,7 @@
         intent.setComponent(resolveSystemService(intent));
         intent.putExtra(
                 "android.bluetooth.notification.extra.NOTIFICATION_REASON", notificationReason);
-        mContext.startService(intent);
+        mCurrentUserContext.startService(intent);
         return Unit.INSTANCE;
     }