Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a26b0729 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adding switch for Forced App Standby"

parents 64d3df8b 4c64777b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4630,6 +4630,12 @@
    <string name="background_activity_summary_off">App\'s background activity is limited when not in use</string>
    <!-- Summary for the background activity when it is disabled [CHAR_LIMIT=120] -->
    <string name="background_activity_summary_disabled">App not allowed to run in background</string>
    <!-- TODO: Pending UX review. Summary for the background activity when it is whitlisted [CHAR_LIMIT=120] -->
    <string name="background_activity_summary_whitelisted">App can not be optimized for battery use</string>
    <!-- TODO: Pending UX review. Title for the warning dialog to show to the user when limiting background activity for an app -->
    <string name="background_activity_warning_dialog_title">Limit background activity?</string>
    <!-- TODO: Pending UX review. Text for the warning dialog to show to the user when limiting background activity for an app -->
    <string name="background_activity_warning_dialog_text">If you limit background activity for an app, it may misbehave</string>
    <!-- Title for the screen usage in power use UI [CHAR_LIMIT=60] -->
    <string name="device_screen_usage">Screen usage since full charge</string>
+12 −2
Original line number Diff line number Diff line
@@ -68,7 +68,8 @@ import java.util.List;
public class AdvancedPowerUsageDetail extends DashboardFragment implements
        ButtonActionDialogFragment.AppButtonsDialogListener,
        AnomalyDialogFragment.AnomalyDialogListener,
        LoaderManager.LoaderCallbacks<List<Anomaly>> {
        LoaderManager.LoaderCallbacks<List<Anomaly>>,
        BackgroundActivityPreferenceController.WarningConfirmationListener {

    public static final String TAG = "AdvancedPowerUsageDetail";
    public static final String EXTRA_UID = "extra_uid";
@@ -109,6 +110,7 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
    @VisibleForTesting
    AnomalySummaryPreferenceController mAnomalySummaryPreferenceController;
    private AppButtonsPreferenceController mAppButtonsPreferenceController;
    private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;

    private DevicePolicyManagerWrapper mDpm;
    private UserManager mUserManager;
@@ -319,7 +321,9 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
        final int uid = bundle.getInt(EXTRA_UID, 0);
        final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);

        controllers.add(new BackgroundActivityPreferenceController(context, uid));
        mBackgroundActivityPreferenceController = new BackgroundActivityPreferenceController(
                context, this, uid, packageName);
        controllers.add(mBackgroundActivityPreferenceController);
        controllers.add(new BatteryOptimizationPreferenceController(
                (SettingsActivity) getActivity(), this, packageName));
        mAppButtonsPreferenceController = new AppButtonsPreferenceController(
@@ -364,4 +368,10 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
    public void onLoaderReset(Loader<List<Anomaly>> loader) {

    }

    @Override
    public void onLimitBackgroundActivity() {
        mBackgroundActivityPreferenceController.setUnchecked(
                findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
    }
}
+93 −28
Original line number Diff line number Diff line
@@ -14,12 +14,17 @@

package com.android.settings.fuelgauge;

import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.Dialog;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.SwitchPreference;
@@ -29,6 +34,7 @@ import android.util.Log;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -45,54 +51,72 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
    private final PackageManager mPackageManager;
    private final AppOpsManager mAppOpsManager;
    private final UserManager mUserManager;
    private final String[] mPackages;
    private final int mUid;
    @VisibleForTesting
    DevicePolicyManagerWrapper mDpm;

    private Fragment mFragment;
    private String mTargetPackage;
    private boolean mIsPreOApp;
    private PowerWhitelistBackend mPowerWhitelistBackend;

    public BackgroundActivityPreferenceController(Context context, Fragment fragment,
            int uid, String packageName) {
        this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance());
    }

    public BackgroundActivityPreferenceController(Context context, int uid) {
    @VisibleForTesting
    BackgroundActivityPreferenceController(Context context, Fragment fragment,
            int uid, String packageName, PowerWhitelistBackend backend) {
        super(context);
        mPowerWhitelistBackend = backend;
        mPackageManager = context.getPackageManager();
        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        mDpm = new DevicePolicyManagerWrapperImpl(
                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        mUid = uid;
        mPackages = mPackageManager.getPackagesForUid(mUid);
        mFragment = fragment;
        mTargetPackage = packageName;
        mIsPreOApp = isLegacyApp(packageName);
    }

    @Override
    public void updateState(Preference preference) {
        final int mode = mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
                .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
        final boolean whitelisted = mPowerWhitelistBackend.isWhitelisted(mTargetPackage);
        // Set checked or not before we may set it disabled
        if (mode != AppOpsManager.MODE_ERRORED) {
            final boolean checked = mode != AppOpsManager.MODE_IGNORED;
            final boolean checked = whitelisted || mode != AppOpsManager.MODE_IGNORED;
            ((SwitchPreference) preference).setChecked(checked);
        }
        if (mode == AppOpsManager.MODE_ERRORED
        if (whitelisted || mode == AppOpsManager.MODE_ERRORED
                || Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mTargetPackage)) {
            preference.setEnabled(false);
        } else {
            preference.setEnabled(true);
        }

        updateSummary(preference);
    }

    @Override
    public boolean isAvailable() {
        if (mPackages == null) {
            return false;
        }
        for (final String packageName : mPackages) {
            if (isLegacyApp(packageName)) {
                mTargetPackage = packageName;
                return true;
            }
        return mTargetPackage != null;
    }

        return false;
    /**
     * Called from the warning dialog, if the user decides to go ahead and disable background
     * activity for this package
     */
    public void setUnchecked(Preference preference) {
        if (mIsPreOApp) {
            mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
                    AppOpsManager.MODE_IGNORED);
        }
        mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
                AppOpsManager.MODE_IGNORED);
        ((SwitchPreference) preference).setChecked(false);
        updateSummary(preference);
    }

    @Override
@@ -102,19 +126,23 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        boolean switchOn = (Boolean) newValue;
        final boolean switchOn = (Boolean) newValue;
        if (!switchOn) {
            final WarningDialogFragment dialogFragment = new WarningDialogFragment();
            dialogFragment.setTargetFragment(mFragment, 0);
            dialogFragment.show(mFragment.getFragmentManager(), TAG);
            return false;
        }
        if (mIsPreOApp) {
            mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
                switchOn ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);

                    AppOpsManager.MODE_ALLOWED);
        }
        mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
                AppOpsManager.MODE_ALLOWED);
        updateSummary(preference);
        return true;
    }

    @VisibleForTesting
    String getTargetPackage() {
        return mTargetPackage;
    }

    @VisibleForTesting
    boolean isLegacyApp(final String packageName) {
        try {
@@ -131,8 +159,12 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo

    @VisibleForTesting
    void updateSummary(Preference preference) {
        if (mPowerWhitelistBackend.isWhitelisted(mTargetPackage)) {
            preference.setSummary(R.string.background_activity_summary_whitelisted);
            return;
        }
        final int mode = mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
                .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);

        if (mode == AppOpsManager.MODE_ERRORED) {
            preference.setSummary(R.string.background_activity_summary_disabled);
@@ -142,4 +174,37 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
                    : R.string.background_activity_summary_off);
        }
    }

    interface WarningConfirmationListener {
        void onLimitBackgroundActivity();
    }

    /**
     * Warning dialog to show to the user as turning off background activity can lead to
     * apps misbehaving as their background task scheduling guarantees will no longer be honored.
     */
    public static class WarningDialogFragment extends InstrumentedDialogFragment {
        @Override
        public int getMetricsCategory() {
            // TODO (b/65494831): add metric id
            return 0;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final WarningConfirmationListener listener =
                    (WarningConfirmationListener) getTargetFragment();
            return new AlertDialog.Builder(getContext())
                    .setTitle(R.string.background_activity_warning_dialog_title)
                    .setMessage(R.string.background_activity_warning_dialog_text)
                    .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            listener.onLimitBackgroundActivity();
                        }
                    })
                    .setNegativeButton(R.string.dlg_cancel, null)
                    .create();
        }
    }
}
+79 −55
Original line number Diff line number Diff line
@@ -16,14 +16,25 @@

