Snap for 11302939 from a01eee9bd2 to 24Q2-release

Change-Id: I7b29659223009766da784f58d26a3dbb981ee529
This commit is contained in:
Android Build Coastguard Worker
2024-01-12 01:29:14 +00:00
24 changed files with 325 additions and 150 deletions

View File

@@ -0,0 +1,8 @@
package: "com.android.settings.flags"
flag {
name: "protect_lock_after_timeout_with_auth"
namespace: "safety_center"
description: "Require an auth challenge to open Lock after timeout page"
bug: "315937886"
}

View File

@@ -17,7 +17,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto">
<com.android.settings.widget.FilterTouchesSwitchPreference
<com.android.settingslib.RestrictedSwitchPreference
android:key="app_ops_settings_switch" />
<com.android.settingslib.widget.FooterPreference

View File

@@ -40,7 +40,7 @@
<!-- available in pin/pattern/password -->
<com.android.settings.display.TimeoutListPreference
<com.android.settings.security.screenlock.ProtectedTimeoutListPreference
android:key="lock_after_timeout"
android:title="@string/lock_after_timeout"
android:summary="@string/summary_placeholder"

View File

@@ -21,7 +21,7 @@ import static android.provider.Settings.System.KEYBOARD_VIBRATION_ENABLED;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
@@ -42,6 +42,8 @@ import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
@@ -62,6 +64,8 @@ public class KeyboardVibrationTogglePreferenceController extends TogglePreferenc
@Nullable
private TwoStatePreference mPreference;
private MetricsFeatureProvider mMetricsFeatureProvider;
public KeyboardVibrationTogglePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mVibrator = context.getSystemService(Vibrator.class);
@@ -75,6 +79,7 @@ public class KeyboardVibrationTogglePreferenceController extends TogglePreferenc
}
}
};
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
@Override
@@ -120,6 +125,8 @@ public class KeyboardVibrationTogglePreferenceController extends TogglePreferenc
@Override
public boolean setChecked(boolean isChecked) {
final boolean success = updateKeyboardVibrationSetting(isChecked);
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_KEYBOARD_VIBRATION_CHANGED, isChecked);
if (success && isChecked) {
// Play the preview vibration effect when the toggle is on.
final VibrationAttributes touchAttrs =

View File

@@ -38,11 +38,11 @@ import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
@@ -57,7 +57,7 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
// TODO: Break out this functionality into its own class.
private AppStateUsageBridge mUsageBridge;
private AppOpsManager mAppOpsManager;
private TwoStatePreference mSwitchPref;
private RestrictedSwitchPreference mSwitchPref;
private Preference mUsageDesc;
private Intent mSettingsIntent;
private UsageState mUsageState;
@@ -78,7 +78,7 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
mDpm = context.getSystemService(DevicePolicyManager.class);
addPreferencesFromResource(R.xml.app_ops_permissions_details);
mSwitchPref = (TwoStatePreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
mSwitchPref = (RestrictedSwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
mUsageDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
getPreferenceScreen().setTitle(R.string.usage_access);
@@ -170,8 +170,16 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
mPackageInfo.applicationInfo.uid);
boolean hasAccess = mUsageState.isPermissible();
boolean shouldEnable = mUsageState.permissionDeclared;
if (shouldEnable && !hasAccess) {
mSwitchPref.checkEcmRestrictionAndSetDisabled(AppOpsManager.OPSTR_GET_USAGE_STATS,
mPackageName, mPackageInfo.applicationInfo.uid);
shouldEnable = !mSwitchPref.isDisabledByEcm();
}
mSwitchPref.setChecked(hasAccess);
mSwitchPref.setEnabled(mUsageState.permissionDeclared);
mSwitchPref.setEnabled(shouldEnable);
ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
PackageManager.GET_META_DATA, mUserId);

View File

@@ -86,6 +86,14 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
return new UserHandle(getUserIdFromDeviceAdminInfo(mInfo));
}
public int getUid() {
return mInfo.getActivityInfo().applicationInfo.uid;
}
public String getPackageName() {
return mInfo.getPackageName();
}
public Intent getLaunchIntent(Context context) {
return new Intent(context, DeviceAdminAdd.class)
.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mInfo.getComponent());

