Merge "Crash apps with bad notification icons." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index e295a63..4b36adc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -106,6 +106,7 @@
     field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
     field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
+    field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
@@ -26444,6 +26445,7 @@
     field public static final java.lang.String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS";
     field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
+    field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
diff --git a/api/system-current.txt b/api/system-current.txt
index 8b9af5e..36cd869 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -180,6 +180,7 @@
     field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
     field public static final java.lang.String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
+    field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
@@ -28502,6 +28503,7 @@
     field public static final java.lang.String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS";
     field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
+    field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c505b0b..e3414d9 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3204,8 +3204,13 @@
      * Called by a profile or device owner to set the application restrictions for a given target
      * application running in the profile.
      *
-     * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be
-     * boolean, int, String, or String[].
+     * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be:
+     * <ul>
+     * <li>{@code boolean}
+     * <li>{@code int}
+     * <li>{@code String} or {@code String[]}
+     * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]}
+     * </ul>
      *
      * <p>The application restrictions are only made visible to the target application and the
      * profile or device owner.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6e178a4..fe95864 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -616,7 +616,33 @@
     /**
      * Activity Action: Show screen for controlling which apps can ignore battery optimizations.
      * <p>
-     * Input: Optionally, the Intent's data URI specifies the application package name
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * <p>
+     * You can use {@link android.os.PowerManager#isIgnoringBatteryOptimizations
+     * PowerManager.isIgnoringBatteryOptimizations()} to determine if an application is
+     * already ignoring optimizations.  You can use
+     * {@link #ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS} to ask the user to put you
+     * on this list.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS =
+            "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
+
+    /**
+     * Activity Action: Ask the user to allow an to ignore battery optimizations (that is,
+     * put them on the whitelist of apps shown by
+     * {@link #ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}).  For an app to use this, it also
+     * must hold the {@link android.Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}
+     * permission.
+     * <p><b>Note:</b> most applications should <em>not</em> use this; there are many facilities
+     * provided by the platform for applications to operate correctly in the various power
+     * saving mode.  This is only for unusual applications that need to deeply control their own
+     * execution, at the potential expense of the user's battery life.  Note that these applications
+     * greatly run the risk of showing to the user has how power consumers on their device.</p>
+     * <p>
+     * Input: The Intent's data URI must specify the application package name
      * to be shown, with the "package" scheme.  That is "package:com.my.app".
      * <p>
      * Output: Nothing.
@@ -626,8 +652,8 @@
      * already ignoring optimizations.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS =
-            "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
+    public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS =
+            "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
 
     /**
      * @hide
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 3b9aca8..584deff 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -314,8 +314,7 @@
                     if (path.contains("!/")) {
                         String[] split = TextUtils.split(path, "!/");
                         if (split.length == 2) {
-                            try {
-                                ZipFile z = new ZipFile(split[0]);
+                            try (ZipFile z = new ZipFile(split[0])) {
                                 ZipEntry e = z.getEntry(split[1]);
                                 if (e != null && e.getMethod() == ZipEntry.STORED) {
                                     newVmSize = Math.max(newVmSize, e.getSize());
@@ -355,8 +354,7 @@
                                              String[] abiList,
                                              String nativeLibFileName) {
         // Search the APK for a native library conforming to a listed ABI.
-        try {
-            ZipFile z = new ZipFile(apkPath);
+        try (ZipFile z = new ZipFile(apkPath)) {
             for (String abi : abiList) {
                 final String entry = "lib/" + abi + "/" + nativeLibFileName;
                 ZipEntry e = z.getEntry(entry);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 5e5450e..6b07a47 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -269,6 +269,10 @@
 #                        is not being compiled with that level. Remove once this has changed.
 LOCAL_CFLAGS += -Wno-c++11-extensions
 
+# b/22414716: thread_local (android/graphics/Paint.cpp) and Clang don't like each other at the
+#             moment.
+LOCAL_CLANG := false
+
 include $(BUILD_SHARED_LIBRARY)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 53b553e8..629d14b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2257,6 +2257,13 @@
     <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
         android:protectionLevel="system|signature" />
 
+    <!-- Permission an application must hold in order to use
+         {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
+         This is a normal permission: an app requesting it will always be granted the
+         permission, without the user needing to approve or see it. -->
+    <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
+        android:protectionLevel="normal" />
+
     <!-- @SystemApi Allows an application to collect battery statistics -->
     <permission android:name="android.permission.BATTERY_STATS"
         android:protectionLevel="signature|privileged|development" />
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index e74334b..b9a9c24 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -148,7 +148,10 @@
     private WifiManager mWfm;
     private static String mWifiConfigFile;
 
+    // Chain of asynchronous operations used when rewriting the wifi supplicant config file
+    WifiDisableRunnable mWifiDisable = null;
     WifiRestoreRunnable mWifiRestore = null;
+    int mRetainedWifiState; // used only during config file rewrite
 
     // Class for capturing a network definition from the wifi supplicant config file
     static class Network {
@@ -407,9 +410,47 @@
         writeNewChecksums(stateChecksums, newState);
     }
 
+    class WifiDisableRunnable implements Runnable {
+        final WifiRestoreRunnable mNextPhase;
+
+        public WifiDisableRunnable(WifiRestoreRunnable next) {
+            mNextPhase = next;
+        }
+
+        @Override
+        public void run() {
+            if (DEBUG_BACKUP) {
+                Log.v(TAG, "Disabling wifi during restore");
+            }
+            final ContentResolver cr = getContentResolver();
+            final int scanAlways = Settings.Global.getInt(cr,
+                    Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
+            final int retainedWifiState = enableWifi(false);
+            if (scanAlways != 0) {
+                Settings.Global.putInt(cr,
+                        Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
+            }
+
+            // Tell the final stage how to clean up after itself
+            mNextPhase.setPriorState(retainedWifiState, scanAlways);
+
+            // And run it after a modest pause to give broadcasts and content
+            // observers time an opportunity to run on this looper thread, so
+            // that the wifi stack actually goes all the way down.
+            new Handler(getMainLooper()).postDelayed(mNextPhase, 2500);
+        }
+    }
+
     class WifiRestoreRunnable implements Runnable {
         private byte[] restoredSupplicantData;
         private byte[] restoredWifiConfigFile;
+        private int retainedWifiState;  // provided by disable stage
+        private int scanAlways; // provided by disable stage
+
+        void setPriorState(int retainedState, int always) {
+            retainedWifiState = retainedState;
+            scanAlways = always;
+        }
 
         void incorporateWifiSupplicant(BackupDataInput data) {
             restoredSupplicantData = new byte[data.getDataSize()];
@@ -437,20 +478,8 @@
         public void run() {
             if (restoredSupplicantData != null || restoredWifiConfigFile != null) {
                 if (DEBUG_BACKUP) {
-                    Log.v(TAG, "Starting deferred restore of wifi data");
+                    Log.v(TAG, "Applying restored wifi data");
                 }
-                final ContentResolver cr = getContentResolver();
-                final int scanAlways = Settings.Global.getInt(cr,
-                        Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
-                final int retainedWifiState = enableWifi(false);
-                if (scanAlways != 0) {
-                    Settings.Global.putInt(cr,
-                            Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
-                }
-                // !!! Give the wifi stack a moment to quiesce.  We've observed the
-                // response to disabling WIFI_SCAN_ALWAYS_AVAILABLE taking more
-                // than 1500ms, so we wait a generous 2500 here before proceeding.
-                try { Thread.sleep(2500); } catch (InterruptedException e) {}
                 if (restoredSupplicantData != null) {
                     restoreWifiSupplicant(FILE_WIFI_SUPPLICANT,
                             restoredSupplicantData, restoredSupplicantData.length);
@@ -465,7 +494,7 @@
                 }
                 // restore the previous WIFI state.
                 if (scanAlways != 0) {
-                    Settings.Global.putInt(cr,
+                    Settings.Global.putInt(getContentResolver(),
                             Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, scanAlways);
                 }
                 enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
@@ -479,6 +508,7 @@
     void initWifiRestoreIfNecessary() {
         if (mWifiRestore == null) {
             mWifiRestore = new WifiRestoreRunnable();
+            mWifiDisable = new WifiDisableRunnable(mWifiRestore);
         }
     }
 
@@ -518,13 +548,16 @@
         }
 
         // If we have wifi data to restore, post a runnable to perform the
-        // bounce-and-update operation a little ways in the future.
+        // bounce-and-update operation a little ways in the future.  The
+        // 'disable' runnable brings down the stack and remembers its state,
+        // and in turn schedules the 'restore' runnable to do the rewrite
+        // and cleanup operations.
         if (mWifiRestore != null) {
             long wifiBounceDelayMillis = Settings.Global.getLong(
                     getContentResolver(),
                     Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS,
                     WIFI_BOUNCE_DELAY_MILLIS);
-            new Handler(getMainLooper()).postDelayed(mWifiRestore, wifiBounceDelayMillis);
+            new Handler(getMainLooper()).postDelayed(mWifiDisable, wifiBounceDelayMillis);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index abdebf3..0068f84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1121,9 +1121,6 @@
             mViewPool.returnViewToPool(tv);
         }
 
-        // Notify the callback that we've removed the task and it can clean up after it
-        mCb.onTaskViewDismissed(removedTask);
-
         // Get the stack scroll of the task to anchor to (since we are removing something, the front
         // most task will be our anchor task)
         Task anchorTask = null;
@@ -1172,6 +1169,11 @@
             // Fade the dismiss button back in
             showDismissAllButton();
         }
+
+        // Notify the callback that we've removed the task and it can clean up after it. Note, we
+        // do this after onAllTaskViewsDismissed() is called, to allow the home activity to be
+        // started before the call to remove the task.
+        mCb.onTaskViewDismissed(removedTask);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 6627360..42a2f90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -601,6 +602,7 @@
     }
 
     private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
+        @Override
         public void onReceive(Context context, Intent intent) {
             post(new Runnable() {
                 @Override
@@ -671,7 +673,8 @@
 
         @Override
         public void onFingerprintError(int msgId, String errString) {
-            if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()) {
+            if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()
+                    || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
                 return;
             }
             // TODO: Go to bouncer if this is "too many attempts" (lockout) error.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ed1dca3..b65bf43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -88,8 +88,10 @@
 
         mapIconSets();
 
-        mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault;
-        mLastState.networkNameData = mCurrentState.networkNameData = mNetworkNameDefault;
+        String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
+                : mNetworkNameDefault;
+        mLastState.networkName = mCurrentState.networkName = networkName;
+        mLastState.networkNameData = mCurrentState.networkNameData = networkName;
         mLastState.enabled = mCurrentState.enabled = hasMobileData;
         mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
         // Get initial data sim state.
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 83e8db0..aab6374 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2604,7 +2604,8 @@
             // Prune the list down to just the requested type.
             visibleAccountTypes = new ArrayList<>();
             visibleAccountTypes.add(type);
-        } // else aggregate all the visible accounts (it won't matter if the list is empty).
+        } // else aggregate all the visible accounts (it won't matter if the
+          // list is empty).
 
         long identityToken = clearCallingIdentity();
         try {
@@ -3788,8 +3789,15 @@
     private List<String> getTypesForCaller(
             int callingUid, int userId, boolean isOtherwisePermitted) {
         List<String> managedAccountTypes = new ArrayList<>();
+        long identityToken = Binder.clearCallingIdentity();
+        Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> serviceInfos;
+        try {
+            serviceInfos = mAuthenticatorCache.getAllServices(userId);
+        } finally {
+            Binder.restoreCallingIdentity(identityToken);
+        }
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
-                mAuthenticatorCache.getAllServices(userId)) {
+                serviceInfos) {
             final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
             if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) {
                 managedAccountTypes.add(serviceInfo.type.type);
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index 8e2ca18..92df851 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -108,6 +108,7 @@
         private AlarmManager mAlarm;
         private PendingIntent mIdleTriggerIntent;
         boolean mIdle;
+        boolean mScreenOn;
 
         public IdlenessTracker() {
             mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
@@ -120,6 +121,7 @@
             // At boot we presume that the user has just "interacted" with the
             // device in some meaningful way.
             mIdle = false;
+            mScreenOn = true;
         }
 
         public boolean isIdle() {
@@ -149,12 +151,14 @@
 
             if (action.equals(Intent.ACTION_SCREEN_ON)
                     || action.equals(Intent.ACTION_DREAMING_STOPPED)) {
-                // possible transition to not-idle
+                if (DEBUG) {
+                    Slog.v(TAG,"exiting idle : " + action);
+                }
+                mScreenOn = true;
+                //cancel the alarm
+                mAlarm.cancel(mIdleTriggerIntent);
                 if (mIdle) {
-                    if (DEBUG) {
-                        Slog.v(TAG, "exiting idle : " + action);
-                    }
-                    mAlarm.cancel(mIdleTriggerIntent);
+                // possible transition to not-idle
                     mIdle = false;
                     reportNewIdleState(mIdle);
                 }
@@ -169,11 +173,12 @@
                     Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
                             + when);
                 }
+                mScreenOn = false;
                 mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                         when, IDLE_WINDOW_SLOP, mIdleTriggerIntent);
             } else if (action.equals(ACTION_TRIGGER_IDLE)) {
-                // idle time starts now
-                if (!mIdle) {
+                // idle time starts now. Do not set mIdle if screen is on.
+                if (!mIdle && !mScreenOn) {
                     if (DEBUG) {
                         Slog.v(TAG, "Idle trigger fired @ " + SystemClock.elapsedRealtime());
                     }
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index 73cb432..7b9c9f1 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -24,6 +24,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
     <uses-sdk android:targetSdkVersion="22" />
     <application android:label="ActivityTest">
         <activity android:name="ActivityTestMain">
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 2f0bf39..5fbfe8a 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -465,9 +465,12 @@
         menu.add("Ignore battery optimizations").setOnMenuItemClickListener(
                 new MenuItem.OnMenuItemClickListener() {
             @Override public boolean onMenuItemClick(MenuItem item) {
-                Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
+                Intent intent;
                 if (!mPower.isIgnoringBatteryOptimizations(getPackageName())) {
+                    intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                     intent.setData(Uri.fromParts("package", getPackageName(), null));
+                } else {
+                    intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
                 }
                 startActivity(intent);
                 return true;