package com.android.settings.fuelgauge;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;

import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.UserManager;
import android.support.v14.preference.SwitchPreference;
import android.widget.Button;

import com.android.settings.R;
import com.android.settings.TestConfig;
@@ -38,22 +49,17 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowDialog;
import org.robolectric.util.FragmentTestUtil;

@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BackgroundActivityPreferenceControllerTest {
    private static final int UID_NORMAL = 1234;
    private static final int UID_SPECIAL = 2345;
    private static final int UID_LOW_SDK = 1234;
    private static final int UID_HIGH_SDK = 3456;
    private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
    private static final String LOW_SDK_PACKAGE = "com.android.package.low";
    private static final String[] PACKAGES_NORMAL = {LOW_SDK_PACKAGE};
    private static final String[] PACKAGES_SPECIAL = {HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE};

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private Context mContext;
@@ -71,6 +77,10 @@ public class BackgroundActivityPreferenceControllerTest {
    private DevicePolicyManager mDevicePolicyManager;
    @Mock
    private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
    @Mock
    private AdvancedPowerUsageDetail mFragment;
    @Mock
    private PowerWhitelistBackend mPowerWhitelistBackend;
    private BackgroundActivityPreferenceController mController;
    private SwitchPreference mPreference;
    private Context mShadowContext;
@@ -85,19 +95,19 @@ public class BackgroundActivityPreferenceControllerTest {
        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
                mDevicePolicyManager);
        when(mPackageManager.getPackagesForUid(UID_NORMAL)).thenReturn(PACKAGES_NORMAL);
        when(mPackageManager.getPackagesForUid(UID_SPECIAL)).thenReturn(PACKAGES_SPECIAL);

        when(mPackageManager.getApplicationInfo(HIGH_SDK_PACKAGE, PackageManager.GET_META_DATA))
                .thenReturn(mHighApplicationInfo);
        when(mPackageManager.getApplicationInfo(LOW_SDK_PACKAGE, PackageManager.GET_META_DATA))
                .thenReturn(mLowApplicationInfo);

        when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(false);
        mHighApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
        mLowApplicationInfo.targetSdkVersion = Build.VERSION_CODES.L;

        mPreference = new SwitchPreference(mShadowContext);
        mController = spy(new BackgroundActivityPreferenceController(mContext, UID_NORMAL));
        mController.isAvailable();
        mController = spy(new BackgroundActivityPreferenceController(
                mContext, mFragment, UID_LOW_SDK, LOW_SDK_PACKAGE, mPowerWhitelistBackend));
        mController.mDpm = mDevicePolicyManagerWrapper;
    }

@@ -105,49 +115,66 @@ public class BackgroundActivityPreferenceControllerTest {
    public void testOnPreferenceChange_TurnOnCheck_MethodInvoked() {
        mController.onPreferenceChange(mPreference, true);

        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL,
                mController.getTargetPackage(), AppOpsManager.MODE_ALLOWED);
        verify(mController).updateSummary(mPreference);
        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);

        assertThat(mPreference.getSummary())
                .isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
    }

    @Test
    public void testOnPreferenceChange_TurnOffCheck_MethodInvoked() {
        mController.onPreferenceChange(mPreference, false);

        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL,
                mController.getTargetPackage(), AppOpsManager.MODE_IGNORED);
        verify(mController).updateSummary(mPreference);
    public void testOnPreferenceChange_TurnOnCheckHighSDK_MethodInvoked() {
        mController = new BackgroundActivityPreferenceController(mContext, mFragment, UID_HIGH_SDK,
                HIGH_SDK_PACKAGE, mPowerWhitelistBackend);
        mController.onPreferenceChange(mPreference, true);
        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_HIGH_SDK,
                HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
        verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_HIGH_SDK,
                HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
        assertThat(mPreference.getSummary())
                .isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
    }

    @Test
    public void testUpdateState_CheckOn_SetCheckedTrue() {
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_DEFAULT);
        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);

        mController.updateState(mPreference);

        assertThat(mPreference.isChecked()).isTrue();
        assertThat(mPreference.isEnabled()).isTrue();
        verify(mController).updateSummary(mPreference);
    }

    @Test
    public void testUpdateState_CheckOff_SetCheckedFalse() {
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_IGNORED);
        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);

        mController.updateState(mPreference);

        assertThat(mPreference.isChecked()).isFalse();
        assertThat(mPreference.isEnabled()).isTrue();
        verify(mController).updateSummary(mPreference);
    }

    @Test
    public void testUpdateState_whitelisted() {
        when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(true);
        mController.updateState(mPreference);
        assertThat(mPreference.isChecked()).isTrue();
        assertThat(mPreference.isEnabled()).isFalse();
        assertThat(mPreference.getSummary()).isEqualTo(
                mShadowContext.getText(R.string.background_activity_summary_whitelisted));
    }

    @Test
    public void testUpdateSummary_modeError_showSummaryDisabled() {
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_ERRORED);
        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ERRORED);
        final CharSequence expectedSummary = mShadowContext.getText(
                R.string.background_activity_summary_disabled);
        mController.updateSummary(mPreference);
