feat: SettingsLib验证通过-使用App module启用

This commit is contained in:
2024-12-09 16:04:49 +08:00
parent 1f18a59dab
commit a7f5c61005
1562 changed files with 181632 additions and 18 deletions

View File

@@ -0,0 +1,211 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.app.usage.UsageStats;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class AllAppsPreferenceControllerTest {
private static final int TEST_APP_COUNT = 3;
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private AllAppsPreferenceController mPreferenceController;
private Preference mPreference;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new AllAppsPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions);
mPreference = new Preference(mContext);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
}
@Test
public void onCreate_isUnavailableByDefault() {
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onCreate_isUnavailableByDefault_zoneWrite() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onCreate_isUnavailableByDefault_zoneRead() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onCreate_isUnavailableByDefault_zoneHidden() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isAvailable() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(AVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isAvailable_zoneWrite() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isAvailable_zoneRead() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
}
@Test
public void onRecentAppsCallback_empty_isAvailable_zoneHidden() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable_zoneWrite() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable_zoneRead() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable_zoneHidden() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onAppCountCallback_summarySet() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onInstalledAppCountLoaded(TEST_APP_COUNT);
assertThat(mPreference.getSummary()).isEqualTo(mContext.getResources().getString(
R.string.apps_view_all_apps_title, TEST_APP_COUNT));
}
}

View File