View File

@@ -18,6 +18,7 @@ package com.android.settings.applications.specialaccess.deviceadmin;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import android.Manifest;
import android.app.AppGlobals;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DeviceAdminReceiver;
@@ -45,12 +46,13 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.widget.AppSwitchPreference;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.TwoTargetPreference;
import org.xmlpull.v1.XmlPullParserException;
@@ -167,35 +169,35 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
if (mFooterPreference != null) {
mFooterPreference.setVisible(mAdmins.isEmpty());
}
final Map<String, AppSwitchPreference> preferenceCache = new ArrayMap<>();
final Map<String, RestrictedSwitchPreference> preferenceCache = new ArrayMap<>();
final Context prefContext = mPreferenceGroup.getContext();
final int childrenCount = mPreferenceGroup.getPreferenceCount();
for (int i = 0; i < childrenCount; i++) {
final Preference pref = mPreferenceGroup.getPreference(i);
if (!(pref instanceof AppSwitchPreference)) {
if (!(pref instanceof RestrictedSwitchPreference switchPref)) {
continue;
}
final AppSwitchPreference appSwitch = (AppSwitchPreference) pref;
preferenceCache.put(appSwitch.getKey(), appSwitch);
preferenceCache.put(switchPref.getKey(), switchPref);
}
for (DeviceAdminListItem item : mAdmins) {
final String key = item.getKey();
AppSwitchPreference pref = preferenceCache.remove(key);
RestrictedSwitchPreference pref = preferenceCache.remove(key);
if (pref == null) {
pref = new AppSwitchPreference(prefContext);
pref = new RestrictedSwitchPreference(prefContext);
mPreferenceGroup.addPreference(pref);
}
bindPreference(item, pref);
}
for (AppSwitchPreference unusedCacheItem : preferenceCache.values()) {
for (RestrictedSwitchPreference unusedCacheItem : preferenceCache.values()) {
mPreferenceGroup.removePreference(unusedCacheItem);
}
}
private void bindPreference(DeviceAdminListItem item, AppSwitchPreference pref) {
private void bindPreference(DeviceAdminListItem item, RestrictedSwitchPreference pref) {
pref.setKey(item.getKey());
pref.setTitle(item.getName());
pref.setIcon(item.getIcon());
pref.setIconSize(TwoTargetPreference.ICON_SIZE_DEFAULT);
pref.setChecked(item.isActive());
pref.setSummary(item.getDescription());
pref.setEnabled(item.isEnabled());
@@ -207,6 +209,8 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
});
pref.setOnPreferenceChangeListener((preference, newValue) -> false);
pref.setSingleLineTitle(true);
pref.checkEcmRestrictionAndSetDisabled(Manifest.permission.BIND_DEVICE_ADMIN,
item.getPackageName(), item.getUid());
}
/**

View File

@@ -26,6 +26,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.datetime.ZoneGetter;
import java.util.Calendar;
@@ -52,6 +53,12 @@ public class TimeZonePreferenceController extends BasePreferenceController {
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (preference instanceof RestrictedPreference
&& ((RestrictedPreference) preference).isDisabledByAdmin()) {
return;
}
preference.setEnabled(shouldEnableManualTimeZoneSelection());
}

View File

@@ -105,8 +105,13 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
public void onActivityCreated(final Bundle icicle) {
super.onActivityCreated(icicle);
Bundle arguments = getArguments();
if (arguments == null) {
Log.e(TAG, "Arguments should not be null");
return;
}
mInputDeviceIdentifier =
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER);
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER,
InputDeviceIdentifier.class);
if (mInputDeviceIdentifier == null) {
Log.e(TAG, "The inputDeviceIdentifier should not be null");
return;
@@ -128,6 +133,7 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
InputDevice inputDevice =
NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier);
if (inputDevice == null) {
Log.e(TAG, "Unable to start: input device is null");
getActivity().finish();
return;
}

View File

@@ -151,7 +151,8 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
mKeyboardA11yCategory.removePreference(mAccessibilityStickyKeys);
}
InputDeviceIdentifier inputDeviceIdentifier = activity.getIntent().getParcelableExtra(
KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
InputDeviceIdentifier.class);
int intentFromWhere =
activity.getIntent().getIntExtra(android.provider.Settings.EXTRA_ENTRYPOINT, -1);
if (intentFromWhere != -1) {
@@ -168,7 +169,8 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
}
private static boolean isAutoSelection(Bundle bundle, InputDeviceIdentifier identifier) {
if (bundle != null && bundle.getParcelable(EXTRA_AUTO_SELECTION) != null) {
if (bundle != null && bundle.getParcelable(EXTRA_AUTO_SELECTION,
InputDeviceIdentifier.class) != null) {
return false;
}
return identifier != null;
@@ -446,7 +448,8 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
if (mIntentWaitingForResult != null) {
InputDeviceIdentifier inputDeviceIdentifier = mIntentWaitingForResult
.getParcelableExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
.getParcelableExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
InputDeviceIdentifier.class);
mIntentWaitingForResult = null;
showKeyboardLayoutDialog(inputDeviceIdentifier);
}

View File

@@ -0,0 +1,40 @@
/*
* 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.settings.security.screenlock;
import android.content.Context;
import android.util.AttributeSet;
import com.android.settings.display.TimeoutListPreference;
import com.android.settings.flags.Flags;
import com.android.settings.wifi.dpp.WifiDppUtils;
/** Wraps {@link TimeoutListPreference} with an authentication challenge for user. */
public class ProtectedTimeoutListPreference extends TimeoutListPreference {
public ProtectedTimeoutListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void performClick() {
if (Flags.protectLockAfterTimeoutWithAuth()) {
WifiDppUtils.showLockScreen(getContext(), super::performClick);
} else {
super.performClick();
}
}
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.spa.app.appinfo
import android.app.settings.SettingsEnums
import android.content.pm.ApplicationInfo
import android.os.UserManager
import androidx.annotation.VisibleForTesting
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Report
import androidx.compose.material3.Text
@@ -87,9 +88,10 @@ class AppForceStopButton(
dialogPresenter.open()
}
private fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when {
@VisibleForTesting
fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when {
packageManager.isPackageStateProtected(app.packageName, app.userId) -> {
RestrictedLockUtilsInternal.getDeviceOwner(context)
RestrictedLockUtilsInternal.getDeviceOwner(context) ?: EnforcedAdmin()
}
else -> RestrictedLockUtilsInternal.checkIfRestrictionEnforced(

View File

@@ -23,9 +23,13 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
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 static org.mockito.Mockito.verify;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
import android.os.vibrator.Flags;
@@ -37,6 +41,7 @@ import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Rule;
@@ -49,7 +54,6 @@ import org.robolectric.RobolectricTestRunner;
/** Tests for {@link KeyboardVibrationTogglePreferenceController}. */
@RunWith(RobolectricTestRunner.class)
public class KeyboardVibrationTogglePreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -59,8 +63,8 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
private Context mContext;
private Resources mResources;
private KeyboardVibrationTogglePreferenceController mController;
private SwitchPreference mPreference;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
@@ -68,6 +72,7 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
mContext = spy(ApplicationProvider.getApplicationContext());
mResources = spy(mContext.getResources());
when(mContext.getResources()).thenReturn(mResources);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mController = new KeyboardVibrationTogglePreferenceController(mContext, "preferenceKey");
mPreference = new SwitchPreference(mContext);
when(mPreferenceScreen.findPreference(
@@ -148,6 +153,8 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
mController.setChecked(true);
assertThat(readSystemSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED)).isEqualTo(ON);
verify(mFeatureFactory.metricsFeatureProvider).action(any(),
eq(SettingsEnums.ACTION_KEYBOARD_VIBRATION_CHANGED), eq(true));
}
@Test
@@ -160,6 +167,8 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
mController.setChecked(false);
assertThat(readSystemSetting(Settings.System.KEYBOARD_VIBRATION_ENABLED)).isEqualTo(OFF);
verify(mFeatureFactory.metricsFeatureProvider).action(any(),
eq(SettingsEnums.ACTION_KEYBOARD_VIBRATION_CHANGED), eq(false));
}
private void updateSystemSetting(String key, int value) {

View File

@@ -19,8 +19,10 @@ package com.android.settings.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo;
@@ -32,6 +34,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -45,7 +48,9 @@ import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.widget.SettingsMainSwitchPreference;
import org.junit.Before;
@@ -53,6 +58,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -298,7 +304,9 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG)
public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning()
@RequiresFlagsDisabled(
com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN)
public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_showDialog()
throws Throwable {
setupServiceWarningRequired(false);
mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null);
@@ -309,6 +317,23 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
AccessibilityDialogUtils.DialogEnums.EDIT_SHORTCUT);
}
@Test
@RequiresFlagsEnabled({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG,
com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN})
public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_launchActivity()
throws Throwable {
setupServiceWarningRequired(false);
mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null);
doNothing().when(mContext).startActivity(any());
mFragment.onSettingsClicked(mFragment.mShortcutPreference);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(captor.capture());
assertThat(captor.getValue().getExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(EditShortcutsPreferenceFragment.class.getName());
}
private void setupTileService(String packageName, String name, String tileName) {
final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE);
final ResolveInfo info = new ResolveInfo();

View File

@@ -23,15 +23,15 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
@@ -45,7 +45,7 @@ public class VrListenerScreenPreferenceControllerTest {
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mContext = ApplicationProvider.getApplicationContext();
mController = new VrListenerScreenPreferenceController(mContext, "key");
mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
}

View File

@@ -25,23 +25,20 @@ import static org.mockito.Mockito.verify;
import android.app.NotificationManager;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowNotificationManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowActivityManager.class,
})
public class ZenAccessControllerTest {
private static final String TEST_PKG = "com.test.package";
@@ -49,15 +46,12 @@ public class ZenAccessControllerTest {
private FakeFeatureFactory mFeatureFactory;
private Context mContext;
private ZenAccessController mController;
private ShadowActivityManager mActivityManager;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mContext = ApplicationProvider.getApplicationContext();
mFeatureFactory = FakeFeatureFactory.setupForTest();
mController = new ZenAccessController(mContext, "key");
mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
}
@Test

View File

@@ -46,6 +46,7 @@ import android.os.UserHandle;
import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -53,7 +54,6 @@ import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.PrimarySwitchPreference;
@@ -65,15 +65,16 @@ import com.android.settingslib.widget.LayoutPreference;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@@ -83,10 +84,13 @@ import java.util.concurrent.TimeUnit;
@Config(
shadows = {
ShadowEntityHeaderController.class,
ShadowActivityManager.class,
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class AdvancedPowerUsageDetailTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final String APP_LABEL = "app label";
private static final String SUMMARY = "summary";
private static final String[] PACKAGE_NAME = {"com.android.app"};
@@ -125,9 +129,7 @@ public class AdvancedPowerUsageDetailTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getPackageName()).thenReturn("foo");
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;

View File

@@ -47,11 +47,11 @@ import android.widget.CompoundButton;
import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
@@ -65,15 +65,16 @@ import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@@ -83,10 +84,13 @@ import java.util.concurrent.TimeUnit;
@Config(
shadows = {
ShadowEntityHeaderController.class,
ShadowActivityManager.class,
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class PowerBackgroundUsageDetailTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final String APP_LABEL = "app label";
private static final String SUMMARY = "summary";
private static final int ICON_ID = 123;
@@ -123,9 +127,7 @@ public class PowerBackgroundUsageDetailTest {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getPackageName()).thenReturn("foo");
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);

View File

@@ -45,29 +45,30 @@ import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.fragment.app.Fragment;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl;
import com.android.settings.testutils.shadow.ShadowActivityEmbeddingUtils;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowPasswordUtils;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@@ -77,11 +78,8 @@ import org.robolectric.util.ReflectionHelpers;
ShadowActivityManager.class,
})
public class SettingsHomepageActivityTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@After
public void tearDown() {
@@ -120,7 +118,8 @@ public class SettingsHomepageActivityTest {
@Config(qualifiers = "mcc999")
public void launch_LowRamDevice_shouldHideAvatar() {
final ShadowActivityManager activityManager = Shadow.extract(
RuntimeEnvironment.application.getSystemService(ActivityManager.class));
ApplicationProvider.getApplicationContext().getSystemService(
ActivityManager.class));
activityManager.setIsLowRamDevice(true);
final SettingsHomepageActivity activity = Robolectric.buildActivity(

View File

@@ -34,21 +34,23 @@ import android.provider.Settings;
import android.widget.Switch;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor;
import com.android.settingslib.widget.MainSwitchPreference;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
@@ -56,7 +58,10 @@ import org.robolectric.shadow.api.Shadow;
ShadowActivityManager.class,
})
public class BubbleNotificationPreferenceControllerTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
private Context mContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
@@ -67,33 +72,29 @@ public class BubbleNotificationPreferenceControllerTest {
private BubbleNotificationPreferenceController mController;
private MainSwitchPreference mPreference;
private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
private ShadowActivityManager mActivityManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContext = ApplicationProvider.getApplicationContext();
mController = new BubbleNotificationPreferenceController(mContext,
KEY_NOTIFICATION_BUBBLES);
mPreference = new MainSwitchPreference(RuntimeEnvironment.application);
mPreference = new MainSwitchPreference(mContext);
mPreference.setKey(mController.getPreferenceKey());
when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
mActivityManager = Shadow.extract(mContext.getSystemService(ActivityManager.class));
}
@Test
public void isAvailable_lowRam_returnsUnsupported() {
final ShadowActivityManager activityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
activityManager.setIsLowRamDevice(true);
mActivityManager.setIsLowRamDevice(true);
assertEquals(UNSUPPORTED_ON_DEVICE, mController.getAvailabilityStatus());
}
@Test
public void isAvailable_notLowRam_returnsAvailable() {
final ShadowActivityManager activityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
activityManager.setIsLowRamDevice(false);
mActivityManager.setIsLowRamDevice(false);
assertEquals(AVAILABLE, mController.getAvailabilityStatus());
}

View File

@@ -30,17 +30,17 @@ import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
@@ -48,19 +48,23 @@ import org.robolectric.shadow.api.Shadow;
})
public class BubbleSummaryNotificationPreferenceControllerTest {
private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
private Context mContext;
private BubbleSummaryNotificationPreferenceController mController;
private Preference mPreference;
private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
private ShadowActivityManager mActivityManager;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mContext = ApplicationProvider.getApplicationContext();
mController = new BubbleSummaryNotificationPreferenceController(mContext,
KEY_NOTIFICATION_BUBBLES);
mPreference = new Preference(RuntimeEnvironment.application);
mPreference = new Preference(mContext);
mActivityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
}
@Test
@@ -80,17 +84,13 @@ public class BubbleSummaryNotificationPreferenceControllerTest {
@Test
public void isAvailable_lowRam_returnsUnsupported() {
final ShadowActivityManager activityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
activityManager.setIsLowRamDevice(true);
mActivityManager.setIsLowRamDevice(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void isAvailable_notLowRam_returnsAvailable() {
final ShadowActivityManager activityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
activityManager.setIsLowRamDevice(false);
mActivityManager.setIsLowRamDevice(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
}

View File

@@ -55,24 +55,26 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
@@ -83,6 +85,8 @@ import java.util.List;
ShadowActivityManager.class,
})
public class BubblePreferenceControllerTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private Context mContext;
@Mock
@@ -103,11 +107,10 @@ public class BubblePreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
mContext = RuntimeEnvironment.application;
mContext = ApplicationProvider.getApplicationContext();
when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
mController = spy(new BubblePreferenceController(mContext, mFragmentManager, mBackend,
false /* isAppPage */, mListener));

View File

@@ -43,27 +43,30 @@ import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.testutils.shadow.ShadowActivityManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowActivityManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowActivityManager.class,
})
public class BubbleSummaryPreferenceControllerTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
private Context mContext;
@Mock
@@ -72,16 +75,17 @@ public class BubbleSummaryPreferenceControllerTest {
private BubbleSummaryPreferenceController mController;
private ShadowActivityManager mActivityManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = RuntimeEnvironment.application;
mContext = ApplicationProvider.getApplicationContext();
when(mBackend.hasSentValidBubble(anyString(), anyInt())).thenReturn(true);
mAppRow = new NotificationBackend.AppRow();
mAppRow.pkg = "pkg";
mAppRow.uid = 0;
mController = spy(new BubbleSummaryPreferenceController(mContext, mBackend));
mActivityManager = Shadow.extract(mContext.getSystemService(ActivityManager.class));
}
@Test
@@ -151,9 +155,7 @@ public class BubbleSummaryPreferenceControllerTest {
Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
mController.onResume(mAppRow, null, null, null, null, null, null);
final ShadowActivityManager activityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
activityManager.setIsLowRamDevice(true);
mActivityManager.setIsLowRamDevice(true);
assertFalse(mController.isAvailable());
}
@@ -162,9 +164,7 @@ public class BubbleSummaryPreferenceControllerTest {
Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
mController.onResume(mAppRow, null, null, null, null, null, null);
final ShadowActivityManager activityManager =
Shadow.extract(mContext.getSystemService(ActivityManager.class));
activityManager.setIsLowRamDevice(false);
mActivityManager.setIsLowRamDevice(false);
assertTrue(mController.isAvailable());
}

