Add VPN app into power saver whitelist for a while to start its service

If the VPN app is not launched, then its background service
cannot receive the VpnManager events.
Add VPN app into power saver whitelist for a while can let its
background service to receive VpnManager events.

Bug: 234104087
Test: Confirm that the VPN app has received VpnManager events.
Change-Id: I9819a78ec0cbbd6879baae645ef42c22756b09d4
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index f62d7c4..2e64a74 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -100,6 +100,12 @@
     /**
      * Action sent in {@link android.content.Intent}s to VpnManager clients when an event occurred.
      *
+     * <p>If the provisioning application declares a service handling this intent action, but is not
+     * already running, it will be started. Upon starting, the application is granted a short grace
+     * period to run in the background even while the device is idle to handle any potential
+     * failures. Applications requiring long-running actions triggered by one of these events should
+     * declare a foreground service to prevent being killed once the grace period expires.
+     *
      * This action will have a category of either {@link #CATEGORY_EVENT_IKE_ERROR},
      * {@link #CATEGORY_EVENT_NETWORK_ERROR}, or {@link #CATEGORY_EVENT_DEACTIVATED_BY_USER},
      * that the app can use to filter events it's interested in reacting to.
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 511aef2..6abe5c6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -192,6 +192,10 @@
     // the device idle allowlist during service launch and VPN bootstrap.
     private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000;
 
+    // Length of time (in milliseconds) that an app registered for VpnManager events is placed on
+    // the device idle allowlist each time the a VpnManager event is fired.
+    private static final long VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS = 30 * 1000;
+
     private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME =
             Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST;
     /**
@@ -720,6 +724,14 @@
             intent.putExtra(VpnManager.EXTRA_ERROR_CLASS, errorClass);
             intent.putExtra(VpnManager.EXTRA_ERROR_CODE, errorCode);
         }
+
+        // Allow VpnManager app to temporarily run background services to handle this error.
+        // If an app requires anything beyond this grace period, they MUST either declare
+        // themselves as a foreground service, or schedule a job/workitem.
+        DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal();
+        idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
+                VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN,
+                "VpnManager event");
         try {
             return mUserIdContext.startService(intent) != null;
         } catch (RuntimeException e) {