@@ -0,0 +1,848 @@
/*
* Copyright (C) 2020 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.car.settings.applications;
import static android.app.Activity.RESULT_FIRST_USER;
import static com.android.car.settings.applications.ApplicationActionButtonsPreferenceController.DISABLE_CONFIRM_DIALOG_TAG;
import static com.android.car.settings.applications.ApplicationActionButtonsPreferenceController.FORCE_STOP_CONFIRM_DIALOG_TAG;
import static com.android.car.settings.applications.ApplicationActionButtonsPreferenceController.UNINSTALL_DEVICE_ADMIN_REQUEST_CODE;
import static com.android.car.settings.applications.ApplicationActionButtonsPreferenceController.UNINSTALL_REQUEST_CODE;
import static com.android.car.settings.common.ActionButtonsPreference.ActionButtons;
import static com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment.DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG;
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.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
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.testng.Assert.assertThrows;
import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.role.RoleManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.ActionButtonInfo;
import com.android.car.settings.common.ActionButtonsPreference;
import com.android.car.settings.common.ActivityResultCallback;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment;
import com.android.car.settings.enterprise.DeviceAdminAddActivity;
import com.android.car.settings.testutils.ResourceTestUtils;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class ApplicationActionButtonsPreferenceControllerTest {
private static final String PACKAGE_NAME = "Test Package Name";
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private ActionButtonsPreference mActionButtonsPreference;
private ApplicationActionButtonsPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private ApplicationInfo mApplicationInfo;
private PackageInfo mPackageInfo;
@Mock
private FragmentController mFragmentController;
@Mock
private ApplicationsState mMockAppState;
@Mock
private ApplicationsState.AppEntry mMockAppEntry;
@Mock
private DevicePolicyManager mMockDpm;
@Mock
private PackageManager mMockPm;
@Mock
private ActivityManager mMockActivityManager;
@Mock
private UserManager mMockUserManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
setMocks();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mActionButtonsPreference = new ActionButtonsPreference(mContext);
mPreferenceController = new ApplicationActionButtonsPreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
}
@Test
public void testCheckInitialized_noAppState_throwException() {
mPreferenceController.setAppEntry(mMockAppEntry).setPackageName(PACKAGE_NAME);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mActionButtonsPreference));
}
@Test
public void testCheckInitialized_noAppEntry_throwException() {
mPreferenceController.setAppState(mMockAppState).setPackageName(PACKAGE_NAME);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mActionButtonsPreference));
}
@Test
public void testCheckInitialized_noPackageNameEntry_throwException() {
mPreferenceController.setAppEntry(mMockAppEntry).setAppState(mMockAppState);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mActionButtonsPreference));
}
@Test
public void onCreate_bundledApp_enabled_showDisableButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getDisableButton().getText()).isEqualTo(
ResourceTestUtils.getString(mContext, "disable_text"));
}
@Test
public void onCreate_bundledApp_disabled_showEnableButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ false, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getDisableButton().getText()).isEqualTo(
ResourceTestUtils.getString(mContext, "enable_text"));
}
@Test
public void onCreate_bundledApp_enabled_disableUntilUsed_showsEnableButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
mApplicationInfo.enabledSetting =
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
mMockAppEntry.info = mApplicationInfo;
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getDisableButton().getText()).isEqualTo(
ResourceTestUtils.getString(mContext, "enable_text"));
}
@Test
public void onCreate_bundledApp_homePackage_disablesDisableButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
ResolveInfo homeActivity = new ResolveInfo();
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = PACKAGE_NAME;
homeActivity.activityInfo = activityInfo;
when(mMockPm.getHomeActivities(anyList())).then(invocation -> {
Object[] args = invocation.getArguments();
((List<ResolveInfo>) args[0]).add(homeActivity);
return null;
});
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getDisableButton().isEnabled()).isFalse();
}
@Test
public void onCreate_bundledApp_systemPackage_disablesDisableButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
mPackageInfo.signatures = new Signature[]{new Signature(PACKAGE_NAME.getBytes())};
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getDisableButton().isEnabled()).isFalse();
}
@Test
public void onCreate_bundledApp_enabledApp_keepEnabledPackage_disablesDisableButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
ResolveInfo phoneActivity = new ResolveInfo();
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = PACKAGE_NAME;
activityInfo.permission = Manifest.permission.BROADCAST_SMS;
phoneActivity.activityInfo = activityInfo;
RoleManager mockRoleManager = mock(RoleManager.class);
when(mContext.getSystemService(RoleManager.class)).thenReturn(mockRoleManager);
when(mockRoleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_DIALER),
any(UserHandle.class))).thenReturn(Collections.singletonList(PACKAGE_NAME));
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getDisableButton().isEnabled()).isFalse();
}
@Test
public void onCreate_notSystemApp_showUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().getText()).isEqualTo(
ResourceTestUtils.getString(mContext, "uninstall_text"));
}
@Test
public void onCreate_packageHasActiveAdmins_doesNotDisableUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
when(mMockDpm.packageHasActiveAdmins(PACKAGE_NAME)).thenReturn(true);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isTrue();
}
@Test
public void onCreate_deviceProvisioningPackage_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
Resources resources = mock(Resources.class);
when(mContext.getResources()).thenReturn(resources);
when(resources.getString(com.android.internal.R.string.config_deviceProvisioningPackage))
.thenReturn(PACKAGE_NAME);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isFalse();
}
@Test
public void onStart_uninstallQueued_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
when(mMockDpm.isUninstallInQueue(PACKAGE_NAME)).thenReturn(true);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isFalse();
}
@Test
public void onStart_noDefaultHome_onlyHomeApp_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
ResolveInfo homeActivity = new ResolveInfo();
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = PACKAGE_NAME;
homeActivity.activityInfo = activityInfo;
when(mMockPm.getHomeActivities(anyList())).then(invocation -> {
Object[] args = invocation.getArguments();
((List<ResolveInfo>) args[0]).add(homeActivity);
return null;
});
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isFalse();
}
@Test
public void onStart_noDefaultHome_multipleHomeApps_enablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
ResolveInfo homeActivity = new ResolveInfo();
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = PACKAGE_NAME;
homeActivity.activityInfo = activityInfo;
ResolveInfo altHomeActivity = new ResolveInfo();
ActivityInfo altActivityInfo = new ActivityInfo();
altActivityInfo.packageName = PACKAGE_NAME + ".Someotherhome";
altHomeActivity.activityInfo = altActivityInfo;
when(mMockPm.getHomeActivities(anyList())).then(invocation -> {
Object[] args = invocation.getArguments();
((List<ResolveInfo>) args[0]).addAll(Arrays.asList(homeActivity, altHomeActivity));
return null;
});
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isTrue();
}
@Test
public void onStart_defaultHomeApp_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
ResolveInfo homeActivity = new ResolveInfo();
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = PACKAGE_NAME;
homeActivity.activityInfo = activityInfo;
ResolveInfo altHomeActivity = new ResolveInfo();
ActivityInfo altActivityInfo = new ActivityInfo();
altActivityInfo.packageName = PACKAGE_NAME + ".Someotherhome";
altHomeActivity.activityInfo = altActivityInfo;
when(mMockPm.getHomeActivities(anyList())).then(invocation -> {
Object[] args = invocation.getArguments();
((List<ResolveInfo>) args[0]).addAll(Arrays.asList(homeActivity, altHomeActivity));
return new ComponentName(PACKAGE_NAME, "SomeClass");
});
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isFalse();
}
@Test
public void onStart_appsControlUserRestriction_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mockDisabledByUserManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isFalse();
}
@Test
public void onStart_appsControlUserRestrictionByDeviceAdmin_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isTrue();
}
@Test
public void onStart_uninstallAppsRestriction_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mockDisabledByUserManagerRestriction(UserManager.DISALLOW_UNINSTALL_APPS);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isFalse();
}
@Test
public void onStart_uninstallAppsRestrictionByDeviceAdmin_disablesUninstallButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_UNINSTALL_APPS);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getUninstallButton().isEnabled()).isTrue();
}
@Test
public void onCreate_forceStopButtonInitialized() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getForceStopButton().getText()).isEqualTo(
ResourceTestUtils.getString(mContext, "force_stop"));
}
@Test
public void onCreate_notStopped_enablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getForceStopButton().isEnabled()).isTrue();
}
@Test
public void onCreate_stopped_disablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ true, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getForceStopButton().isEnabled()).isFalse();
}
@Test
public void onCreate_packageHasActiveAdmins_disablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
when(mMockDpm.packageHasActiveAdmins(PACKAGE_NAME)).thenReturn(true);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getForceStopButton().isEnabled()).isFalse();
}
@Test
public void onCreate_appsControlUserRestriction_disablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mockDisabledByUserManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getForceStopButton().isEnabled()).isFalse();
}
@Test
public void onCreate_appsControlUserRestrictionByDeviceAdmin_disablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(getForceStopButton().isEnabled()).isTrue();
}
@Test
public void onCreate_packageExplicitlyStopped_queriesPackageRestart() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ true, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
verify(mContext).sendOrderedBroadcastAsUser(any(Intent.class),
eq(UserHandle.CURRENT),
/* receiverPermission= */
eq(android.Manifest.permission.HANDLE_QUERY_PACKAGE_RESTART),
any(BroadcastReceiver.class),
/* scheduler= */ isNull(),
eq(Activity.RESULT_CANCELED),
/* initialData= */ isNull(),
/* initialExtras= */ isNull());
}
@Test
public void onCreate_packageExplicitlyStopped_success_enablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ true, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.mCheckKillProcessesReceiver.setPendingResult(
new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
"resultData",
/* resultExtras= */ null,
BroadcastReceiver.PendingResult.TYPE_UNREGISTERED,
/* ordered= */ true,
/* sticky= */ false,
/* token= */ null,
UserHandle.myUserId(),
/* flags= */ 0));
mPreferenceController.mCheckKillProcessesReceiver.onReceive(mContext, /* intent= */ null);
assertThat(getForceStopButton().isEnabled()).isTrue();
}
@Test
public void onCreate_packageExplicitlyStopped_failure_disablesForceStopButton() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ true, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.mCheckKillProcessesReceiver.setPendingResult(
new BroadcastReceiver.PendingResult(Activity.RESULT_CANCELED,
"resultData",
/* resultExtras= */ null,
BroadcastReceiver.PendingResult.TYPE_UNREGISTERED,
/* ordered= */ true,
/* sticky= */ false,
/* token= */ null,
UserHandle.myUserId(),
/* flags= */ 0));
mPreferenceController.mCheckKillProcessesReceiver.onReceive(mContext, /* intent= */ null);
assertThat(getForceStopButton().isEnabled()).isFalse();
}
@Test
public void forceStopClicked_showsDialog() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
getForceStopButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ConfirmationDialogFragment.class),
eq(FORCE_STOP_CONFIRM_DIALOG_TAG));
}
@Test
public void forceStopClicked_showsDisabledByDeviceAdminDialog() {
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
getForceStopButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ActionDisabledByAdminDialogFragment.class),
eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
}
@Test
public void forceStopClicked_notDisabledByDeviceAdminDialog_forDifferentUserRestrictionType() {
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_UNINSTALL_APPS);
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
getForceStopButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ConfirmationDialogFragment.class),
eq(FORCE_STOP_CONFIRM_DIALOG_TAG));
}
@Test
@UiThreadTest
public void forceStopDialogConfirmed_forceStopsPackage() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.mForceStopConfirmListener.onConfirm(/* arguments= */ null);
verify(mMockActivityManager).forceStopPackage(PACKAGE_NAME);
verify(mMockAppState).invalidatePackage(eq(PACKAGE_NAME), anyInt());
}
@Test
public void disableClicked_showsDialog() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
getDisableButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ConfirmationDialogFragment.class),
eq(DISABLE_CONFIRM_DIALOG_TAG));
}
@Test
public void disableDialogConfirmed_disablesPackage() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.mDisableConfirmListener.onConfirm(/* arguments= */ null);
verify(mMockPm).setApplicationEnabledSetting(PACKAGE_NAME,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, /* flags= */ 0);
}
@Test
public void disableClicked_showsDisabledByDeviceAdminDialog() {
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
getDisableButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ActionDisabledByAdminDialogFragment.class),
eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
verify(mMockPm, never()).setApplicationEnabledSetting(PACKAGE_NAME,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, /* flags= */ 0);
}
@Test
public void enableClicked_enablesPackage() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ false, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
getDisableButton().getOnClickListener().onClick(/* view= */ null);
verify(mMockPm).setApplicationEnabledSetting(PACKAGE_NAME,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, /* flags= */ 0);
}
@Test
public void enableClicked_showsDisabledByDeviceAdminDialog() {
mockDisabledByDevicePolicyManagerRestriction(UserManager.DISALLOW_APPS_CONTROL);
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ false, /* system= */ true);
mPreferenceController.onCreate(mLifecycleOwner);
getDisableButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ActionDisabledByAdminDialogFragment.class),
eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
verify(mMockPm, never()).setApplicationEnabledSetting(PACKAGE_NAME,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, /* flags= */ 0);
}
@Test
public void uninstallClicked_packageHasActiveAdmins_startsDeviceAdminAddActivity() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
when(mMockDpm.packageHasActiveAdmins(PACKAGE_NAME)).thenReturn(true);
mPreferenceController.onCreate(mLifecycleOwner);
getUninstallButton().getOnClickListener().onClick(/* view= */ null);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(
Intent.class);
verify(mFragmentController).startActivityForResult(intentArgumentCaptor.capture(),
eq(UNINSTALL_DEVICE_ADMIN_REQUEST_CODE),
any(ApplicationActionButtonsPreferenceController.class));
Intent intent = intentArgumentCaptor.getValue();
assertThat(intent.getComponent().getClassName())
.isEqualTo(DeviceAdminAddActivity.class.getName());
assertThat(intent.getStringExtra(DeviceAdminAddActivity.EXTRA_DEVICE_ADMIN_PACKAGE_NAME))
.isEqualTo(PACKAGE_NAME);
}
@Test
public void uninstallClicked_startsUninstallActivity() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
getUninstallButton().getOnClickListener().onClick(/* view= */ null);
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(
Intent.class);
verify(mFragmentController).startActivityForResult(intentArgumentCaptor.capture(),
eq(UNINSTALL_REQUEST_CODE), any(ActivityResultCallback.class));
Intent intent = intentArgumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE);
assertThat(intent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)).isTrue();
assertThat(intent.getData().toString()).isEqualTo("package:" + PACKAGE_NAME);
}
@Test
public void uninstallClicked_showsDisabledByDeviceAdminDialog_forDisallowAppsControl() {
testShowingDisabledByDeviceAdminDialogWhenUninstallClicked(
UserManager.DISALLOW_APPS_CONTROL);
}
@Test
public void uninstallClicked_showsDisabledByDeviceAdminDialog_forDisallowUninstallApps() {
testShowingDisabledByDeviceAdminDialogWhenUninstallClicked(
UserManager.DISALLOW_UNINSTALL_APPS);
}
private void testShowingDisabledByDeviceAdminDialogWhenUninstallClicked(String restriction) {
mockDisabledByDevicePolicyManagerRestriction(restriction);
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
getUninstallButton().getOnClickListener().onClick(/* view= */ null);
verify(mFragmentController).showDialog(any(ActionDisabledByAdminDialogFragment.class),
eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
}
@Test
public void processActivityResult_uninstall_resultOk_goesBack() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.processActivityResult(UNINSTALL_REQUEST_CODE,
Activity.RESULT_OK, /* data= */ null);
verify(mFragmentController).goBack();
}
@Test
public void processActivityResult_uninstallDeviceAdmin_resultOk_goesBack() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.processActivityResult(UNINSTALL_DEVICE_ADMIN_REQUEST_CODE,
Activity.RESULT_OK, /* data= */ null);
verify(mFragmentController).goBack();
}
@Test
public void processActivityResult_uninstallDeviceAdmin_resultFirstUser_showsDisabledDialog() {
setupAndAssignPreference();
setApplicationInfo(/* stopped= */ false, /* enabled= */ true, /* system= */ false);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.processActivityResult(UNINSTALL_DEVICE_ADMIN_REQUEST_CODE,
RESULT_FIRST_USER, /* data= */ null);
verify(mFragmentController).showDialog(any(ActionDisabledByAdminDialogFragment.class),
eq(DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG));
}
private void setMocks() {
mPackageInfo = new PackageInfo();
mPackageInfo.packageName = PACKAGE_NAME;
when(mMockAppState.getEntry(eq(PACKAGE_NAME), anyInt())).thenReturn(mMockAppEntry);
when(mContext.getPackageManager()).thenReturn(mMockPm);
when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mMockActivityManager);
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mMockDpm);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
PackageInfo systemPackage = new PackageInfo();
systemPackage.packageName = "android";
systemPackage.signatures = new Signature[]{new Signature(PACKAGE_NAME.getBytes())};
ApplicationInfo systemApplicationInfo = new ApplicationInfo();
systemApplicationInfo.packageName = "android";
systemPackage.applicationInfo = systemApplicationInfo;
try {
when(mMockPm.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(mPackageInfo);
when(mMockPm.getPackageInfo("android", PackageManager.GET_SIGNATURES))
.thenReturn(systemPackage);
} catch (PackageManager.NameNotFoundException e) {
// no-op - don't catch exception inside test
}
}
private void setupAndAssignPreference() {
mPreferenceController.setAppEntry(mMockAppEntry).setAppState(mMockAppState).setPackageName(
PACKAGE_NAME);
PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mActionButtonsPreference);
}
private void setApplicationInfo(boolean stopped, boolean enabled, boolean system) {
mApplicationInfo = new ApplicationInfo();
if (stopped) {
mApplicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
}
if (!enabled) {
mApplicationInfo.enabled = false;
}
if (system) {
mApplicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
}
mMockAppEntry.info = mApplicationInfo;
}
private ActionButtonInfo getForceStopButton() {
return mActionButtonsPreference.getButton(ActionButtons.BUTTON2);
}
private ActionButtonInfo getDisableButton() {
// Same button is used with a different handler. This method is purely for readability.
return getUninstallButton();
}
private ActionButtonInfo getUninstallButton() {
return mActionButtonsPreference.getButton(ActionButtons.BUTTON1);
}
private void mockDisabledByUserManagerRestriction(String restriction) {
when(mMockUserManager.hasUserRestriction(restriction)).thenReturn(true);
when(mMockUserManager.hasBaseUserRestriction(eq(restriction), any())).thenReturn(true);
}
private void mockDisabledByDevicePolicyManagerRestriction(String restriction) {
when(mMockUserManager.hasUserRestriction(restriction)).thenReturn(true);
when(mMockUserManager.hasBaseUserRestriction(eq(restriction), any())).thenReturn(false);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2020 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class ApplicationPreferenceControllerTest {
private static final String PACKAGE_NAME = "Test Package Name";
private Preference mPreference;
private CarUxRestrictions mCarUxRestrictions;
private ApplicationPreferenceController mController;
@Mock
private FragmentController mFragmentController;
@Mock
private ApplicationsState mMockAppState;
@Mock
private ApplicationsState.AppEntry mMockAppEntry;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = ApplicationProvider.getApplicationContext();
mMockAppEntry.label = PACKAGE_NAME;
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreference = new Preference(context);
mController = new ApplicationPreferenceController(context,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
when(mMockAppState.getEntry(PACKAGE_NAME, UserHandle.myUserId())).thenReturn(mMockAppEntry);
}
@Test
public void testCheckInitialized_noAppState_throwException() {
mController.setAppEntry(mMockAppEntry);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mController, mPreference));
}
@Test
public void testCheckInitialized_noAppEntry_throwException() {
mController.setAppState(mMockAppState);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mController, mPreference));
}
@Test
public void testRefreshUi_hasResolveInfo_setTitle() {
LifecycleOwner lifecycleOwner = new TestLifecycleOwner();
mController.setAppEntry(mMockAppEntry);
mController.setAppState(mMockAppState);
PreferenceControllerTestUtil.assignPreference(mController, mPreference);
mController.onCreate(lifecycleOwner);
mController.refreshUi();
assertThat(mPreference.getTitle()).isEqualTo(PACKAGE_NAME);
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
public class ApplicationsSettingsPreferenceControllerTest {
private static final String SOURCE = "source";
private static final int UID = 12;
private static final String LABEL = "label";
private static final String SIZE_STR = "12.34 MB";
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private LogicalPreferenceGroup mPreferenceGroup;
private ApplicationsSettingsPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mFragmentController;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mPreferenceController = new ApplicationsSettingsPreferenceController(mContext,
"key", mFragmentController, mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
mPreferenceController.onCreate(mLifecycleOwner);
}
@Test
public void defaultInitialize_hasNoPreference() {
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
}
@Test
public void onDataLoaded_addPreference_hasOnePreference() {
ArrayList<ApplicationsState.AppEntry> apps = new ArrayList<>();
ApplicationInfo appInfo = new ApplicationInfo();
appInfo.uid = UID;
appInfo.sourceDir = SOURCE;
ApplicationsState.AppEntry appEntry = new ApplicationsState.AppEntry(mContext, appInfo,
1234L);
appEntry.label = LABEL;
appEntry.sizeStr = SIZE_STR;
appEntry.icon = mContext.getDrawable(R.drawable.test_icon);
apps.add(appEntry);
mPreferenceController.onDataLoaded(apps);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
assertThat(mPreferenceGroup.getPreference(0).getTitle()).isEqualTo(LABEL);
assertThat(mPreferenceGroup.getPreference(0).getSummary()).isEqualTo(SIZE_STR);
}
@Test
@UiThreadTest
public void preferenceClick_launchesDetailFragment() {
ArrayList<ApplicationsState.AppEntry> apps = new ArrayList<>();
ApplicationInfo appInfo = new ApplicationInfo();
appInfo.uid = UID;
appInfo.sourceDir = SOURCE;
ApplicationsState.AppEntry appEntry = new ApplicationsState.AppEntry(mContext, appInfo,
1234L);
appEntry.label = LABEL;
appEntry.sizeStr = SIZE_STR;
appEntry.icon = mContext.getDrawable(R.drawable.test_icon);
apps.add(appEntry);
mPreferenceController.onDataLoaded(apps);
Preference preference = mPreferenceGroup.getPreference(0);
preference.performClick();
verify(mFragmentController).launchFragment(any(ApplicationDetailsFragment.class));
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
import static com.android.car.settings.applications.ApplicationsUtils.PROPERTY_APP_HIBERNATION_ENABLED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageManager;
import android.permission.PermissionControllerManager;
import android.provider.DeviceConfig;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;
@RunWith(AndroidJUnit4.class)
public class HibernatedAppsItemManagerTest {
private static final int CALLBACK_TIMEOUT_MS = 100;
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
private final TestListener mHibernatedAppsCountListener = new TestListener();
@Mock
private PackageManager mPackageManager;
@Mock
private PermissionControllerManager mPermissionControllerManager;
@Captor
private ArgumentCaptor<IntConsumer> mIntConsumerCaptor;
private Context mContext;
private HibernatedAppsItemManager mManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
"true", false);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(PermissionControllerManager.class))
.thenReturn(mPermissionControllerManager);
mManager = new HibernatedAppsItemManager(mContext);
mManager.setListener(mHibernatedAppsCountListener);
}
@Test
public void getSummary_getsRightCountForHibernatedPackage() throws Exception {
mManager.startLoading();
mCountDownLatch.await(CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
verify(mPermissionControllerManager).getUnusedAppCount(any(), mIntConsumerCaptor.capture());
mIntConsumerCaptor.getValue().accept(1);
assertThat(mHibernatedAppsCountListener.mResult).isEqualTo(1);
}
private class TestListener implements HibernatedAppsItemManager.HibernatedAppsCountListener {
int mResult;
@Override
public void onHibernatedAppsCountLoaded(int hibernatedAppsCount) {
mResult = hibernatedAppsCount;
mCountDownLatch.countDown();
}
};
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
import static com.android.car.settings.applications.ApplicationsUtils.PROPERTY_APP_HIBERNATION_ENABLED;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.apphibernation.AppHibernationManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.DeviceConfig;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.ui.preference.CarUiPreference;
import com.android.settingslib.utils.StringUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class HibernatedAppsPreferenceControllerTest {
@Mock
private FragmentController mFragmentController;
@Mock
private PackageManager mPackageManager;
@Mock
private AppHibernationManager mAppHibernationManager;
@Mock
private Preference mPreference;
private static final String KEY = "key";
private Context mContext;
private HibernatedAppsPreferenceController mController;
private CarUxRestrictions mCarUxRestrictions;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
"true", false);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(AppHibernationManager.class))
.thenReturn(mAppHibernationManager);
mPreference = new CarUiPreference(mContext);
mController = new HibernatedAppsPreferenceController(mContext, KEY, mFragmentController,
mCarUxRestrictions);
}
@Test
public void getAvailabilityStatus_featureDisabled_shouldNotReturnAvailable() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
assertThat((mController).getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_featureDisabled_shouldNotReturnAvailable_zoneWrite() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
mController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_featureDisabled_shouldNotReturnAvailable_zoneRead() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
mController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_featureDisabled_shouldNotReturnAvailable_zoneHidden() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
mController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_featureEnabled_shouldReturnAvailable() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "true", /* makeDefault= */ true);
assertThat((mController).getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_featureEnabled_shouldReturnAvailable_zoneWrite() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "true", /* makeDefault= */ true);
mController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
AVAILABLE);
}
@Test
public void getAvailabilityStatus_featureEnabled_shouldReturnAvailable_zoneRead() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "true", /* makeDefault= */ true);
mController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
AVAILABLE_FOR_VIEWING);
}
@Test
public void getAvailabilityStatus_featureEnabled_shouldReturnAvailable_zoneHidden() {
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "true", /* makeDefault= */ true);
mController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onHibernatedAppsCountCallback_setsSummary() {
assignPreference();
int totalHibernated = 2;
mController.onHibernatedAppsCountLoaded(totalHibernated);
assertThat(mPreference.getSummary()).isEqualTo(StringUtil.getIcuPluralsString(mContext,
totalHibernated, R.string.unused_apps_summary));
}
private void assignPreference() {
PreferenceControllerTestUtil.assignPreference(mController,
mPreference);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2020 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.ColoredSwitchPreference;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class HideSystemSwitchPreferenceControllerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private SwitchPreference mSwitchPreference;
private HideSystemSwitchPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private LifecycleOwner mLifecycleOwner;
private SharedPreferences mSharedPreferences;
@Mock
private FragmentController mFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mSharedPreferences = mContext.getSharedPreferences(
AppListFragment.SHARED_PREFERENCE_PATH, Context.MODE_PRIVATE);
mSwitchPreference = new ColoredSwitchPreference(mContext);
mPreferenceController = new HideSystemSwitchPreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mSwitchPreference);
}
@After
public void tearDown() {
mSharedPreferences.edit().clear().apply();
}
@Test
public void onStart_sharedPreferenceTrue_switchChecked() {
mSharedPreferences.edit().putBoolean(AppListFragment.KEY_HIDE_SYSTEM, true).apply();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void onStart_sharedPreferenceFalse_switchUnchecked() {
mSharedPreferences.edit().putBoolean(AppListFragment.KEY_HIDE_SYSTEM, false).apply();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void onPreferenceClicked_sharedPreferenceToggled() {
mSharedPreferences.edit().putBoolean(AppListFragment.KEY_HIDE_SYSTEM, true).apply();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mSwitchPreference.performClick();
assertThat(mSharedPreferences.getBoolean(AppListFragment.KEY_HIDE_SYSTEM,
/* defaultValue= */ true)).isFalse();
mSwitchPreference.performClick();
assertThat(mSharedPreferences.getBoolean(AppListFragment.KEY_HIDE_SYSTEM,
/* defaultValue= */ false)).isTrue();
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class InstalledAppCountItemManagerTest {
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private InstalledAppCountItemManager mInstalledAppCountItemManager;
@Mock
private ApplicationInfo mMockApplicationInfo;
@Mock
private PackageManager mMockPm;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mInstalledAppCountItemManager = new InstalledAppCountItemManager(mContext);
}
@Test
public void isUpdatedSystemApp_isCounted() {
mMockApplicationInfo.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
assertThat(mInstalledAppCountItemManager.shouldCountApp(mMockApplicationInfo)).isTrue();
}
@Test
public void isSystemApp_userCanOpen_isCounted() {
mMockApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
List<ResolveInfo> intents = new ArrayList<>();
intents.add(new ResolveInfo());
when(mContext.getPackageManager()).thenReturn(mMockPm);
when(mMockPm.queryIntentActivitiesAsUser(any(), anyInt(), anyInt())).thenReturn(intents);
assertThat(mInstalledAppCountItemManager.shouldCountApp(mMockApplicationInfo)).isTrue();
}
@Test
public void isSystemApp_userCannotOpen_isNotCounted() {
mMockApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
List<ResolveInfo> intents = new ArrayList<>();
when(mContext.getPackageManager()).thenReturn(mMockPm);
when(mMockPm.queryIntentActivitiesAsUser(any(), anyInt(), anyInt())).thenReturn(intents);
assertThat(mInstalledAppCountItemManager.shouldCountApp(mMockApplicationInfo)).isFalse();
}
}

View File

@@ -0,0 +1,285 @@
/*
* Copyright (C) 2019 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.car.settings.applications;
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.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.SwitchPreference;
import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class NotificationsPreferenceControllerTest {
private static final String PKG_NAME = "package.name";
private static final int UID = 1001010;
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private CarUxRestrictions mCarUxRestrictions;
private NotificationsPreferenceController mController;
private TwoStatePreference mTwoStatePreference;
private PackageInfo mPackageInfo;
@Mock
private FragmentController mFragmentController;
@Mock
private INotificationManager mMockNotificationManager;
@Mock
private PackageManager mMockPackageManager;
@Mock
private NotificationChannel mMockChannel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mTwoStatePreference = new SwitchPreference(mContext);
mController = new NotificationsPreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mController, mTwoStatePreference);
mController.mNotificationManager = mMockNotificationManager;
mPackageInfo = new PackageInfo();
mPackageInfo.packageName = PKG_NAME;
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = PKG_NAME;
mPackageInfo.applicationInfo = applicationInfo;
mPackageInfo.applicationInfo.uid = UID;
mPackageInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.TIRAMISU;
mController.setPackageInfo(mPackageInfo);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
}
@Test
public void onCreate_notificationEnabled_isChecked() throws Exception {
when(mMockNotificationManager.areNotificationsEnabledForPackage(PKG_NAME, UID))
.thenReturn(true);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isTrue();
}
@Test
public void onCreate_notificationDisabled_isNotChecked() throws Exception {
when(mMockNotificationManager.areNotificationsEnabledForPackage(PKG_NAME, UID))
.thenReturn(false);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isFalse();
}
@Test
public void onCreate_importanceLocked_isNotEnabled() throws Exception {
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(true);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void onCreate_noNotificationPermission_isNotEnabled() throws Exception {
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void onCreate_systemFixedFlag_isNotEnabled() throws Exception {
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
when(mMockPackageManager.getPermissionFlags(eq(Manifest.permission.POST_NOTIFICATIONS),
eq(PKG_NAME), any())).thenReturn(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void onCreate_policyFixedFlag_isNotEnabled() throws Exception {
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
when(mMockPackageManager.getPermissionFlags(eq(Manifest.permission.POST_NOTIFICATIONS),
eq(PKG_NAME), any())).thenReturn(PackageManager.FLAG_PERMISSION_POLICY_FIXED);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void onCreate_hasPermissions_isEnabled() throws Exception {
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
when(mMockPackageManager.getPermissionFlags(eq(Manifest.permission.POST_NOTIFICATIONS),
eq(PKG_NAME), any())).thenReturn(0);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isTrue();
}
@Test
public void onCreate_targetSdkBelow33_systemFixedFlag_isNotEnabled() throws Exception {
mPackageInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.S;
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
when(mMockPackageManager.getPermissionFlags(eq(Manifest.permission.POST_NOTIFICATIONS),
eq(PKG_NAME), any())).thenReturn(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void onCreate_targetSdkBelow33_policyFixedFlag_isNotEnabled() throws Exception {
mPackageInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.S;
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
when(mMockPackageManager.getPermissionFlags(eq(Manifest.permission.POST_NOTIFICATIONS),
eq(PKG_NAME), any())).thenReturn(PackageManager.FLAG_PERMISSION_POLICY_FIXED);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void onCreate_targetSdkBelow33_doesNotHavePermission_isEnabled() throws Exception {
mPackageInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.S;
when(mMockNotificationManager.isImportanceLocked(PKG_NAME, UID)).thenReturn(false);
PackageInfo packageInfo = new PackageInfo();
packageInfo.requestedPermissions = new String[] {};
when(mMockPackageManager.getPackageInfoAsUser(eq(PKG_NAME),
eq(PackageManager.GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
when(mMockPackageManager.getPermissionFlags(eq(Manifest.permission.POST_NOTIFICATIONS),
eq(PKG_NAME), any())).thenReturn(0);
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isEnabled()).isTrue();
}
@Test
public void callChangeListener_setEnable_enablingNotification() throws Exception {
when(mMockNotificationManager.onlyHasDefaultChannel(PKG_NAME, UID)).thenReturn(false);
mTwoStatePreference.callChangeListener(true);
verify(mMockNotificationManager).setNotificationsEnabledForPackage(PKG_NAME, UID, true);
}
@Test
public void callChangeListener_setDisable_disablingNotification() throws Exception {
when(mMockNotificationManager.onlyHasDefaultChannel(PKG_NAME, UID)).thenReturn(false);
mTwoStatePreference.callChangeListener(false);
verify(mMockNotificationManager).setNotificationsEnabledForPackage(PKG_NAME, UID, false);
}
@Test
public void callChangeListener_onlyHasDefaultChannel_updateChannel() throws Exception {
when(mMockNotificationManager.onlyHasDefaultChannel(PKG_NAME, UID)).thenReturn(true);
when(mMockNotificationManager
.getNotificationChannelForPackage(
PKG_NAME, UID, NotificationChannel.DEFAULT_CHANNEL_ID, null, true))
.thenReturn(mMockChannel);
mTwoStatePreference.callChangeListener(true);
verify(mMockNotificationManager)
.updateNotificationChannelForPackage(PKG_NAME, UID, mMockChannel);
}
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static android.car.watchdog.PackageKillableState.KILLABLE_STATE_NEVER;
import static android.car.watchdog.PackageKillableState.KILLABLE_STATE_NO;
import static android.car.watchdog.PackageKillableState.KILLABLE_STATE_YES;
import static com.android.car.settings.applications.PrioritizeAppPerformancePreferenceController.TURN_ON_PRIORITIZE_APP_PERFORMANCE_DIALOG_TAG;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.car.Car;
import android.car.drivingstate.CarUxRestrictions;
import android.car.watchdog.CarWatchdogManager;
import android.car.watchdog.PackageKillableState;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.SwitchPreference;
import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.util.Collections;
@RunWith(AndroidJUnit4.class)
public final class PrioritizeAppPerformancePreferenceControllerTest {
private static final String TEST_PKG_NAME = "test.package.name";
private static final int TEST_UID = 10012345;
private static final int TEST_USER_ID = 100;
private final Context mContext = ApplicationProvider.getApplicationContext();
private MockitoSession mMockingSession;
private LifecycleOwner mLifecycleOwner;
private CarUxRestrictions mCarUxRestrictions;
private PrioritizeAppPerformancePreferenceController mController;
private TwoStatePreference mTwoStatePreference;
@Captor
ArgumentCaptor<Car.CarServiceLifecycleListener> mCarLifecycleCaptor;
@Captor
ArgumentCaptor<ConfirmationDialogFragment> mDialogFragment;
@Mock
private FragmentController mFragmentController;
@Mock
private Car mMockCar;
@Mock
private CarWatchdogManager mMockManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mMockingSession = mockitoSession()
.initMocks(this)
.mockStatic(Car.class)
.strictness(Strictness.LENIENT)
.startMocking();
mLifecycleOwner = new TestLifecycleOwner();
mTwoStatePreference = new SwitchPreference(mContext);
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mController = new PrioritizeAppPerformancePreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, restrictions);
PreferenceControllerTestUtil.assignPreference(mController, mTwoStatePreference);
when(Car.createCar(any(), any(), anyLong(), mCarLifecycleCaptor.capture())).then(
invocation -> {
Car.CarServiceLifecycleListener listener = mCarLifecycleCaptor.getValue();
listener.onLifecycleChanged(mMockCar, true);
return mMockCar;
});
when(mMockCar.getCarManager(Car.CAR_WATCHDOG_SERVICE)).thenReturn(mMockManager);
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = TEST_PKG_NAME;
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.uid = TEST_UID;
packageInfo.applicationInfo.packageName = TEST_PKG_NAME;
mController.setPackageInfo(packageInfo);
}
@After
public void tearDown() {
mMockingSession.finishMocking();
}
@Test
public void onCreate_prioritizeAppPerformance_withKillableStateYes() {
when(mMockManager.getPackageKillableStatesAsUser(any())).thenReturn(
Collections.singletonList(
new PackageKillableState(TEST_PKG_NAME, TEST_USER_ID, KILLABLE_STATE_YES)));
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isFalse();
assertThat(mTwoStatePreference.isEnabled()).isTrue();
}
@Test
public void onCreate_prioritizeAppPerformance_withKillableStateNo() {
when(mMockManager.getPackageKillableStatesAsUser(any())).thenReturn(
Collections.singletonList(
new PackageKillableState(TEST_PKG_NAME, TEST_USER_ID, KILLABLE_STATE_NO)));
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isTrue();
assertThat(mTwoStatePreference.isEnabled()).isTrue();
}
@Test
public void onCreate_prioritizeAppPerformance_withKillableStateNever() {
when(mMockManager.getPackageKillableStatesAsUser(any())).thenReturn(
Collections.singletonList(new PackageKillableState(
TEST_PKG_NAME, TEST_USER_ID, KILLABLE_STATE_NEVER)));
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isFalse();
assertThat(mTwoStatePreference.isEnabled()).isFalse();
}
@Test
public void callChangeListener_turnOffPrioritizeAppPerformance() {
when(mMockManager.getPackageKillableStatesAsUser(any())).thenReturn(
Collections.singletonList(
new PackageKillableState(TEST_PKG_NAME, TEST_USER_ID, KILLABLE_STATE_NO)));
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isTrue();
mTwoStatePreference.performClick();
verify(mMockManager).setKillablePackageAsUser(
TEST_PKG_NAME, UserHandle.getUserHandleForUid(TEST_UID), true);
assertThat(mTwoStatePreference.isChecked()).isFalse();
assertThat(mTwoStatePreference.isEnabled()).isTrue();
}
@Test
public void callChangeListener_turnOnPrioritizeAppPerformance() {
when(mMockManager.getPackageKillableStatesAsUser(any())).thenReturn(
Collections.singletonList(
new PackageKillableState(TEST_PKG_NAME, TEST_USER_ID, KILLABLE_STATE_YES)));
mController.onCreate(mLifecycleOwner);
assertThat(mTwoStatePreference.isChecked()).isFalse();
mTwoStatePreference.callChangeListener(true);
verify(mFragmentController).showDialog(
mDialogFragment.capture(), eq(TURN_ON_PRIORITIZE_APP_PERFORMANCE_DIALOG_TAG));
mDialogFragment.getValue().getConfirmListener().onConfirm(new Bundle());
verify(mMockManager).setKillablePackageAsUser(
TEST_PKG_NAME, UserHandle.getUserHandleForUid(TEST_UID), false);
assertThat(mTwoStatePreference.isChecked()).isTrue();
assertThat(mTwoStatePreference.isEnabled()).isTrue();
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.app.usage.UsageStats;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class RecentAppsGroupPreferenceControllerTest {
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private RecentAppsGroupPreferenceController mPreferenceController;
private LogicalPreferenceGroup mPreference;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new RecentAppsGroupPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions);
mPreference = new LogicalPreferenceGroup(mContext);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
}
@Test
public void onCreate_isAvailableByDefault() {
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(AVAILABLE);
}
@Test
public void onCreate_isAvailableByDefault_zoneWrite() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
}
@Test
public void onCreate_isAvailableByDefault_zoneRead() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
}
@Test
public void onCreate_isAvailableByDefault_zoneHidden() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isUnavailable() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isUnavailable_zoneWrite() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isUnavailable_zoneRead() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_empty_isUnavailable_zoneHidden() {
List<UsageStats> usageStats = new ArrayList<>();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(AVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable_zoneWrite() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable_zoneRead() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
}
@Test
public void onRecentAppsCallback_notEmpty_isUnavailable_zoneHidden() {
List<UsageStats> usageStats = new ArrayList<>();
usageStats.add(new UsageStats());
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onRecentAppStatsLoaded(usageStats);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
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.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class RecentAppsItemManagerTest {
private static final String MOCK_PACKAGE_NAME_1 = "pkg1";
private static final String MOCK_PACKAGE_NAME_2 = "pkg2";
private static final String MOCK_PACKAGE_NAME_3 = "pkg3";
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private RecentAppsItemManager mRecentAppsItemManager;
@Mock
private UsageStatsManager mUsageStatsManager;
@Mock
private ApplicationsState mAppState;
@Mock
private PackageManager mPackageManager;
@Mock
private ApplicationsState.AppEntry mAppEntry;
@Mock
private ApplicationInfo mApplicationInfo;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getApplicationContext()).thenReturn(mContext);
when(mContext.getSystemService(UsageStatsManager.class)).thenReturn(mUsageStatsManager);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
mRecentAppsItemManager = new RecentAppsItemManager(mContext,
3 /* maximumApps */, mAppState);
}
@Test
public void loadDisplayableRecentApps_oneValidRecentAppSet_shouldHaveOneRecentApp() {
final List<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = createUsageStats(MOCK_PACKAGE_NAME_1);
stats.add(stat1);
// stat1 is valid app.
when(mAppState.getEntry(eq(stat1.mPackageName), anyInt()))
.thenReturn(mAppEntry);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mRecentAppsItemManager.loadDisplayableRecentApps(3);
assertThat(mRecentAppsItemManager.mRecentApps.size()).isEqualTo(1);
}
@Test
public void loadDisplayableRecentApps_oneValidAndTwoInvalidSet_shouldHaveOneRecentApp() {
final List<UsageStats> stats = new ArrayList<>();
final UsageStats stat1 = createUsageStats(MOCK_PACKAGE_NAME_1);
final UsageStats stat2 = createUsageStats(MOCK_PACKAGE_NAME_2);
final UsageStats stat3 = createUsageStats(MOCK_PACKAGE_NAME_3);
stats.add(stat1);
stats.add(stat2);
stats.add(stat3);
// stat1, stat2 are valid apps. stat3 is invalid.
when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
.thenReturn(mAppEntry);
when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
.thenReturn(null);
when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
mAppEntry.info = mApplicationInfo;
mRecentAppsItemManager.loadDisplayableRecentApps(3);
// Only stat1. stat2 is skipped because of the package name, stat3 skipped because
// it's invalid app.
assertThat(mRecentAppsItemManager.mRecentApps.size()).isEqualTo(2);
}
private UsageStats createUsageStats(String packageName) {
UsageStats usageStats = new UsageStats();
usageStats.mPackageName = packageName;
usageStats.mLastTimeUsed = System.currentTimeMillis();
return usageStats;
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.usage.UsageStats;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class RecentAppsListPreferenceControllerTest {
private static final String MOCK_PACKAGE_NAME_1 = "pkg1";
private static final String MOCK_PACKAGE_NAME_2 = "pkg2";
private static final String MOCK_PACKAGE_NAME_3 = "pkg3";
private static final String MOCK_PACKAGE_NAME_4 = "pkg4";
private static final String MOCK_APP_NAME_1 = "title1";
private static final String MOCK_APP_NAME_2 = "title2";
private static final String MOCK_APP_NAME_3 = "title3";
private static final String MOCK_APP_NAME_4 = "title4";
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private RecentAppsListPreferenceController mPreferenceController;
private PreferenceCategory mPreferenceCategory;
private CarUxRestrictions mCarUxRestrictions;
private int mMaxEntryCount;
@Mock
private FragmentController mMockFragmentController;
@Mock
private ApplicationsState mMockApplicationsState;
@Mock
private ApplicationInfo mApplicationInfo;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new RecentAppsListPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockApplicationsState);
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceCategory = new PreferenceCategory(mContext);
screen.addPreference(mPreferenceCategory);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceCategory);
mMaxEntryCount = mContext.getResources().getInteger(
R.integer.recent_notifications_apps_list_count);
}
@Test
public void onRecentAppsLoaded_displaysApps() {
mPreferenceController.onCreate(mLifecycleOwner);
UsageStats usageStats = createUsageStats(MOCK_PACKAGE_NAME_1);
List<UsageStats> mUsageStatsList = new ArrayList<>();
mUsageStatsList.add(usageStats);
ApplicationsState.AppEntry appEntry = createAppEntry(MOCK_APP_NAME_1);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_1), anyInt()))
.thenReturn(appEntry);
mPreferenceController.onRecentAppStatsLoaded(mUsageStatsList);
assertThat(mPreferenceCategory.getPreference(0).getTitle()).isEqualTo(appEntry.label);
}
@Test
public void onRecentAppsLoaded_doesNotDisplayInvalidApps() {
mPreferenceController.onCreate(mLifecycleOwner);
UsageStats usageStats1 = createUsageStats(MOCK_PACKAGE_NAME_1);
UsageStats usageStats2 = createUsageStats(MOCK_PACKAGE_NAME_2);
List<UsageStats> mUsageStatsList = new ArrayList<>();
mUsageStatsList.add(usageStats1);
mUsageStatsList.add(usageStats2);
ApplicationsState.AppEntry appEntry = createAppEntry(MOCK_APP_NAME_1);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_1), anyInt()))
.thenReturn(appEntry);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_2), anyInt())).thenReturn(null);
mPreferenceController.onRecentAppStatsLoaded(mUsageStatsList);
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
}
@Test
public void onRecentAppsLoaded_moreThanMaximumAllowed_maximumShown() {
mPreferenceController.onCreate(mLifecycleOwner);
UsageStats usageStats1 = createUsageStats(MOCK_PACKAGE_NAME_1);
UsageStats usageStats2 = createUsageStats(MOCK_PACKAGE_NAME_2);
UsageStats usageStats3 = createUsageStats(MOCK_PACKAGE_NAME_3);
UsageStats usageStats4 = createUsageStats(MOCK_PACKAGE_NAME_4);
List<UsageStats> mUsageStatsList = new ArrayList<>();
mUsageStatsList.add(usageStats1);
mUsageStatsList.add(usageStats2);
mUsageStatsList.add(usageStats3);
mUsageStatsList.add(usageStats4);
ApplicationsState.AppEntry appEntry1 = createAppEntry(MOCK_APP_NAME_1);
ApplicationsState.AppEntry appEntry2 = createAppEntry(MOCK_APP_NAME_2);
ApplicationsState.AppEntry appEntry3 = createAppEntry(MOCK_APP_NAME_3);
ApplicationsState.AppEntry appEntry4 = createAppEntry(MOCK_APP_NAME_4);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_1), anyInt()))
.thenReturn(appEntry1);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_2), anyInt()))
.thenReturn(appEntry2);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_3), anyInt()))
.thenReturn(appEntry3);
when(mMockApplicationsState.getEntry(eq(MOCK_PACKAGE_NAME_4), anyInt()))
.thenReturn(appEntry4);
mPreferenceController.onRecentAppStatsLoaded(mUsageStatsList);
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(mMaxEntryCount);
}
private UsageStats createUsageStats(String packageName) {
UsageStats usageStats = new UsageStats();
usageStats.mPackageName = packageName;
usageStats.mEndTimeStamp = System.currentTimeMillis();
return usageStats;
}
private ApplicationsState.AppEntry createAppEntry(String label) {
ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = mApplicationInfo;
appEntry.label = label;
return appEntry;
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class RecentAppsViewAllPreferenceControllerTest {
private static final int TEST_APP_COUNT = 3;
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private RecentAppsViewAllPreferenceController mPreferenceController;
private Preference mPreference;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new RecentAppsViewAllPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions);
mPreference = new Preference(mContext);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
}
@Test
public void onCreate_isUnavailableByDefault() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onInstalledAppCountLoaded(TEST_APP_COUNT);
assertThat(mPreference.getTitle()).isEqualTo(mContext.getResources().getString(
R.string.apps_view_all_apps_title, TEST_APP_COUNT));
}
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright (C) 2021 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.car.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiPreference;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class StoragePreferenceControllerTest {
private static final String PACKAGE_NAME = "Test Package Name";
private static final String SIZE_STR = "1.4Mb";
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private CarUiPreference mPreference;
private StoragePreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Mock
private ApplicationsState mMockApplicationsState;
@Mock
private ApplicationsState.AppEntry mMockAppEntry;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreference = new CarUiPreference(mContext);
mPreferenceController = new StoragePreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController, mCarUxRestrictions);
}
@Test
public void testCheckInitialized_noApplicationsEntry_throwException() {
mPreferenceController.setAppState(mMockApplicationsState);
mPreferenceController.setPackageName(PACKAGE_NAME);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mPreference));
}
@Test
public void testCheckInitialized_noApplicationsState_throwException() {
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setPackageName(PACKAGE_NAME);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mPreference));
}
@Test
public void testCheckInitialized_noPackageName_throwException() {
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setAppState(mMockApplicationsState);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mPreference));
}
@Test
public void onCreate_nullSize_calculatingSummary() {
when(mMockApplicationsState.getEntry(PACKAGE_NAME, UserHandle.myUserId()))
.thenReturn(mMockAppEntry);
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setAppState(mMockApplicationsState);
mPreferenceController.setPackageName(PACKAGE_NAME);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.memory_calculating_size));
}
@Test
public void onCreate_validApp_sizeSummary() {
when(mMockApplicationsState.getEntry(PACKAGE_NAME, UserHandle.myUserId()))
.thenReturn(mMockAppEntry);
mMockAppEntry.sizeStr = SIZE_STR;
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setAppState(mMockApplicationsState);
mPreferenceController.setPackageName(PACKAGE_NAME);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.storage_type_internal, SIZE_STR));
}
@Test
public void onCreate_lateAppLoad_updateSummary() {
when(mMockApplicationsState.getEntry(PACKAGE_NAME, UserHandle.myUserId()))
.thenReturn(mMockAppEntry);
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setAppState(mMockApplicationsState);
mPreferenceController.setPackageName(PACKAGE_NAME);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.memory_calculating_size));
mMockAppEntry.sizeStr = SIZE_STR;
mPreferenceController.mApplicationStateCallbacks.onAllSizesComputed();
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.storage_type_internal, SIZE_STR));
}
@Test
public void onCreate_packageSizeChange_updateSummary() {
when(mMockApplicationsState.getEntry(PACKAGE_NAME, UserHandle.myUserId()))
.thenReturn(mMockAppEntry);
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setAppState(mMockApplicationsState);
mPreferenceController.setPackageName(PACKAGE_NAME);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.memory_calculating_size));
mMockAppEntry.sizeStr = SIZE_STR;
mPreferenceController.mApplicationStateCallbacks.onPackageSizeChanged(PACKAGE_NAME);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.storage_type_internal, SIZE_STR));
}
@Test
public void onCreate_otherPackageSizeChange_doesNotUpdateSummary() {
when(mMockApplicationsState.getEntry(PACKAGE_NAME, UserHandle.myUserId()))
.thenReturn(mMockAppEntry);
mPreferenceController.setAppEntry(mMockAppEntry);
mPreferenceController.setAppState(mMockApplicationsState);
mPreferenceController.setPackageName(PACKAGE_NAME);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.memory_calculating_size));
mMockAppEntry.sizeStr = SIZE_STR;
mPreferenceController.mApplicationStateCallbacks.onPackageSizeChanged("other_package");
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.memory_calculating_size));
}
}

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2023 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.car.settings.applications.appinfo
import android.car.drivingstate.CarUxRestrictions
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.location.LocationManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.car.settings.common.FragmentController
import com.android.car.settings.common.PreferenceController.AVAILABLE
import com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE
import com.android.car.settings.common.PreferenceControllerTestUtil
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatcher
import org.mockito.kotlin.argThat
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class AppAllServicesPreferenceControllerTest {
private val mockFragmentController = mock<FragmentController>()
private val mockPackageManager = mock<PackageManager>()
private val mockResolveInfo = mock<ResolveInfo>()
private val mockLocationManager = mock<LocationManager>()
private val context = spy(ApplicationProvider.getApplicationContext<Context>()) {
on { packageManager } doReturn mockPackageManager
on { getSystemService(LocationManager::class.java) } doReturn mockLocationManager
}
private val carUxRestrictions = CarUxRestrictions.Builder(
/* reqOpt = */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE,
/* time = */ 0
).build()
private val controller = AppAllServicesPreferenceController(
context,
preferenceKey,
mockFragmentController,
carUxRestrictions
)
@Test
fun getAvailabilityStatus_shouldReturnAvailable() {
controller.setPackageName(primaryPackageName)
val intent = getFeaturesIntent(primaryPackageName)
whenever(
mockPackageManager.resolveActivity(matchIntent(intent), /* flags = */ eq(0))
) doReturn mockResolveInfo
whenever(
mockLocationManager.isProviderPackage(null, primaryPackageName, null)
) doReturn true
PreferenceControllerTestUtil.assertAvailability(controller.availabilityStatus, AVAILABLE)
}
@Test
fun getAvailabilityStatus_isNotLocationProvider_shouldReturnConditionallyUnavailable() {
controller.setPackageName(primaryPackageName)
val intent = getFeaturesIntent(primaryPackageName)
whenever(
mockPackageManager.resolveActivity(matchIntent(intent), /* flags = */ eq(0))
) doReturn mockResolveInfo
whenever(
mockLocationManager.isProviderPackage(null, primaryPackageName, null)
) doReturn false
PreferenceControllerTestUtil.assertAvailability(
controller.availabilityStatus,
CONDITIONALLY_UNAVAILABLE
)
}
@Test
fun getAvailabilityStatus_canNotHandleIntent_shouldReturnConditionallyUnavailable() {
controller.setPackageName(primaryPackageName)
val intent = getFeaturesIntent(secondaryPackageName)
// Trying to match with a package that cannot handle the intent
whenever(
mockPackageManager.resolveActivity(matchIntent(intent), /* flags = */ eq(0))
) doReturn mockResolveInfo
whenever(
mockLocationManager.isProviderPackage(null, primaryPackageName, null)
) doReturn true
PreferenceControllerTestUtil.assertAvailability(
controller.availabilityStatus,
CONDITIONALLY_UNAVAILABLE
)
}
@Test
fun getAvailabilityStatus_shouldReturnConditionallyUnavailable() {
controller.setPackageName(primaryPackageName)
val intent = getFeaturesIntent(secondaryPackageName)
whenever(
mockPackageManager.resolveActivity(matchIntent(intent), /* flags = */ eq(0))
) doReturn mockResolveInfo
whenever(
mockLocationManager.isProviderPackage(null, primaryPackageName, null)
) doReturn false
PreferenceControllerTestUtil.assertAvailability(
controller.availabilityStatus,
CONDITIONALLY_UNAVAILABLE
)
}
@Test
fun canPackageHandleIntent_nullPackageInfo_shouldNotCrash() {
controller.setPackageName(null)
// no crash
PreferenceControllerTestUtil.assertAvailability(
controller.availabilityStatus,
CONDITIONALLY_UNAVAILABLE
)
}
private fun getFeaturesIntent(pkgName: String?): Intent {
return Intent(Intent.ACTION_VIEW_APP_FEATURES).apply {
`package` = pkgName
}
}
private fun matchIntent(incoming: Intent): Intent {
return argThat(IntentEqualityMatcher(incoming))
}
private class IntentEqualityMatcher (private val baseIntent: Intent) : ArgumentMatcher<Intent> {
override fun matches(argument: Intent?): Boolean {
return baseIntent.`package` == argument?.`package` &&
baseIntent.action == argument?.action
}
}
private companion object {
const val primaryPackageName = "Package1"
const val secondaryPackageName = "Package2"
const val preferenceKey = "pref_key"
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright (C) 2021 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.car.settings.applications.appinfo;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED;
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
import static com.android.car.settings.applications.ApplicationsUtils.PROPERTY_APP_HIBERNATION_ENABLED;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.DeviceConfig;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class HibernationSwitchPreferenceControllerTest {
private static final int PACKAGE_UID = 1;
private static final String INVALID_PACKAGE_NAME = "invalid_package";
private static final String KEY = "key";
private static final String VALID_PACKAGE_NAME = "package";
private static final String EXEMPTED_PACKAGE_NAME = "exempted_package";
private static final String UNEXEMPTED_PACKAGE_NAME = "unexempted_package";
@Mock
private FragmentController mFragmentController;
@Mock
private AppOpsManager mAppOpsManager;
@Mock
private PackageManager mPackageManager;
@Mock
private SwitchPreference mPreference;
private LifecycleOwner mLifecycleOwner;
private CarUxRestrictions mCarUxRestrictions;
private HibernationSwitchPreferenceController mController;
private Context mContext;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mContext = spy(ApplicationProvider.getApplicationContext());
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
when(mPackageManager.getPackageUid(eq(VALID_PACKAGE_NAME), anyInt()))
.thenReturn(PACKAGE_UID);
when(mPackageManager.getPackageUid(eq(INVALID_PACKAGE_NAME), anyInt()))
.thenThrow(new PackageManager.NameNotFoundException());
when(mPackageManager.getTargetSdkVersion(eq(EXEMPTED_PACKAGE_NAME)))
.thenReturn(android.os.Build.VERSION_CODES.Q);
when(mPackageManager.getTargetSdkVersion(eq(UNEXEMPTED_PACKAGE_NAME)))
.thenReturn(android.os.Build.VERSION_CODES.S);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "true", /* makeDefault= */ true);
mController = new HibernationSwitchPreferenceController(
mContext, KEY, mFragmentController, mCarUxRestrictions);
}
@Test
public void getAvailabilityStatus_featureNotEnabled_shouldNotReturnAvailable() {
mController.setPackageName(VALID_PACKAGE_NAME);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
assertThat(mController.getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_featureNotEnabled_shouldNotReturnAvailable_zoneWrite() {
mController.setAvailabilityStatusForZone("write");
mController.setPackageName(VALID_PACKAGE_NAME);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_featureNotEnabled_shouldNotReturnAvailable_zoneRead() {
mController.setAvailabilityStatusForZone("read");
mController.setPackageName(VALID_PACKAGE_NAME);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_featureNotEnabled_shouldNotReturnAvailable_zoneHidden() {
mController.setAvailabilityStatusForZone("hidden");
mController.setPackageName(VALID_PACKAGE_NAME);
DeviceConfig.setProperty(NAMESPACE_APP_HIBERNATION, PROPERTY_APP_HIBERNATION_ENABLED,
/* value= */ "false", /* makeDefault= */ true);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_invalidPackage_shouldReturnNotAvailable() {
mController.setPackageName(INVALID_PACKAGE_NAME);
assertThat(mController.getAvailabilityStatus()).isNotEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_invalidPackage_shouldReturnNotAvailable_zoneWrite() {
mController.setAvailabilityStatusForZone("write");
mController.setPackageName(INVALID_PACKAGE_NAME);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_invalidPackage_shouldReturnNotAvailable_zoneRead() {
mController.setAvailabilityStatusForZone("read");
mController.setPackageName(INVALID_PACKAGE_NAME);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_invalidPackage_shouldReturnNotAvailable_zoneHidden() {
mController.setAvailabilityStatusForZone("hidden");
mController.setPackageName(INVALID_PACKAGE_NAME);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_validPackage_shouldReturnAvailable() {
mController.setPackageName(VALID_PACKAGE_NAME);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_validPackage_shouldReturnAvailable_zoneWrite() {
mController.setAvailabilityStatusForZone("write");
mController.setPackageName(VALID_PACKAGE_NAME);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
AVAILABLE);
}
@Test
public void getAvailabilityStatus_validPackage_shouldReturnAvailable_zoneRead() {
mController.setAvailabilityStatusForZone("read");
mController.setPackageName(VALID_PACKAGE_NAME);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
AVAILABLE_FOR_VIEWING);
}
@Test
public void getAvailabilityStatus_validPackage_shouldReturnAvailable_zoneHidden() {
mController.setAvailabilityStatusForZone("hidden");
mController.setPackageName(VALID_PACKAGE_NAME);
PreferenceControllerTestUtil.assertAvailability(mController.getAvailabilityStatus(),
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void updateState_exemptedByDefaultPackage_shouldNotCheck() {
assignPreference();
when(mAppOpsManager.unsafeCheckOpNoThrow(
eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(EXEMPTED_PACKAGE_NAME)))
.thenReturn(MODE_DEFAULT);
mController.setPackageName(EXEMPTED_PACKAGE_NAME);
mController.onCreate(mLifecycleOwner);
verify(mPreference).setChecked(false);
}
@Test
public void updateState_exemptedPackageOverrideByUser_shouldCheck() {
assignPreference();
when(mAppOpsManager.unsafeCheckOpNoThrow(
eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(EXEMPTED_PACKAGE_NAME)))
.thenReturn(MODE_ALLOWED);
mController.setPackageName(EXEMPTED_PACKAGE_NAME);
mController.onCreate(mLifecycleOwner);
verify(mPreference).setChecked(true);
}
@Test
public void updateState_unexemptedPackageOverrideByUser_shouldNotCheck() {
assignPreference();
when(mAppOpsManager.unsafeCheckOpNoThrow(
eq(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED), anyInt(), eq(UNEXEMPTED_PACKAGE_NAME)))
.thenReturn(MODE_IGNORED);
mController.setPackageName(UNEXEMPTED_PACKAGE_NAME);
mController.onCreate(mLifecycleOwner);
verify(mPreference).setChecked(false);
}
private void assignPreference() {
PreferenceControllerTestUtil.assignPreference(mController,
mPreference);
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.car.drivingstate.CarUxRestrictions;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.SwitchPreference;
import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.internal.app.AssistUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class AssistConfigBasePreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "com.test.package";
private static final String TEST_SERVICE = "TestService";
private final int mUserId = UserHandle.myUserId();
private static final Uri ASSIST_URI = Settings.Secure.getUriFor(Settings.Secure.ASSISTANT);
private static final Uri ASSIST_STRUCTURE_URI =
Settings.Secure.getUriFor(Settings.Secure.ASSIST_STRUCTURE_ENABLED);
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private TwoStatePreference mPreference;
private TestAssistConfigBasePreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private ComponentName mComponentName;
@Mock
private FragmentController mMockFragmentController;
@Mock
private AssistUtils mMockAssistUtils;
@Mock
private ContentResolver mMockContentResolver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mComponentName = new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE);
mPreference = new SwitchPreference(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new TestAssistConfigBasePreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockAssistUtils);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
}
@Test
public void getAvailabilityStatus_hasAssistComponent_isAvailable() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_hasAssistComponent_isAvailable_zoneWrite() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
}
@Test
public void getAvailabilityStatus_hasAssistComponent_isAvailable_zoneRead() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
}
@Test
public void getAvailabilityStatus_hasAssistComponent_isAvailable_zoneHidden() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_noAssistComponent_conditionallyUnavailable() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_noAssistComponent_conditionallyUnavailable_zoneWrite() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_noAssistComponent_conditionallyUnavailable_zoneRead() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_noAssistComponent_conditionallyUnavailable_zoneHidden() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onStart_registersObserver() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
when(mContext.getContentResolver()).thenReturn(mMockContentResolver);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
verify(mMockContentResolver).registerContentObserver(eq(ASSIST_URI), eq(false),
any());
verify(mMockContentResolver).registerContentObserver(eq(ASSIST_STRUCTURE_URI),
eq(false), any());
}
@Test
public void onStop_unregistersObserver() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
when(mContext.getContentResolver()).thenReturn(mMockContentResolver);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.onStop(mLifecycleOwner);
verify(mMockContentResolver).unregisterContentObserver(any());
}
@Test
public void onChange_changeRegisteredSetting_callsRefreshUi() {
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(mComponentName);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
int currentCount = mPreferenceController.getNumCallsToUpdateState();
mPreferenceController.mSettingObserver
.onChange(/* selfChange= */ false, ASSIST_STRUCTURE_URI);
assertThat(mPreferenceController.getNumCallsToUpdateState())
.isEqualTo(currentCount + 1);
}
private static class TestAssistConfigBasePreferenceController extends
AssistConfigBasePreferenceController {
private int mNumCallsToUpdateState;
TestAssistConfigBasePreferenceController(Context context, String preferenceKey,
FragmentController fragmentController, CarUxRestrictions uxRestrictions,
AssistUtils assistUtils) {
super(context, preferenceKey, fragmentController, uxRestrictions, assistUtils);
mNumCallsToUpdateState = 0;
}
public int getNumCallsToUpdateState() {
return mNumCallsToUpdateState;
}
@Override
protected void updateState(TwoStatePreference preference) {
mNumCallsToUpdateState++;
}
@Override
protected List<Uri> getSettingUris() {
return Collections.singletonList(ASSIST_STRUCTURE_URI);
}
}
}

View File

@@ -0,0 +1,356 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
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 static org.mockito.Mockito.withSettings;
import android.car.drivingstate.CarUxRestrictions;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiTwoActionIconPreference;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.app.AssistUtils;
import com.android.settingslib.applications.DefaultAppInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
@RunWith(AndroidJUnit4.class)
public class DefaultVoiceInputPickerEntryPreferenceControllerTest {
private static final String TEST_PACKAGE = "com.android.car.settings.testutils";
private static final String TEST_ASSIST = "TestAssistService";
private static final String TEST_VOICE = "TestVoiceService";
private static final Uri ASSIST_URI = Settings.Secure.getUriFor(Settings.Secure.ASSISTANT);
private final int mUserId = UserHandle.myUserId();
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private CarUiTwoActionIconPreference mPreference;
private DefaultVoiceInputPickerEntryPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private MockitoSession mSession;
@Mock
private FragmentController mMockFragmentController;
@Mock
private AssistUtils mMockAssistUtils;
@Mock
private VoiceInputInfoProvider mMockVoiceInputInfoProvider;
@Mock
private VoiceInputInfoProvider.VoiceInputInfo mMockVoiceInputInfo;
@Mock
private ContentResolver mMockContentResolver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mPreference = new CarUiTwoActionIconPreference(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new DefaultVoiceInputPickerEntryPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockVoiceInputInfoProvider, mMockAssistUtils);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mSession = ExtendedMockito.mockitoSession().mockStatic(
VoiceInputUtils.class, withSettings().lenient()).startMocking();
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_ASSIST));
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
}
@After
public void tearDown() {
if (mSession != null) {
mSession.finishMocking();
}
}
@Test
public void getAvailabilityStatus_sameComponents_returnsConditionallyUnavailable() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_sameComponents_returnsConditionallyUnavailable_zoneWrite() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_sameComponents_returnsConditionallyUnavailable_zoneRead() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_sameComponents_returnsConditionallyUnavailable_zoneHidden() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_VOICE));
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_bothNull_returnsConditionallyUnavailable() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(null);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_bothNull_returnsConditionallyUnavailable_zoneWrite() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(null);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_bothNull_returnsConditionallyUnavailable_zoneRead() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(null);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_bothNull_returnsConditionallyUnavailable_zoneHidden() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(null);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(null);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_differentComponents_returnsAvailable() {
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
PreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_differentComponents_returnsAvailable_zoneWrite() {
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
}
@Test
public void getAvailabilityStatus_differentComponents_returnsAvailable_zoneRead() {
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
}
@Test
public void getAvailabilityStatus_differentComponents_returnsAvailable_zoneHidden() {
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onStart_registersObserver() {
when(mContext.getContentResolver()).thenReturn(mMockContentResolver);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
verify(mMockContentResolver).registerContentObserver(eq(ASSIST_URI), eq(false),
any());
}
@Test
public void onStop_unregistersObserver() {
when(mContext.getContentResolver()).thenReturn(mMockContentResolver);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.onStop(mLifecycleOwner);
verify(mMockContentResolver).unregisterContentObserver(any());
}
@Test
public void onChange_changeRegisteredSetting_callsRefreshUi() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
assertThat(mPreferenceController.getAvailabilityStatus())
.isEqualTo(PreferenceController.AVAILABLE);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_ASSIST));
mPreferenceController.mSettingObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT));
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
PreferenceController.CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onChange_changeRegisteredSetting_callsRefreshUi_zoneWrite() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_ASSIST));
mPreferenceController.mSettingObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT));
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onChange_changeRegisteredSetting_callsRefreshUi_zoneRead() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_ASSIST));
mPreferenceController.mSettingObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT));
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void onChange_changeRegisteredSetting_callsRefreshUi_zoneHidden() {
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE, TEST_ASSIST));
mPreferenceController.mSettingObserver.onChange(/* selfChange= */ false,
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT));
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getCurrentDefaultAppInfo_providerHasCurrentService_returnsValidDefaultAppInfo() {
when(mMockVoiceInputInfoProvider.getInfoForComponent(any()))
.thenReturn(mMockVoiceInputInfo);
assertThat(mPreferenceController.getCurrentDefaultAppInfo()).isNotNull();
}
@Test
public void getCurrentDefaultAppInfo_providerHasNoService_returnsNull() {
when(mMockVoiceInputInfoProvider.getInfoForComponent(any())).thenReturn(null);
assertThat(mPreferenceController.getCurrentDefaultAppInfo()).isNull();
}
@Test
public void getSettingIntent_nullInput_returnsNull() {
assertThat(mPreferenceController.getSettingIntent(null)).isEqualTo(null);
}
@Test
public void getSettingIntent_inputIsWrongType_returnsNull() {
DefaultAppInfo info = mock(DefaultAppInfo.class);
assertThat(mPreferenceController.getSettingIntent(info)).isEqualTo(null);
}
@Test
public void getSettingIntent_validInput_returnsIntent() {
Intent intent = new Intent();
DefaultVoiceInputServiceInfo info = mock(DefaultVoiceInputServiceInfo.class);
when(info.getSettingIntent()).thenReturn(intent);
assertThat(mPreferenceController.getSettingIntent(info)).isEqualTo(intent);
}
}