View File

@@ -17,79 +17,82 @@
package com.android.settings.spa.app.appinfo
import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.UserHandle
import android.os.UserManager
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.button.ActionButton
import com.android.settings.R
import com.android.settingslib.spa.testutils.delay
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.model.app.userId
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.Mockito.`when` as whenever
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class)
class AppForceStopButtonTest {
@get:Rule
val composeTestRule = createComposeRule()
@get:Rule
val mockito: MockitoRule = MockitoJUnit.rule()
private val mockPackageManager = mock<PackageManager>()
@Spy
private val context: Context = ApplicationProvider.getApplicationContext()
private val mockDevicePolicyManager = mock<DevicePolicyManager>()
@Mock
private lateinit var packageInfoPresenter: PackageInfoPresenter
@Mock
private lateinit var packageManager: PackageManager
@Mock
private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var appForceStopButton: AppForceStopButton
@Before
fun setUp() {
whenever(packageInfoPresenter.context).thenReturn(context)
whenever(context.packageManager).thenReturn(packageManager)
whenever(context.devicePolicyManager).thenReturn(devicePolicyManager)
appForceStopButton = AppForceStopButton(packageInfoPresenter)
private val mockUserManager = mock<UserManager> {
on { getUserRestrictionSources(any(), any()) } doReturn emptyList()
}
@Test
fun getActionButton() {
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { packageManager } doReturn mockPackageManager
on { devicePolicyManager } doReturn mockDevicePolicyManager
on { getSystemService(Context.DEVICE_POLICY_SERVICE) } doReturn mockDevicePolicyManager
on { getSystemService(Context.USER_SERVICE) } doReturn mockUserManager
}
private val packageInfoPresenter = mock<PackageInfoPresenter> {
on { context } doReturn context
}
private val appForceStopButton = AppForceStopButton(packageInfoPresenter)
@Test
fun getActionButton_isActiveAdmin_buttonDisabled() {
val app = createApp()
whenever(devicePolicyManager.packageHasActiveAdmins(PACKAGE_NAME, app.userId))
.thenReturn(true)
mockDevicePolicyManager.stub {
on { packageHasActiveAdmins(PACKAGE_NAME, app.userId) } doReturn true
}
val actionButton = setForceStopButton(app)
setForceStopButton(app)
assertThat(actionButton.enabled).isFalse()
composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
}
@Test
fun getActionButton_isUninstallInQueue_buttonDisabled() {
val app = createApp()
whenever(devicePolicyManager.isUninstallInQueue(PACKAGE_NAME)).thenReturn(true)
mockDevicePolicyManager.stub {
on { isUninstallInQueue(PACKAGE_NAME) } doReturn true
}
val actionButton = setForceStopButton(app)
setForceStopButton(app)
assertThat(actionButton.enabled).isFalse()
composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
}
@Test
@@ -98,35 +101,79 @@ class AppForceStopButtonTest {
flags = ApplicationInfo.FLAG_STOPPED
}
val actionButton = setForceStopButton(app)
setForceStopButton(app)
assertThat(actionButton.enabled).isFalse()
composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
}
@Test
fun getActionButton_regularApp_buttonEnabled() {
val app = createApp()
val actionButton = setForceStopButton(app)
setForceStopButton(app)
assertThat(actionButton.enabled).isTrue()
composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsEnabled()
}
private fun setForceStopButton(app: ApplicationInfo): ActionButton {
lateinit var actionButton: ActionButton
composeTestRule.setContent {
actionButton = appForceStopButton.getActionButton(app)
@Test
fun getAdminRestriction_packageNotProtected() {
mockPackageManager.stub {
on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn false
}
return actionButton
val admin = appForceStopButton.getAdminRestriction(createApp())
assertThat(admin).isNull()
}
@Test
fun getAdminRestriction_packageProtectedAndHaveOwner() {
mockPackageManager.stub {
on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn true
}
mockDevicePolicyManager.stub {
on { deviceOwnerComponentOnAnyUser } doReturn DEVICE_OWNER
}
val admin = appForceStopButton.getAdminRestriction(createApp())!!
assertThat(admin.component).isEqualTo(DEVICE_OWNER)
}
@Test
fun getAdminRestriction_packageProtectedAndNotHaveOwner() {
mockPackageManager.stub {
on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn true
}
mockDevicePolicyManager.stub {
on { deviceOwnerComponentOnAnyUser } doReturn null
}
val admin = appForceStopButton.getAdminRestriction(createApp())!!
assertThat(admin.component).isNull()
}
private fun setForceStopButton(app: ApplicationInfo) {
composeTestRule.setContent {
val actionButton = appForceStopButton.getActionButton(app)
Button(onClick = {}, enabled = actionButton.enabled) {
Text(actionButton.text)
}
}
composeTestRule.delay()
}
private fun createApp(builder: ApplicationInfo.() -> Unit = {}) =
ApplicationInfo().apply {
packageName = PACKAGE_NAME
uid = UID
enabled = true
}.apply(builder)
private companion object {
const val PACKAGE_NAME = "package.name"
const val UID = 10000
val DEVICE_OWNER = ComponentName("device", "Owner")
}
}
}