diff options
15 files changed, 142 insertions, 41 deletions
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 @@ package android { 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 @@ package android.provider { 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 @@ package android { 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 @@ package android.provider { 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 @@ public class DevicePolicyManager { * 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,20 +616,46 @@ public final class Settings { /** * 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 - * to be shown, with the "package" scheme. That is "package:com.my.app". + * 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. + * 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. + * <p> + * You can use {@link android.os.PowerManager#isIgnoringBatteryOptimizations + * PowerManager.isIgnoringBatteryOptimizations()} to determine if an application is + * already ignoring optimizations. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = + "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; + + /** * @hide * Activity Action: Show the "app ops" settings screen. * <p> 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 @@ public final class WebViewFactory { 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 @@ public final class WebViewFactory { 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 @@ LOCAL_CFLAGS += -Wall -Werror -Wno-error=deprecated-declarations -Wunused -Wunre # 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 class SettingsBackupAgent extends BackupAgentHelper { public void run() { if (restoredSupplicantData != null || restoredWifiConfigFile != null) { if (DEBUG_BACKUP) { - Log.v(TAG, "Starting deferred restore of 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); + Log.v(TAG, "Applying restored wifi data"); } - // !!! 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { void initWifiRestoreIfNecessary() { if (mWifiRestore == null) { mWifiRestore = new WifiRestoreRunnable(); + mWifiDisable = new WifiDisableRunnable(mWifiRestore); } } @@ -518,13 +548,16 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // 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 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal 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 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // 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.ActivityInfo; 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 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { post(new Runnable() { @Override @@ -671,7 +673,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @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 @@ public class MobileSignalController extends SignalController< 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 @@ public class AccountManagerService // 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 @@ public class AccountManagerService 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 @@ public class IdleController extends StateController { private AlarmManager mAlarm; private PendingIntent mIdleTriggerIntent; boolean mIdle; + boolean mScreenOn; public IdlenessTracker() { mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); @@ -120,6 +121,7 @@ public class IdleController extends StateController { // 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 @@ public class IdleController extends StateController { 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 @@ public class IdleController extends StateController { 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 @@ public class ActivityTestMain extends Activity { 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; |