View File

@@ -0,0 +1,239 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.car.drivingstate.CarUxRestrictions;
import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.app.AssistUtils;
import com.android.settingslib.applications.DefaultAppInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class DefaultVoiceInputPickerPreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "com.test.package";
private static final String TEST_SERVICE = "TestService";
private static final String TEST_OTHER_SERVICE = "TestOtherService";
private static final String TEST_RECOGNIZER = "TestRecognizer";
private final int mUserId = UserHandle.myUserId();
private Context mContext = ApplicationProvider.getApplicationContext();
private LogicalPreferenceGroup mPreference;
private DefaultVoiceInputPickerPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private MockitoSession mSession;
@Mock
private FragmentController mMockFragmentController;
@Mock
private AssistUtils mMockAssistUtils;
@Mock
private VoiceInputInfoProvider mMockVoiceInputInfoProvider;
@Mock
private VoiceInputInfoProvider.VoiceInteractionInfo mMockVoiceInteractionInfo;
@Mock
private VoiceInputInfoProvider.VoiceRecognitionInfo mMockVoiceRecognitionInfo;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mSession = ExtendedMockito.mockitoSession().mockStatic(
VoiceInputUtils.class, withSettings().lenient()).startMocking();
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE));
when(mMockAssistUtils.getAssistComponentForUser(mUserId)).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE));
mPreference = new LogicalPreferenceGroup(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new DefaultVoiceInputPickerPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockAssistUtils, mMockVoiceInputInfoProvider);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
}
@After
@UiThreadTest
public void tearDown() {
if (mSession != null) {
mSession.finishMocking();
}
}
@Test
public void getCandidates_voiceInteractionService_hasOneElement() {
when(mMockVoiceInputInfoProvider.getVoiceInteractionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceInteractionInfo));
when(mMockVoiceInteractionInfo.getComponentName()).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE));
when(mMockVoiceInputInfoProvider.getVoiceRecognitionInfoList()).thenReturn(
Collections.emptyList());
assertThat(mPreferenceController.getCandidates()).hasSize(1);
}
@Test
public void getCandidates_voiceRecognitionService_hasOneElement() {
when(mMockVoiceInputInfoProvider.getVoiceInteractionInfoList()).thenReturn(
Collections.emptyList());
when(mMockVoiceInputInfoProvider.getVoiceRecognitionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceRecognitionInfo));
assertThat(mPreferenceController.getCandidates()).hasSize(1);
}
@Test
public void getCandidates_oneIsSameAsAssistant_hasTwoElements() {
when(mMockVoiceInputInfoProvider.getVoiceInteractionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceInteractionInfo));
when(mMockVoiceInteractionInfo.getComponentName()).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE));
when(mMockVoiceInputInfoProvider.getVoiceRecognitionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceRecognitionInfo));
assertThat(mPreferenceController.getCandidates()).hasSize(2);
}
@Test
public void getCandidates_oneIsSameAsAssistant_sameOneIsEnabled() {
when(mMockVoiceInputInfoProvider.getVoiceInteractionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceInteractionInfo));
when(mMockVoiceInteractionInfo.getComponentName()).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE));
when(mMockVoiceInputInfoProvider.getVoiceRecognitionInfoList()).thenReturn(
Collections.emptyList());
List<DefaultAppInfo> defaultAppInfo = mPreferenceController.getCandidates();
assertThat(defaultAppInfo).hasSize(1);
assertThat(defaultAppInfo.get(0)).isNotNull();
assertThat(defaultAppInfo.get(0).enabled).isTrue();
}
@Test
public void getCandidates_oneIsSameAsAssistant_differentOneIsDisabled() {
when(mMockVoiceInputInfoProvider.getVoiceInteractionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceInteractionInfo));
when(mMockVoiceInteractionInfo.getComponentName()).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_OTHER_SERVICE));
when(mMockVoiceInputInfoProvider.getVoiceRecognitionInfoList()).thenReturn(
Collections.emptyList());
List<DefaultAppInfo> defaultAppInfo = mPreferenceController.getCandidates();
assertThat(defaultAppInfo).hasSize(1);
assertThat(defaultAppInfo.get(0)).isNotNull();
assertThat(defaultAppInfo.get(0).enabled).isFalse();
}
@Test
public void getCandidates_voiceRecognitionInfo_IsEnabled() {
when(mMockVoiceInputInfoProvider.getVoiceInteractionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceInteractionInfo));
when(mMockVoiceInteractionInfo.getComponentName()).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE));
when(mMockVoiceInputInfoProvider.getVoiceRecognitionInfoList()).thenReturn(
Collections.singletonList(mMockVoiceRecognitionInfo));
when(mMockVoiceRecognitionInfo.getComponentName()).thenReturn(
new ComponentName(TEST_PACKAGE_NAME, TEST_OTHER_SERVICE));
DefaultAppInfo defaultAppInfo = null;
for (DefaultAppInfo info : mPreferenceController.getCandidates()) {
if (info.componentName.equals(
new ComponentName(TEST_PACKAGE_NAME, TEST_OTHER_SERVICE))) {
defaultAppInfo = info;
}
}
assertThat(defaultAppInfo).isNotNull();
assertThat(defaultAppInfo.enabled).isTrue();
}
@Test
public void getCurrentDefaultKey_defaultIsNull_returnsNull() {
ExtendedMockito.when(VoiceInputUtils.getCurrentService(mContext)).thenReturn(null);
assertThat(mPreferenceController.getCurrentDefaultKey()).isNull();
}
@Test
public void getCurrentDefaultKey_defaultExists_returnsComponentName() {
ComponentName cn = new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE);
assertThat(mPreferenceController.getCurrentDefaultKey()).isEqualTo(cn.flattenToString());
}
@Test
public void setCurrentDefault_typeVoiceInteractionInfo_setsServices() {
when(mMockVoiceInputInfoProvider.getInfoForComponent(any()))
.thenReturn(mMockVoiceInteractionInfo);
when(mMockVoiceInteractionInfo.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
when(mMockVoiceInteractionInfo.getRecognitionService()).thenReturn(TEST_RECOGNIZER);
String key = new ComponentName(TEST_PACKAGE_NAME, TEST_SERVICE).flattenToString();
String recognizer = new ComponentName(TEST_PACKAGE_NAME, TEST_RECOGNIZER).flattenToString();
mPreferenceController.setCurrentDefault(key);
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE)).isEqualTo(key);
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE)).isEqualTo(recognizer);
}
@Test
public void setCurrentDefault_typeVoiceRecognitionInfo_setsRecognitionService() {
when(mMockVoiceInputInfoProvider.getInfoForComponent(any()))
.thenReturn(mMockVoiceRecognitionInfo);
String key = new ComponentName(TEST_PACKAGE_NAME, TEST_RECOGNIZER).flattenToString();
mPreferenceController.setCurrentDefault(key);
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE)).isEmpty();
assertThat(Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE)).isEqualTo(key);
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.google.common.truth.Truth.assertThat;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.provider.Settings;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiSwitchPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class ScreenshotContextPreferenceControllerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private TwoStatePreference mPreference;
private ScreenshotContextPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mPreference = new CarUiSwitchPreference(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new ScreenshotContextPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
}
@Test
public void refreshUi_screenshotEnabled_preferenceChecked() {
mPreference.setChecked(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1);
mPreferenceController.refreshUi();
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void refreshUi_screenshotDisabled_preferenceUnchecked() {
mPreference.setChecked(true);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 0);
mPreferenceController.refreshUi();
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void refreshUi_structureEnabled_preferenceEnabled() {
mPreference.setEnabled(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1);
mPreferenceController.refreshUi();
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void refreshUi_structureDisabled_preferenceDisabled() {
mPreference.setEnabled(true);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 0);
mPreferenceController.refreshUi();
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void callChangeListener_toggleTrue_screenshotEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 0);
mPreference.callChangeListener(true);
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 0)).isEqualTo(1);
}
@Test
public void callChangeListener_toggleFalse_screenshotDisabled() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1);
mPreference.callChangeListener(false);
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1)).isEqualTo(0);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.google.common.truth.Truth.assertThat;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.provider.Settings;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.TwoStatePreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiSwitchPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class TextContextPreferenceControllerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private TwoStatePreference mPreference;
private TextContextPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mPreference = new CarUiSwitchPreference(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new TextContextPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
}
@Test
public void refreshUi_contextEnabled_preferenceChecked() {
mPreference.setChecked(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1);
mPreferenceController.refreshUi();
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void refreshUi_contextDisabled_preferenceUnchecked() {
mPreference.setChecked(true);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 0);
mPreferenceController.refreshUi();
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void callChangeListener_toggleTrue_contextEnabled() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 0);
mPreference.callChangeListener(true);
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 0)).isEqualTo(1);
}
@Test
public void callChangeListener_toggleFalse_contextDisabled() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1);
mPreference.callChangeListener(false);
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1)).isEqualTo(0);
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.android.car.settings.applications.assist.VoiceInputInfoProvider.VOICE_INTERACTION_SERVICE_TAG;
import static com.android.car.settings.applications.assist.VoiceInputInfoProvider.VOICE_RECOGNITION_SERVICE_TAG;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.service.voice.VoiceInteractionServiceInfo;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class VoiceInputInfoProviderTest {
private static final String TEST_PACKAGE = "test.package";
private static final String TEST_CLASS = "Class1";
private static final String TEST_RECOGNITION_SERVICE = "Recognition1";
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private VoiceInputInfoProvider mVoiceInputInfoProvider;
@Mock
private PackageManager mMockPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void getInteractionInfoList_hasElement() {
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = new ServiceInfo();
resolveInfo.serviceInfo.packageName = TEST_PACKAGE;
resolveInfo.serviceInfo.name = TEST_CLASS;
resolveInfo.serviceInfo.permission = Manifest.permission.BIND_VOICE_INTERACTION;
List<ResolveInfo> resolveInfoList = new ArrayList<>();
resolveInfoList.add(resolveInfo);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.queryIntentServices(VOICE_INTERACTION_SERVICE_TAG,
PackageManager.GET_META_DATA)).thenReturn(resolveInfoList);
mVoiceInputInfoProvider = new TestVoiceInputInfoProvider(mContext);
assertThat(mVoiceInputInfoProvider.getVoiceInteractionInfoList()).hasSize(1);
}
@Test
public void getRecognitionInfoList_hasElement() {
ResolveInfo otherInfo = new ResolveInfo();
otherInfo.serviceInfo = new ServiceInfo();
otherInfo.serviceInfo.packageName = TEST_PACKAGE;
otherInfo.serviceInfo.name = TEST_RECOGNITION_SERVICE;
List<ResolveInfo> resolveInfoList = new ArrayList<>();
resolveInfoList.add(otherInfo);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.queryIntentServices(VOICE_RECOGNITION_SERVICE_TAG,
PackageManager.GET_META_DATA)).thenReturn(resolveInfoList);
mVoiceInputInfoProvider = new TestVoiceInputInfoProvider(mContext);
assertThat(mVoiceInputInfoProvider.getVoiceRecognitionInfoList()).hasSize(1);
}
private static class TestVoiceInputInfoProvider extends VoiceInputInfoProvider {
TestVoiceInputInfoProvider(Context context) {
super(context);
}
@Override
boolean hasParseError(VoiceInteractionServiceInfo voiceInteractionServiceInfo) {
return false;
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2021 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.car.settings.applications.assist;
import static com.google.common.truth.Truth.assertThat;
import android.content.ComponentName;
import android.content.Context;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class VoiceInputUtilsTest {
private static final String TEST_PACKAGE = "test.package";
private static final String TEST_CLASS_1 = "Class1";
private static final String TEST_CLASS_2 = "Class2";
private Context mContext = ApplicationProvider.getApplicationContext();
@Test
public void getCurrentService_nullInteraction_nullRecognition_returnsNull() {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE, null);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE, null);
assertThat(VoiceInputUtils.getCurrentService(mContext)).isNull();
}
@Test
public void getCurrentService_emptyInteraction_emptyRecognition_returnsNull() {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE, "");
assertThat(VoiceInputUtils.getCurrentService(mContext)).isNull();
}
@Test
public void getCurrentService_hasInteraction_returnsInteraction() {
ComponentName interaction = new ComponentName(TEST_PACKAGE, TEST_CLASS_1);
ComponentName recognition = new ComponentName(TEST_PACKAGE, TEST_CLASS_2);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE, interaction.flattenToString());
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE, recognition.flattenToString());
assertThat(VoiceInputUtils.getCurrentService(mContext)).isEqualTo(interaction);
}
@Test
public void getCurrentService_noInteraction_hasRecognition_returnsRecogntion() {
ComponentName recognition = new ComponentName(TEST_PACKAGE, TEST_CLASS_2);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE, recognition.flattenToString());
assertThat(VoiceInputUtils.getCurrentService(mContext)).isEqualTo(recognition);
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2021 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.car.settings.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiPreference;
import com.android.settingslib.applications.DefaultAppInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class DefaultAppEntryBasePreferenceControllerTest {
private static final CharSequence TEST_LABEL = "Test Label";
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private CarUiPreference mPreference;
private TestDefaultAppEntryBasePreferenceController mController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreference = new CarUiPreference(mContext);
mController = new TestDefaultAppEntryBasePreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mController, mPreference);
}
@Test
public void refreshUi_hasDefaultAppWithLabel_summaryAndIconAreSet() {
DefaultAppInfo defaultAppInfo = mock(DefaultAppInfo.class);
when(defaultAppInfo.loadLabel()).thenReturn(TEST_LABEL);
when(defaultAppInfo.loadIcon()).thenReturn(mContext.getDrawable(R.drawable.test_icon));
mController.setCurrentDefaultAppInfo(defaultAppInfo);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
assertThat(mPreference.getSummary()).isEqualTo(TEST_LABEL);
assertThat(mPreference.getIcon()).isNotNull();
}
@Test
public void refreshUi_hasDefaultAppWithoutLabel_summaryAndIconAreNotSet() {
DefaultAppInfo defaultAppInfo = mock(DefaultAppInfo.class);
when(defaultAppInfo.loadLabel()).thenReturn(null);
when(defaultAppInfo.loadIcon()).thenReturn(null);
mController.setCurrentDefaultAppInfo(defaultAppInfo);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
assertThat(mPreference.getSummary()).isEqualTo(
mContext.getString(R.string.app_list_preference_none));
assertThat(mPreference.getIcon()).isNull();
}
@Test
public void refreshUi_hasNoDefaultApp_summaryAndIconAreNotSet() {
mController.setCurrentDefaultAppInfo(null);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
assertThat(mPreference.getSummary()).isEqualTo(
mContext.getString(R.string.app_list_preference_none));
assertThat(mPreference.getIcon()).isNull();
}
private static class TestDefaultAppEntryBasePreferenceController extends
DefaultAppEntryBasePreferenceController<Preference> {
private DefaultAppInfo mDefaultAppInfo;
TestDefaultAppEntryBasePreferenceController(Context context,
String preferenceKey, FragmentController fragmentController,
CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
}
@Override
protected Class<Preference> getPreferenceType() {
return Preference.class;
}
@Nullable
@Override
protected DefaultAppInfo getCurrentDefaultAppInfo() {
return mDefaultAppInfo;
}
protected void setCurrentDefaultAppInfo(DefaultAppInfo defaultAppInfo) {
mDefaultAppInfo = defaultAppInfo;
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2021 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.car.settings.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.graphics.drawable.Drawable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class DefaultAppUtilsTest {
@Test
public void setSafeIcon_smallerThanLimit() {
Context context = ApplicationProvider.getApplicationContext();
Drawable drawable = context.getDrawable(R.drawable.test_icon_2);
int height = drawable.getMinimumHeight();
int width = drawable.getMinimumWidth();
// Set to some value larger than current height or width;
int testMaxDimensions = Math.max(height, width) + 1;
Drawable icon = DefaultAppUtils.getSafeIcon(drawable, testMaxDimensions);
assertThat(icon.getMinimumHeight()).isEqualTo(height);
assertThat(icon.getMinimumWidth()).isEqualTo(width);
}
@Test
public void setSafeIcon_largerThanLimit() {
Context context = ApplicationProvider.getApplicationContext();
Drawable drawable = context.getDrawable(R.drawable.test_icon_2);
int height = drawable.getMinimumHeight();
int width = drawable.getMinimumWidth();
// Set to some value smaller than current height or width;
int testMaxDimensions = Math.min(height, width) - 5;
Drawable icon = DefaultAppUtils.getSafeIcon(drawable, testMaxDimensions);
assertThat(icon.getMinimumHeight()).isEqualTo(testMaxDimensions);
assertThat(icon.getMinimumWidth()).isEqualTo(testMaxDimensions);
}
@Test
public void setSafeIcon_noChangeForVectorDrawable() {
Context context = ApplicationProvider.getApplicationContext();
Drawable drawable = context.getDrawable(R.drawable.test_icon);
int height = drawable.getMinimumHeight();
int width = drawable.getMinimumWidth();
// Set to some value smaller than current height or width;
int testMaxDimensions = Math.min(height, width) - 1;
Drawable icon = DefaultAppUtils.getSafeIcon(drawable, testMaxDimensions);
assertThat(icon.getMinimumHeight()).isEqualTo(height);
assertThat(icon.getMinimumWidth()).isEqualTo(width);
}
}

View File

@@ -0,0 +1,308 @@
/*
* Copyright (C) 2021 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.car.settings.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiRadioButtonPreference;
import com.android.settingslib.applications.DefaultAppInfo;
import com.google.android.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class DefaultAppsPickerBasePreferenceControllerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private PreferenceGroup mPreferenceGroup;
private TestDefaultAppsPickerBasePreferenceController mController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mFragmentController;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mController = new TestDefaultAppsPickerBasePreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mController, mPreferenceGroup);
}
@Test
@UiThreadTest
public void refreshUi_noCandidates_hasSingleNoneElement() {
mController.setCurrentDefault("");
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
// Has the "None" element.
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
Preference preference = mPreferenceGroup.getPreference(0);
assertThat(preference.getTitle()).isEqualTo(
mContext.getString(R.string.app_list_preference_none));
assertThat(preference.getIcon()).isNotNull();
}
@Test
@UiThreadTest
public void refreshUi_noCandidates_noNoneElement() {
mController.setCurrentDefault("");
mController.setIncludeNonePreference(false);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
// None element removed.
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
}
@Test
@UiThreadTest
public void refreshUi_hasAdditionalCandidate_hasTwoElements() {
String testKey = "testKey";
DefaultAppInfo testApp = mock(DefaultAppInfo.class);
when(testApp.getKey()).thenReturn(testKey);
mController.setTestCandidates(Lists.newArrayList(testApp));
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
}
@Test
@UiThreadTest
public void refreshUi_hasAdditionalCandidateAsDefault_secondElementIsSelected() {
String testKey = "testKey";
DefaultAppInfo testApp = mock(DefaultAppInfo.class);
when(testApp.getKey()).thenReturn(testKey);
mController.setTestCandidates(Lists.newArrayList(testApp));
mController.setCurrentDefault(testKey);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
CarUiRadioButtonPreference preference = mPreferenceGroup.findPreference(testKey);
assertThat(preference.isChecked()).isTrue();
}
@Test
@UiThreadTest
public void performClick_currentDefaultApp_nothingHappened() {
String testKey = "testKey";
DefaultAppInfo testApp = mock(DefaultAppInfo.class);
when(testApp.getKey()).thenReturn(testKey);
mController.setTestCandidates(Lists.newArrayList(testApp));
mController.setCurrentDefault(testKey);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
CarUiRadioButtonPreference currentDefault = mPreferenceGroup.findPreference(testKey);
CarUiRadioButtonPreference otherOption =
(CarUiRadioButtonPreference) mPreferenceGroup.getPreference(0);
assertThat(currentDefault.isChecked()).isTrue();
assertThat(otherOption.isChecked()).isFalse();
currentDefault.performClick();
currentDefault = mPreferenceGroup.findPreference(testKey);
otherOption = (CarUiRadioButtonPreference) mPreferenceGroup.getPreference(0);
assertThat(currentDefault.isChecked()).isTrue();
assertThat(otherOption.isChecked()).isFalse();
}
@Test
@UiThreadTest
public void performClick_otherOptionNoMessage_otherOptionSelected() {
String testKey = "testKey";
DefaultAppInfo testApp = mock(DefaultAppInfo.class);
when(testApp.getKey()).thenReturn(testKey);
mController.setTestCandidates(Lists.newArrayList(testApp));
mController.setCurrentDefault(testKey);
mController.setTestMessage(null);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
CarUiRadioButtonPreference currentDefault = mPreferenceGroup.findPreference(testKey);
CarUiRadioButtonPreference otherOption =
(CarUiRadioButtonPreference) mPreferenceGroup.getPreference(0);
assertThat(currentDefault.isChecked()).isTrue();
assertThat(otherOption.isChecked()).isFalse();
otherOption.performClick();
currentDefault = mPreferenceGroup.findPreference(testKey);
otherOption = (CarUiRadioButtonPreference) mPreferenceGroup.getPreference(0);
assertThat(currentDefault.isChecked()).isFalse();
assertThat(otherOption.isChecked()).isTrue();
}
@Test
@UiThreadTest
public void performClick_otherOptionHasMessage_dialogOpened() {
String testKey = "testKey";
DefaultAppInfo testApp = mock(DefaultAppInfo.class);
when(testApp.getKey()).thenReturn(testKey);
mController.setTestCandidates(Lists.newArrayList(testApp));
mController.setCurrentDefault(testKey);
mController.setTestMessage("Non-empty message");
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
CarUiRadioButtonPreference currentDefault = mPreferenceGroup.findPreference(testKey);
CarUiRadioButtonPreference otherOption =
(CarUiRadioButtonPreference) mPreferenceGroup.getPreference(0);
assertThat(currentDefault.isChecked()).isTrue();
assertThat(otherOption.isChecked()).isFalse();
otherOption.performClick();
verify(mFragmentController).showDialog(
any(ConfirmationDialogFragment.class),
eq(ConfirmationDialogFragment.TAG));
}
@Test
@UiThreadTest
public void performClick_otherOptionNoMessage_newKeySet() {
String testKey = "testKey";
DefaultAppInfo testApp = mock(DefaultAppInfo.class);
when(testApp.getKey()).thenReturn(testKey);
mController.setTestCandidates(Lists.newArrayList(testApp));
// Currently, the testApp is the default selection.
mController.setCurrentDefault(testKey);
mController.onCreate(mLifecycleOwner);
mController.refreshUi();
// This preference represents the "None" option.
CarUiRadioButtonPreference otherOption =
(CarUiRadioButtonPreference) mPreferenceGroup.getPreference(0);
assertThat(mController.getCurrentDefaultKey()).isEqualTo(testKey);
otherOption.performClick();
assertThat(mController.getCurrentDefaultKey()).isEqualTo("");
}
private static class TestDefaultAppsPickerBasePreferenceController extends
DefaultAppsPickerBasePreferenceController {
private List<DefaultAppInfo> mCandidates;
private String mKey;
private CharSequence mMessage;
private boolean mIncludeNone = true;
TestDefaultAppsPickerBasePreferenceController(Context context, String preferenceKey,
FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
}
public void setTestCandidates(List<DefaultAppInfo> candidates) {
mCandidates = candidates;
}
public void setTestMessage(String s) {
mMessage = s;
}
public void setIncludeNonePreference(boolean include) {
mIncludeNone = include;
}
@Override
protected List<DefaultAppInfo> getCandidates() {
return mCandidates;
}
@Override
protected String getCurrentDefaultKey() {
return mKey;
}
@Override
protected void setCurrentDefault(String key) {
mKey = key;
}
@Override
protected CharSequence getConfirmationMessage(DefaultAppInfo info) {
return mMessage;
}
@Override
protected boolean includeNonePreference() {
return mIncludeNone;
}
}
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2022 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.car.settings.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
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 android.app.role.RoleManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiTwoActionIconPreference;
import com.android.settingslib.applications.DefaultAppInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
@RunWith(AndroidJUnit4.class)
public class DefaultAssistantPickerEntryPreferenceControllerTest {
private static final String TEST_PACKAGE = "com.android.car.settings.testutils";
private static final String TEST_CLASS = "BaseTestActivity";
private static final String TEST_COMPONENT =
new ComponentName(TEST_PACKAGE, TEST_CLASS).flattenToString();
private final int mUserId = UserHandle.myUserId();
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private CarUiTwoActionIconPreference mPreference;
private TestDefaultAssistantPickerEntryPreferenceController mController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mFragmentController;
@Mock
private RoleManager mMockRoleManager;
@Mock
private PackageManager mMockPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
when(mContext.getSystemService(RoleManager.class)).thenReturn(mMockRoleManager);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.queryIntentServices(any(), eq(PackageManager.GET_META_DATA)))
.thenReturn(Collections.emptyList());
doNothing().when(mContext).startActivity(any());
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreference = new CarUiTwoActionIconPreference(mContext);
mController = new TestDefaultAssistantPickerEntryPreferenceController(mContext,
/* preferenceKey= */ "key", mFragmentController, mCarUxRestrictions);
PreferenceControllerTestUtil.assignPreference(mController, mPreference);
mController.onCreate(mLifecycleOwner);
}
@Test
public void getCurrentDefaultAppInfo_noAssistant_returnsNull() {
when(mMockRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT))
.thenReturn(Collections.emptyList());
DefaultAppInfo info = mController.getCurrentDefaultAppInfo();
assertThat(info).isNull();
}
@Test
public void getCurrentDefaultAppInfo_hasService_returnsDefaultAppInfo() {
when(mMockRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT))
.thenReturn(Collections.singletonList(TEST_PACKAGE));
when(mMockPackageManager.queryIntentServices(any(), eq(PackageManager.GET_META_DATA)))
.thenReturn(Collections.singletonList(new ResolveInfo()));
mController.setSettingsActivity(TEST_CLASS);
DefaultAppInfo info = mController.getCurrentDefaultAppInfo();
assertThat(info.getKey()).isEqualTo(TEST_COMPONENT);
}
@Test
public void getSettingIntent_noAssistant_returnsNull() {
when(mMockRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT))
.thenReturn(Collections.emptyList());
DefaultAppInfo info = new DefaultAppInfo(mContext, mContext.getPackageManager(),
mUserId, ComponentName.unflattenFromString(TEST_COMPONENT));
Intent settingIntent = mController.getSettingIntent(info);
assertThat(settingIntent).isNull();
}
@Test
public void getSettingIntent_hasAssistant_noAssistSupport_returnsNull() {
when(mMockRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT))
.thenReturn(Collections.singletonList(TEST_PACKAGE));
when(mMockPackageManager.queryIntentServices(any(), eq(PackageManager.GET_META_DATA)))
.thenReturn(Collections.singletonList(new ResolveInfo()));
DefaultAppInfo info = new DefaultAppInfo(mContext, mContext.getPackageManager(),
mUserId, ComponentName.unflattenFromString(TEST_COMPONENT));
Intent settingIntent = mController.getSettingIntent(info);
assertThat(settingIntent).isNull();
}
@Test
public void getSettingIntent_hasAssistant_supportsAssist_hasSettingsActivity_returnsIntent() {
when(mMockRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT))
.thenReturn(Collections.singletonList(TEST_PACKAGE));
when(mMockPackageManager.queryIntentServices(any(), eq(PackageManager.GET_META_DATA)))
.thenReturn(Collections.singletonList(new ResolveInfo()));
mController.setSettingsActivity(TEST_CLASS);
DefaultAppInfo info = new DefaultAppInfo(mContext, mContext.getPackageManager(),
mUserId, ComponentName.unflattenFromString(TEST_COMPONENT));
Intent result = mController.getSettingIntent(info);
assertThat(result.getAction()).isEqualTo(Intent.ACTION_MAIN);
assertThat(result.getComponent()).isEqualTo(
new ComponentName(TEST_PACKAGE, TEST_CLASS));
}
@Test
public void performClick_permissionControllerExists_startsPermissionController() {
String testPackage = "com.test.permissions";
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(testPackage);
mController.handlePreferenceClicked(mPreference);
ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(argumentCaptor.capture());
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MANAGE_DEFAULT_APP);
assertThat(intent.getPackage()).isEqualTo(testPackage);
assertThat(intent.getStringExtra(Intent.EXTRA_ROLE_NAME)).isEqualTo(
RoleManager.ROLE_ASSISTANT);
}
@Test
public void performClick_permissionControllerDoesntExist_doesNotStartPermissionController() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(null);
mController.handlePreferenceClicked(mPreference);
verify(mContext, never()).startActivity(any());
}
private static class TestDefaultAssistantPickerEntryPreferenceController extends
DefaultAssistantPickerEntryPreferenceController {
private String mSettingsActivity;
TestDefaultAssistantPickerEntryPreferenceController(Context context,
String preferenceKey, FragmentController fragmentController,
CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
}
public void setSettingsActivity(String activity) {
mSettingsActivity = activity;
}
@Override
String getAssistSettingsActivity(PackageManager pm, ResolveInfo resolveInfo) {
return mSettingsActivity;
}
}
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2021 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.car.settings.applications.managedomainurls;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static com.android.car.settings.applications.managedomainurls.AppLaunchSettingsBasePreferenceController.sBrowserIntent;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.ListPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
@RunWith(AndroidJUnit4.class)
public class AppLinkStatePreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "com.example.test";
private static final int TEST_PACKAGE_ID = 1;
private static final String TEST_PATH = "TEST_PATH";
private final int mUserId = UserHandle.myUserId();
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private ListPreference mPreference;
private AppLinkStatePreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Mock
private PackageManager mMockPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mPreference = new ListPreference(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new AppLinkStatePreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockPackageManager);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
}
@Test
public void onCreate_isBrowserApp_isDisabled() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(true);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void onCreate_isNotBrowserApp_noDomainUrls_isDisabled() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
info.privateFlags = 0;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(false);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void onCreate_isNotBrowserApp_hasDomainUrls_isEnabled() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(false);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void onCreate_isNotBrowserApp_hasDomainUrls_defaultState_entrySetToAsk() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(false);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE_NAME, mUserId))
.thenReturn(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getEntry()).isEqualTo(
mContext.getString(R.string.app_link_open_ask));
}
@Test
public void onCreate_isNotBrowserApp_hasDomainUrls_askState_entrySetToAsk() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(false);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE_NAME, mUserId))
.thenReturn(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getEntry()).isEqualTo(
mContext.getString(R.string.app_link_open_ask));
}
@Test
public void onCreate_isNotBrowserApp_hasDomainUrls_alwaysState_entrySetToAlways() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(false);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE_NAME, mUserId))
.thenReturn(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getEntry()).isEqualTo(
mContext.getString(R.string.app_link_open_always));
}
@Test
public void onCreate_isNotBrowserApp_hasDomainUrls_neverState_entrySetToNever() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
info.privateFlags = ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
setupIsBrowserApp(false);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE_NAME, mUserId))
.thenReturn(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getEntry()).isEqualTo(
mContext.getString(R.string.app_link_open_never));
}
private void setupIsBrowserApp(boolean isBrowserApp) {
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.activityInfo = new ActivityInfo();
resolveInfo.handleAllWebDataURI = isBrowserApp;
sBrowserIntent.setPackage(TEST_PACKAGE_NAME);
when(mMockPackageManager.queryIntentActivitiesAsUser(sBrowserIntent,
PackageManager.MATCH_ALL, mUserId)).thenReturn(
Collections.singletonList(resolveInfo));
}
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2021 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.car.settings.applications.managedomainurls;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.os.RemoteException;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiPreference;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
@RunWith(AndroidJUnit4.class)
public class ClearDefaultsPreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "com.example.test";
private static final String TEST_OTHER_PACKAGE_NAME = "com.example.other.test";
private static final int TEST_PACKAGE_ID = 1;
private static final String TEST_PATH = "TEST_PATH";
private final int mUserId = UserHandle.myUserId();
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private CarUiPreference mPreference;
private ClearDefaultsPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private MockitoSession mSession;
@Mock
private FragmentController mMockFragmentController;
@Mock
private PackageManager mMockPackageManager;
@Mock
private IUsbManager mMockIUsbManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mPreference = new CarUiPreference(mContext);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new ClearDefaultsPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockPackageManager, mMockIUsbManager);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mSession = ExtendedMockito.mockitoSession().mockStatic(
AppUtils.class, withSettings().lenient()).startMocking();
}
@After
public void tearDown() {
if (mSession != null) {
mSession.finishMocking();
}
}
@Test
public void onCreate_hasPreferredActivities_hasSummary() {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(true);
setupPreferenceController();
assertThat(mPreference.getSummary().toString()).isNotEmpty();
}
@Test
public void onCreate_isDefaultBrowser_hasSummary() {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(false);
when(mMockPackageManager.getDefaultBrowserPackageNameAsUser(mUserId))
.thenReturn(TEST_PACKAGE_NAME);
setupPreferenceController();
assertThat(mPreference.getSummary().toString()).isNotEmpty();
}
@Test
public void onCreate_hasUsbDefaults_hasSummary() throws RemoteException {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(false);
when(mMockPackageManager.getDefaultBrowserPackageNameAsUser(mUserId))
.thenReturn(TEST_OTHER_PACKAGE_NAME);
when(mMockIUsbManager.hasDefaults(TEST_PACKAGE_NAME, mUserId)).thenReturn(true);
setupPreferenceController();
assertThat(mPreference.getSummary().toString()).isNotEmpty();
}
@Test
public void onCreate_autoLaunchDisabled_hasNoSummary() throws RemoteException {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(false);
when(mMockPackageManager.getDefaultBrowserPackageNameAsUser(mUserId))
.thenReturn(TEST_OTHER_PACKAGE_NAME);
when(mMockIUsbManager.hasDefaults(TEST_PACKAGE_NAME, mUserId)).thenReturn(false);
setupPreferenceController();
assertThat(mPreference.getSummary()).isNull();
}
@Test
public void performClick_hasUsbManager_hasPreferredActivities_clearsPreferredActivities() {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(true);
when(mMockPackageManager.getDefaultBrowserPackageNameAsUser(mUserId))
.thenReturn(TEST_OTHER_PACKAGE_NAME);
setupPreferenceController();
mPreference.performClick();
verify(mMockPackageManager).clearPackagePreferredActivities(TEST_PACKAGE_NAME);
}
@Test
public void performClick_hasUsbManager_isDefaultBrowser_clearsDefaultBrowser() {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(false);
when(mMockPackageManager.getDefaultBrowserPackageNameAsUser(mUserId))
.thenReturn(TEST_PACKAGE_NAME);
setupPreferenceController();
mPreference.performClick();
verify(mMockPackageManager).setDefaultBrowserPackageNameAsUser(/* packageName= */ null,
mUserId);
}
@Test
public void performClick_hasUsbDefaults_clearsUsbDefaults() throws RemoteException {
ExtendedMockito.when(AppUtils.hasPreferredActivities(mMockPackageManager,
TEST_PACKAGE_NAME)).thenReturn(false);
when(mMockPackageManager.getDefaultBrowserPackageNameAsUser(mUserId))
.thenReturn(TEST_OTHER_PACKAGE_NAME);
when(mMockIUsbManager.hasDefaults(TEST_PACKAGE_NAME, mUserId)).thenReturn(true);
setupPreferenceController();
mPreference.performClick();
verify(mMockIUsbManager).clearDefaults(TEST_PACKAGE_NAME, mUserId);
}
private void setupPreferenceController() {
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
mPreferenceController.setAppEntry(entry);
mPreferenceController.onCreate(mLifecycleOwner);
}
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (C) 2021 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.car.settings.applications.managedomainurls;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
public class DomainAppPreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "com.android.test.package";
private static final int TEST_PACKAGE_ID = 1;
private static final String TEST_LABEL = "Test App";
private static final String TEST_PATH = "TEST_PATH";
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private PreferenceGroup mPreferenceGroup;
private DomainAppPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Mock
private PackageManager mMockPackageManager;
@Mock
private ApplicationsState mMockApplicationsState;
@Mock
private ApplicationsState.Session mMockSession;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new DomainAppPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockApplicationsState, mMockPackageManager);
}
@Test
public void checkInitialized_noLifecycle_throwsError() {
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil.assignPreference(mPreferenceController,
mPreferenceGroup));
}
@Test
public void onRebuildComplete_sessionLoadsValues_preferenceGroupHasValues() {
setupPreferenceController();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
ArrayList<ApplicationsState.AppEntry> apps = new ArrayList<>();
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
entry.label = TEST_LABEL;
apps.add(entry);
mPreferenceController.mApplicationStateCallbacks.onRebuildComplete(apps);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
}
@Test
@UiThreadTest
public void performClick_startsApplicationLaunchSettingsFragmentWithPackageName() {
setupPreferenceController();
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
ArrayList<ApplicationsState.AppEntry> apps = new ArrayList<>();
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
ApplicationsState.AppEntry entry = new ApplicationsState.AppEntry(mContext, info,
TEST_PACKAGE_ID);
entry.label = TEST_LABEL;
apps.add(entry);
mPreferenceController.mApplicationStateCallbacks.onRebuildComplete(apps);
Preference preference = mPreferenceGroup.getPreference(0);
preference.performClick();
ArgumentCaptor<ApplicationLaunchSettingsFragment> captor = ArgumentCaptor.forClass(
ApplicationLaunchSettingsFragment.class);
verify(mMockFragmentController).launchFragment(captor.capture());
String pkgName = captor.getValue().getArguments().getString(
ApplicationLaunchSettingsFragment.ARG_PACKAGE_NAME);
assertThat(pkgName).isEqualTo(TEST_PACKAGE_NAME);
}
private void setupPreferenceController() {
when(mMockApplicationsState.newSession(any(), any())).thenReturn(mMockSession);
mPreferenceController.setLifecycle(mLifecycleOwner.getLifecycle());
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
}
}

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2021 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.car.settings.applications.managedomainurls;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArraySet;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiPreference;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
@RunWith(AndroidJUnit4.class)
public class DomainUrlsPreferenceControllerTest {
private static final String TEST_PACKAGE_NAME = "com.example.test";
private static final int TEST_PACKAGE_ID = 1;
private static final String TEST_PATH = "TEST_PATH";
private static final String TEST_DOMAIN = "example.com";
private static final String TEST_SUMMARY = "test_summary";
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private Preference mPreference;
private DomainUrlsPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private MockitoSession mSession;
private ApplicationsState.AppEntry mAppEntry;
private ArraySet<String> mMockDomains;
private boolean mIsBrowserApp;
@Mock
private FragmentController mFragmentController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreference = new CarUiPreference(mContext);
mPreferenceController = new TestDomainUrlsPreferenceController(mContext,
"key", mFragmentController, mCarUxRestrictions);
ApplicationInfo info = new ApplicationInfo();
info.packageName = TEST_PACKAGE_NAME;
info.uid = TEST_PACKAGE_ID;
info.sourceDir = TEST_PATH;
mAppEntry = new ApplicationsState.AppEntry(mContext, info, TEST_PACKAGE_ID);
mMockDomains = new ArraySet<>();
mSession = ExtendedMockito.mockitoSession().mockStatic(DomainUrlsUtils.class,
withSettings().lenient()).startMocking();
when(DomainUrlsUtils.getHandledDomains(any(PackageManager.class),
eq(TEST_PACKAGE_NAME))).thenReturn(mMockDomains);
when(DomainUrlsUtils.getDomainsSummary(mContext, TEST_PACKAGE_NAME, UserHandle.myUserId(),
mMockDomains)).thenReturn(TEST_SUMMARY);
}
@After
public void tearDown() {
if (mSession != null) {
mSession.finishMocking();
}
}
@Test
public void onCreate_isBrowserApp_isDisabled() {
mIsBrowserApp = true;
mMockDomains.add(TEST_DOMAIN);
mPreferenceController.setAppEntry(mAppEntry);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void onCreate_isNotBrowserApp_isEnabled() {
mIsBrowserApp = false;
mMockDomains.add(TEST_DOMAIN);
mPreferenceController.setAppEntry(mAppEntry);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void onCreate_hasNoDomains_isDisabled() {
mIsBrowserApp = false;
mPreferenceController.setAppEntry(mAppEntry);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void onCreate_isBrowserApp_summarySet() {
mIsBrowserApp = true;
mMockDomains.add(TEST_DOMAIN);
mPreferenceController.setAppEntry(mAppEntry);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary()).isEqualTo(TEST_SUMMARY);
}
@Test
public void onCreate_isNotBrowserApp_summarySet() {
mIsBrowserApp = false;
mMockDomains.add(TEST_DOMAIN);
mPreferenceController.setAppEntry(mAppEntry);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
assertThat(mPreference.getSummary()).isEqualTo(TEST_SUMMARY);
}
@Test
public void performClick_isNotBrowserApp_opensDialog() {
mIsBrowserApp = false;
mMockDomains.add(TEST_DOMAIN);
mPreferenceController.setAppEntry(mAppEntry);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
mPreference.performClick();
verify(mFragmentController).showDialog(
any(ConfirmationDialogFragment.class), eq(ConfirmationDialogFragment.TAG));
}
private class TestDomainUrlsPreferenceController extends DomainUrlsPreferenceController {
TestDomainUrlsPreferenceController(Context context, String preferenceKey,
FragmentController fragmentController,
CarUxRestrictions uxRestrictions) {
super(context, preferenceKey, fragmentController, uxRestrictions);
}
@Override
protected boolean isBrowserApp() {
return mIsBrowserApp;
}
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (C) 2021 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.car.settings.applications.managedomainurls;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
import android.util.ArraySet;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
public class DomainUrlsUtilsTest {
private static final String TEST_PACKAGE = "com.test.android.Package";
private static final int USER_ID = 10;
private Context mContext = spy(ApplicationProvider.getApplicationContext());
@Mock
private PackageManager mMockPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void getDomainsSummary_domainStatusSetToNever_showNoneText() {
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE, USER_ID))
.thenReturn(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER);
assertThat(DomainUrlsUtils.getDomainsSummary(mContext, TEST_PACKAGE, USER_ID,
new ArraySet<>())).isEqualTo(mContext.getString(R.string.domain_urls_summary_none));
}
@Test
public void getDomainsSummary_domainStatusSet_noDomains_showNoneText() {
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE, USER_ID))
.thenReturn(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK);
assertThat(DomainUrlsUtils.getDomainsSummary(mContext, TEST_PACKAGE, USER_ID,
new ArraySet<>())).isEqualTo(mContext.getString(R.string.domain_urls_summary_none));
}
@Test
public void getDomainsSummary_domainStatusSet_oneDomain_showSingleDomain() {
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE, USER_ID))
.thenReturn(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK);
ArraySet<String> domains = new ArraySet<>();
domains.add("test.domain.com");
assertThat(DomainUrlsUtils.getDomainsSummary(mContext, TEST_PACKAGE, USER_ID,
domains)).isEqualTo(
mContext.getString(R.string.domain_urls_summary_one, domains.valueAt(0)));
}
@Test
public void getDomainsSummary_domainStatusSet_multipleDomain_showMultipleDomains() {
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.getIntentVerificationStatusAsUser(TEST_PACKAGE, USER_ID))
.thenReturn(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK);
ArraySet<String> domains = new ArraySet<>();
domains.add("test.domain.com");
domains.add("test.domain2.com");
assertThat(DomainUrlsUtils.getDomainsSummary(mContext, TEST_PACKAGE, USER_ID,
domains)).isEqualTo(
mContext.getString(R.string.domain_urls_summary_some, domains.valueAt(0)));
}
@Test
public void getHandledDomains_includeIntentFilterVerificationInfoDomains() {
String domain = "test.domain.com";
ArraySet<String> domains = new ArraySet<>();
domains.add(domain);
IntentFilterVerificationInfo info = new IntentFilterVerificationInfo(TEST_PACKAGE, domains);
when(mMockPackageManager.getIntentFilterVerifications(TEST_PACKAGE))
.thenReturn(Arrays.asList(info));
when(mMockPackageManager.getAllIntentFilters(TEST_PACKAGE)).thenReturn(null);
assertThat(DomainUrlsUtils.getHandledDomains(mMockPackageManager, TEST_PACKAGE))
.hasSize(1);
assertThat(DomainUrlsUtils.getHandledDomains(mMockPackageManager, TEST_PACKAGE))
.contains(domain);
}
@Test
public void getHandledDomains_includeBrowsableIntentFiltersWithHttpDataScheme() {
String domain = "test.domain.com";
String port = "80";
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_BROWSABLE);
filter.addDataScheme(IntentFilter.SCHEME_HTTP);
filter.addDataAuthority(new IntentFilter.AuthorityEntry(domain, port));
when(mMockPackageManager.getIntentFilterVerifications(TEST_PACKAGE))
.thenReturn(null);
when(mMockPackageManager.getAllIntentFilters(TEST_PACKAGE))
.thenReturn(Arrays.asList(filter));
assertThat(DomainUrlsUtils.getHandledDomains(mMockPackageManager, TEST_PACKAGE))
.hasSize(1);
assertThat(DomainUrlsUtils.getHandledDomains(mMockPackageManager, TEST_PACKAGE))
.contains(domain);
}
@Test
public void getHandledDomains_includeBrowsableIntentFiltersWithHttpsDataScheme() {
String domain = "test.domain.com";
String port = "80";
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_BROWSABLE);
filter.addDataScheme(IntentFilter.SCHEME_HTTPS);
filter.addDataAuthority(new IntentFilter.AuthorityEntry(domain, port));
when(mMockPackageManager.getIntentFilterVerifications(TEST_PACKAGE))
.thenReturn(null);
when(mMockPackageManager.getAllIntentFilters(TEST_PACKAGE))
.thenReturn(Arrays.asList(filter));
assertThat(DomainUrlsUtils.getHandledDomains(mMockPackageManager, TEST_PACKAGE))
.hasSize(1);
assertThat(DomainUrlsUtils.getHandledDomains(mMockPackageManager, TEST_PACKAGE))
.contains(domain);
}
@Test
public void getHandledDomains_excludeBrowsableIntentFiltersWithOtherDataScheme() {
PackageManager pm = mock(PackageManager.class);
String domain = "test.domain.com";
String port = "80";
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_BROWSABLE);
filter.addDataAuthority(new IntentFilter.AuthorityEntry(domain, port));
when(mMockPackageManager.getIntentFilterVerifications(TEST_PACKAGE))
.thenReturn(null);
when(mMockPackageManager.getAllIntentFilters(TEST_PACKAGE))
.thenReturn(Arrays.asList(filter));
assertThat(DomainUrlsUtils.getHandledDomains(pm, TEST_PACKAGE)).isEmpty();
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2022 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.car.settings.applications.performance;
import static android.car.settings.CarSettings.Secure.KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class PerfImpactingAppsItemManagerTest {
private static final int CALLBACK_TIMEOUT_MS = 100;
private static final String TEST_PKG_NAME = "test.package.name";
private static final String TEST_PRIVILEGE_PKG_NAME = "test.privilege.package.name";
private static final String TEST_DISABLED_PACKAGES_SETTING_STRING = TEST_PKG_NAME + ";"
+ TEST_PRIVILEGE_PKG_NAME;
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
private final TestListener mPerfImpactingAppsListener = new TestListener();
private MockitoSession mMockingSession;
private Context mContext;
private PerfImpactingAppsItemManager mManager;
@Before
public void setUp() {
mMockingSession = mockitoSession()
.initMocks(this)
.mockStatic(Settings.Secure.class)
.strictness(Strictness.LENIENT)
.startMocking();
mContext = spy(ApplicationProvider.getApplicationContext());
when(Settings.Secure.getString(any(), eq(KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE)))
.thenReturn(TEST_DISABLED_PACKAGES_SETTING_STRING);
mManager = new PerfImpactingAppsItemManager(mContext);
mManager.addListener(mPerfImpactingAppsListener);
}
@After
public void tearDown() {
mMockingSession.finishMocking();
}
@Test
public void startLoading_getDisabledPackagesCount() throws Exception {
mManager.startLoading();
mCountDownLatch.await(CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertThat(mPerfImpactingAppsListener.mResult).isEqualTo(2);
}
private class TestListener implements PerfImpactingAppsItemManager.PerfImpactingAppsListener {
int mResult;
@Override
public void onPerfImpactingAppsLoaded(int disabledPackagesCount) {
mResult = disabledPackagesCount;
mCountDownLatch.countDown();
}
}
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright (C) 2022 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.car.settings.applications.performance;
import static android.car.settings.CarSettings.Secure.KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE;
import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.car.Car;
import android.car.drivingstate.CarUxRestrictions;
import android.car.watchdog.CarWatchdogManager;
import android.car.watchdog.PackageKillableState;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiTwoActionTextPreference;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
@RunWith(AndroidJUnit4.class)
public final class PerfImpactingAppsPreferenceControllerTest {
private static final int TEST_USER_ID = 100;
private static final int TEST_PKG_UID = 10000001;
private static final String TEST_PKG_NAME = "test.package.name";
private static final int TEST_PRIVILEGE_PKG_UID = 10000002;
private static final String TEST_PRIVILEGE_PKG_NAME = "test.privilege.package.name";
private static final String TEST_DISABLED_PACKAGES_SETTING_STRING =
TEST_PKG_NAME + ";" + TEST_PRIVILEGE_PKG_NAME;
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
private MockitoSession mMockingSession;
private LifecycleOwner mLifecycleOwner;
private PerfImpactingAppsPreferenceController mController;
private LogicalPreferenceGroup mPreferenceGroup;
@Captor
private ArgumentCaptor<Car.CarServiceLifecycleListener> mCarLifecycleCaptor;
@Captor
private ArgumentCaptor<ConfirmationDialogFragment> mDialogFragmentCaptor;
@Mock
private PackageManager mMockPackageManager;
@Mock
private FragmentController mMockFragmentController;
@Mock
private Car mMockCar;
@Mock
private CarWatchdogManager mMockCarWatchdogManager;
@Before
@UiThreadTest
public void setUp() {
mMockingSession = mockitoSession()
.initMocks(this)
.mockStatic(Car.class)
.mockStatic(Settings.Secure.class)
.strictness(Strictness.LENIENT)
.startMocking();
mLifecycleOwner = new TestLifecycleOwner();
mDialogFragmentCaptor = ArgumentCaptor.forClass(ConfirmationDialogFragment.class);
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(Car.createCar(any(), any(), anyLong(), mCarLifecycleCaptor.capture())).then(
invocation -> {
Car.CarServiceLifecycleListener listener = mCarLifecycleCaptor.getValue();
listener.onLifecycleChanged(mMockCar, true);
return mMockCar;
});
when(mMockCar.getCarManager(Car.CAR_WATCHDOG_SERVICE)).thenReturn(mMockCarWatchdogManager);
when(mMockCarWatchdogManager.getPackageKillableStatesAsUser(
UserHandle.getUserHandleForUid(TEST_PKG_UID)))
.thenReturn(List.of(
new PackageKillableState(TEST_PKG_NAME, TEST_USER_ID,
PackageKillableState.KILLABLE_STATE_YES),
new PackageKillableState(TEST_PRIVILEGE_PKG_NAME, TEST_USER_ID,
PackageKillableState.KILLABLE_STATE_NEVER)));
CarUxRestrictions restrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mController = new PerfImpactingAppsPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController, restrictions);
PreferenceControllerTestUtil.assignPreference(mController, mPreferenceGroup);
initController();
}
@After
@UiThreadTest
public void tearDown() {
(new File(mContext.getDataDir(), TEST_PKG_NAME)).delete();
(new File(mContext.getDataDir(), TEST_PRIVILEGE_PKG_NAME)).delete();
mMockingSession.finishMocking();
}
@Test
@UiThreadTest
public void onPreferenceClick_primaryAppAction_sendAppDetailIntent() {
doNothing().when(mContext).startActivity(any());
Preference actualPreference = mPreferenceGroup.getPreference(0);
Preference.OnPreferenceClickListener onPreferenceClickListener =
actualPreference.getOnPreferenceClickListener();
onPreferenceClickListener.onPreferenceClick(actualPreference);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(captor.capture());
Intent intent = captor.getValue();
assertThat(intent).isNotNull();
assertWithMessage("Intent action").that(intent.getAction())
.isEqualTo(ACTION_APPLICATION_DETAILS_SETTINGS);
assertWithMessage("Intent data").that(intent.getData())
.isEqualTo(Uri.parse("package:" + TEST_PKG_NAME));
}
@Test
@UiThreadTest
public void onPreferenceClick_showConfirmationDialog_prioritizeApp() {
CarUiTwoActionTextPreference actualPreference =
(CarUiTwoActionTextPreference) mPreferenceGroup.getPreference(0);
actualPreference.performSecondaryActionClick();
verify(mMockFragmentController).showDialog(mDialogFragmentCaptor.capture(), anyString());
ConfirmationDialogFragment dialogFragment = mDialogFragmentCaptor.getValue();
assertThat(dialogFragment).isNotNull();
dialogFragment.onClick(dialogFragment.getDialog(), DialogInterface.BUTTON_POSITIVE);
verify(mMockCarWatchdogManager).setKillablePackageAsUser(TEST_PKG_NAME,
UserHandle.getUserHandleForUid(TEST_PKG_UID),
/* isKillable= */ false);
}
@Test
@UiThreadTest
public void onPreferenceClick_showConfirmationDialog_prioritizePrivilegedApp() {
CarUiTwoActionTextPreference actualPreference =
(CarUiTwoActionTextPreference) mPreferenceGroup.getPreference(1);
actualPreference.performSecondaryActionClick();
verify(mMockFragmentController).showDialog(mDialogFragmentCaptor.capture(), anyString());
ConfirmationDialogFragment dialogFragment = mDialogFragmentCaptor.getValue();
assertThat(dialogFragment).isNotNull();
dialogFragment.onClick(dialogFragment.getDialog(), DialogInterface.BUTTON_POSITIVE);
verify(mMockPackageManager).setApplicationEnabledSetting(TEST_PRIVILEGE_PKG_NAME,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, /* flags= */ 0);
}
@Test
@UiThreadTest
public void onPreferenceClick_showConfirmationDialog_cancel() {
CarUiTwoActionTextPreference actualPreference =
(CarUiTwoActionTextPreference) mPreferenceGroup.getPreference(1);
actualPreference.performSecondaryActionClick();
verify(mMockFragmentController).showDialog(mDialogFragmentCaptor.capture(), anyString());
ConfirmationDialogFragment dialogFragment = mDialogFragmentCaptor.getValue();
assertThat(dialogFragment).isNotNull();
dialogFragment.onClick(dialogFragment.getDialog(), DialogInterface.BUTTON_NEGATIVE);
verify(mMockPackageManager, never())
.setApplicationEnabledSetting(anyString(), anyInt(), anyInt());
verifyNoMoreInteractions(mMockCarWatchdogManager);
}
@Test
@UiThreadTest
public void onCreate_perfImpactingApps_withNoPackages() {
when(Settings.Secure.getString(any(), eq(KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE)))
.thenReturn("");
mController.onDestroy(mLifecycleOwner);
mController.onCreate(mLifecycleOwner);
assertWithMessage("Preference group count")
.that(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
}
private void initController() {
List<ResolveInfo> expectedResultInfos = getResultInfos();
when(Settings.Secure.getString(any(), eq(KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE)))
.thenReturn(TEST_DISABLED_PACKAGES_SETTING_STRING);
when(mMockPackageManager.queryIntentActivities(any(), any()))
.thenReturn(expectedResultInfos);
mController.onCreate(mLifecycleOwner);
List<CarUiTwoActionTextPreference> expectedPreferences =
getPreferences(expectedResultInfos);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(expectedPreferences.size());
for (int idx = 0; idx < expectedPreferences.size(); idx++) {
assertThatPreferenceAreEqual(idx,
(CarUiTwoActionTextPreference) mPreferenceGroup.getPreference(idx),
expectedPreferences.get(idx));
}
}
private List<CarUiTwoActionTextPreference> getPreferences(List<ResolveInfo> resolveInfos) {
return resolveInfos.stream().map(
resolveInfo ->
new PerfImpactingAppsPreferenceController.PerformanceImpactingAppPreference(
mContext, resolveInfo.activityInfo.applicationInfo))
.collect(Collectors.toList());
}
private List<ResolveInfo> getResultInfos() {
// Non-privileged Package
ResolveInfo resolveInfo1 = new ResolveInfo();
resolveInfo1.activityInfo = new ActivityInfo();
resolveInfo1.activityInfo.applicationInfo = new ApplicationInfo();
resolveInfo1.activityInfo.applicationInfo.uid = TEST_PKG_UID;
resolveInfo1.activityInfo.applicationInfo.packageName = TEST_PKG_NAME;
File appFile = new File(mContext.getDataDir(), TEST_PKG_NAME);
assertWithMessage("%s dir", TEST_PKG_NAME).that(appFile.mkdir()).isTrue();
resolveInfo1.activityInfo.applicationInfo.sourceDir = appFile.getAbsolutePath();
// Privileged Package
ResolveInfo resolveInfo2 = new ResolveInfo();
resolveInfo2.activityInfo = new ActivityInfo();
resolveInfo2.activityInfo.applicationInfo = new ApplicationInfo();
resolveInfo2.activityInfo.applicationInfo.uid = TEST_PRIVILEGE_PKG_UID;
resolveInfo2.activityInfo.applicationInfo.packageName = TEST_PRIVILEGE_PKG_NAME;
appFile = new File(mContext.getDataDir(), TEST_PRIVILEGE_PKG_NAME);
assertWithMessage("%s dir", TEST_PRIVILEGE_PKG_NAME).that(appFile.mkdir()).isTrue();
resolveInfo2.activityInfo.applicationInfo.sourceDir = appFile.getAbsolutePath();
return List.of(resolveInfo1, resolveInfo2);
}
private static void assertThatPreferenceAreEqual(int index, CarUiTwoActionTextPreference p1,
CarUiTwoActionTextPreference p2) {
assertWithMessage("Preference %s key", index).that(p1.getKey()).isEqualTo(p2.getKey());
assertWithMessage("Preference %s title", index).that(p1.getTitle().toString())
.isEqualTo(p2.getTitle().toString());
assertWithMessage("Preference %s secondary action text", index)
.that(p2.getSecondaryActionText().toString())
.isEqualTo(p2.getSecondaryActionText().toString());
}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Looper;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class AppEntryListManagerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private AppEntryListManager mAppEntryListManager;
@Mock
private ApplicationsState mMockApplicationsState;
@Mock
private ApplicationsState.Session mMockSession;
@Mock
private AppEntryListManager.ExtraInfoBridge mMockExtraInfoBridge;
@Mock
private AppEntryListManager.AppFilterProvider mMockFilterProvider;
@Mock
private AppEntryListManager.Callback mMockCallback;
@Captor
private ArgumentCaptor<ApplicationsState.Callbacks> mSessionCallbacksCaptor;
@Captor
private ArgumentCaptor<List<ApplicationsState.AppEntry>> mEntriesCaptor;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mMockApplicationsState.newSession(mSessionCallbacksCaptor.capture()))
.thenReturn(mMockSession);
when(mMockApplicationsState.getBackgroundLooper()).thenReturn(Looper.getMainLooper());
mAppEntryListManager = new AppEntryListManager(mContext, mMockApplicationsState);
mAppEntryListManager.init(mMockExtraInfoBridge, mMockFilterProvider, mMockCallback);
}
@Test
public void start_resumesSession() {
mAppEntryListManager.start();
verify(mMockSession).onResume();
}
@Test
public void onPackageListChanged_loadsExtraInfo() {
mSessionCallbacksCaptor.getValue().onPackageListChanged();
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
verify(mMockExtraInfoBridge).loadExtraInfo(any());
}
@Test
public void onLoadEntriesComplete_loadsExtraInfo() {
mSessionCallbacksCaptor.getValue().onLoadEntriesCompleted();
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
verify(mMockExtraInfoBridge).loadExtraInfo(any());
}
@Test
public void stop_pausesSession() {
mAppEntryListManager.stop();
verify(mMockSession).onPause();
}
@Test
public void destroy_destroysSession() {
mAppEntryListManager.destroy();
verify(mMockSession).onDestroy();
}
@Test
public void forceUpdate_loadsExtraInfo() {
ArrayList<ApplicationsState.AppEntry> entries = new ArrayList<>();
entries.add(mock(ApplicationsState.AppEntry.class));
when(mMockSession.getAllApps()).thenReturn(entries);
mAppEntryListManager.forceUpdate();
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
verify(mMockExtraInfoBridge).loadExtraInfo(entries);
}
@Test
public void forceUpdate_forEntry_loadsExtraInfo() {
ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
mAppEntryListManager.forceUpdate(entry);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
verify(mMockExtraInfoBridge).loadExtraInfo(mEntriesCaptor.capture());
assertThat(mEntriesCaptor.getValue()).containsExactly(entry);
}
@Test
public void loadingFinished_rebuildsSession() {
ApplicationsState.AppFilter appFilter = mock(ApplicationsState.AppFilter.class);
when(mMockFilterProvider.getAppFilter()).thenReturn(appFilter);
mSessionCallbacksCaptor.getValue().onLoadEntriesCompleted();
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
verify(mMockSession).rebuild(eq(appFilter),
eq(ApplicationsState.ALPHA_COMPARATOR), /* foreground= */ eq(false));
}
@Test
public void onRebuildComplete_callsCallback() {
ArrayList<ApplicationsState.AppEntry> entries = new ArrayList<>();
entries.add(mock(ApplicationsState.AppEntry.class));
mSessionCallbacksCaptor.getValue().onRebuildComplete(entries);
verify(mMockCallback).onAppEntryListChanged(entries);
}
}

