Snap for 10157673 from 263049e89d to udc-qpr1-release
Change-Id: I252624612c9e166a995dda93bc1d233ddfb21447
This commit is contained in:
@@ -60,6 +60,8 @@
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:hyphenationFrequency="normalFast"
|
||||
|
||||
@@ -258,8 +258,10 @@
|
||||
|
||||
<!-- Title for stylus device details page [CHAR LIMIT=50] -->
|
||||
<string name="stylus_device_details_title">Stylus</string>
|
||||
<!-- Preference title for setting the default note taking app [CHAR LIMIT=none] -->
|
||||
<string name="stylus_default_notes_app">Default notes app</string>
|
||||
<!-- Preference title for setting the app that opens when stylus button is pressed [CHAR LIMIT=none] -->
|
||||
<string name="stylus_default_notes_app">Tail button press</string>
|
||||
<!-- Summary for the app that opens when tail button is pressed, if set to a work profile app [CHAR LIMIT=none] -->
|
||||
<string name="stylus_default_notes_summary_work"><xliff:g id="app_name" example="WhatsApp">%s</xliff:g> (Work profile)</string>
|
||||
<!-- Preference title for toggling whether handwriting in textfields is enabled [CHAR LIMIT=none] -->
|
||||
<string name="stylus_textfield_handwriting">Write in text fields</string>
|
||||
<!-- Preference title for toggling whether stylus button presses are ignored [CHAR LIMIT=none] -->
|
||||
@@ -8164,6 +8166,12 @@
|
||||
<!-- [CHAR LIMIT=NONE] Channel notification settings: Block option description-->
|
||||
<string name="notification_content_block_summary">Never show notifications in the shade or on peripheral devices</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] App notification settings: Full screen intent permission option title -->
|
||||
<string name="app_notification_fsi_permission_title">Allow full screen notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] App notification settings: Full screen intent permission option description -->
|
||||
<string name="app_notification_fsi_permission_summary">Allow notifications to take up the full screen when the device is locked</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE BACKUP_MESSAGE_ID:7166470350070693657] App notification settings: Badging option title -->
|
||||
<string name="notification_badge_title">Allow notification dot</string>
|
||||
|
||||
@@ -10158,7 +10166,9 @@
|
||||
<string name="financed_privacy_restrictions_removed">All restrictions are removed from the device</string>
|
||||
<!-- Label explaining that the app installed by credit provider can be uninstalled. [CHAR LIMIT=60]-->
|
||||
<string name="financed_privacy_uninstall_creditor_app">You can uninstall the creditor app</string>
|
||||
|
||||
<!-- Title of setting on security settings screen on a device provisioned by Device Lock. This will take the user to a screen in Device Lock with information about what a device provider can control and their impact on the user's privacy. Shown on Device Lock provisioned devices only. [CHAR LIMIT=NONE] -->
|
||||
<!-- TODO(b/282040794): Update the title -->
|
||||
<string name="device_lock_info">Device Lock</string>
|
||||
<!-- Strings for displaying which applications were set as default for specific actions. -->
|
||||
<!-- Title for the apps that have been set as default handlers of camera-related intents. [CHAR LIMIT=30] -->
|
||||
<string name="default_camera_app_title">{count, plural,
|
||||
|
||||
@@ -193,6 +193,8 @@
|
||||
android:key="long_background_tasks"
|
||||
android:title="@string/long_background_tasks_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:isPreferenceVisible="false"
|
||||
settings:searchable="false"
|
||||
settings:controller="com.android.settings.applications.appinfo.LongBackgroundTasksDetailsPreferenceController" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
@@ -59,38 +59,57 @@
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="allow_sound"
|
||||
android:title="@string/allow_interruption"
|
||||
android:summary="@string/allow_interruption_summary" />
|
||||
android:summary="@string/allow_interruption_summary"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
<!-- Visibility Override -->
|
||||
<com.android.settings.RestrictedListPreference
|
||||
android:key="visibility_override"
|
||||
android:title="@string/app_notification_visibility_override_title"/>
|
||||
android:title="@string/app_notification_visibility_override_title"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
<!-- Bypass DND -->
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="bypass_dnd"
|
||||
android:title="@string/app_notification_override_dnd_title"
|
||||
android:summary="@string/app_notification_override_dnd_summary"/>
|
||||
android:summary="@string/app_notification_override_dnd_summary"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
<!-- Allow full-screen intents -->
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="fsi_permission"
|
||||
android:title="@string/app_notification_fsi_permission_title"
|
||||
android:summary="@string/app_notification_fsi_permission_summary"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
<!-- Show badge -->
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="badge"
|
||||
android:title="@string/notification_badge_title"
|
||||
settings:useAdditionalSummary="true"
|
||||
android:order="1001"
|
||||
android:icon="@drawable/ic_notification_dot"
|
||||
settings:useAdditionalSummary="true"
|
||||
settings:restrictedSwitchSummary="@string/enabled_by_admin"
|
||||
android:order="1001"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
<Preference
|
||||
android:key="app_link"
|
||||
android:order="1003"
|
||||
android:icon="@drawable/ic_settings_24dp"
|
||||
android:title="@string/app_settings_link" />
|
||||
android:title="@string/app_settings_link"
|
||||
android:order="1003"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:key="deleted"
|
||||
android:icon="@drawable/ic_trash_can"
|
||||
android:order="8000" />
|
||||
android:order="8000"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="false" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -146,6 +146,13 @@
|
||||
android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
|
||||
settings:controller="com.android.settings.enterprise.FinancedPrivacyPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="device_lock_info"
|
||||
android:title="@string/device_lock_info"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:controller="com.android.settings.devicelock.DeviceLockPreferenceController">
|
||||
<intent android:action="com.android.devicelockcontroller.action.DEVICE_INFO_SETTINGS"/>
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
|
||||
@@ -58,6 +58,13 @@
|
||||
android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
|
||||
settings:controller="com.android.settings.enterprise.FinancedPrivacyPreferenceController"/>
|
||||
|
||||
<Preference
|
||||
android:key="device_lock_info"
|
||||
android:title="@string/device_lock_info"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:controller="com.android.settings.devicelock.DeviceLockPreferenceController">
|
||||
<intent android:action="com.android.devicelockcontroller.action.DEVICE_INFO_SETTINGS"/>
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
|
||||
@@ -128,6 +128,8 @@
|
||||
android:title="@string/long_background_tasks_title"
|
||||
android:order="-800"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
|
||||
settings:isPreferenceVisible="false"
|
||||
settings:searchable="false"
|
||||
settings:keywords="@string/keywords_long_background_tasks"
|
||||
settings:controller="com.android.settings.applications.specialaccess.applications.LongBackgroundTaskController">
|
||||
<extra
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import static android.Manifest.permission.RUN_USER_INITIATED_JOBS;
|
||||
import static android.app.AppOpsManager.OP_RUN_USER_INITIATED_JOBS;
|
||||
import static android.app.AppOpsManager.opToPermission;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
@@ -345,7 +341,9 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
|
||||
|
||||
@Override
|
||||
public boolean isLongBackgroundTaskPermissionToggleSupported() {
|
||||
return TextUtils.equals(RUN_USER_INITIATED_JOBS,
|
||||
opToPermission(OP_RUN_USER_INITIATED_JOBS));
|
||||
// Since the RUN_USER_INITIATED_JOBS permission related to this controller is a normal
|
||||
// app-op permission allowed by default, this should always return false - if it is ever
|
||||
// converted to a special app-op permission, this should be updated.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -37,6 +37,6 @@ public class LongBackgroundTaskController extends BasePreferenceController {
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mAppFeatureProvider.isLongBackgroundTaskPermissionToggleSupported()
|
||||
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
||||
|
||||
private static final String ENABLE_DUAL_MODE_AUDIO =
|
||||
"persist.bluetooth.enable_dual_mode_audio";
|
||||
private static final String CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT = "le_audio_enabled_by_default";
|
||||
|
||||
private LocalBluetoothManager mManager;
|
||||
private LocalBluetoothProfileManager mProfileManager;
|
||||
@@ -99,7 +100,9 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
||||
mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true);
|
||||
mIsLeAudioToggleEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_LE_AUDIO_DEVICE_DETAIL_ENABLED, false);
|
||||
SettingsUIDeviceConfig.BT_LE_AUDIO_DEVICE_DETAIL_ENABLED, false)
|
||||
|| DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH,
|
||||
CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT, false);
|
||||
// Call refresh here even though it will get called later in onResume, to avoid the
|
||||
// list of switches appearing to "pop" into the page.
|
||||
refresh();
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
|
||||
package com.android.settings.connecteddevice.stylus;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.role.RoleManager;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.text.TextUtils;
|
||||
@@ -38,6 +43,8 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
|
||||
import com.android.settings.dashboard.profileselector.UserAdapter;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -45,6 +52,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -73,6 +81,9 @@ public class StylusDevicesController extends AbstractPreferenceController implem
|
||||
@VisibleForTesting
|
||||
PreferenceCategory mPreferencesContainer;
|
||||
|
||||
@VisibleForTesting
|
||||
Dialog mDialog;
|
||||
|
||||
public StylusDevicesController(Context context, InputDevice inputDevice,
|
||||
CachedBluetoothDevice cachedBluetoothDevice, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
@@ -100,8 +111,8 @@ public class StylusDevicesController extends AbstractPreferenceController implem
|
||||
pref.setOnPreferenceClickListener(this);
|
||||
pref.setEnabled(true);
|
||||
|
||||
List<String> roleHolders = rm.getRoleHoldersAsUser(RoleManager.ROLE_NOTES,
|
||||
mContext.getUser());
|
||||
UserHandle user = getDefaultNoteTaskProfile();
|
||||
List<String> roleHolders = rm.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user);
|
||||
if (roleHolders.isEmpty()) {
|
||||
pref.setSummary(R.string.default_app_none);
|
||||
return pref;
|
||||
@@ -117,7 +128,13 @@ public class StylusDevicesController extends AbstractPreferenceController implem
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Notes role package not found.");
|
||||
}
|
||||
pref.setSummary(appName);
|
||||
|
||||
if (mContext.getSystemService(UserManager.class).isManagedProfile(user.getIdentifier())) {
|
||||
pref.setSummary(
|
||||
mContext.getString(R.string.stylus_default_notes_summary_work, appName));
|
||||
} else {
|
||||
pref.setSummary(appName);
|
||||
}
|
||||
return pref;
|
||||
}
|
||||
|
||||
@@ -155,7 +172,13 @@ public class StylusDevicesController extends AbstractPreferenceController implem
|
||||
String packageName = pm.getPermissionControllerPackageName();
|
||||
Intent intent = new Intent(Intent.ACTION_MANAGE_DEFAULT_APP).setPackage(
|
||||
packageName).putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_NOTES);
|
||||
mContext.startActivity(intent);
|
||||
|
||||
List<UserHandle> users = getUserAndManagedProfiles();
|
||||
if (users.size() <= 1) {
|
||||
mContext.startActivity(intent);
|
||||
} else {
|
||||
createAndShowProfileSelectDialog(intent, users);
|
||||
}
|
||||
break;
|
||||
case KEY_HANDWRITING:
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
@@ -229,6 +252,55 @@ public class StylusDevicesController extends AbstractPreferenceController implem
|
||||
return inputMethod != null && inputMethod.supportsStylusHandwriting();
|
||||
}
|
||||
|
||||
private List<UserHandle> getUserAndManagedProfiles() {
|
||||
UserManager um = mContext.getSystemService(UserManager.class);
|
||||
final ArrayList<UserHandle> userManagedProfiles = new ArrayList<>();
|
||||
// Add the current user, then add all the associated managed profiles.
|
||||
final UserHandle currentUser = Process.myUserHandle();
|
||||
userManagedProfiles.add(currentUser);
|
||||
|
||||
final List<UserInfo> userInfos = um.getUsers();
|
||||
for (UserInfo info : userInfos) {
|
||||
if (um.isManagedProfile(info.id)
|
||||
&& um.getProfileParent(info.id).id == currentUser.getIdentifier()) {
|
||||
userManagedProfiles.add(UserHandle.of(info.id));
|
||||
}
|
||||
}
|
||||
return userManagedProfiles;
|
||||
}
|
||||
|
||||
private UserHandle getDefaultNoteTaskProfile() {
|
||||
final int userId = Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Secure.DEFAULT_NOTE_TASK_PROFILE,
|
||||
UserHandle.myUserId());
|
||||
return UserHandle.of(userId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
UserAdapter.OnClickListener createProfileDialogClickCallback(
|
||||
Intent intent, List<UserHandle> users) {
|
||||
// TODO(b/281659827): improve UX flow for when activity is cancelled
|
||||
return (int position) -> {
|
||||
intent.putExtra(Intent.EXTRA_USER, users.get(position));
|
||||
|
||||
Secure.putInt(mContext.getContentResolver(),
|
||||
Secure.DEFAULT_NOTE_TASK_PROFILE,
|
||||
users.get(position).getIdentifier());
|
||||
mContext.startActivity(intent);
|
||||
|
||||
mDialog.dismiss();
|
||||
};
|
||||
}
|
||||
|
||||
private void createAndShowProfileSelectDialog(Intent intent, List<UserHandle> users) {
|
||||
mDialog = ProfileSelectDialog.createDialog(
|
||||
mContext,
|
||||
users,
|
||||
createProfileDialogClickCallback(intent, users));
|
||||
mDialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies whether a device is a stylus using the associated {@link InputDevice} or
|
||||
* {@link CachedBluetoothDevice}.
|
||||
|
||||
@@ -39,6 +39,7 @@ public class BluetoothLeAudioDeviceDetailsPreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
|
||||
|
||||
private static final String PREFERENCE_KEY = "bluetooth_show_leaudio_device_details";
|
||||
private static final String CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT = "le_audio_enabled_by_default";
|
||||
static int sLeAudioSupportedStateCache = BluetoothStatusCodes.ERROR_UNKNOWN;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -87,8 +88,12 @@ public class BluetoothLeAudioDeviceDetailsPreferenceController
|
||||
final boolean leAudioDeviceDetailEnabled = DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||
SettingsUIDeviceConfig.BT_LE_AUDIO_DEVICE_DETAIL_ENABLED, false);
|
||||
final boolean leAudioEnabledByDefault = DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_BLUETOOTH, CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT, false);
|
||||
|
||||
((SwitchPreference) mPreference).setChecked(leAudioDeviceDetailEnabled);
|
||||
mPreference.setEnabled(!leAudioEnabledByDefault);
|
||||
((SwitchPreference) mPreference).setChecked(leAudioDeviceDetailEnabled
|
||||
|| leAudioEnabledByDefault);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,11 +28,9 @@ import androidx.fragment.app.FragmentManager;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
/**
|
||||
* Dialog fragment for reboot confirmation when enabling certain features.
|
||||
*/
|
||||
/** Dialog fragment for reboot confirmation when enabling certain features. */
|
||||
public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment
|
||||
implements DialogInterface.OnClickListener {
|
||||
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
|
||||
|
||||
private static final String TAG = "FreeformPrefRebootDlg";
|
||||
|
||||
@@ -40,18 +38,17 @@ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment
|
||||
private final int mCancelButtonId;
|
||||
private final RebootConfirmationDialogHost mHost;
|
||||
|
||||
/**
|
||||
* Show an instance of this dialog.
|
||||
*/
|
||||
/** Show an instance of this dialog. */
|
||||
public static void show(Fragment fragment, int messageId, RebootConfirmationDialogHost host) {
|
||||
show(fragment, messageId, R.string.reboot_dialog_reboot_later, host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an instance of this dialog with cancel button string set as cancelButtonId
|
||||
*/
|
||||
public static void show(Fragment fragment, int messageId,
|
||||
int cancelButtonId, RebootConfirmationDialogHost host) {
|
||||
/** Show an instance of this dialog with cancel button string set as cancelButtonId */
|
||||
public static void show(
|
||||
Fragment fragment,
|
||||
int messageId,
|
||||
int cancelButtonId,
|
||||
RebootConfirmationDialogHost host) {
|
||||
final FragmentManager manager = fragment.getActivity().getSupportFragmentManager();
|
||||
if (manager.findFragmentByTag(TAG) == null) {
|
||||
final RebootConfirmationDialogFragment dialog =
|
||||
@@ -60,8 +57,8 @@ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment
|
||||
}
|
||||
}
|
||||
|
||||
private RebootConfirmationDialogFragment(int messageId,
|
||||
int cancelButtonId, RebootConfirmationDialogHost host) {
|
||||
private RebootConfirmationDialogFragment(
|
||||
int messageId, int cancelButtonId, RebootConfirmationDialogHost host) {
|
||||
mMessageId = messageId;
|
||||
mCancelButtonId = cancelButtonId;
|
||||
mHost = host;
|
||||
@@ -89,4 +86,10 @@ public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment
|
||||
mHost.onRebootCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
mHost.onRebootDialogDismissed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,22 +20,20 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* Host of {@link RebootConfirmationDialogFragment} that provides callback when user
|
||||
* interacts with the UI.
|
||||
* Host of {@link RebootConfirmationDialogFragment} that provides callback when user interacts with
|
||||
* the UI.
|
||||
*/
|
||||
public interface RebootConfirmationDialogHost {
|
||||
/**
|
||||
* Called when user made a decision to reboot the device.
|
||||
*/
|
||||
/** Called when user made a decision to reboot the device. */
|
||||
default void onRebootConfirmed(Context context) {
|
||||
// user presses button "Reboot now", reboot the device
|
||||
final Intent intent = new Intent(Intent.ACTION_REBOOT);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when user made a decision to cancel the reboot
|
||||
* Default to do nothing
|
||||
*/
|
||||
/** Called when user made a decision to cancel the reboot Default to do nothing */
|
||||
default void onRebootCancelled() {}
|
||||
|
||||
/** Called when reboot dialog is dismissed Default to do nothing */
|
||||
default void onRebootDialogDismissed() {}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.development.graphicsdriver;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.GraphicsEnvironment;
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
@@ -33,9 +34,7 @@ import com.android.settings.development.RebootConfirmationDialogFragment;
|
||||
import com.android.settings.development.RebootConfirmationDialogHost;
|
||||
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
||||
|
||||
/**
|
||||
* Controller to handle the events when user toggles this developer option switch: Enable ANGLE
|
||||
*/
|
||||
/** Controller to handle the events when user toggles this developer option switch: Enable ANGLE */
|
||||
public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
extends DeveloperOptionsPreferenceController
|
||||
implements Preference.OnPreferenceChangeListener,
|
||||
@@ -50,14 +49,15 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
|
||||
private final GraphicsDriverSystemPropertiesWrapper mSystemProperties;
|
||||
|
||||
private boolean mShouldToggleSwitchBackOnRebootDialogDismiss;
|
||||
|
||||
@VisibleForTesting
|
||||
static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String PROPERTY_PERSISTENT_GRAPHICS_EGL = "persist.graphics.egl";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String ANGLE_DRIVER_SUFFIX = "angle";
|
||||
@VisibleForTesting static final String ANGLE_DRIVER_SUFFIX = "angle";
|
||||
|
||||
@VisibleForTesting
|
||||
static class Injector {
|
||||
@@ -87,6 +87,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
super(context);
|
||||
mFragment = fragment;
|
||||
mSystemProperties = injector.createSystemPropertiesWrapper();
|
||||
// By default, when the reboot dialog is dismissed we want to toggle the switch back.
|
||||
// Exception is when user chooses to reboot now, the switch should keep its current value
|
||||
// and persist its' state over reboot.
|
||||
mShouldToggleSwitchBackOnRebootDialogDismiss = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,11 +112,12 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
@VisibleForTesting
|
||||
void showRebootDialog() {
|
||||
RebootConfirmationDialogFragment.show(
|
||||
mFragment, R.string.reboot_dialog_enable_angle_as_system_driver,
|
||||
R.string.cancel, this);
|
||||
mFragment,
|
||||
R.string.reboot_dialog_enable_angle_as_system_driver,
|
||||
R.string.cancel,
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
// set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor
|
||||
@@ -120,8 +125,9 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
final String currentGlesDriver =
|
||||
mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
||||
final boolean isAngle = TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver);
|
||||
final boolean isAngleSupported = TextUtils
|
||||
.equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
|
||||
final boolean isAngleSupported =
|
||||
TextUtils.equals(
|
||||
mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
|
||||
((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported);
|
||||
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
|
||||
}
|
||||
@@ -130,8 +136,9 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
// only enable the switch if ro.gfx.angle.supported is true
|
||||
// we use ro.gfx.angle.supported to indicate if ANGLE libs are installed under /vendor
|
||||
final boolean isAngleSupported = TextUtils
|
||||
.equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
|
||||
final boolean isAngleSupported =
|
||||
TextUtils.equals(
|
||||
mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
|
||||
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
|
||||
}
|
||||
|
||||
@@ -145,9 +152,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
((SwitchPreference) mPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebootCancelled() {
|
||||
// if user presses button "Cancel", do not reboot the device, and toggles switch back
|
||||
void toggleSwitchBack() {
|
||||
final String currentGlesDriver =
|
||||
mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
||||
if (TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver)) {
|
||||
@@ -169,4 +174,40 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
||||
// if persist.graphics.egl holds values other than the above two, log error message
|
||||
Log.e(TAG, "Invalid persist.graphics.egl property value");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void rebootDevice(Context context) {
|
||||
final Intent intent = new Intent(Intent.ACTION_REBOOT);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebootConfirmed(Context context) {
|
||||
// User chooses to reboot now, do not toggle switch back
|
||||
mShouldToggleSwitchBackOnRebootDialogDismiss = false;
|
||||
|
||||
// Reboot the device
|
||||
rebootDevice(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebootCancelled() {
|
||||
// User chooses to cancel reboot, toggle switch back
|
||||
mShouldToggleSwitchBackOnRebootDialogDismiss = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebootDialogDismissed() {
|
||||
// If reboot dialog is dismissed either from
|
||||
// 1) User clicks cancel
|
||||
// 2) User taps phone screen area outside of reboot dialog
|
||||
// do not reboot the device, and toggles switch back.
|
||||
if (mShouldToggleSwitchBackOnRebootDialogDismiss) {
|
||||
toggleSwitchBack();
|
||||
}
|
||||
|
||||
// Reset the flag so that the default option is to toggle switch back
|
||||
// on reboot dialog dismissed.
|
||||
mShouldToggleSwitchBackOnRebootDialogDismiss = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.devicelock;
|
||||
|
||||
import android.content.Context;
|
||||
import android.devicelock.DeviceLockManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
/**
|
||||
* The PreferenceController that manages the Device Lock entry preference.
|
||||
*/
|
||||
public final class DeviceLockPreferenceController extends BasePreferenceController {
|
||||
|
||||
private static final String TAG = "DeviceLockPreferenceController";
|
||||
|
||||
private final DeviceLockManager mDeviceLockManager;
|
||||
|
||||
public DeviceLockPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mDeviceLockManager = mContext.getSystemService(DeviceLockManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
// TODO(b/282856378): make this entry searchable
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
mDeviceLockManager.getKioskApps(mContext.getMainExecutor(),
|
||||
result -> {
|
||||
// if kiosk apps present on the device, the device is provisioned by Device Lock
|
||||
boolean isDeviceProvisionedByDeviceLock = result != null && !result.isEmpty();
|
||||
Log.d(TAG, "Set preference visibility to " + isDeviceProvisionedByDeviceLock);
|
||||
// TODO(b/282179089): find alternatives instead of calling setVisible
|
||||
preference.setVisible(isDeviceProvisionedByDeviceLock);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,9 @@ package com.android.settings.fuelgauge.batterytip;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.BadParcelableException;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
@@ -142,14 +144,26 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
|
||||
}
|
||||
|
||||
public void restoreInstanceState(Bundle bundle) {
|
||||
if (bundle != null) {
|
||||
if (bundle == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<BatteryTip> batteryTips = bundle.getParcelableArrayList(KEY_BATTERY_TIPS);
|
||||
updateBatteryTips(batteryTips);
|
||||
} catch (BadParcelableException e) {
|
||||
Log.e(TAG, "failed to invoke restoreInstanceState()", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveInstanceState(Bundle outState) {
|
||||
outState.putParcelableList(KEY_BATTERY_TIPS, mBatteryTips);
|
||||
public void saveInstanceState(Bundle bundle) {
|
||||
if (bundle == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
bundle.putParcelableList(KEY_BATTERY_TIPS, mBatteryTips);
|
||||
} catch (BadParcelableException e) {
|
||||
Log.e(TAG, "failed to invoke saveInstanceState()", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean needUpdate() {
|
||||
|
||||
@@ -79,10 +79,13 @@ public class SpinnerPreference extends Preference {
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (state == null || !state.getClass().equals(SavedState.class)) {
|
||||
if (state == null || state == BaseSavedState.EMPTY_STATE) {
|
||||
super.onRestoreInstanceState(state);
|
||||
return;
|
||||
}
|
||||
if (!(state instanceof SavedState)) {
|
||||
return;
|
||||
}
|
||||
SavedState savedState = (SavedState) state;
|
||||
super.onRestoreInstanceState(savedState.getSuperState());
|
||||
mSavedSpinnerPosition = savedState.getSpinnerPosition();
|
||||
|
||||
@@ -74,6 +74,7 @@ public class AppNotificationSettings extends NotificationSettings {
|
||||
mControllers = new ArrayList<>();
|
||||
mControllers.add(new HeaderPreferenceController(context, this));
|
||||
mControllers.add(new BlockPreferenceController(context, mDependentFieldListener, mBackend));
|
||||
mControllers.add(new FullScreenIntentPermissionPreferenceController(context, mBackend));
|
||||
mControllers.add(new BadgePreferenceController(context, mBackend));
|
||||
mControllers.add(new AllowSoundPreferenceController(
|
||||
context, mDependentFieldListener, mBackend));
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.notification.app
|
||||
|
||||
import android.Manifest.permission.USE_FULL_SCREEN_INTENT
|
||||
import android.app.AppOpsManager
|
||||
import android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT
|
||||
import android.content.AttributionSource
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
|
||||
import android.content.pm.PackageManager.GET_PERMISSIONS
|
||||
import android.os.UserHandle
|
||||
import android.permission.PermissionManager
|
||||
import android.util.Log
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener
|
||||
import com.android.settings.notification.NotificationBackend
|
||||
import com.android.settingslib.RestrictedSwitchPreference
|
||||
|
||||
class FullScreenIntentPermissionPreferenceController(
|
||||
context: Context,
|
||||
backend: NotificationBackend
|
||||
) : NotificationPreferenceController(context, backend), OnPreferenceChangeListener {
|
||||
private val packageManager = mPm!!
|
||||
private val permissionManager = context.getSystemService(PermissionManager::class.java)!!
|
||||
private val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
|
||||
|
||||
private val packageName get() = mAppRow.pkg
|
||||
private val uid get() = mAppRow.uid
|
||||
private val userHandle get() = UserHandle.getUserHandleForUid(uid)
|
||||
|
||||
override fun getPreferenceKey() = KEY_FSI_PERMISSION
|
||||
|
||||
override fun isAvailable(): Boolean {
|
||||
val inAppWidePreferences = mChannelGroup == null && mChannel == null
|
||||
|
||||
if (!inAppWidePreferences) {
|
||||
Log.wtf(TAG, "Belongs only in app-wide notification preferences!")
|
||||
}
|
||||
|
||||
return super.isAvailable() && inAppWidePreferences && isPermissionRequested()
|
||||
}
|
||||
|
||||
override fun isIncludedInFilter() = false
|
||||
|
||||
override fun updateState(preference: Preference) {
|
||||
check(KEY_FSI_PERMISSION.equals(preference.key))
|
||||
check(preference is RestrictedSwitchPreference)
|
||||
|
||||
preference.setDisabledByAdmin(mAdmin)
|
||||
preference.isEnabled = !preference.isDisabledByAdmin
|
||||
preference.isChecked = isPermissionGranted()
|
||||
}
|
||||
|
||||
override fun onPreferenceChange(preference: Preference, value: Any): Boolean {
|
||||
check(KEY_FSI_PERMISSION.equals(preference.key))
|
||||
check(preference is RestrictedSwitchPreference)
|
||||
check(value is Boolean)
|
||||
|
||||
if (isPermissionGranted() != value) {
|
||||
setPermissionGranted(value)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isPermissionRequested(): Boolean {
|
||||
val packageInfo = packageManager.getPackageInfo(packageName, GET_PERMISSIONS)
|
||||
|
||||
for (requestedPermission in packageInfo.requestedPermissions) {
|
||||
if (USE_FULL_SCREEN_INTENT.equals(requestedPermission)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isPermissionGranted(): Boolean {
|
||||
val attributionSource = AttributionSource.Builder(uid).setPackageName(packageName).build()
|
||||
|
||||
val permissionResult =
|
||||
permissionManager.checkPermissionForPreflight(USE_FULL_SCREEN_INTENT, attributionSource)
|
||||
|
||||
return (permissionResult == PermissionManager.PERMISSION_GRANTED)
|
||||
}
|
||||
|
||||
private fun setPermissionGranted(allowed: Boolean) {
|
||||
val mode = if (allowed) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
|
||||
appOpsManager.setUidMode(OP_USE_FULL_SCREEN_INTENT, uid, mode)
|
||||
packageManager.updatePermissionFlags(
|
||||
USE_FULL_SCREEN_INTENT,
|
||||
packageName,
|
||||
FLAG_PERMISSION_USER_SET,
|
||||
FLAG_PERMISSION_USER_SET,
|
||||
userHandle
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_FSI_PERMISSION = "fsi_permission"
|
||||
const val TAG = "FsiPermPrefController"
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,8 @@ public class NumberingSystemItemController extends BasePreferenceController {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE,
|
||||
ARG_VALUE_NUMBERING_SYSTEM_SELECT);
|
||||
bundle.putString(KEY_SELECTED_LANGUAGE, updatedLocale.toLanguageTag());
|
||||
bundle.putString(KEY_SELECTED_LANGUAGE,
|
||||
updatedLocale != null ? updatedLocale.toLanguageTag() : "");
|
||||
mParentFragment.setArguments(bundle);
|
||||
continue;
|
||||
}
|
||||
@@ -194,13 +195,14 @@ public class NumberingSystemItemController extends BasePreferenceController {
|
||||
private Locale saveNumberingSystemToLocale(Locale targetLocale, String value) {
|
||||
LocaleList localeList = LocalePicker.getLocales();
|
||||
Locale[] locales = new Locale[localeList.size()];
|
||||
Locale updatedLocale = null;
|
||||
for (int i = 0; i < localeList.size(); i++) {
|
||||
Locale locale = localeList.get(i);
|
||||
if (targetLocale.equals(locale)) {
|
||||
if (value.equals(RegionalPreferencesDataUtils.DEFAULT_VALUE)) {
|
||||
if (RegionalPreferencesDataUtils.DEFAULT_VALUE.equals(value)) {
|
||||
value = null;
|
||||
}
|
||||
Locale updatedLocale = new Locale.Builder()
|
||||
updatedLocale = new Locale.Builder()
|
||||
.setLocale(locale)
|
||||
.setUnicodeLocaleKeyword(ExtensionTypes.NUMBERING_SYSTEM, value)
|
||||
.build();
|
||||
@@ -210,7 +212,7 @@ public class NumberingSystemItemController extends BasePreferenceController {
|
||||
locales[i] = localeList.get(i);
|
||||
}
|
||||
LocalePicker.updateLocales(new LocaleList(locales));
|
||||
return targetLocale;
|
||||
return updatedLocale;
|
||||
}
|
||||
|
||||
private static String getNumberingSystem(Locale locale) {
|
||||
|
||||
@@ -18,6 +18,10 @@ package com.android.settings.connecteddevice.stylus;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
@@ -27,13 +31,17 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.role.RoleManager;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.view.InputDevice;
|
||||
@@ -48,6 +56,7 @@ import androidx.preference.SwitchPreference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.profileselector.UserAdapter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
@@ -59,7 +68,9 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class StylusDevicesControllerTest {
|
||||
@@ -79,6 +90,8 @@ public class StylusDevicesControllerTest {
|
||||
@Mock
|
||||
private PackageManager mPm;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private RoleManager mRm;
|
||||
@Mock
|
||||
private Lifecycle mLifecycle;
|
||||
@@ -87,7 +100,6 @@ public class StylusDevicesControllerTest {
|
||||
@Mock
|
||||
private BluetoothDevice mBluetoothDevice;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -101,6 +113,7 @@ public class StylusDevicesControllerTest {
|
||||
|
||||
when(mContext.getSystemService(InputMethodManager.class)).thenReturn(mImm);
|
||||
when(mContext.getSystemService(RoleManager.class)).thenReturn(mRm);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
doNothing().when(mContext).startActivity(any());
|
||||
|
||||
when(mImm.getCurrentInputMethodInfo()).thenReturn(mInputMethodInfo);
|
||||
@@ -115,6 +128,8 @@ public class StylusDevicesControllerTest {
|
||||
when(mPm.getApplicationInfo(eq(NOTES_PACKAGE_NAME),
|
||||
any(PackageManager.ApplicationInfoFlags.class))).thenReturn(new ApplicationInfo());
|
||||
when(mPm.getApplicationLabel(any(ApplicationInfo.class))).thenReturn(NOTES_APP_LABEL);
|
||||
when(mUserManager.getUsers()).thenReturn(Arrays.asList(new UserInfo(0, "default", 0)));
|
||||
when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
|
||||
|
||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||
|
||||
@@ -228,21 +243,35 @@ public class StylusDevicesControllerTest {
|
||||
when(mInputMethodInfo.supportsStylusHandwriting()).thenReturn(false);
|
||||
|
||||
showScreen(mController);
|
||||
Preference handwritingPref = mPreferenceContainer.getPreference(1);
|
||||
|
||||
Preference handwritingPref = mPreferenceContainer.getPreference(1);
|
||||
assertThat(handwritingPref.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultNotesPreference_showsNotesRoleApp() {
|
||||
public void defaultNotesPreference_singleUser_showsNotesRoleApp() {
|
||||
showScreen(mController);
|
||||
Preference defaultNotesPref = mPreferenceContainer.getPreference(0);
|
||||
|
||||
Preference defaultNotesPref = mPreferenceContainer.getPreference(0);
|
||||
assertThat(defaultNotesPref.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.stylus_default_notes_app));
|
||||
assertThat(defaultNotesPref.getSummary().toString()).isEqualTo(NOTES_APP_LABEL.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultNotesPreference_workProfileUser_showsWorkNotesRoleApp() {
|
||||
when(mUserManager.isManagedProfile(0)).thenReturn(true);
|
||||
|
||||
showScreen(mController);
|
||||
|
||||
Preference defaultNotesPref = mPreferenceContainer.getPreference(0);
|
||||
assertThat(defaultNotesPref.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.stylus_default_notes_app));
|
||||
assertThat(defaultNotesPref.getSummary().toString()).isEqualTo(
|
||||
mContext.getString(R.string.stylus_default_notes_summary_work,
|
||||
NOTES_APP_LABEL.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultNotesPreference_roleHolderChanges_updatesPreference() {
|
||||
showScreen(mController);
|
||||
@@ -267,7 +296,7 @@ public class StylusDevicesControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultNotesPreferenceClick_sendsManageDefaultRoleIntent() {
|
||||
public void defaultNotesPreferenceClick_singleUser_sendsManageDefaultRoleIntent() {
|
||||
final String permissionPackageName = "permissions.package";
|
||||
when(mPm.getPermissionControllerPackageName()).thenReturn(permissionPackageName);
|
||||
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
@@ -282,6 +311,46 @@ public class StylusDevicesControllerTest {
|
||||
assertThat(intent.getPackage()).isEqualTo(permissionPackageName);
|
||||
assertThat(intent.getStringExtra(Intent.EXTRA_ROLE_NAME)).isEqualTo(
|
||||
RoleManager.ROLE_NOTES);
|
||||
assertNull(mController.mDialog);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultNotesPreferenceClick_multiUser_showsProfileSelectorDialog() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final String permissionPackageName = "permissions.package";
|
||||
final UserHandle currentUser = Process.myUserHandle();
|
||||
List<UserInfo> userInfos = Arrays.asList(
|
||||
new UserInfo(currentUser.getIdentifier(), "current", 0),
|
||||
new UserInfo(1, "profile", UserInfo.FLAG_PROFILE)
|
||||
);
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
when(mUserManager.isManagedProfile(1)).thenReturn(true);
|
||||
when(mUserManager.getUserInfo(currentUser.getIdentifier())).thenReturn(userInfos.get(0));
|
||||
when(mUserManager.getUserInfo(1)).thenReturn(userInfos.get(1));
|
||||
when(mUserManager.getProfileParent(1)).thenReturn(userInfos.get(0));
|
||||
when(mPm.getPermissionControllerPackageName()).thenReturn(permissionPackageName);
|
||||
|
||||
showScreen(mController);
|
||||
Preference defaultNotesPref = mPreferenceContainer.getPreference(0);
|
||||
mController.onPreferenceClick(defaultNotesPref);
|
||||
|
||||
assertTrue(mController.mDialog.isShowing());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profileSelectDialogClickCallback_onClick_sendsIntent() {
|
||||
Intent intent = new Intent();
|
||||
UserHandle user1 = mock(UserHandle.class);
|
||||
UserHandle user2 = mock(UserHandle.class);
|
||||
List<UserHandle> users = Arrays.asList(new UserHandle[] {user1, user2});
|
||||
mController.mDialog = mock(Dialog.class);
|
||||
UserAdapter.OnClickListener callback = mController
|
||||
.createProfileDialogClickCallback(intent, users);
|
||||
|
||||
callback.onClick(1);
|
||||
|
||||
assertEquals(intent.getExtra(Intent.EXTRA_USER), user2);
|
||||
verify(mContext).startActivity(intent);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.devicelock;
|
||||
|
||||
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.devicelock.DeviceLockManager;
|
||||
import android.os.OutcomeReceiver;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
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.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public final class DeviceLockPreferenceControllerTest {
|
||||
|
||||
private static final String TEST_PREFERENCE_KEY = "KEY";
|
||||
private static final Map<Integer, String> TEST_KIOSK_APPS = Map.of(0, "test");
|
||||
@Mock
|
||||
private DeviceLockManager mDeviceLockManager;
|
||||
@Captor
|
||||
private ArgumentCaptor<OutcomeReceiver<Map<Integer, String>, Exception>>
|
||||
mOutcomeReceiverArgumentCaptor;
|
||||
private DeviceLockPreferenceController mController;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
Context context = spy(mContext);
|
||||
when(context.getSystemService(DeviceLockManager.class)).thenReturn(mDeviceLockManager);
|
||||
mController = new DeviceLockPreferenceController(context, TEST_PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_preferenceBecomesInvisibleIfNoKioskAppsPresent() {
|
||||
Preference preference = new Preference(mContext, null, 0, 0);
|
||||
preference.setVisible(true);
|
||||
|
||||
mController.updateState(preference);
|
||||
|
||||
verify(mDeviceLockManager).getKioskApps(any(), mOutcomeReceiverArgumentCaptor.capture());
|
||||
OutcomeReceiver<Map<Integer, String>, Exception> outcomeReceiver =
|
||||
mOutcomeReceiverArgumentCaptor.getValue();
|
||||
|
||||
outcomeReceiver.onResult(Collections.emptyMap());
|
||||
assertThat(preference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_preferenceBecomesVisibleIfKioskAppsPresent() {
|
||||
Preference preference = new Preference(mContext, null, 0, 0);
|
||||
preference.setVisible(false);
|
||||
|
||||
mController.updateState(preference);
|
||||
|
||||
verify(mDeviceLockManager).getKioskApps(any(), mOutcomeReceiverArgumentCaptor.capture());
|
||||
OutcomeReceiver<Map<Integer, String>, Exception> outcomeReceiver =
|
||||
mOutcomeReceiverArgumentCaptor.getValue();
|
||||
|
||||
outcomeReceiver.onResult(TEST_KIOSK_APPS);
|
||||
assertThat(preference.isVisible()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 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.notification.app
|
||||
|
||||
import android.Manifest.permission.USE_FULL_SCREEN_INTENT
|
||||
import android.app.AppOpsManager
|
||||
import android.app.AppOpsManager.MODE_ALLOWED
|
||||
import android.app.AppOpsManager.MODE_ERRORED
|
||||
import android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationChannelGroup
|
||||
import android.app.NotificationManager.IMPORTANCE_UNSPECIFIED
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
|
||||
import android.content.pm.PackageManager.GET_PERMISSIONS
|
||||
import android.os.UserHandle
|
||||
import android.permission.PermissionManager.PERMISSION_GRANTED
|
||||
import android.permission.PermissionManager.PERMISSION_HARD_DENIED
|
||||
import android.permission.PermissionManager.PERMISSION_SOFT_DENIED
|
||||
import android.permission.PermissionManager.PermissionResult
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.notification.NotificationBackend
|
||||
import com.android.settings.notification.NotificationBackend.AppRow
|
||||
import com.android.settings.notification.app.FullScreenIntentPermissionPreferenceController.Companion.KEY_FSI_PERMISSION
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
|
||||
import com.android.settingslib.RestrictedSwitchPreference
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
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.Mockito.mock
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.shadows.ShadowApplicationPackageManager
|
||||
import org.robolectric.shadows.ShadowPermissionChecker
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [ShadowApplicationPackageManager::class])
|
||||
class FullScreenIntentPermissionPreferenceControllerTest {
|
||||
@JvmField
|
||||
@Rule
|
||||
val mockitoRule = MockitoJUnit.rule()!!
|
||||
|
||||
@Mock
|
||||
private lateinit var packageManager: PackageManager
|
||||
|
||||
@Mock
|
||||
private lateinit var appOpsManager: AppOpsManager
|
||||
|
||||
private lateinit var preference: RestrictedSwitchPreference
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private lateinit var screen: PreferenceScreen
|
||||
|
||||
private lateinit var controller: FullScreenIntentPermissionPreferenceController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
val context = spy(ApplicationProvider.getApplicationContext<Context>())
|
||||
|
||||
whenever(context.packageManager).thenReturn(packageManager)
|
||||
whenever(context.getSystemService(AppOpsManager::class.java)).thenReturn(appOpsManager)
|
||||
|
||||
preference = RestrictedSwitchPreference(context).apply { key = KEY_FSI_PERMISSION }
|
||||
|
||||
whenever(screen.findPreference<Preference>(KEY_FSI_PERMISSION)).thenReturn(preference)
|
||||
|
||||
controller = FullScreenIntentPermissionPreferenceController(
|
||||
context,
|
||||
mock(NotificationBackend::class.java)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsAvailable_notWhenPermissionNotRequested() {
|
||||
setPermissionRequestedInManifest(requested = false)
|
||||
initController()
|
||||
|
||||
assertFalse(controller.isAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsAvailable_notWhenOnChannelScreen() {
|
||||
setPermissionRequestedInManifest()
|
||||
initController(channel = makeTestChannel())
|
||||
|
||||
assertFalse(controller.isAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsAvailable_notWhenOnGroupScreen() {
|
||||
setPermissionRequestedInManifest()
|
||||
initController(group = makeTestGroup())
|
||||
|
||||
assertFalse(controller.isAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsAvailable_onAppScreenWhenRequested() {
|
||||
setPermissionRequestedInManifest()
|
||||
initController()
|
||||
|
||||
assertTrue(controller.isAvailable)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsEnabled_notWhenDisabledByAdmin() {
|
||||
setPermissionRequestedInManifest()
|
||||
initController(admin = makeTestAdmin())
|
||||
|
||||
controller.updateState(preference)
|
||||
|
||||
assertFalse(preference.isEnabled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsEnabled_whenNotDisabledByAdmin() {
|
||||
setPermissionRequestedInManifest()
|
||||
initController()
|
||||
|
||||
controller.updateState(preference)
|
||||
|
||||
assertTrue(preference.isEnabled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsChecked_notWhenHardDenied() {
|
||||
setPermissionRequestedInManifest()
|
||||
setPermissionResult(PERMISSION_HARD_DENIED)
|
||||
initController()
|
||||
|
||||
controller.updateState(preference)
|
||||
|
||||
assertFalse(preference.isChecked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsChecked_notWhenSoftDenied() {
|
||||
setPermissionRequestedInManifest()
|
||||
setPermissionResult(PERMISSION_SOFT_DENIED)
|
||||
initController()
|
||||
|
||||
controller.updateState(preference)
|
||||
|
||||
assertFalse(preference.isChecked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsChecked_whenGranted() {
|
||||
setPermissionRequestedInManifest()
|
||||
setPermissionResult(PERMISSION_GRANTED)
|
||||
initController()
|
||||
|
||||
controller.updateState(preference)
|
||||
|
||||
assertTrue(preference.isChecked)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnPreferenceChange_whenHardDenied() {
|
||||
setPermissionRequestedInManifest()
|
||||
setPermissionResult(PERMISSION_HARD_DENIED)
|
||||
initController()
|
||||
controller.displayPreference(screen)
|
||||
controller.updateState(preference)
|
||||
assertFalse(preference.isChecked)
|
||||
|
||||
setPreferenceChecked(true)
|
||||
|
||||
verifySetAppOpMode(MODE_ALLOWED)
|
||||
verifySetPermissionUserSetFlag()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnPreferenceChange_whenSoftDenied() {
|
||||
setPermissionRequestedInManifest()
|
||||
setPermissionResult(PERMISSION_SOFT_DENIED)
|
||||
initController()
|
||||
controller.displayPreference(screen)
|
||||
controller.updateState(preference)
|
||||
assertFalse(preference.isChecked)
|
||||
|
||||
setPreferenceChecked(true)
|
||||
|
||||
verifySetAppOpMode(MODE_ALLOWED)
|
||||
verifySetPermissionUserSetFlag()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnPreferenceChange_whenGranted() {
|
||||
setPermissionRequestedInManifest()
|
||||
setPermissionResult(PERMISSION_GRANTED)
|
||||
initController()
|
||||
controller.displayPreference(screen)
|
||||
controller.updateState(preference)
|
||||
assertTrue(preference.isChecked)
|
||||
|
||||
setPreferenceChecked(false)
|
||||
|
||||
verifySetAppOpMode(MODE_ERRORED)
|
||||
verifySetPermissionUserSetFlag()
|
||||
}
|
||||
|
||||
private fun setPermissionRequestedInManifest(
|
||||
requested: Boolean = true
|
||||
) {
|
||||
whenever(packageManager.getPackageInfo(TEST_PACKAGE, GET_PERMISSIONS)).thenReturn(
|
||||
PackageInfo().apply {
|
||||
packageName = TEST_PACKAGE
|
||||
applicationInfo = ApplicationInfo().apply { packageName = TEST_PACKAGE }
|
||||
requestedPermissions = if (requested) arrayOf(USE_FULL_SCREEN_INTENT) else arrayOf()
|
||||
})
|
||||
}
|
||||
|
||||
private fun setPermissionResult(@PermissionResult result: Int) {
|
||||
ShadowPermissionChecker.setResult(TEST_PACKAGE, USE_FULL_SCREEN_INTENT, result)
|
||||
}
|
||||
|
||||
private fun setPreferenceChecked(checked: Boolean) {
|
||||
preference.isChecked = checked
|
||||
|
||||
/* This shouldn't be necessary, but for some reason it's not called automatically when
|
||||
isChecked is changed. */
|
||||
controller.onPreferenceChange(preference, checked)
|
||||
}
|
||||
|
||||
private fun verifySetAppOpMode(@AppOpsManager.Mode expectedMode: Int) {
|
||||
verify(appOpsManager).setUidMode(OP_USE_FULL_SCREEN_INTENT, TEST_UID, expectedMode)
|
||||
}
|
||||
|
||||
private fun verifySetPermissionUserSetFlag() {
|
||||
verify(packageManager).updatePermissionFlags(
|
||||
USE_FULL_SCREEN_INTENT,
|
||||
TEST_PACKAGE,
|
||||
FLAG_PERMISSION_USER_SET,
|
||||
FLAG_PERMISSION_USER_SET,
|
||||
makeTestUserHandle()
|
||||
)
|
||||
}
|
||||
|
||||
private fun initController(
|
||||
channel: NotificationChannel? = null,
|
||||
group: NotificationChannelGroup? = null,
|
||||
admin: EnforcedAdmin? = null
|
||||
) {
|
||||
controller.onResume(
|
||||
makeTestAppRow(),
|
||||
channel,
|
||||
group,
|
||||
/* conversationDrawable = */null,
|
||||
/* conversationInfo = */null,
|
||||
admin,
|
||||
/* preferenceFilter = */null
|
||||
)
|
||||
}
|
||||
|
||||
private fun makeTestChannel() =
|
||||
NotificationChannel("test_channel_id", "Test Channel Name", IMPORTANCE_UNSPECIFIED)
|
||||
|
||||
private fun makeTestGroup() = NotificationChannelGroup("test_group_id", "Test Group Name")
|
||||
|
||||
private fun makeTestAppRow() = AppRow().apply { pkg = TEST_PACKAGE; uid = TEST_UID }
|
||||
|
||||
private fun makeTestUserHandle() = UserHandle.getUserHandleForUid(TEST_UID)
|
||||
|
||||
private fun makeTestAdmin() = mock(EnforcedAdmin::class.java)
|
||||
|
||||
private companion object {
|
||||
const val TEST_PACKAGE = "test.package.name"
|
||||
const val TEST_UID = 12345
|
||||
}
|
||||
}
|
||||
@@ -56,11 +56,39 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
|
||||
private GraphicsDriverEnableAngleAsSystemDriverController mController;
|
||||
|
||||
@Mock
|
||||
private DevelopmentSettingsDashboardFragment mFragment;
|
||||
// Signal to wait for SystemProperty values changed
|
||||
private class PropertyChangeSignal {
|
||||
private CountDownLatch mCountDownLatch;
|
||||
|
||||
@Mock
|
||||
private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock;
|
||||
private Runnable mCountDownJob;
|
||||
|
||||
PropertyChangeSignal() {
|
||||
mCountDownLatch = new CountDownLatch(1);
|
||||
mCountDownJob =
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCountDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Runnable getCountDownJob() {
|
||||
return mCountDownJob;
|
||||
}
|
||||
|
||||
public void wait(int timeoutInMilliSeconds) {
|
||||
try {
|
||||
mCountDownLatch.await(timeoutInMilliSeconds, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Mock private DevelopmentSettingsDashboardFragment mFragment;
|
||||
|
||||
@Mock private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -76,18 +104,27 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
// so we can force the SystemProperties with values we need to run tests.
|
||||
// 2) Override the showRebootDialog() to do nothing.
|
||||
// We do not need to pop up the reboot dialog in the test.
|
||||
// 3) Override the rebootDevice() to do nothing.
|
||||
mController = new GraphicsDriverEnableAngleAsSystemDriverController(
|
||||
mContext, mFragment, new Injector(){
|
||||
@Override
|
||||
public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() {
|
||||
return mSystemPropertiesMock;
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
void showRebootDialog() {
|
||||
// do nothing
|
||||
}
|
||||
};
|
||||
mContext,
|
||||
mFragment,
|
||||
new Injector() {
|
||||
@Override
|
||||
public GraphicsDriverSystemPropertiesWrapper
|
||||
createSystemPropertiesWrapper() {
|
||||
return mSystemPropertiesMock;
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
void showRebootDialog() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
void rebootDevice(Context context) {
|
||||
// do nothing
|
||||
}
|
||||
};
|
||||
|
||||
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
@@ -99,58 +136,42 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_switchOn_shouldEnableAngleAsSystemDriver() {
|
||||
// Step 1: toggle the switch "Enable ANGLE" on
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
Runnable countDown = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
SystemProperties.addChangeCallback(countDown);
|
||||
|
||||
// Test onPreferenceChange(true) updates the persist.graphics.egl to "angle"
|
||||
PropertyChangeSignal propertyChangeSignal = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
try {
|
||||
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
propertyChangeSignal.wait(100);
|
||||
|
||||
// Step 2: verify results
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
|
||||
|
||||
// Step 3: clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(countDown);
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_switchOff_shouldDisableAngleAsSystemDriver() {
|
||||
// Step 1: toggle the switch "Enable ANGLE" off
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
Runnable countDown = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
SystemProperties.addChangeCallback(countDown);
|
||||
|
||||
// Test onPreferenceChange(false) updates the persist.graphics.egl to ""
|
||||
PropertyChangeSignal propertyChangeSignal = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
try {
|
||||
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
propertyChangeSignal.wait(100);
|
||||
|
||||
// Step 2: verify results
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo("");
|
||||
|
||||
// Step 3: clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(countDown);
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,8 +183,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
|
||||
@Test
|
||||
public void updateState_angleNotSupported_PreferenceShouldNotBeChecked() {
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||
.thenReturn("");
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())).thenReturn("");
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
}
|
||||
@@ -191,8 +211,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
updateState_angleSupported_angleIsNotSystemGLESDriver_PreferenceShouldNotBeChecked() {
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||
.thenReturn("true");
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn("");
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())).thenReturn("");
|
||||
mController.updateState(mPreference);
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
}
|
||||
@@ -218,28 +237,18 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
Runnable countDown = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
SystemProperties.addChangeCallback(countDown);
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
|
||||
// Test that onDeveloperOptionSwitchDisabled,
|
||||
// persist.graphics.egl updates to ""
|
||||
mController.onDeveloperOptionsSwitchDisabled();
|
||||
try {
|
||||
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
propertyChangeSignal1.wait(100);
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo("");
|
||||
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(countDown);
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -256,70 +265,217 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||
|
||||
@Test
|
||||
public void onRebootCancelled_ToggleSwitchFromOnToOff() {
|
||||
// Step 1: Toggle the "Enable ANGLE" switch on
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
Runnable countDown = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
SystemProperties.addChangeCallback(countDown);
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
// Block the following code execution until the "persist.graphics.egl" property value is
|
||||
// changed.
|
||||
propertyChangeSignal1.wait(100);
|
||||
|
||||
// Test that if the current persist.graphics.egl is "angle",
|
||||
// when reboot is cancelled, persist.graphics.egl is changed back to "",
|
||||
// and switch is set to unchecked.
|
||||
// Step 2: Cancel reboot
|
||||
PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn(ANGLE_DRIVER_SUFFIX);
|
||||
.thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
|
||||
mController.onRebootCancelled();
|
||||
try {
|
||||
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
mController.onRebootDialogDismissed();
|
||||
// Block the following code execution until the "persist.graphics.egl" property valye is
|
||||
// changed.
|
||||
propertyChangeSignal2.wait(100);
|
||||
|
||||
// Step 3: Verify results
|
||||
// 1) Test that persist.graphics.egl is changed back to "".
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo("");
|
||||
// 2) Test that the switch is set to unchecked.
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
|
||||
// Done with the test, remove the callback.
|
||||
SystemProperties.removeChangeCallback(countDown);
|
||||
// Step 4: Clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootCancelled_ToggleSwitchFromOffToOn() {
|
||||
// Step 1: Toggle off the switch "Enable ANGLE"
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
Runnable countDown = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
SystemProperties.addChangeCallback(countDown);
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
// Block the following code execution until the "persist.graphics.egl" property value is
|
||||
// changed.
|
||||
propertyChangeSignal1.wait(100);
|
||||
|
||||
// Test that if the current persist.graphics.egl is "",
|
||||
// when reboot is cancelled, persist.graphics.egl is changed back to "angle",
|
||||
// and switch is set to checked.
|
||||
// Step 2: Cancel reboot
|
||||
PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn("");
|
||||
.thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
|
||||
mController.onRebootCancelled();
|
||||
try {
|
||||
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
mController.onRebootDialogDismissed();
|
||||
// Block the following code execution until the "persist.graphics.egl" property valye is
|
||||
// changed.
|
||||
propertyChangeSignal2.wait(100);
|
||||
|
||||
// Step 3: Verify results
|
||||
// 1) Test that persist.graphics.egl is changed back to "ANGLE"
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
|
||||
// 2) Test that the switch is set to checked
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
|
||||
// Step 4: Clean up
|
||||
// Done with the test, remove the callback.
|
||||
SystemProperties.removeChangeCallback(countDown);
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogDismissed_ToggleSwitchFromOnToOff() {
|
||||
// Step 1: Toggle on the switch "Enable ANGLE"
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
// Block the following code execution until the "persist.graphics.egl" property value is
|
||||
// changed.
|
||||
propertyChangeSignal1.wait(100);
|
||||
|
||||
// Step 2: Dismiss the reboot dialog
|
||||
PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
|
||||
mController.onRebootDialogDismissed();
|
||||
// Block the following code execution until the "persist.graphics.egl" property valye is
|
||||
// changed.
|
||||
propertyChangeSignal2.wait(100);
|
||||
|
||||
// Step 3: Verify results
|
||||
// 1) Test that persist.graphics.egl is changed back to "".
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo("");
|
||||
// 2) Test that the switch is set to unchecked.
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
|
||||
// Step 4: Clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogDismissed_ToggleSwitchFromOffToOn() {
|
||||
// Step 1: Toggle on the switch "Enable ANGLE"
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
// Block the following code execution until the "persist.graphics.egl" property value is
|
||||
// changed.
|
||||
propertyChangeSignal1.wait(100);
|
||||
|
||||
// Step 2: Dismiss the reboot dialog
|
||||
PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
|
||||
mController.onRebootDialogDismissed();
|
||||
// Block the following code execution until the "persist.graphics.egl" property valye is
|
||||
// changed.
|
||||
propertyChangeSignal2.wait(100);
|
||||
|
||||
// Step 3: Verify results
|
||||
// 1) Test that persist.graphics.egl is changed back to "ANGLE"
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
|
||||
// 2) Test that the switch is set to checked
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
|
||||
// Step 4: Clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogConfirmed_ToggleSwitchOnRemainsOn() {
|
||||
// Step 1: Toggle on the switch "Enable ANGLE"
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
// Block the following code execution until the "persist.graphics.egl" property value is
|
||||
// changed.
|
||||
propertyChangeSignal1.wait(100);
|
||||
|
||||
// Step 2: Confirm reboot
|
||||
PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
|
||||
mController.onRebootConfirmed(mContext);
|
||||
mController.onRebootDialogDismissed();
|
||||
// Block the following code execution until the "persist.graphics.egl" property valye is
|
||||
// changed.
|
||||
propertyChangeSignal2.wait(100);
|
||||
|
||||
// Step 3: Verify Results
|
||||
// Test that persist.graphics.egl remains to be "ANGLE"
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
|
||||
|
||||
// Step 4: Clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRebootDialogConfirmed_ToggleSwitchOffRemainsOff() {
|
||||
// Step 1: Toggle off the switch "Enable ANGLE"
|
||||
// Add a callback when SystemProperty changes.
|
||||
// This allows the thread to wait until
|
||||
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||
PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
// Block the following code execution until the "persist.graphics.egl" property value is
|
||||
// changed.
|
||||
propertyChangeSignal1.wait(100);
|
||||
|
||||
// Step 2: Confirm reboot
|
||||
PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
|
||||
SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||
.thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
|
||||
mController.onRebootConfirmed(mContext);
|
||||
mController.onRebootDialogDismissed();
|
||||
// Block the following code execution until the "persist.graphics.egl" property valye is
|
||||
// changed.
|
||||
propertyChangeSignal2.wait(100);
|
||||
|
||||
// Step 3: Verify Results
|
||||
// Test that persist.graphics.egl remains to be ""
|
||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||
assertThat(systemEGLDriver).isEqualTo("");
|
||||
|
||||
// Step 4: Clean up
|
||||
// Done with the test, remove the callback
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
|
||||
SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.regionalpreferences;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -34,6 +36,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.internal.app.LocalePicker;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.widget.TickButtonPreference;
|
||||
|
||||
@@ -68,6 +71,7 @@ public class NumberingSystemItemControllerTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
LocaleList.setDefault(mCacheLocale);
|
||||
LocalePicker.updateLocales(mCacheLocale);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,6 +126,31 @@ public class NumberingSystemItemControllerTest {
|
||||
"test_key");
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void handlePreferenceTreeClick_numbersSelect_numberingSystemIsUpdated() {
|
||||
LocalePicker.updateLocales(LocaleList.forLanguageTags("en-US,zh-TW,ar-BH"));
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE,
|
||||
NumberingSystemItemController.ARG_VALUE_NUMBERING_SYSTEM_SELECT);
|
||||
bundle.putString(
|
||||
NumberingSystemItemController.KEY_SELECTED_LANGUAGE, "ar-BH");
|
||||
TickButtonPreference defaultPreference = new TickButtonPreference(mApplicationContext);
|
||||
TickButtonPreference numberPreference = new TickButtonPreference(mApplicationContext);
|
||||
defaultPreference.setKey("default");
|
||||
numberPreference.setKey("latn");
|
||||
mPreferenceScreen.addPreference(defaultPreference);
|
||||
mPreferenceScreen.addPreference(numberPreference);
|
||||
mController = new NumberingSystemItemController(mApplicationContext, bundle);
|
||||
mController.setParentFragment(mFragment);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
|
||||
mController.handlePreferenceTreeClick(numberPreference);
|
||||
|
||||
assertThat(LocalePicker.getLocales().toLanguageTags()).contains(
|
||||
"en-US,zh-TW,ar-BH-u-nu-latn");
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void displayPreference_languageOptAndHas2LocaleWithSingleNu_showNothing() {
|
||||
|
||||
Reference in New Issue
Block a user