@@ -157,9 +184,8 @@ public class BackgroundActivityPreferenceControllerTest {

    @Test
    public void testUpdateSummary_modeDefault_showSummaryOn() {
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_DEFAULT);
        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_DEFAULT);
        final CharSequence expectedSummary = mShadowContext.getText(
                R.string.background_activity_summary_on);

@@ -170,9 +196,8 @@ public class BackgroundActivityPreferenceControllerTest {

    @Test
    public void testUpdateSummary_modeIgnored_showSummaryOff() {
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_IGNORED);
        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
        final CharSequence expectedSummary = mShadowContext.getText(
                R.string.background_activity_summary_off);

@@ -182,31 +207,30 @@ public class BackgroundActivityPreferenceControllerTest {
    }

    @Test
    public void testIsPackageAvailable_SdkLowerThanO_ReturnTrue() {
    public void testIsLegacyApp_SdkLowerThanO_ReturnTrue() {
        assertThat(mController.isLegacyApp(LOW_SDK_PACKAGE)).isTrue();
    }

    @Test
    public void testIsPackageAvailable_SdkLargerOrEqualThanO_ReturnFalse() {
    public void testIsLegacyApp_SdkLargerOrEqualThanO_ReturnFalse() {
        assertThat(mController.isLegacyApp(HIGH_SDK_PACKAGE)).isFalse();
    }

    @Test
    public void testMultiplePackages_ReturnStatusForTargetPackage() {
        mController = new BackgroundActivityPreferenceController(mContext, UID_SPECIAL);
        mController.mDpm = mDevicePolicyManagerWrapper;
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, LOW_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_ALLOWED);
        when(mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, HIGH_SDK_PACKAGE))
                .thenReturn(AppOpsManager.MODE_IGNORED);

        final boolean available = mController.isAvailable();
        mController.updateState(mPreference);
    public void testIsAvailable_ReturnTrue() {
        assertThat(mController.isAvailable()).isTrue();
    }

        assertThat(available).isTrue();
        // Should get status from LOW_SDK_PACKAGE
        assertThat(mPreference.isChecked()).isTrue();
    @Test
    public void testWarningDialog() {
        BackgroundActivityPreferenceController.WarningDialogFragment dialogFragment =
                new BackgroundActivityPreferenceController.WarningDialogFragment();
        dialogFragment.setTargetFragment(mFragment, 0);
        FragmentTestUtil.startFragment(dialogFragment);
        final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
        ShadowAlertDialog shadowDialog = shadowOf(dialog);
        final Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
        shadowDialog.clickOn(okButton.getId());
        verify(mFragment).onLimitBackgroundActivity();
    }
}