View File

@@ -0,0 +1,305 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.Manifest;
import android.app.AppOpsManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Looper;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class AppOpsPreferenceControllerTest {
private static final int APP_OP_CODE = AppOpsManager.OP_WRITE_SETTINGS;
private static final String PERMISSION = Manifest.permission.WRITE_SETTINGS;
private static final int NEGATIVE_MODE = AppOpsManager.MODE_ERRORED;
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private PreferenceGroup mPreferenceGroup;
private AppOpsPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Mock
private AppOpsManager mMockAppOpsManager;
@Mock
private AppEntryListManager mMockAppEntryListManager;
@Mock
private ApplicationsState mMockApplicationsState;
@Captor
private ArgumentCaptor<AppEntryListManager.Callback> mCallbackCaptor;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
when(mMockApplicationsState.getBackgroundLooper()).thenReturn(Looper.getMainLooper());
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new AppOpsPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockAppOpsManager);
}
@Test
public void checkInitialized_noOpCode_throwsIllegalStateException() {
mPreferenceController.init(AppOpsManager.OP_NONE, PERMISSION, NEGATIVE_MODE);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil
.assignPreference(mPreferenceController, mPreferenceGroup));
}
@Test
public void checkInitialized_noPermission_throwsIllegalStateException() {
mPreferenceController.init(APP_OP_CODE, /* permission= */ null, NEGATIVE_MODE);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil
.assignPreference(mPreferenceController, mPreferenceGroup));
}
@Test
public void checkInitialized_noNegativeOpMode_throwsIllegalStateException() {
mPreferenceController.init(APP_OP_CODE, PERMISSION, /* negativeOpMode= */-1);
assertThrows(IllegalStateException.class,
() -> PreferenceControllerTestUtil
.assignPreference(mPreferenceController, mPreferenceGroup));
}
@Test
public void onStart_startsListManager() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
verify(mMockAppEntryListManager).start();
}
@Test
public void onStop_stopsListManager() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.onStop(mLifecycleOwner);
verify(mMockAppEntryListManager).stop();
}
@Test
public void onDestroy_destroysListManager() {
setupPreferenceController();
mPreferenceController.onDestroy(mLifecycleOwner);
verify(mMockAppEntryListManager).destroy();
}
@Test
public void onAppEntryListChanged_addsPreferencesForEntries() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
List<ApplicationsState.AppEntry> entries = Arrays.asList(
createAppEntry("test.package", /* uid= */ 1, /* isOpPermissible= */ true),
createAppEntry("another.test.package", /* uid= */ 2, /* isOpPermissible= */ false));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
assertThat(((TwoStatePreference) mPreferenceGroup.getPreference(0)).isChecked()).isTrue();
assertThat(((TwoStatePreference) mPreferenceGroup.getPreference(1)).isChecked()).isFalse();
}
@Test
public void onPreferenceChange_checkedState_setsAppOpModeAllowed() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
String packageName = "test.package";
int uid = 1;
List<ApplicationsState.AppEntry> entries = Collections.singletonList(
createAppEntry(packageName, uid, /* isOpPermissible= */ false));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
TwoStatePreference appPref = (TwoStatePreference) mPreferenceGroup.getPreference(0);
appPref.performClick();
verify(mMockAppOpsManager).setMode(APP_OP_CODE, uid, packageName,
AppOpsManager.MODE_ALLOWED);
}
@Test
public void onPreferenceChange_uncheckedState_setsNegativeAppOpMode() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
String packageName = "test.package";
int uid = 1;
List<ApplicationsState.AppEntry> entries = Collections.singletonList(
createAppEntry(packageName, uid, /* isOpPermissible= */ true));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
TwoStatePreference appPref = (TwoStatePreference) mPreferenceGroup.getPreference(0);
appPref.performClick();
verify(mMockAppOpsManager).setMode(APP_OP_CODE, uid, packageName,
NEGATIVE_MODE);
}
@Test
public void onPreferenceChange_updatesEntry() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
List<ApplicationsState.AppEntry> entries = Collections.singletonList(
createAppEntry("test.package", /* uid= */ 1, /* isOpPermissible= */ false));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
TwoStatePreference appPref = (TwoStatePreference) mPreferenceGroup.getPreference(0);
appPref.performClick();
verify(mMockAppEntryListManager).forceUpdate(entries.get(0));
}
@Test
public void showSystem_updatesEntries() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.setShowSystem(true);
verify(mMockAppEntryListManager).forceUpdate();
}
@Test
public void appFilter_showingSystemApps_keepsSystemEntries() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.setShowSystem(true);
ArgumentCaptor<AppEntryListManager.AppFilterProvider> filterCaptor =
ArgumentCaptor.forClass(AppEntryListManager.AppFilterProvider.class);
verify(mMockAppEntryListManager).init(any(), filterCaptor.capture(), any());
ApplicationsState.AppFilter filter = filterCaptor.getValue().getAppFilter();
ApplicationsState.AppEntry systemApp = createAppEntry("test.package",
/* uid= */ 1, /* isOpPermissible= */false);
systemApp.info.flags |= ApplicationInfo.FLAG_SYSTEM;
assertThat(filter.filterApp(systemApp)).isTrue();
}
@Test
public void appFilter_notShowingSystemApps_removesSystemEntries() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
// Not showing system by default.
ArgumentCaptor<AppEntryListManager.AppFilterProvider> filterCaptor =
ArgumentCaptor.forClass(AppEntryListManager.AppFilterProvider.class);
verify(mMockAppEntryListManager).init(any(), filterCaptor.capture(), any());
ApplicationsState.AppFilter filter = filterCaptor.getValue().getAppFilter();
ApplicationsState.AppEntry systemApp = createAppEntry("test.package",
/* uid= */ 1, /* isOpPermissible= */false);
systemApp.info.flags |= ApplicationInfo.FLAG_SYSTEM;
assertThat(filter.filterApp(systemApp)).isFalse();
}
@Test
public void appFilter_removesNullExtraInfoEntries() {
setupPreferenceController();
mPreferenceController.onStart(mLifecycleOwner);
ArgumentCaptor<AppEntryListManager.AppFilterProvider> filterCaptor =
ArgumentCaptor.forClass(AppEntryListManager.AppFilterProvider.class);
verify(mMockAppEntryListManager).init(any(), filterCaptor.capture(), any());
ApplicationsState.AppFilter filter = filterCaptor.getValue().getAppFilter();
ApplicationsState.AppEntry appEntry = createAppEntry("test.package",
/* uid= */ 1, /* isOpPermissible= */false);
appEntry.extraInfo = null;
assertThat(filter.filterApp(appEntry)).isFalse();
}
private ApplicationsState.AppEntry createAppEntry(String packageName, int uid,
boolean isOpPermissible) {
ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
info.uid = uid;
AppStateAppOpsBridge.PermissionState extraInfo = mock(
AppStateAppOpsBridge.PermissionState.class);
when(extraInfo.isPermissible()).thenReturn(isOpPermissible);
ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
appEntry.label = packageName;
appEntry.extraInfo = extraInfo;
return appEntry;
}
private void setupPreferenceController() {
mPreferenceController.init(APP_OP_CODE, PERMISSION, NEGATIVE_MODE);
mPreferenceController.mAppEntryListManager = mMockAppEntryListManager;
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreferenceGroup);
mPreferenceController.onCreate(mLifecycleOwner);
verify(mMockAppEntryListManager).init(any(AppStateAppOpsBridge.class), any(),
mCallbackCaptor.capture());
}
}

