Merge "Allowed custom secure-adb confirmation via Activity or Service. It used to only be available via an Activity." into klp-modular-dev
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0b42588..88deb39 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1332,10 +1332,10 @@
          Example: com.google.android.myapp/.resolver.MyResolverActivity  -->
     <string name="config_customResolverActivity"></string>
 
-    <!-- Name of the activity that prompts the user to reject, accept, or whitelist
+    <!-- Name of the activity or service that prompts the user to reject, accept, or whitelist
          an adb host's public key, when an unwhitelisted host connects to the local adbd.
          Can be customized for other product types -->
-    <string name="config_customAdbPublicKeyActivity"
+    <string name="config_customAdbPublicKeyConfirmationComponent"
             >com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity</string>
 
     <!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 323494a..f88b8bb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1625,7 +1625,7 @@
   <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
   <java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
   <java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
-  <java-symbol type="string" name="config_customAdbPublicKeyActivity" />
+  <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index f73d425..0946c5a 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -20,6 +20,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
@@ -210,7 +212,7 @@
                 case MESSAGE_ADB_CONFIRM: {
                     String key = (String)msg.obj;
                     mFingerprints = getFingerprints(key);
-                    showConfirmationDialog(key, mFingerprints);
+                    startConfirmation(key, mFingerprints);
                     break;
                 }
 
@@ -245,22 +247,60 @@
         return sb.toString();
     }
 
-    private void showConfirmationDialog(String key, String fingerprints) {
-        Intent intent = new Intent();
+    private void startConfirmation(String key, String fingerprints) {
+        String nameString = Resources.getSystem().getString(
+                com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
+        ComponentName componentName = ComponentName.unflattenFromString(nameString);
+        if (startConfirmationActivity(componentName, key, fingerprints)
+                || startConfirmationService(componentName, key, fingerprints)) {
+            return;
+        }
+        Slog.e(TAG, "unable to start customAdbPublicKeyConfirmationComponent "
+                + nameString + " as an Activity or a Service");
+    }
 
-        ComponentName componentName = ComponentName.unflattenFromString(
-                Resources.getSystem().getString(
-                        com.android.internal.R.string.config_customAdbPublicKeyActivity));
-        intent.setClassName(componentName.getPackageName(),
-                componentName.getClassName());
+    /**
+     * @returns true if the componentName led to an Activity that was started.
+     */
+    private boolean startConfirmationActivity(ComponentName componentName, String key,
+            String fingerprints) {
+        PackageManager packageManager = mContext.getPackageManager();
+        Intent intent = createConfirmationIntent(componentName, key, fingerprints);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
+            try {
+                mContext.startActivity(intent);
+                return true;
+            } catch (ActivityNotFoundException e) {
+                Slog.e(TAG, "unable to start adb whitelist activity: " + componentName, e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @returns true if the componentName led to a Service that was started.
+     */
+    private boolean startConfirmationService(ComponentName componentName, String key,
+            String fingerprints) {
+        Intent intent = createConfirmationIntent(componentName, key, fingerprints);
+        try {
+            if (mContext.startService(intent) != null) {
+                return true;
+            }
+        } catch (SecurityException e) {
+            Slog.e(TAG, "unable to start adb whitelist service: " + componentName, e);
+        }
+        return false;
+    }
+
+    private Intent createConfirmationIntent(ComponentName componentName, String key,
+            String fingerprints) {
+        Intent intent = new Intent();
+        intent.setClassName(componentName.getPackageName(), componentName.getClassName());
         intent.putExtra("key", key);
         intent.putExtra("fingerprints", fingerprints);
-        try {
-            mContext.startActivity(intent);
-        } catch (ActivityNotFoundException e) {
-            Slog.e(TAG, "unable to start UsbDebuggingActivity");
-        }
+        return intent;
     }
 
     private File getUserKeyFile() {