Merge "Move force stop button into option menu."

This commit is contained in:
TreeHugger Robot
2018-01-30 06:30:20 +00:00
committed by Android (Google) Code Review
6 changed files with 442 additions and 184 deletions

View File

@@ -18,27 +18,18 @@ package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.v7.preference.PreferenceScreen;
@@ -120,16 +111,14 @@ public class AppActionButtonPreferenceControllerTest {
}
@Test
public void displayPreference_shouldInitializeForceStopButton() {
public void displayPreference_shouldSetButton2Invisible() {
final PreferenceScreen screen = mock(PreferenceScreen.class);
final ActionButtonPreference preference = spy(new ActionButtonPreference(mContext));
when(screen.findPreference(mController.getPreferenceKey())).thenReturn(preference);
mController.displayPreference(screen);
verify(preference).setButton2Positive(false);
verify(preference).setButton2Text(R.string.force_stop);
verify(preference).setButton2Enabled(false);
verify(preference).setButton2Visible(false);
}
@Test
@@ -138,14 +127,12 @@ public class AppActionButtonPreferenceControllerTest {
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
doNothing().when(mController).checkForceStop(appEntry, packageInfo);
doNothing().when(mController).initUninstallButtons(appEntry, packageInfo);
when(mFragment.getAppEntry()).thenReturn(appEntry);
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
mController.refreshUi();
verify(mController).checkForceStop(appEntry, packageInfo);
verify(mController).initUninstallButtons(appEntry, packageInfo);
}
@@ -198,71 +185,6 @@ public class AppActionButtonPreferenceControllerTest {
assertThat(mController.initUninstallButtonForUserApp()).isFalse();
}
// Tests that we don't show the force stop button for instant apps (they aren't allowed to run
// when they aren't in the foreground).
@Test
public void checkForceStop_instantApps_shouldNotShowForceStop() {
// Make this app appear to be instant.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> true));
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Visible(false);
}
@Test
public void checkForceStop_hasActiveAdmin_shouldDisableForceStop() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final String packageName = "Package1";
final PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
when(mDevicePolicyManager.packageHasActiveAdmins(packageName)).thenReturn(true);
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Enabled(false);
}
@Test
public void checkForceStop_appRunning_shouldEnableForceStop() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Enabled(true);
}
@Test
public void checkForceStop_appStopped_shouldQueryPackageRestart() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
info.flags = ApplicationInfo.FLAG_STOPPED;
info.packageName = "com.android.setting";
mController.checkForceStop(appEntry, packageInfo);
verify(mContext).sendOrderedBroadcastAsUser(argThat(intent-> intent != null
&& intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)),
any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class),
nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class));
}
@Test
public void handleDisableable_appIsHomeApp_buttonShouldNotWork() {
final ApplicationInfo info = new ApplicationInfo();

View File

@@ -42,7 +42,9 @@ import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -53,6 +55,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -103,7 +106,8 @@ public class AppHeaderViewPreferenceControllerTest {
appEntry.info = info;
when(mFragment.getAppEntry()).thenReturn(appEntry);
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final TextView title = mHeader.findViewById(R.id.entity_header_title);
final TextView summary = mHeader.findViewById(R.id.entity_header_summary);

View File

@@ -0,0 +1,215 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.appinfo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.Menu;
import android.view.MenuItem;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(
manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION
)
public final class ForceStopOptionsMenuControllerTest {
private static final String PACKAGE_NAME = "test_package_name";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private UserManager mUserManager;
@Mock
private SettingsActivity mActivity;
@Mock
private DevicePolicyManagerWrapper mDevicePolicyManager;
@Mock
private PackageManager mPackageManager;
private AppInfoDashboardFragment mFragment;
private ForceStopOptionsMenuController mController;
private Context mShadowContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mShadowContext = spy(RuntimeEnvironment.application);
mFragment = spy(new AppInfoDashboardFragment());
ReflectionHelpers.setField(mFragment, "mDpm", mDevicePolicyManager);
ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
doReturn(mActivity).when(mFragment).getActivity();
doReturn(mShadowContext).when(mFragment).getContext();
doReturn(mPackageManager).when(mActivity).getPackageManager();
when(mShadowContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(new ForceStopOptionsMenuController(
mShadowContext, mFragment, mDevicePolicyManager,
null /* metricsFeatureProvider */, null /* lifecycle */));
// Default to not considering any apps to be instant (individual tests can override this).
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
}
@Test
public void onCreateOptionsMenu_shouldAddForceStop() {
final Menu menu = mock(Menu.class);
when(menu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mock(MenuItem.class));
mController.onCreateOptionsMenu(menu, null /* inflater */);
verify(menu).add(anyInt(), eq(AppInfoDashboardFragment.FORCE_STOP_MENU), anyInt(),
eq(R.string.force_stop));
}
@Test
public void onPrepareOptionsMenu_shouldUpdateForceStopMenu() {
final Menu menu = mock(Menu.class);
doNothing().when(mController).updateForceStopMenu(any(), any());
doReturn(mock(AppEntry.class)).when(mFragment).getAppEntry();
doReturn(mock(PackageInfo.class)).when(mFragment).getPackageInfo();
mController.onPrepareOptionsMenu(menu);
verify(mController).updateForceStopMenu(any(), any());
}
@Test
public void onOptionsItemSelected_shouldHandleForceStopMenuClick() {
doReturn(mock(AppEntry.class)).when(mFragment).getAppEntry();
doNothing().when(mController).handleForceStopMenuClick();
final MenuItem menu = mock(MenuItem.class);
when(menu.getItemId()).thenReturn(AppInfoDashboardFragment.FORCE_STOP_MENU);
mController.onOptionsItemSelected(menu);
verify(mController).handleForceStopMenuClick();
}
// Tests that we don't show the force stop button for instant apps (they aren't allowed to run
// when they aren't in the foreground).
@Test
public void updateForceStopMenu_instantApps_shouldNotShowForceStop() {
when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
final MenuItem forceStopMenu = mock(MenuItem.class);
ReflectionHelpers.setField(mController, "mForceStopMenu", forceStopMenu);
// Make this app appear to be instant.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> true));
final PackageInfo packageInfo = mock(PackageInfo.class);
final AppEntry appEntry = mock(AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
mController.updateForceStopMenu(appEntry, packageInfo);
verify(forceStopMenu).setVisible(false);
}
@Test
public void updateForceStopMenu_hasActiveAdmin_shouldDisableForceStop() {
when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
final MenuItem forceStopMenu = mock(MenuItem.class);
ReflectionHelpers.setField(mController, "mForceStopMenu", forceStopMenu);
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final String packageName = "Package1";
final PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
final AppEntry appEntry = mock(AppEntry.class);
when(mDevicePolicyManager.packageHasActiveAdmins(packageName)).thenReturn(true);
mController.updateForceStopMenu(appEntry, packageInfo);
verify(forceStopMenu).setEnabled(false);
}
@Test
public void updateForceStopMenu_appRunning_shouldEnableForceStop() {
when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
final MenuItem forceStopMenu = mock(MenuItem.class);
ReflectionHelpers.setField(mController, "mForceStopMenu", forceStopMenu);
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final PackageInfo packageInfo = mock(PackageInfo.class);
final AppEntry appEntry = mock(AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
mController.updateForceStopMenu(appEntry, packageInfo);
verify(forceStopMenu).setEnabled(true);
}
@Test
public void updateForceStopMenu_appStopped_shouldQueryPackageRestart() {
when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final PackageInfo packageInfo = mock(PackageInfo.class);
final AppEntry appEntry = mock(AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
info.flags = ApplicationInfo.FLAG_STOPPED;
info.packageName = "com.android.setting";
mController.updateForceStopMenu(appEntry, packageInfo);
verify(mShadowContext).sendOrderedBroadcastAsUser(argThat(intent-> intent != null
&& intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)),
any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class),
nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class));
}
}