View File

@@ -0,0 +1,315 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
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.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import android.Manifest;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
import android.os.UserHandle;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.AdditionalMatchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class AppStateAppOpsBridgeTest {
private static final int APP_OP_CODE = AppOpsManager.OP_WRITE_SETTINGS;
private static final String PERMISSION = Manifest.permission.WRITE_SETTINGS;
private static final int USER_ID1 = 1;
private static final int USER_ID2 = 2;
private Context mContext = ApplicationProvider.getApplicationContext();
private AppOpsManager mAppOpsManager;
private AppStateAppOpsBridge mBridge;
private ParceledListSlice<PackageInfo> mParceledListSlice1;
private ParceledListSlice<PackageInfo> mParceledListSlice2;
private List<PackageInfo> mPackages;
private MockitoSession mSession;
@Mock
private IPackageManager mMockIPackageManager;
@Mock
private AppOpsManager mMockAppOpsManager;
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mPackages = new ArrayList<>();
mParceledListSlice1 = new ParceledListSlice<>(mPackages);
when(mMockIPackageManager.getPackagesHoldingPermissions(
AdditionalMatchers.aryEq(new String[]{PERMISSION}),
eq((long) PackageManager.GET_PERMISSIONS),
eq(USER_ID1)))
.thenReturn(mParceledListSlice1);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
UserHandle userHandle = UserHandle.of(USER_ID1);
mBridge = new AppStateAppOpsBridge(mContext, APP_OP_CODE, PERMISSION, mMockIPackageManager,
Collections.singletonList(userHandle), mMockAppOpsManager);
mSession = ExtendedMockito.mockitoSession().mockStatic(
UserHandle.class, withSettings().lenient()).startMocking();
ExtendedMockito.when(UserHandle.getUserId(USER_ID1)).thenReturn(USER_ID1);
}
@After
public void tearDown() {
if (mSession != null) {
mSession.finishMocking();
}
}
@Test
public void androidPackagesIgnored() throws RemoteException {
String packageName = "android";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
addPackageWithPermission(packageInfo, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNull();
}
@Test
public void selfPackageIgnored() throws RemoteException {
String packageName = mContext.getPackageName();
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
addPackageWithPermission(packageInfo, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNull();
}
@Test
public void packagesNotRequestingPermissionIgnored() throws RemoteException {
String packageName = "test.package";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
packageInfo.requestedPermissions = null;
mPackages.add(packageInfo);
when(mMockIPackageManager.isPackageAvailable(packageInfo.packageName, USER_ID1))
.thenReturn(true);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNull();
}
@Test
public void unavailablePackageIgnored() throws RemoteException {
String packageName = "test.package";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
addPackageWithPermission(packageInfo, AppOpsManager.MODE_ALLOWED);
when(mMockIPackageManager.isPackageAvailable(packageInfo.packageName, USER_ID1))
.thenReturn(false);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNull();
}
@Test
public void loadsAppOpsExtraInfo_modeAllowed_isPermissible() throws RemoteException {
String packageName = "test.package";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
addPackageWithPermission(packageInfo, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
assertThat(entry.extraInfo).isNull();
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNotNull();
assertThat(((AppStateAppOpsBridge.PermissionState) entry.extraInfo).isPermissible())
.isTrue();
}
@Test
public void loadsAppOpsExtraInfo_modeDefault_isPermissible() throws RemoteException {
String packageName = "test.package";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
addPackageWithPermission(packageInfo, AppOpsManager.MODE_DEFAULT);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
assertThat(entry.extraInfo).isNull();
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNotNull();
assertThat(((AppStateAppOpsBridge.PermissionState) entry.extraInfo).isPermissible())
.isTrue();
}
@Test
public void loadsAppOpsExtraInfo_modeIgnored_isNotPermissible() throws RemoteException {
ExtendedMockito.when(UserHandle.getUserId(anyInt())).thenReturn(USER_ID1);
String packageName = "test.package";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
addPackageWithPermission(packageInfo, AppOpsManager.MODE_IGNORED);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
assertThat(entry.extraInfo).isNull();
mockPackageOps(packageName, USER_ID1, AppOpsManager.MODE_IGNORED);
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNotNull();
assertThat(((AppStateAppOpsBridge.PermissionState) entry.extraInfo).isPermissible())
.isFalse();
}
@Test
public void loadsAppOpsExtraInfo_multipleApps() throws RemoteException {
String packageName1 = "test.package1";
PackageInfo packageInfo1 = createPackageInfo(packageName1, USER_ID1);
addPackageWithPermission(packageInfo1, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry1 = createAppEntry(packageInfo1);
String packageName2 = "test.package2";
PackageInfo packageInfo2 = createPackageInfo(packageName2, USER_ID2);
addPackageWithPermission(packageInfo2, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry2 = createAppEntry(packageInfo2);
ExtendedMockito.when(UserHandle.getUserId(USER_ID2)).thenReturn(USER_ID1);
mBridge.loadExtraInfo(Arrays.asList(entry1, entry2));
assertThat(entry1.extraInfo).isNotNull();
assertThat(entry2.extraInfo).isNotNull();
}
@Test
public void loadsAppOpExtraInfo_multipleProfiles() throws RemoteException {
String packageName1 = "test.package1";
PackageInfo packageInfo1 = createPackageInfo(packageName1, USER_ID1);
addPackageWithPermission(packageInfo1, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry1 = createAppEntry(packageInfo1);
// Add a package for another profile.
String packageName2 = "test.package2";
PackageInfo packageInfo2 = createPackageInfo(packageName2, USER_ID2);
mParceledListSlice2 = new ParceledListSlice<>(Collections.singletonList(packageInfo2));
when(mMockIPackageManager.getPackagesHoldingPermissions(
AdditionalMatchers.aryEq(new String[]{PERMISSION}),
eq((long) PackageManager.GET_PERMISSIONS),
eq(USER_ID2)))
.thenReturn(mParceledListSlice2);
when(mMockIPackageManager.isPackageAvailable(packageInfo2.packageName,
USER_ID2)).thenReturn(true);
mAppOpsManager.setMode(APP_OP_CODE, packageInfo2.applicationInfo.uid,
packageInfo2.packageName, AppOpsManager.MODE_ALLOWED);
ApplicationsState.AppEntry entry2 = createAppEntry(packageInfo2);
ExtendedMockito.when(UserHandle.getUserId(USER_ID2)).thenReturn(USER_ID2);
// Recreate the bridge so it has all user profiles.
UserHandle userHandle1 = new UserHandle(USER_ID1);
UserHandle userHandle2 = new UserHandle(USER_ID2);
mBridge = new AppStateAppOpsBridge(mContext, APP_OP_CODE, PERMISSION, mMockIPackageManager,
Arrays.asList(userHandle1, userHandle2), mMockAppOpsManager);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
mBridge.loadExtraInfo(Arrays.asList(entry1, entry2));
assertThat(entry1.extraInfo).isNotNull();
assertThat(entry2.extraInfo).isNotNull();
}
@Test
public void appEntryNotIncluded_extraInfoCleared() {
String packageName = "test.package";
PackageInfo packageInfo = createPackageInfo(packageName, USER_ID1);
ApplicationsState.AppEntry entry = createAppEntry(packageInfo);
entry.extraInfo = new Object();
mBridge.loadExtraInfo(Collections.singletonList(entry));
assertThat(entry.extraInfo).isNull();
}
private PackageInfo createPackageInfo(String packageName, int uid) {
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = packageName;
applicationInfo.uid = uid;
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
packageInfo.applicationInfo = applicationInfo;
packageInfo.requestedPermissions = new String[]{PERMISSION};
return packageInfo;
}
private void addPackageWithPermission(PackageInfo packageInfo, int mode)
throws RemoteException {
mPackages.add(packageInfo);
when(mMockIPackageManager.isPackageAvailable(packageInfo.packageName,
USER_ID1)).thenReturn(true);
mAppOpsManager.setMode(APP_OP_CODE, packageInfo.applicationInfo.uid,
packageInfo.packageName, mode);
}
private ApplicationsState.AppEntry createAppEntry(PackageInfo packageInfo) {
ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = packageInfo.applicationInfo;
return appEntry;
}
private void mockPackageOps(String packageName, int uid, int mode) {
AppOpsManager.OpEntry opEntry = mock(AppOpsManager.OpEntry.class);
when(opEntry.getMode()).thenReturn(mode);
AppOpsManager.PackageOps packageOps = new AppOpsManager.PackageOps(packageName, uid,
Collections.singletonList(opEntry));
List<AppOpsManager.PackageOps> packageOpsList = Collections.singletonList(packageOps);
when(mMockAppOpsManager.getPackagesForOps((int[]) any())).thenReturn(packageOpsList);
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.pm.ApplicationInfo;
import android.telephony.SmsManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
public class AppStatePremiumSmsBridgeTest {
private AppStatePremiumSmsBridge mBridge;
@Mock
private SmsManager mSmsManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mBridge = new AppStatePremiumSmsBridge(mSmsManager);
}
@Test
public void loadExtraInfo() {
String package1 = "test.package1";
ApplicationsState.AppEntry appEntry1 = createAppEntry(package1);
int value1 = SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW;
when(mSmsManager.getPremiumSmsConsent(package1)).thenReturn(value1);
String package2 = "test.package2";
ApplicationsState.AppEntry appEntry2 = createAppEntry(package2);
int value2 = SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW;
when(mSmsManager.getPremiumSmsConsent(package2)).thenReturn(value2);
mBridge.loadExtraInfo(Arrays.asList(appEntry1, appEntry2));
assertThat(appEntry1.extraInfo).isEqualTo(value1);
assertThat(appEntry2.extraInfo).isEqualTo(value2);
}
private ApplicationsState.AppEntry createAppEntry(String packageName) {
ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
appEntry.label = packageName;
return appEntry;
}
}

View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
import static com.android.car.settings.common.PreferenceController.AVAILABLE;
import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING;
import static com.android.car.settings.common.PreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.car.settings.common.PreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.car.ui.preference.CarUiPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class MoreSpecialAccessPreferenceControllerTest {
private static final String PACKAGE = "test.package";
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private CarUiPreference mPreference;
private Intent mIntent;
private ResolveInfo mResolveInfo;
private MoreSpecialAccessPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Mock
private PackageManager mMockPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
mIntent = new Intent(Intent.ACTION_MANAGE_SPECIAL_APP_ACCESSES);
mIntent.setPackage(PACKAGE);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = PACKAGE;
applicationInfo.name = "TestClass";
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.applicationInfo = applicationInfo;
mResolveInfo = new ResolveInfo();
mResolveInfo.activityInfo = activityInfo;
}
@Test
public void getAvailabilityStatus_noPermissionController_returnsUnsupportedOnDevice() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(null);
setUpPreferenceController();
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noPermissionController_zoneWrite() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(null);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noPermissionController_zoneRead() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(null);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noPermissionController_zoneHidden() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(null);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noResolvedActivity_returnsUnsupportedOnDevice() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(null);
setUpPreferenceController();
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noResolvedActivity_returnsUnsupportedOnDevice_zoneWrite() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(null);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noResolvedActivity_returnsUnsupportedOnDevice_zoneRead() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(null);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noResolvedActivity_returnsUnsupportedOnDevice_zoneHidden() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(null);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_resolvedActivity_returnsAvailable() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(mResolveInfo);
setUpPreferenceController();
assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
AVAILABLE);
}
@Test
public void getAvailabilityStatus_resolvedActivity_returnsAvailable_zoneWrite() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(mResolveInfo);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("write");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE);
}
@Test
public void getAvailabilityStatus_resolvedActivity_returnsAvailable_zoneRead() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(mResolveInfo);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("read");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), AVAILABLE_FOR_VIEWING);
}
@Test
public void getAvailabilityStatus_resolvedActivity_returnsAvailable_zoneHidden() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(mResolveInfo);
setUpPreferenceController();
mPreferenceController.setAvailabilityStatusForZone("hidden");
PreferenceControllerTestUtil.assertAvailability(
mPreferenceController.getAvailabilityStatus(), CONDITIONALLY_UNAVAILABLE);
}
@Test
public void preferenceClicked_startsResolvedActivity() {
when(mMockPackageManager.getPermissionControllerPackageName()).thenReturn(PACKAGE);
when(mMockPackageManager.resolveActivity(any(), eq(PackageManager.MATCH_DEFAULT_ONLY)))
.thenReturn(mResolveInfo);
doNothing().when(mContext).startActivity(any());
setUpPreferenceController();
mPreference.performClick();
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(captor.capture());
Intent intent = captor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MANAGE_SPECIAL_APP_ACCESSES);
assertThat(intent.getPackage()).isEqualTo(PACKAGE);
}
private void setUpPreferenceController() {
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new MoreSpecialAccessPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockPackageManager);
mPreference = new CarUiPreference(mContext);
PreferenceControllerTestUtil.assignPreference(mPreferenceController, mPreference);
mPreferenceController.onCreate(mLifecycleOwner);
}
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
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.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.app.NotificationManager;
import android.car.drivingstate.CarUxRestrictions;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.UserHandle;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.ConfirmationDialogFragment;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.PollingCheck;
import com.android.car.settings.testutils.TestLifecycleOwner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
@RunWith(AndroidJUnit4.class)
public class NotificationAccessPreferenceControllerTest {
private static final String PACKAGE_NAME = "com.android.test.package";
private Context mContext = spy(ApplicationProvider.getApplicationContext());
private LifecycleOwner mLifecycleOwner;
private PreferenceGroup mPreferenceGroup;
private NotificationAccessPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
private ServiceInfo mListenerServiceInfo;
private ComponentName mListenerComponent;
private ApplicationInfo mApplicationInfo;
private NotificationManager mNotificationManager;
@Mock
private FragmentController mMockFragmentController;
@Mock
private PackageManager mMockPackageManager;
@Mock
private Resources mMockResources;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mNotificationManager = spy(mContext.getSystemService(NotificationManager.class));
mPreferenceController = new NotificationAccessPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mNotificationManager);
PreferenceControllerTestUtil
.assignPreference(mPreferenceController, mPreferenceGroup);
mListenerServiceInfo = new ServiceInfo();
mListenerServiceInfo.permission = Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
mListenerServiceInfo.packageName = PACKAGE_NAME;
mListenerServiceInfo.name = "SomeListenerService";
mListenerServiceInfo.nonLocalizedLabel = "label";
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.uid = 123;
mApplicationInfo.name = "SomeApplicationInfo";
mListenerServiceInfo.applicationInfo = mApplicationInfo;
mListenerComponent = new ComponentName(mListenerServiceInfo.packageName,
mListenerServiceInfo.name);
}
@Test
public void onStart_loadsListenerServices_preferenceEnabled()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */true, mListenerServiceInfo);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
assertThat(preference.isEnabled()).isTrue();
}
@Test
@UiThreadTest
public void onStart_loadsFixedPackage_preferenceDisabled()
throws PackageManager.NameNotFoundException {
String[] fixedPackages = new String[] {PACKAGE_NAME};
when(mContext.getResources()).thenReturn(mMockResources);
when(mMockResources.getStringArray(anyInt()))
.thenReturn(fixedPackages);
mPreferenceController = new NotificationAccessPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mNotificationManager);
PreferenceControllerTestUtil
.assignPreference(mPreferenceController, mPreferenceGroup);
setupPreferenceController(/* permissionGranted= */ true, mListenerServiceInfo);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
assertThat(preference.isEnabled()).isFalse();
}
@Test
public void onStart_serviceAccessGranted_setsPreferenceChecked()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */true, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
assertThat(preference.isChecked()).isTrue();
}
@Test
public void onStart_serviceAccessNotGranted_setsPreferenceUnchecked()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */false, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
assertThat(preference.isChecked()).isFalse();
}
@Test
public void preferenceClicked_serviceAccessGranted_showsRevokeConfirmDialog()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */true, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
preference.performClick();
verify(mMockFragmentController).showDialog(any(
ConfirmationDialogFragment.class),
eq(NotificationAccessPreferenceController.REVOKE_CONFIRM_DIALOG_TAG));
}
@Test
public void preferenceClicked_serviceAccessNotGranted_showsGrantConfirmDialog()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */false, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
preference.performClick();
verify(mMockFragmentController).showDialog(any(
ConfirmationDialogFragment.class),
eq(NotificationAccessPreferenceController.GRANT_CONFIRM_DIALOG_TAG));
}
@Test
public void revokeConfirmed_revokesNotificationAccess()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */true, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
preference.performClick();
ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
ConfirmationDialogFragment.class);
verify(mMockFragmentController).showDialog(dialogCaptor.capture(),
eq(NotificationAccessPreferenceController.REVOKE_CONFIRM_DIALOG_TAG));
ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
dialogFragment.onClick(/* dialog= */ null, DialogInterface.BUTTON_POSITIVE);
assertThat(mNotificationManager.isNotificationListenerAccessGranted(mListenerComponent))
.isFalse();
}
@Test
public void revokeConfirmed_notificationPolicyAccessNotGranted_removesAutomaticZenRules()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */true, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
preference.performClick();
ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
ConfirmationDialogFragment.class);
verify(mMockFragmentController).showDialog(dialogCaptor.capture(),
eq(NotificationAccessPreferenceController.REVOKE_CONFIRM_DIALOG_TAG));
ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
mNotificationManager.setNotificationPolicyAccessGranted(
mListenerServiceInfo.packageName, /* granted= */ false);
dialogFragment.onClick(/* dialog= */ null, DialogInterface.BUTTON_POSITIVE);
PollingCheck.waitFor(
() -> mPreferenceController.mAsyncTask.getStatus() == AsyncTask.Status.FINISHED);
verify(mNotificationManager).removeAutomaticZenRules(any());
}
@Test
public void grantConfirmed_grantsNotificationAccess()
throws PackageManager.NameNotFoundException {
setupPreferenceController(/* permissionGranted= */false, mListenerServiceInfo);
TwoStatePreference preference = (TwoStatePreference) mPreferenceGroup.getPreference(0);
preference.performClick();
ArgumentCaptor<ConfirmationDialogFragment> dialogCaptor = ArgumentCaptor.forClass(
ConfirmationDialogFragment.class);
verify(mMockFragmentController).showDialog(dialogCaptor.capture(),
eq(NotificationAccessPreferenceController.GRANT_CONFIRM_DIALOG_TAG));
ConfirmationDialogFragment dialogFragment = dialogCaptor.getValue();
dialogFragment.onClick(/* dialog= */ null, DialogInterface.BUTTON_POSITIVE);
assertThat(mNotificationManager.isNotificationListenerAccessGranted(mListenerComponent))
.isTrue();
}
private void setupPreferenceController(boolean permissionGranted, ServiceInfo serviceInfo)
throws PackageManager.NameNotFoundException {
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockPackageManager.getApplicationInfoAsUser(mListenerServiceInfo.packageName,
/* flags= */ 0, UserHandle.myUserId())).thenReturn(mApplicationInfo);
mNotificationManager.setNotificationListenerAccessGranted(mListenerComponent,
/* granted= */ permissionGranted);
mPreferenceController.onCreate(mLifecycleOwner);
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.onServicesReloaded(Collections.singletonList(serviceInfo));
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2021 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.car.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Looper;
import android.telephony.SmsManager;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.car.settings.common.FragmentController;
import com.android.car.settings.common.LogicalPreferenceGroup;
import com.android.car.settings.common.PreferenceControllerTestUtil;
import com.android.car.settings.testutils.TestLifecycleOwner;
import com.android.settingslib.applications.ApplicationsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class PremiumSmsAccessPreferenceControllerTest {
private Context mContext = ApplicationProvider.getApplicationContext();
private LifecycleOwner mLifecycleOwner;
private PreferenceGroup mPreferenceGroup;
private PremiumSmsAccessPreferenceController mPreferenceController;
private CarUxRestrictions mCarUxRestrictions;
@Mock
private FragmentController mMockFragmentController;
@Mock
private AppEntryListManager mMockAppEntryListManager;
@Mock
private ApplicationsState mMockApplicationsState;
@Mock
private SmsManager mMockSmsManager;
@Captor
private ArgumentCaptor<AppEntryListManager.Callback> mCallbackCaptor;
@Before
@UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = new TestLifecycleOwner();
when(mMockApplicationsState.getBackgroundLooper()).thenReturn(Looper.getMainLooper());
PreferenceManager preferenceManager = new PreferenceManager(mContext);
PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreferenceGroup = new LogicalPreferenceGroup(mContext);
screen.addPreference(mPreferenceGroup);
mCarUxRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */ true,
CarUxRestrictions.UX_RESTRICTIONS_BASELINE, /* timestamp= */ 0).build();
mPreferenceController = new PremiumSmsAccessPreferenceController(mContext,
/* preferenceKey= */ "key", mMockFragmentController,
mCarUxRestrictions, mMockSmsManager, mMockAppEntryListManager);
PreferenceControllerTestUtil
.assignPreference(mPreferenceController, mPreferenceGroup);
mPreferenceController.onCreate(mLifecycleOwner);
verify(mMockAppEntryListManager).init(any(AppStatePremiumSmsBridge.class), any(),
mCallbackCaptor.capture());
}
@Test
public void onStart_startsListManager() {
mPreferenceController.onStart(mLifecycleOwner);
verify(mMockAppEntryListManager).start();
}
@Test
public void onStop_stopsListManager() {
mPreferenceController.onStart(mLifecycleOwner);
mPreferenceController.onStop(mLifecycleOwner);
verify(mMockAppEntryListManager).stop();
}
@Test
public void onDestroy_destroysListManager() {
mPreferenceController.onDestroy(mLifecycleOwner);
verify(mMockAppEntryListManager).destroy();
}
@Test
public void onAppEntryListChanged_addsPreferencesForEntries() {
mPreferenceController.onStart(mLifecycleOwner);
List<ApplicationsState.AppEntry> entries = Arrays.asList(
createAppEntry("test.package", /* uid= */ 1,
SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW),
createAppEntry("another.test.package", /* uid= */ 2,
SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
assertThat(((ListPreference) mPreferenceGroup.getPreference(0)).getValue()).isEqualTo(
String.valueOf(SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW));
assertThat(((ListPreference) mPreferenceGroup.getPreference(1)).getValue()).isEqualTo(
String.valueOf(SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW));
}
@Test
public void onPreferenceChange_setsPremiumSmsPermission() {
mPreferenceController.onStart(mLifecycleOwner);
String packageName = "test.package";
List<ApplicationsState.AppEntry> entries = Collections.singletonList(
createAppEntry(packageName, /* uid= */ 1,
SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
Preference appPref = mPreferenceGroup.getPreference(0);
int updatedValue = SmsManager.PREMIUM_SMS_CONSENT_ASK_USER;
appPref.getOnPreferenceChangeListener().onPreferenceChange(appPref,
String.valueOf(updatedValue));
verify(mMockSmsManager).setPremiumSmsConsent(packageName, updatedValue);
}
@Test
public void onPreferenceChange_updatesEntry() {
mPreferenceController.onStart(mLifecycleOwner);
List<ApplicationsState.AppEntry> entries = Collections.singletonList(
createAppEntry("test.package", /* uid= */ 1,
SmsManager.PREMIUM_SMS_CONSENT_NEVER_ALLOW));
mCallbackCaptor.getValue().onAppEntryListChanged(entries);
Preference appPref = mPreferenceGroup.getPreference(0);
appPref.getOnPreferenceChangeListener().onPreferenceChange(appPref,
String.valueOf(SmsManager.PREMIUM_SMS_CONSENT_ASK_USER));
verify(mMockAppEntryListManager).forceUpdate(entries.get(0));
}
@Test
public void appFilter_removesUnknownStates() {
mPreferenceController.onStart(mLifecycleOwner);
ArgumentCaptor<AppEntryListManager.AppFilterProvider> filterCaptor =
ArgumentCaptor.forClass(AppEntryListManager.AppFilterProvider.class);
verify(mMockAppEntryListManager).init(any(), filterCaptor.capture(), any());
ApplicationsState.AppFilter filter = filterCaptor.getValue().getAppFilter();
ApplicationsState.AppEntry unknownStateApp = createAppEntry("test.package", /* uid= */ 1,
SmsManager.PREMIUM_SMS_CONSENT_UNKNOWN);
assertThat(filter.filterApp(unknownStateApp)).isFalse();
}
private ApplicationsState.AppEntry createAppEntry(String packageName, int uid, int smsState) {
ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
info.uid = uid;
ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
appEntry.label = packageName;
appEntry.extraInfo = smsState;
return appEntry;
}
}