Snap for 9556278 from 2d2db1f711 to udc-release
Change-Id: Ia179f19b0d54e8d08bfbb4780b0d23552344197b
This commit is contained in:
@@ -667,4 +667,25 @@
|
||||
<string name="reset_internet_text" product="default">This will end your phone call</string>
|
||||
<!-- Description for interrupting the voice call alert. [CHAR_LIMIT=NONE] -->
|
||||
<string name="reset_internet_text" product="tablet">This will end your phone call</string>
|
||||
|
||||
<!-- An explanation text that the pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_details_frp" product="default">Your phone was reset to factory settings. To use this phone, enter your previous pattern.</string>
|
||||
<!-- An explanation text that the pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_details_frp" product="tablet">Your tablet was reset to factory settings. To use this tablet, enter your previous pattern.</string>
|
||||
<!-- An explanation text that the pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous pattern.</string>
|
||||
|
||||
<!-- An explanation text that the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pin_details_frp" product="default">Your phone was reset to factory settings. To use this phone, enter your previous PIN.</string>
|
||||
<!-- An explanation text that the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pin_details_frp" product="tablet">Your tablet was reset to factory settings. To use this tablet, enter your previous PIN.</string>
|
||||
<!-- An explanation text that the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pin_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous PIN.</string>
|
||||
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="default">Your phone was reset to factory settings. To use this phone, enter your previous password.</string>
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="tablet">Your tablet was reset to factory settings. To use this tablet, enter your previous password.</string>
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous password.</string>
|
||||
</resources>
|
||||
|
||||
File diff suppressed because one or more lines are too long
1
res/raw-sw600dp/lottie_button_nav_menu.json
Normal file
1
res/raw-sw600dp/lottie_button_nav_menu.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
res/raw-sw600dp/lottie_system_nav_3_button.json
Normal file
1
res/raw-sw600dp/lottie_system_nav_3_button.json
Normal file
File diff suppressed because one or more lines are too long
1
res/raw-sw600dp/lottie_system_nav_fully_gestural.json
Normal file
1
res/raw-sw600dp/lottie_system_nav_fully_gestural.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1044,6 +1044,10 @@
|
||||
<string name="no_screen_lock_issue_summary">For added security, set a PIN, pattern, or password for this device.</string>
|
||||
<!-- Action label for the issue card in Safety Center when no screen lock is set [CHAR LIMIT=50] -->
|
||||
<string name="no_screen_lock_issue_action_label">Set screen lock</string>
|
||||
<!-- Title of the notification shown by Safety Center when no screen lock is set. This notification is shown in the notification shade, outside of the main Safety Center UI. [CHAR LIMIT=50] -->
|
||||
<string name="no_screen_lock_issue_notification_title">Device has no screen lock</string>
|
||||
<!-- Summary/body text of the notification shown by Safety Center when no screen lock is set. This notification is shown in the notification shade, outside of the main Safety Center UI. [CHAR LIMIT=NONE] -->
|
||||
<string name="no_screen_lock_issue_notification_text">For added security, set a PIN, pattern, or password for this device.</string>
|
||||
|
||||
<!-- Unlock Picker Settings --><skip />
|
||||
|
||||
@@ -3330,27 +3334,6 @@
|
||||
continue. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_strong_auth_required_work_password">For added security, enter your work password</string>
|
||||
|
||||
<!-- An explanation text that the pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_details_frp" product="default">Your phone was reset to factory settings. To use this phone, enter your previous pattern.</string>
|
||||
<!-- An explanation text that the pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_details_frp" product="tablet">Your tablet was reset to factory settings. To use this tablet, enter your previous pattern.</string>
|
||||
<!-- An explanation text that the pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous pattern.</string>
|
||||
|
||||
<!-- An explanation text that the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pin_details_frp" product="default">Your phone was reset to factory settings. To use this phone, enter your previous PIN.</string>
|
||||
<!-- An explanation text that the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pin_details_frp" product="tablet">Your tablet was reset to factory settings. To use this tablet, enter your previous PIN.</string>
|
||||
<!-- An explanation text that the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pin_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous PIN.</string>
|
||||
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="default">Your phone was reset to factory settings. To use this phone, enter your previous password.</string>
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="tablet">Your tablet was reset to factory settings. To use this tablet, enter your previous password.</string>
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous password.</string>
|
||||
|
||||
<!-- Header shown when pattern needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_pattern_header_frp">Verify pattern</string>
|
||||
<!-- Header shown when the pin needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
@@ -3824,6 +3807,8 @@
|
||||
<string name="language_and_input_for_work_category_title">Work profile keyboards & tools</string>
|
||||
<!-- Title for the 'Virtual keyboards for work' preference. [CHAR LIMIT=45] -->
|
||||
<string name="virtual_keyboards_for_work_title">On-screen keyboard for work</string>
|
||||
<!-- Summary text for none selected keyboard default layout -->
|
||||
<string name="keyboard_default_layout">Default</string>
|
||||
|
||||
<!-- Title for the button to trigger the 'trackpad settings' page if only connect with a touchpad. [CHAR LIMIT=35] -->
|
||||
<string name="trackpad_settings">Touchpad</string>
|
||||
@@ -10255,14 +10240,14 @@
|
||||
<!-- Apps > App Details > Wifi access > Description. [CHAR LIMIT=NONE] -->
|
||||
<string name="change_wifi_state_app_detail_summary">Allow this app to turn Wi-Fi on or off, scan and connect to Wi-Fi networks, add or remove networks, or start a local-only hotspot</string>
|
||||
|
||||
<!-- Title for Nfc Tag apps control [CHAR LIMIT=35] -->
|
||||
<string name="change_nfc_tag_apps_title">NFC Tag apps control</string>
|
||||
<!-- Title for NFC launch [CHAR LIMIT=35] -->
|
||||
<string name="change_nfc_tag_apps_title">NFC launch</string>
|
||||
|
||||
<!-- Apps > App Details > Nfc Tag apps control > Switch title. [CHAR LIMIT=NONE] -->
|
||||
<string name="change_nfc_tag_apps_detail_switch">Allow app to popup upon NFC tags detected</string>
|
||||
<!-- Apps > App Details > Nfc launch > Switch title. [CHAR LIMIT=NONE] -->
|
||||
<string name="change_nfc_tag_apps_detail_switch">Allow launch on NFC scan</string>
|
||||
|
||||
<!-- Apps > App Details > Nfc Tag apps control > Description. [CHAR LIMIT=NONE] -->
|
||||
<string name="change_nfc_tag_apps_detail_summary">Allow this app to launch and get tag contents when the device detests NFC tags</string>
|
||||
<!-- Apps > App Details > Nfc launch > Description. [CHAR LIMIT=NONE] -->
|
||||
<string name="change_nfc_tag_apps_detail_summary">Allow this app to launch when a NFC tag is scanned.\nIf this permission is on, the app will be available as an option whenever a tag is detected.</string>
|
||||
|
||||
<!-- Title for media output settings -->
|
||||
<string name="media_output_title">Play media to</string>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
android:key="bubbles_illustration"
|
||||
settings:searchable="false"
|
||||
app:lottie_rawRes="@raw/lottie_bubbles"
|
||||
settings:dynamicColor="true"
|
||||
settings:controller="com.android.settings.notification.BubbleNotificationIllustrationPreferenceController"/>
|
||||
|
||||
<com.android.settingslib.widget.MainSwitchPreference
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<com.android.settingslib.widget.IllustrationPreference
|
||||
android:key="gesture_power_menu_video"
|
||||
settings:searchable="false"
|
||||
settings:dynamicColor="true"
|
||||
settings:lottie_imageAssetsFolder="button_nav_menu"
|
||||
settings:lottie_rawRes="@raw/lottie_button_nav_menu"/>
|
||||
|
||||
|
||||
@@ -16,8 +16,5 @@
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/physical_keyboard_title">
|
||||
<PreferenceCategory
|
||||
android:key="enabled_locales_keyboard_layout"
|
||||
android:title="@string/enabled_locales_keyboard_layout">
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -1277,4 +1277,16 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the current user is able to use Dreams.
|
||||
*/
|
||||
public static boolean canCurrentUserDream(Context context) {
|
||||
final UserHandle mainUser = context.getSystemService(UserManager.class).getMainUser();
|
||||
if (mainUser == null) {
|
||||
return false;
|
||||
}
|
||||
return context.createContextAsUser(mainUser, 0).getSystemService(UserManager.class)
|
||||
.isUserForeground();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Default reviewers for this and subdirectories.
|
||||
danielnorman@google.com
|
||||
menghanli@google.com
|
||||
thomasli@google.com
|
||||
|
||||
per-file HapticFeedbackIntensityPreferenceController.java = michaelwr@google.com
|
||||
per-file *Vibration* = michaelwr@google.com
|
||||
|
||||
@@ -24,8 +24,11 @@ import android.hardware.fingerprint.FingerprintManager;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Helper for {@link BiometricEnrollActivity} when multiple sensors exist on a device.
|
||||
*/
|
||||
@@ -45,14 +48,39 @@ public class MultiBiometricEnrollHelper {
|
||||
private final int mUserId;
|
||||
private final boolean mRequestEnrollFace;
|
||||
private final boolean mRequestEnrollFingerprint;
|
||||
private final FingerprintManager mFingerprintManager;
|
||||
private final FaceManager mFaceManager;
|
||||
private final Intent mFingerprintEnrollIntroductionIntent;
|
||||
private final Intent mFaceEnrollIntroductionIntent;
|
||||
private Function<Long, byte[]> mGatekeeperHatSupplier;
|
||||
|
||||
@VisibleForTesting
|
||||
MultiBiometricEnrollHelper(@NonNull FragmentActivity activity, int userId,
|
||||
boolean enrollFace, boolean enrollFingerprint, long gkPwHandle) {
|
||||
boolean enrollFace, boolean enrollFingerprint, long gkPwHandle,
|
||||
FingerprintManager fingerprintManager,
|
||||
FaceManager faceManager, Intent fingerprintEnrollIntroductionIntent,
|
||||
Intent faceEnrollIntroductionIntent, Function<Long, byte[]> gatekeeperHatSupplier) {
|
||||
mActivity = activity;
|
||||
mUserId = userId;
|
||||
mGkPwHandle = gkPwHandle;
|
||||
mRequestEnrollFace = enrollFace;
|
||||
mRequestEnrollFingerprint = enrollFingerprint;
|
||||
mFingerprintManager = fingerprintManager;
|
||||
mFaceManager = faceManager;
|
||||
mFingerprintEnrollIntroductionIntent = fingerprintEnrollIntroductionIntent;
|
||||
mFaceEnrollIntroductionIntent = faceEnrollIntroductionIntent;
|
||||
mGatekeeperHatSupplier = gatekeeperHatSupplier;
|
||||
}
|
||||
|
||||
MultiBiometricEnrollHelper(@NonNull FragmentActivity activity, int userId,
|
||||
boolean enrollFace, boolean enrollFingerprint, long gkPwHandle) {
|
||||
this(activity, userId, enrollFace, enrollFingerprint, gkPwHandle,
|
||||
activity.getSystemService(FingerprintManager.class),
|
||||
activity.getSystemService(FaceManager.class),
|
||||
BiometricUtils.getFingerprintIntroIntent(activity, activity.getIntent()),
|
||||
BiometricUtils.getFaceIntroIntent(activity, activity.getIntent()),
|
||||
(challenge) -> BiometricUtils.requestGatekeeperHat(activity, gkPwHandle,
|
||||
userId, challenge));
|
||||
}
|
||||
|
||||
void startNextStep() {
|
||||
@@ -67,45 +95,39 @@ public class MultiBiometricEnrollHelper {
|
||||
}
|
||||
|
||||
private void launchFaceEnroll() {
|
||||
final FaceManager faceManager = mActivity.getSystemService(FaceManager.class);
|
||||
faceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
|
||||
mGkPwHandle, mUserId, challenge);
|
||||
final Intent faceIntent = BiometricUtils.getFaceIntroIntent(mActivity,
|
||||
mActivity.getIntent());
|
||||
faceIntent.putExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
||||
faceIntent.putExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||
BiometricUtils.launchEnrollForResult(mActivity, faceIntent, REQUEST_FACE_ENROLL,
|
||||
hardwareAuthToken, mGkPwHandle, mUserId);
|
||||
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
final byte[] hardwareAuthToken = mGatekeeperHatSupplier.apply(challenge);
|
||||
mFaceEnrollIntroductionIntent.putExtra(
|
||||
BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
||||
mFaceEnrollIntroductionIntent.putExtra(
|
||||
BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||
BiometricUtils.launchEnrollForResult(mActivity, mFaceEnrollIntroductionIntent,
|
||||
REQUEST_FACE_ENROLL, hardwareAuthToken, mGkPwHandle, mUserId);
|
||||
});
|
||||
}
|
||||
|
||||
private void launchFingerprintEnroll() {
|
||||
final FingerprintManager fingerprintManager = mActivity
|
||||
.getSystemService(FingerprintManager.class);
|
||||
fingerprintManager.generateChallenge(mUserId, ((sensorId, userId, challenge) -> {
|
||||
final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
|
||||
mGkPwHandle, mUserId, challenge);
|
||||
final Intent intent = BiometricUtils.getFingerprintIntroIntent(mActivity,
|
||||
mActivity.getIntent());
|
||||
intent.putExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
||||
intent.putExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||
mFingerprintManager.generateChallenge(mUserId, ((sensorId, userId, challenge) -> {
|
||||
final byte[] hardwareAuthToken = mGatekeeperHatSupplier.apply(challenge);
|
||||
mFingerprintEnrollIntroductionIntent.putExtra(
|
||||
BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
||||
mFingerprintEnrollIntroductionIntent.putExtra(
|
||||
BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||
if (mRequestEnrollFace) {
|
||||
// Give FingerprintEnroll a pendingIntent pointing to face enrollment, so that it
|
||||
// can be started when user skips or finishes fingerprint enrollment.
|
||||
// FLAG_UPDATE_CURRENT ensures it is launched with the most recent values.
|
||||
final Intent faceIntent = BiometricUtils.getFaceIntroIntent(mActivity,
|
||||
mActivity.getIntent());
|
||||
faceIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
faceIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
|
||||
mGkPwHandle);
|
||||
mFaceEnrollIntroductionIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
mFaceEnrollIntroductionIntent.putExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, mGkPwHandle);
|
||||
final PendingIntent faceAfterFp = PendingIntent.getActivity(mActivity,
|
||||
0 /* requestCode */, faceIntent,
|
||||
0 /* requestCode */, mFaceEnrollIntroductionIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
intent.putExtra(EXTRA_ENROLL_AFTER_FINGERPRINT, faceAfterFp);
|
||||
mFingerprintEnrollIntroductionIntent.putExtra(EXTRA_ENROLL_AFTER_FINGERPRINT,
|
||||
faceAfterFp);
|
||||
}
|
||||
BiometricUtils.launchEnrollForResult(mActivity, intent, REQUEST_FINGERPRINT_ENROLL,
|
||||
hardwareAuthToken, mGkPwHandle, mUserId);
|
||||
BiometricUtils.launchEnrollForResult(mActivity, mFingerprintEnrollIntroductionIntent,
|
||||
REQUEST_FINGERPRINT_ENROLL, hardwareAuthToken, mGkPwHandle, mUserId);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -86,6 +87,18 @@ public class CombinedBiometricStatusUtils {
|
||||
return faceConsentRequired && fpConsentRequired ? faceAdmin : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title of combined biometric settings entity.
|
||||
*/
|
||||
public String getTitle() {
|
||||
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
if (userManager != null && userManager.isProfile()) {
|
||||
return mContext.getString(R.string.security_settings_work_biometric_preference_title);
|
||||
} else {
|
||||
return mContext.getString(R.string.security_settings_biometric_preference_title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the summary of combined biometric settings entity.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.biometrics.face;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Settings;
|
||||
@@ -58,6 +59,18 @@ public class FaceStatusUtils {
|
||||
mContext, BiometricAuthenticator.TYPE_FACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title of face settings entity.
|
||||
*/
|
||||
public String getTitle() {
|
||||
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
if (userManager != null && userManager.isProfile()) {
|
||||
return mContext.getString(R.string.security_settings_face_profile_preference_title);
|
||||
} else {
|
||||
return mContext.getString(R.string.security_settings_face_preference_title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the summary of face settings entity.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.biometrics.fingerprint;
|
||||
import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricAuthenticator;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
@@ -59,6 +60,17 @@ public class FingerprintStatusUtils {
|
||||
return ParentalControlsUtils.parentConsentRequired(
|
||||
mContext, BiometricAuthenticator.TYPE_FINGERPRINT);
|
||||
}
|
||||
/**
|
||||
* Returns the title of fingerprint settings entity.
|
||||
*/
|
||||
public String getTitle() {
|
||||
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
if (userManager != null && userManager.isProfile()) {
|
||||
return mContext.getString(R.string.security_settings_work_fingerprint_preference_title);
|
||||
} else {
|
||||
return mContext.getString(R.string.security_settings_fingerprint_preference_title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the summary of fingerprint settings entity.
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
package com.android.settings.communal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
/**
|
||||
@@ -32,14 +32,8 @@ public class CommunalPreferenceController extends BasePreferenceController {
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
// TODO(b/257333623): Allow the communal user to be non-SystemUser user in HSUM.
|
||||
return (mContext.getResources().getBoolean(R.bool.config_show_communal_settings)
|
||||
&& isSystemUser())
|
||||
&& Utils.canCurrentUserDream(mContext))
|
||||
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
private boolean isSystemUser() {
|
||||
final UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
return userManager != null && userManager.isSystemUser();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.android.settings.development.tare.DropdownActivity.POLICY_ALAR
|
||||
import static com.android.settings.development.tare.DropdownActivity.POLICY_JOB_SCHEDULER;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.tare.EconomyManager;
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
@@ -29,6 +30,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
@@ -41,6 +43,8 @@ import com.android.settings.R;
|
||||
|
||||
/** Class for creating the TARE homepage in settings */
|
||||
public class TareHomePage extends Activity {
|
||||
private static final String TAG = "TareHomePage";
|
||||
|
||||
private Switch mOnSwitch;
|
||||
private Button mRevButton;
|
||||
private TextView mAlarmManagerView;
|
||||
@@ -131,8 +135,6 @@ public class TareHomePage extends Activity {
|
||||
}
|
||||
|
||||
private class ConfigObserver extends ContentObserver {
|
||||
private static final String KEY_DC_ENABLE_TARE = "enable_tare";
|
||||
|
||||
private int mEnableTareSetting;
|
||||
|
||||
ConfigObserver(Handler handler) {
|
||||
@@ -163,7 +165,8 @@ public class TareHomePage extends Activity {
|
||||
try {
|
||||
mEnableTareSetting = Integer.parseInt(setting);
|
||||
} catch (NumberFormatException e) {
|
||||
mEnableTareSetting = Settings.Global.DEFAULT_ENABLE_TARE;
|
||||
Log.e(TAG, "Invalid setting value", e);
|
||||
mEnableTareSetting = EconomyManager.DEFAULT_ENABLE_TARE_MODE;
|
||||
}
|
||||
}
|
||||
final boolean enabled;
|
||||
@@ -178,9 +181,10 @@ public class TareHomePage extends Activity {
|
||||
}
|
||||
|
||||
private boolean getDefaultEnabledStatus() {
|
||||
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TARE, KEY_DC_ENABLE_TARE,
|
||||
Settings.Global.DEFAULT_ENABLE_TARE == SETTING_VALUE_ON);
|
||||
// Show Shadow Mode as "off" in the UI since it won't be affecting device behavior.
|
||||
return DeviceConfig.getInt(DeviceConfig.NAMESPACE_TARE,
|
||||
EconomyManager.KEY_ENABLE_TARE_MODE,
|
||||
EconomyManager.DEFAULT_ENABLE_TARE_MODE) == EconomyManager.ENABLED_MODE_ON;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
@@ -44,6 +46,7 @@ public class SimStatusPreferenceController extends BasePreferenceController {
|
||||
|
||||
private Fragment mFragment;
|
||||
private SlotSimStatus mSlotSimStatus;
|
||||
private Observer<LifecycleOwner> mLifecycleOwnerObserver;
|
||||
private Observer mSimChangeObserver;
|
||||
|
||||
public SimStatusPreferenceController(Context context, String prefKey) {
|
||||
@@ -112,13 +115,25 @@ public class SimStatusPreferenceController extends BasePreferenceController {
|
||||
if (mFragment == null) {
|
||||
return;
|
||||
}
|
||||
final int simSlot = getSimSlotIndex();
|
||||
if (mSimChangeObserver == null) {
|
||||
mSimChangeObserver = x -> updateStateBySlot(preference, simSlot);
|
||||
mFragment.getViewLifecycleOwnerLiveData().observeForever(lifecycleOwner -> {
|
||||
mSlotSimStatus.observe(lifecycleOwner, mSimChangeObserver);
|
||||
});
|
||||
} else {
|
||||
if (mLifecycleOwnerObserver == null) {
|
||||
final LiveData<LifecycleOwner> dataLifecycleOwner
|
||||
= mFragment.getViewLifecycleOwnerLiveData();
|
||||
mLifecycleOwnerObserver = owner -> {
|
||||
if (owner != null) {
|
||||
final int simSlot = getSimSlotIndex();
|
||||
mSimChangeObserver = x -> updateStateBySlot(preference, simSlot);
|
||||
mSlotSimStatus.observe(owner, mSimChangeObserver);
|
||||
} else {
|
||||
if (mSimChangeObserver != null) {
|
||||
mSlotSimStatus.removeObserver(mSimChangeObserver);
|
||||
mSimChangeObserver = null;
|
||||
}
|
||||
dataLifecycleOwner.removeObserver(mLifecycleOwnerObserver);
|
||||
}
|
||||
};
|
||||
dataLifecycleOwner.observeForever(mLifecycleOwnerObserver);
|
||||
} else if (mSimChangeObserver != null) {
|
||||
final int simSlot = getSimSlotIndex();
|
||||
updateStateBySlot(preference, simSlot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
package com.android.settings.display;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.dream.DreamSettings;
|
||||
@@ -39,9 +39,8 @@ public class ScreenSaverPreferenceController extends BasePreferenceController im
|
||||
com.android.internal.R.bool.config_dreamsSupported);
|
||||
final boolean dreamsOnlyEnabledForDockUser = mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_dreamsOnlyEnabledForDockUser);
|
||||
final UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
// TODO(b/257333623): Allow the Dock User to be non-SystemUser user in HSUM.
|
||||
return (dreamsSupported && (!dreamsOnlyEnabledForDockUser || userManager.isMainUser()))
|
||||
return (dreamsSupported && (!dreamsOnlyEnabledForDockUser
|
||||
|| Utils.canCurrentUserDream(mContext)))
|
||||
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
@@ -56,6 +55,8 @@ import com.android.settingslib.widget.SelectorWithWidgetPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Power usage detail fragment for each app, this fragment contains
|
||||
@@ -91,6 +92,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
private static final int REQUEST_UNINSTALL = 0;
|
||||
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
|
||||
|
||||
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
@VisibleForTesting
|
||||
LayoutPreference mHeaderPreference;
|
||||
@VisibleForTesting
|
||||
@@ -98,8 +101,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
@VisibleForTesting
|
||||
ApplicationsState.AppEntry mAppEntry;
|
||||
@VisibleForTesting
|
||||
BatteryUtils mBatteryUtils;
|
||||
@VisibleForTesting
|
||||
BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
@VisibleForTesting
|
||||
FooterPreference mFooterPreference;
|
||||
@@ -244,7 +245,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
super.onAttach(activity);
|
||||
|
||||
mState = ApplicationsState.getInstance(getActivity().getApplication());
|
||||
mBatteryUtils = BatteryUtils.getInstance(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,12 +267,15 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
initHeader();
|
||||
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
|
||||
initPreferenceForTriState(getContext());
|
||||
final String packageName = mBatteryOptimizeUtils.getPackageName();
|
||||
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
|
||||
.action(
|
||||
getContext(),
|
||||
SettingsEnums.OPEN_APP_BATTERY_USAGE,
|
||||
packageName);
|
||||
mExecutor.execute(() -> {
|
||||
String packageName =
|
||||
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
|
||||
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
|
||||
.action(
|
||||
getContext(),
|
||||
SettingsEnums.OPEN_APP_BATTERY_USAGE,
|
||||
packageName);
|
||||
});
|
||||
mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
|
||||
}
|
||||
|
||||
@@ -444,17 +447,21 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (metricCategory != 0) {
|
||||
final String packageName = mBatteryOptimizeUtils.getPackageName();
|
||||
if (metricCategory == 0) {
|
||||
return;
|
||||
}
|
||||
int finalMetricCategory = metricCategory;
|
||||
mExecutor.execute(() -> {
|
||||
String packageName =
|
||||
getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
|
||||
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider()
|
||||
.action(
|
||||
/* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
|
||||
/* action */ metricCategory,
|
||||
/* action */ finalMetricCategory,
|
||||
/* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
|
||||
TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName,
|
||||
packageName,
|
||||
getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onCreateForTriState(String packageName) {
|
||||
@@ -498,4 +505,9 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
|
||||
return String.format("%s\n(%s)", usageSummary, slotSummary);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLoggingPackageName(Context context, String originalPackingName) {
|
||||
return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
|
||||
? originalPackingName : PACKAGE_NAME_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.InstallSourceInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
@@ -34,6 +35,7 @@ import android.os.SystemClock;
|
||||
import android.os.UidBatteryConsumer;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
@@ -83,6 +85,8 @@ public class BatteryUtils {
|
||||
|
||||
public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass";
|
||||
|
||||
private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({StatusType.SCREEN_USAGE,
|
||||
StatusType.FOREGROUND,
|
||||
@@ -597,6 +601,21 @@ public class BatteryUtils {
|
||||
return -1L;
|
||||
}
|
||||
|
||||
/** Whether the package is installed from Google Play Store or not */
|
||||
public static boolean isAppInstalledFromGooglePlayStore(Context context, String packageName) {
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return false;
|
||||
}
|
||||
InstallSourceInfo installSourceInfo;
|
||||
try {
|
||||
installSourceInfo = context.getPackageManager().getInstallSourceInfo(packageName);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return installSourceInfo != null
|
||||
&& GOOGLE_PLAY_STORE_PACKAGE.equals(installSourceInfo.getInitiatingPackageName());
|
||||
}
|
||||
|
||||
/** Gets the latest sticky battery intent from the Android system. */
|
||||
public static Intent getBatteryIntent(Context context) {
|
||||
return context.registerReceiver(
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.gestures;
|
||||
|
||||
import static android.os.UserHandle.USER_CURRENT;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
|
||||
@@ -74,6 +75,8 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment i
|
||||
|
||||
private static final String KEY_SHOW_A11Y_TUTORIAL_DIALOG = "show_a11y_tutorial_dialog_bool";
|
||||
|
||||
private static final int MIN_LARGESCREEN_WIDTH_DP = 600;
|
||||
|
||||
private boolean mA11yTutorialDialogShown = false;
|
||||
|
||||
private IOverlayManager mOverlayManager;
|
||||
@@ -112,6 +115,11 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment i
|
||||
ServiceManager.getService(Context.OVERLAY_SERVICE));
|
||||
|
||||
mVideoPreference = new IllustrationPreference(context);
|
||||
Context windowContext = context.createWindowContext(TYPE_APPLICATION_OVERLAY, null);
|
||||
if (windowContext.getResources()
|
||||
.getConfiguration().smallestScreenWidthDp >= MIN_LARGESCREEN_WIDTH_DP) {
|
||||
mVideoPreference.applyDynamicColor();
|
||||
}
|
||||
setIllustrationVideo(mVideoPreference, getDefaultKey());
|
||||
|
||||
migrateOverlaySensitivityToSettings(context, mOverlayManager);
|
||||
|
||||
@@ -20,64 +20,124 @@ import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputDeviceIdentifier;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.hardware.input.KeyboardLayout;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.view.InputDevice;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.inputmethod.NewKeyboardSettingsUtils.KeyboardInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
|
||||
implements InputManager.InputDeviceListener {
|
||||
|
||||
private static final String TAG = "NewKeyboardLayoutEnabledLocalesFragment";
|
||||
private static final String PREF_KEY_ENABLED_LOCALES = "enabled_locales_keyboard_layout";
|
||||
|
||||
static final String EXTRA_KEYBOARD_DEVICE_NAME = "extra_keyboard_device_name";
|
||||
|
||||
private InputManager mIm;
|
||||
private InputMethodManager mImm;
|
||||
private InputDeviceIdentifier mInputDeviceIdentifier;
|
||||
private int mUserId;
|
||||
private int mInputDeviceId;
|
||||
private Context mContext;
|
||||
private Map<String, KeyboardInfo> mKeyboardLanguageLayouts = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(final Bundle icicle) {
|
||||
super.onActivityCreated(icicle);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
final String title = arguments.getString(EXTRA_KEYBOARD_DEVICE_NAME);
|
||||
mInputDeviceIdentifier = arguments.getParcelable(
|
||||
KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
|
||||
final String title =
|
||||
arguments.getString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_DEVICE_NAME);
|
||||
mInputDeviceIdentifier =
|
||||
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER);
|
||||
getActivity().setTitle(title);
|
||||
final PreferenceCategory category = findPreference(PREF_KEY_ENABLED_LOCALES);
|
||||
updateCheckedState();
|
||||
}
|
||||
|
||||
// TODO(b/252816846): Need APIs to get the available keyboards from Inputmanager.
|
||||
// For example: InputMethodManager.getEnabledInputMethodLocales()
|
||||
// InputManager.getKeyboardLayoutForLocale()
|
||||
// Hardcode the default value for demo purpose
|
||||
String[] keyboardLanguages = {"English (US)", "German (Germany)", "Spanish (Spain)"};
|
||||
String[] keyboardLayouts = {"English (US)", "German", "Spanish"};
|
||||
for (int i = 0; i < keyboardLanguages.length; i++) {
|
||||
private void updateCheckedState() {
|
||||
PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
preferenceScreen.removeAll();
|
||||
List<InputMethodInfo> infoList = mImm.getEnabledInputMethodListAsUser(mUserId);
|
||||
for (InputMethodInfo info : infoList) {
|
||||
mKeyboardLanguageLayouts.clear();
|
||||
List<InputMethodSubtype> subtypes =
|
||||
mImm.getEnabledInputMethodSubtypeList(info, true);
|
||||
for (InputMethodSubtype subtype : subtypes) {
|
||||
if (subtype.isSuitableForPhysicalKeyboardLayoutMapping()) {
|
||||
mapLanguageWithLayout(info, subtype);
|
||||
}
|
||||
}
|
||||
updatePreferenceLayout(preferenceScreen, info);
|
||||
}
|
||||
}
|
||||
|
||||
private void mapLanguageWithLayout(InputMethodInfo info, InputMethodSubtype subtype) {
|
||||
KeyboardLayout[] keyboardLayouts = getKeyboardLayouts(info, subtype);
|
||||
String layout = getKeyboardLayout(info, subtype);
|
||||
String language = getLanguage(info, subtype);
|
||||
if (layout != null) {
|
||||
for (int i = 0; i < keyboardLayouts.length; i++) {
|
||||
if (keyboardLayouts[i].getDescriptor().equals(layout)) {
|
||||
KeyboardInfo keyboardInfo = new KeyboardInfo(
|
||||
language,
|
||||
keyboardLayouts[i].getLabel(),
|
||||
info,
|
||||
subtype);
|
||||
mKeyboardLanguageLayouts.put(subtype.getLanguageTag(), keyboardInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if there is no auto-selected layout, we should show "Default"
|
||||
KeyboardInfo keyboardInfo = new KeyboardInfo(
|
||||
language,
|
||||
mContext.getString(R.string.keyboard_default_layout),
|
||||
info,
|
||||
subtype);
|
||||
mKeyboardLanguageLayouts.put(subtype.getLanguageTag(), keyboardInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePreferenceLayout(PreferenceScreen preferenceScreen, InputMethodInfo info) {
|
||||
if (mKeyboardLanguageLayouts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
|
||||
preferenceCategory.setTitle(info.loadLabel(mContext.getPackageManager()).toString());
|
||||
preferenceCategory.setKey(info.getPackageName());
|
||||
preferenceScreen.addPreference(preferenceCategory);
|
||||
for (Map.Entry<String, KeyboardInfo> entry : mKeyboardLanguageLayouts.entrySet()) {
|
||||
final Preference pref = new Preference(mContext);
|
||||
String key = "keyboard_language_label_" + String.valueOf(i);
|
||||
String keyboardLanguageTitle = keyboardLanguages[i];
|
||||
String keyboardLanguageSummary = keyboardLayouts[i];
|
||||
// TODO: Waiting for new API to use a prefix with special number to setKey
|
||||
String key = "keyboard_language_" + entry.getKey();
|
||||
NewKeyboardSettingsUtils.KeyboardInfo keyboardInfo = entry.getValue();
|
||||
pref.setKey(key);
|
||||
pref.setTitle(keyboardLanguageTitle);
|
||||
pref.setSummary(keyboardLanguageSummary);
|
||||
pref.setTitle(keyboardInfo.getLanguage());
|
||||
pref.setSummary(keyboardInfo.getLayout());
|
||||
pref.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
showKeyboardLayoutPicker(
|
||||
keyboardLanguageTitle,
|
||||
keyboardLanguageSummary,
|
||||
mInputDeviceIdentifier);
|
||||
keyboardInfo.getLanguage(),
|
||||
keyboardInfo.getLayout(),
|
||||
mInputDeviceIdentifier,
|
||||
mUserId,
|
||||
keyboardInfo.getInputMethodInfo(),
|
||||
keyboardInfo.getInputMethodSubtype());
|
||||
return true;
|
||||
});
|
||||
category.addPreference(pref);
|
||||
preferenceCategory.addPreference(pref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +156,7 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
|
||||
// TODO(b/252816846): Need APIs to update the available keyboards.
|
||||
updateCheckedState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +165,9 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
|
||||
super.onCreate(savedInstanceState);
|
||||
mContext = getContext();
|
||||
mIm = mContext.getSystemService(InputManager.class);
|
||||
mImm = mContext.getSystemService(InputMethodManager.class);
|
||||
mInputDeviceId = -1;
|
||||
mUserId = UserHandle.myUserId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,7 +193,7 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// TODO(b/252816846): Need APIs to get the available keyboards from Inputmanager.
|
||||
updateCheckedState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,17 +211,50 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
|
||||
return R.xml.keyboard_settings_enabled_locales_list;
|
||||
}
|
||||
|
||||
private void showKeyboardLayoutPicker(String language, String layout,
|
||||
InputDeviceIdentifier inputDeviceIdentifier) {
|
||||
private void showKeyboardLayoutPicker(
|
||||
String language,
|
||||
String layout,
|
||||
InputDeviceIdentifier inputDeviceIdentifier,
|
||||
int userId,
|
||||
InputMethodInfo inputMethodInfo,
|
||||
InputMethodSubtype inputMethodSubtype) {
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putParcelable(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
|
||||
inputDeviceIdentifier);
|
||||
arguments.putString(NewKeyboardLayoutPickerFragment.EXTRA_TITLE, language);
|
||||
arguments.putString(NewKeyboardLayoutPickerFragment.EXTRA_KEYBOARD_LAYOUT, layout);
|
||||
arguments.putParcelable(
|
||||
NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER, inputDeviceIdentifier);
|
||||
arguments.putParcelable(
|
||||
NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_INFO, inputMethodInfo);
|
||||
arguments.putParcelable(
|
||||
NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE, inputMethodSubtype);
|
||||
arguments.putInt(NewKeyboardSettingsUtils.EXTRA_USER_ID, userId);
|
||||
arguments.putString(NewKeyboardSettingsUtils.EXTRA_TITLE, language);
|
||||
arguments.putString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_LAYOUT, layout);
|
||||
new SubSettingLauncher(mContext)
|
||||
.setSourceMetricsCategory(getMetricsCategory())
|
||||
.setDestination(NewKeyboardLayoutPickerFragment.class.getName())
|
||||
.setArguments(arguments)
|
||||
.launch();
|
||||
}
|
||||
|
||||
private KeyboardLayout[] getKeyboardLayouts(InputMethodInfo info, InputMethodSubtype subtype) {
|
||||
return mIm.getKeyboardLayoutListForInputDevice(
|
||||
mInputDeviceIdentifier, mUserId, info, subtype);
|
||||
}
|
||||
|
||||
private String getKeyboardLayout(InputMethodInfo info, InputMethodSubtype subtype) {
|
||||
return mIm.getKeyboardLayoutForInputDevice(
|
||||
mInputDeviceIdentifier, mUserId, info, subtype);
|
||||
}
|
||||
|
||||
private String getLanguage(InputMethodInfo info, InputMethodSubtype subtype) {
|
||||
String language;
|
||||
if (subtype.getLanguageTag().isEmpty()) {
|
||||
language = subtype.getDisplayName(
|
||||
mContext,
|
||||
info.getPackageName(),
|
||||
info.getServiceInfo().applicationInfo).toString();
|
||||
} else {
|
||||
language = Locale.forLanguageTag(subtype.getLanguageTag()).getDisplayName();
|
||||
}
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputDeviceIdentifier;
|
||||
import android.os.Bundle;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
@@ -28,31 +30,28 @@ public class NewKeyboardLayoutPickerContent extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "KeyboardLayoutPicker";
|
||||
|
||||
static final String EXTRA_TITLE = "keyboard_layout_picker_title";
|
||||
static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
|
||||
|
||||
/**
|
||||
* Intent extra: The input device descriptor of the keyboard whose keyboard
|
||||
* layout is to be changed.
|
||||
*/
|
||||
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
final String title = arguments.getString(EXTRA_TITLE);
|
||||
final String layout = arguments.getString(EXTRA_KEYBOARD_LAYOUT);
|
||||
final String title = arguments.getString(NewKeyboardSettingsUtils.EXTRA_TITLE);
|
||||
final String layout = arguments.getString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_LAYOUT);
|
||||
final int userId = arguments.getInt(NewKeyboardSettingsUtils.EXTRA_USER_ID);
|
||||
final InputDeviceIdentifier inputDeviceIdentifier =
|
||||
arguments.getParcelable(EXTRA_INPUT_DEVICE_IDENTIFIER);
|
||||
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER);
|
||||
final InputMethodInfo inputMethodInfo =
|
||||
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_INFO);
|
||||
final InputMethodSubtype inputMethodSubtype =
|
||||
arguments.getParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_METHOD_SUBTYPE);
|
||||
|
||||
|
||||
if (inputDeviceIdentifier == null) {
|
||||
getActivity().finish();
|
||||
}
|
||||
getActivity().setTitle(title);
|
||||
use(NewKeyboardLayoutPickerController.class).initialize(this /*parent*/,
|
||||
inputDeviceIdentifier, layout);
|
||||
use(NewKeyboardLayoutPickerController.class).initialize(this /*parent*/, userId,
|
||||
inputDeviceIdentifier, inputMethodInfo, inputMethodSubtype, layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.hardware.input.InputDeviceIdentifier;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.hardware.input.KeyboardLayout;
|
||||
import android.view.InputDevice;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
@@ -31,7 +33,6 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -42,7 +43,11 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController
|
||||
|
||||
private Fragment mParent;
|
||||
private int mInputDeviceId;
|
||||
private int mUserId;
|
||||
private InputDeviceIdentifier mInputDeviceIdentifier;
|
||||
private InputMethodInfo mInputMethodInfo;
|
||||
private InputMethodSubtype mInputMethodSubtype;
|
||||
|
||||
private KeyboardLayout[] mKeyboardLayouts;
|
||||
private PreferenceScreen mScreen;
|
||||
private String mPreviousSelection;
|
||||
@@ -55,13 +60,16 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController
|
||||
mPreferenceMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public void initialize(Fragment parent, InputDeviceIdentifier inputDeviceIdentifier,
|
||||
String layout) {
|
||||
mLayout = layout;
|
||||
public void initialize(Fragment parent, int userId, InputDeviceIdentifier inputDeviceIdentifier,
|
||||
InputMethodInfo imeInfo, InputMethodSubtype imeSubtype, String layout) {
|
||||
mParent = parent;
|
||||
mUserId = userId;
|
||||
mInputDeviceIdentifier = inputDeviceIdentifier;
|
||||
mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
|
||||
Arrays.sort(mKeyboardLayouts);
|
||||
mInputMethodInfo = imeInfo;
|
||||
mInputMethodSubtype = imeSubtype;
|
||||
mLayout = layout;
|
||||
mKeyboardLayouts = mIm.getKeyboardLayoutListForInputDevice(
|
||||
inputDeviceIdentifier, userId, imeInfo, imeSubtype);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,15 +110,12 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController
|
||||
}
|
||||
|
||||
final KeyboardLayoutPreference pref = (KeyboardLayoutPreference) preference;
|
||||
// TODO(b/259530132): Need APIs to update the available keyboards for input device.
|
||||
// For example:
|
||||
// inputManager.setCurrentKeyboardLayoutForInputDevice(
|
||||
// InputDevice..., Userid..., ImeSubType ..., String keyboardLayoutDescriptor)
|
||||
pref.setCheckMark(true);
|
||||
if (mPreviousSelection != null && !mPreviousSelection.equals(preference.getKey())) {
|
||||
KeyboardLayoutPreference preSelectedPref = mScreen.findPreference(mPreviousSelection);
|
||||
pref.setCheckMark(true);
|
||||
preSelectedPref.setCheckMark(false);
|
||||
}
|
||||
setLayout(pref);
|
||||
mPreviousSelection = preference.getKey();
|
||||
return true;
|
||||
}
|
||||
@@ -129,13 +134,7 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int deviceId) {
|
||||
if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
|
||||
updateCheckedState();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCheckedState() {
|
||||
// TODO(b/259530132): Need API to update the keyboard language layout list.
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
private void createPreferenceHierarchy() {
|
||||
@@ -143,14 +142,22 @@ public class NewKeyboardLayoutPickerController extends BasePreferenceController
|
||||
final KeyboardLayoutPreference pref;
|
||||
if (mLayout.equals(layout.getLabel())) {
|
||||
pref = new KeyboardLayoutPreference(mScreen.getContext(), layout.getLabel(), true);
|
||||
mPreviousSelection = layout.getLabel();
|
||||
mPreviousSelection = layout.getDescriptor();
|
||||
} else {
|
||||
pref = new KeyboardLayoutPreference(mScreen.getContext(), layout.getLabel(), false);
|
||||
}
|
||||
// TODO: Waiting for new API to use a prefix with special number to setKey
|
||||
pref.setKey(layout.getLabel());
|
||||
pref.setKey(layout.getDescriptor());
|
||||
mScreen.addPreference(pref);
|
||||
mPreferenceMap.put(pref, layout);
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayout(KeyboardLayoutPreference preference) {
|
||||
mIm.setKeyboardLayoutForInputDevice(
|
||||
mInputDeviceIdentifier,
|
||||
mUserId,
|
||||
mInputMethodInfo,
|
||||
mInputMethodSubtype,
|
||||
mPreferenceMap.get(preference).getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,15 +27,6 @@ import com.android.settings.R;
|
||||
|
||||
public class NewKeyboardLayoutPickerFragment extends Fragment {
|
||||
|
||||
static final String EXTRA_TITLE = "keyboard_layout_picker_title";
|
||||
static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
|
||||
|
||||
/**
|
||||
* Intent extra: The input device descriptor of the keyboard whose keyboard
|
||||
* layout is to be changed.
|
||||
*/
|
||||
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
|
||||
|
||||
private ViewGroup mFragmentView;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.inputmethod;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utilities of keyboard settings
|
||||
*/
|
||||
public class NewKeyboardSettingsUtils {
|
||||
|
||||
static final String EXTRA_KEYBOARD_DEVICE_NAME = "extra_keyboard_device_name";
|
||||
static final String EXTRA_TITLE = "keyboard_layout_picker_title";
|
||||
static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
|
||||
static final String EXTRA_USER_ID = "user_id";
|
||||
static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
|
||||
static final String EXTRA_INPUT_METHOD_INFO = "input_method_info";
|
||||
static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype";
|
||||
|
||||
static InputMethodInfo getActiveIme(Context context, InputMethodManager imm) {
|
||||
InputMethodInfo activeIme = null;
|
||||
List<InputMethodInfo> infoList = imm.getEnabledInputMethodList();
|
||||
String imeId = Settings.Secure.getStringForUser(context.getContentResolver(),
|
||||
Settings.Secure.DEFAULT_INPUT_METHOD, context.getUserId());
|
||||
for (InputMethodInfo method : infoList) {
|
||||
if (method.getId().equals(imeId)) {
|
||||
activeIme = method;
|
||||
}
|
||||
}
|
||||
return activeIme;
|
||||
}
|
||||
|
||||
static List<String> getSuitableImeLabels(Context context, InputMethodManager imm, int userId) {
|
||||
List<String> suitableInputMethodInfoLabels = new ArrayList<>();
|
||||
List<InputMethodInfo> infoList = imm.getEnabledInputMethodListAsUser(userId);
|
||||
for (InputMethodInfo info : infoList) {
|
||||
List<InputMethodSubtype> subtypes =
|
||||
imm.getEnabledInputMethodSubtypeList(info, true);
|
||||
for (InputMethodSubtype subtype : subtypes) {
|
||||
if (subtype.isSuitableForPhysicalKeyboardLayoutMapping()) {
|
||||
suitableInputMethodInfoLabels.add(
|
||||
info.loadLabel(context.getPackageManager()).toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return suitableInputMethodInfoLabels;
|
||||
}
|
||||
|
||||
static class KeyboardInfo {
|
||||
String mLanguage;
|
||||
String mLayout;
|
||||
InputMethodInfo mInputMethodInfo;
|
||||
InputMethodSubtype mInputMethodSubtype;
|
||||
|
||||
KeyboardInfo(
|
||||
String language,
|
||||
String layout,
|
||||
InputMethodInfo inputMethodInfo,
|
||||
InputMethodSubtype inputMethodSubtype) {
|
||||
mLanguage = language;
|
||||
mLayout = layout;
|
||||
mInputMethodInfo = inputMethodInfo;
|
||||
mInputMethodSubtype = inputMethodSubtype;
|
||||
}
|
||||
|
||||
String getLanguage() {
|
||||
return mLanguage;
|
||||
}
|
||||
|
||||
String getLayout() {
|
||||
return mLayout;
|
||||
}
|
||||
|
||||
InputMethodInfo getInputMethodInfo() {
|
||||
return mInputMethodInfo;
|
||||
}
|
||||
|
||||
InputMethodSubtype getInputMethodSubtype() {
|
||||
return mInputMethodSubtype;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import android.provider.Settings.Secure;
|
||||
import android.text.TextUtils;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.view.InputDevice;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||
@@ -54,9 +55,7 @@ import com.android.settingslib.utils.ThreadUtils;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@SearchIndexable
|
||||
@@ -73,6 +72,7 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
||||
private final ArrayList<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
|
||||
|
||||
private InputManager mIm;
|
||||
private InputMethodManager mImm;
|
||||
@NonNull
|
||||
private PreferenceCategory mKeyboardAssistanceCategory;
|
||||
@NonNull
|
||||
@@ -90,6 +90,7 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
||||
mBluetoothAddress = activity.getIntent().getStringExtra(EXTRA_BT_ADDRESS);
|
||||
addPreferencesFromResource(R.xml.physical_keyboard_settings);
|
||||
mIm = Preconditions.checkNotNull(activity.getSystemService(InputManager.class));
|
||||
mImm = Preconditions.checkNotNull(activity.getSystemService(InputMethodManager.class));
|
||||
mKeyboardAssistanceCategory = Preconditions.checkNotNull(
|
||||
(PreferenceCategory) findPreference(KEYBOARD_OPTIONS_CATEGORY));
|
||||
mShowVirtualKeyboardSwitch = Preconditions.checkNotNull(
|
||||
@@ -194,21 +195,15 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
||||
final Preference pref = new Preference(getPrefContext());
|
||||
pref.setTitle(hardKeyboardDeviceInfo.mDeviceName);
|
||||
if (mIsNewKeyboardSettings) {
|
||||
// TODO(b/252816846): Need InputMethodManager to provide the enabled locales.
|
||||
// Hardcode Languages for demo until inputMethodManager provides the latest API.
|
||||
// For example: InputMethodManager.getEnabledInputMethodLocales();
|
||||
String[] keyboardLanguages =
|
||||
{"English (US)", "German (Germany)", "Spanish (Spain)"};
|
||||
String[] keyboardLayouts = {"English (US)", "German", "Spanish"};
|
||||
Map<String, String> keyboardMap = new HashMap<>();
|
||||
for (int i = 0; i < keyboardLanguages.length; i++) {
|
||||
keyboardMap.put(keyboardLanguages[i], keyboardLayouts[i]);
|
||||
}
|
||||
if (!keyboardMap.isEmpty()) {
|
||||
String summary = keyboardMap.get(keyboardLanguages[0]);
|
||||
List<String> suitableImes = new ArrayList<>();
|
||||
suitableImes.addAll(
|
||||
NewKeyboardSettingsUtils.getSuitableImeLabels(
|
||||
getContext(), mImm, UserHandle.myUserId()));
|
||||
if (!suitableImes.isEmpty()) {
|
||||
String summary = suitableImes.get(0);
|
||||
StringBuilder result = new StringBuilder(summary);
|
||||
for (int i = 1; i < keyboardLanguages.length; i++) {
|
||||
result.append(", ").append(keyboardMap.get(keyboardLanguages[i]));
|
||||
for (int i = 1; i < suitableImes.size(); i++) {
|
||||
result.append(", ").append(suitableImes.get(i));
|
||||
}
|
||||
pref.setSummary(result.toString());
|
||||
} else {
|
||||
@@ -245,12 +240,10 @@ public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
|
||||
|
||||
private void showEnabledLocalesKeyboardLayoutList(String keyboardName,
|
||||
InputDeviceIdentifier inputDeviceIdentifier) {
|
||||
// TODO(b/252816846: Need to get enabled locales.
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putParcelable(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
|
||||
arguments.putParcelable(NewKeyboardSettingsUtils.EXTRA_INPUT_DEVICE_IDENTIFIER,
|
||||
inputDeviceIdentifier);
|
||||
arguments.putString(NewKeyboardLayoutEnabledLocalesFragment.EXTRA_KEYBOARD_DEVICE_NAME,
|
||||
keyboardName);
|
||||
arguments.putString(NewKeyboardSettingsUtils.EXTRA_KEYBOARD_DEVICE_NAME, keyboardName);
|
||||
new SubSettingLauncher(getContext())
|
||||
.setSourceMetricsCategory(getMetricsCategory())
|
||||
.setDestination(NewKeyboardLayoutEnabledLocalesFragment.class.getName())
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.inputmethod;
|
||||
|
||||
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -97,8 +96,7 @@ public class TrackpadGestureDialogFragment extends BottomSheetDialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
mInflater = (LayoutInflater) mContext.getSystemService(
|
||||
LAYOUT_INFLATER_SERVICE);
|
||||
mInflater = mContext.getSystemService(LayoutInflater.class);
|
||||
|
||||
View gestureEducationView = mInflater.inflate(R.layout.trackpad_gesture_preview, null);
|
||||
addViewPager(gestureEducationView);
|
||||
|
||||
@@ -18,11 +18,7 @@ package com.android.settings.notification;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.widget.IllustrationPreference;
|
||||
import com.android.settingslib.widget.LottieColorUtils;
|
||||
|
||||
/**
|
||||
* Controller for the illustration shown for the feature level settings screen for bubbles.
|
||||
@@ -37,13 +33,4 @@ public class BubbleNotificationIllustrationPreferenceController extends BasePref
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
IllustrationPreference illustrationPreference = screen.findPreference(getPreferenceKey());
|
||||
illustrationPreference.setOnBindListener(animationView -> {
|
||||
LottieColorUtils.applyDynamicColors(mContext, animationView);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.safetycenter.SafetyEvent;
|
||||
import android.safetycenter.SafetySourceData;
|
||||
import android.safetycenter.SafetySourceStatus;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricNavigationUtils;
|
||||
import com.android.settings.biometrics.combination.CombinedBiometricStatusUtils;
|
||||
@@ -63,7 +62,7 @@ public final class BiometricsSafetySource {
|
||||
final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
|
||||
combinedBiometricStatusUtils.getDisablingAdmin();
|
||||
setBiometricSafetySourceData(context,
|
||||
context.getString(R.string.security_settings_biometric_preference_title),
|
||||
combinedBiometricStatusUtils.getTitle(),
|
||||
combinedBiometricStatusUtils.getSummary(),
|
||||
createPendingIntent(context,
|
||||
biometricNavigationUtils.getBiometricSettingsIntent(context,
|
||||
@@ -83,7 +82,7 @@ public final class BiometricsSafetySource {
|
||||
final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
|
||||
faceStatusUtils.getDisablingAdmin();
|
||||
setBiometricSafetySourceData(context,
|
||||
context.getString(R.string.security_settings_face_preference_title),
|
||||
faceStatusUtils.getTitle(),
|
||||
faceStatusUtils.getSummary(),
|
||||
createPendingIntent(context,
|
||||
biometricNavigationUtils.getBiometricSettingsIntent(context,
|
||||
@@ -105,7 +104,7 @@ public final class BiometricsSafetySource {
|
||||
final RestrictedLockUtils.EnforcedAdmin disablingAdmin =
|
||||
fingerprintStatusUtils.getDisablingAdmin();
|
||||
setBiometricSafetySourceData(context,
|
||||
context.getString(R.string.security_settings_fingerprint_preference_title),
|
||||
fingerprintStatusUtils.getTitle(),
|
||||
fingerprintStatusUtils.getSummary(),
|
||||
createPendingIntent(context,
|
||||
biometricNavigationUtils.getBiometricSettingsIntent(context,
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.safetycenter.SafetyEvent;
|
||||
import android.safetycenter.SafetySourceData;
|
||||
import android.safetycenter.SafetySourceIssue;
|
||||
@@ -56,6 +57,11 @@ public final class LockScreenSafetySource {
|
||||
return;
|
||||
}
|
||||
|
||||
UserManager userManager = context.getSystemService(UserManager.class);
|
||||
if (userManager != null && userManager.isProfile()) {
|
||||
return; // LockScreen source only supports primary profile.
|
||||
}
|
||||
|
||||
if (!screenLockPreferenceDetailsUtils.isAvailable()) {
|
||||
return;
|
||||
}
|
||||
@@ -138,6 +144,12 @@ public final class LockScreenSafetySource {
|
||||
SET_SCREEN_LOCK_ACTION_ID,
|
||||
context.getString(R.string.no_screen_lock_issue_action_label),
|
||||
pendingIntent).build();
|
||||
// Custom notification deliberately has zero actions
|
||||
final SafetySourceIssue.Notification customNotification =
|
||||
new SafetySourceIssue.Notification.Builder(
|
||||
context.getString(R.string.no_screen_lock_issue_notification_title),
|
||||
context.getString(R.string.no_screen_lock_issue_notification_text))
|
||||
.build();
|
||||
return new SafetySourceIssue.Builder(
|
||||
NO_SCREEN_LOCK_ISSUE_ID,
|
||||
context.getString(R.string.no_screen_lock_issue_title),
|
||||
@@ -145,6 +157,10 @@ public final class LockScreenSafetySource {
|
||||
SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
|
||||
NO_SCREEN_LOCK_ISSUE_TYPE_ID)
|
||||
.setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
|
||||
.addAction(action).build();
|
||||
.addAction(action)
|
||||
.setIssueActionability(SafetySourceIssue.ISSUE_ACTIONABILITY_MANUAL)
|
||||
.setCustomNotification(customNotification)
|
||||
.setNotificationBehavior(SafetySourceIssue.NOTIFICATION_BEHAVIOR_DELAYED)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.framework.util.filterItem
|
||||
@@ -48,6 +48,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
object AllAppListPageProvider : SettingsPageProvider {
|
||||
override val name = "AllAppList"
|
||||
private val owner = createSettingsPage()
|
||||
|
||||
@Composable
|
||||
override fun Page(arguments: Bundle?) {
|
||||
@@ -55,7 +56,7 @@ object AllAppListPageProvider : SettingsPageProvider {
|
||||
}
|
||||
|
||||
fun buildInjectEntry() = SettingsEntryBuilder
|
||||
.createInject(owner = SettingsPage.create(name))
|
||||
.createInject(owner)
|
||||
.setSearchDataFn { null }
|
||||
.setUiLayoutFn {
|
||||
Preference(object : PreferenceModel {
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
@@ -36,13 +37,17 @@ private const val TAG = "AppPermissionPreference"
|
||||
private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
|
||||
|
||||
@Composable
|
||||
fun AppPermissionPreference(app: ApplicationInfo) {
|
||||
fun AppPermissionPreference(
|
||||
app: ApplicationInfo,
|
||||
summaryLiveData: LiveData<AppPermissionSummaryState> = rememberAppPermissionSummary(app),
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val summaryLiveData = remember { AppPermissionSummaryLiveData(context, app) }
|
||||
val summaryState = summaryLiveData.observeAsState(initial = AppPermissionSummaryState(
|
||||
summary = stringResource(R.string.summary_placeholder),
|
||||
enabled = false,
|
||||
))
|
||||
val summaryState = summaryLiveData.observeAsState(
|
||||
initial = AppPermissionSummaryState(
|
||||
summary = stringResource(R.string.summary_placeholder),
|
||||
enabled = false,
|
||||
)
|
||||
)
|
||||
Preference(
|
||||
model = remember {
|
||||
object : PreferenceModel {
|
||||
|
||||
@@ -20,6 +20,9 @@ import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager.OnPermissionsChangedListener
|
||||
import android.icu.text.ListFormatter
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.applications.PermissionsSummaryHelper
|
||||
@@ -33,6 +36,12 @@ data class AppPermissionSummaryState(
|
||||
val enabled: Boolean,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun rememberAppPermissionSummary(app: ApplicationInfo): AppPermissionSummaryLiveData {
|
||||
val context = LocalContext.current
|
||||
return remember { AppPermissionSummaryLiveData(context, app) }
|
||||
}
|
||||
|
||||
class AppPermissionSummaryLiveData(
|
||||
private val context: Context,
|
||||
private val app: ApplicationInfo,
|
||||
|
||||
@@ -40,8 +40,8 @@ import com.android.settings.R
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settings.spa.app.startUninstallActivity
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||
@@ -74,6 +74,7 @@ const val BACKGROUND_INSTALL_CONTROL_FLAG = PackageManager.MATCH_ALL.toLong()
|
||||
|
||||
object BackgroundInstalledAppsPageProvider : SettingsPageProvider {
|
||||
override val name = "BackgroundInstalledAppsPage"
|
||||
private val owner = createSettingsPage()
|
||||
private var backgroundInstallService = IBackgroundInstallControlService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE))
|
||||
private var featureIsDisabled = featureIsDisabled()
|
||||
@@ -95,7 +96,7 @@ object BackgroundInstalledAppsPageProvider : SettingsPageProvider {
|
||||
}
|
||||
|
||||
fun buildInjectEntry() = SettingsEntryBuilder
|
||||
.createInject(owner = SettingsPage.create(name))
|
||||
.createInject(owner)
|
||||
.setSearchDataFn { null }
|
||||
.setUiLayoutFn { EntryItem() }
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntry
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
@@ -31,6 +31,7 @@ import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
||||
|
||||
object SpecialAppAccessPageProvider : SettingsPageProvider {
|
||||
override val name = "SpecialAppAccess"
|
||||
private val owner = createSettingsPage()
|
||||
|
||||
@Composable
|
||||
override fun Page(arguments: Bundle?) {
|
||||
@@ -51,10 +52,9 @@ object SpecialAppAccessPageProvider : SettingsPageProvider {
|
||||
)
|
||||
}
|
||||
|
||||
fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
|
||||
fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner)
|
||||
|
||||
override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
|
||||
val owner = SettingsPage.create(name, parameter = parameter, arguments = arguments)
|
||||
return listOf(
|
||||
AllFilesAccessAppListProvider,
|
||||
DisplayOverOtherAppsAppListProvider,
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -67,9 +68,7 @@ public class TimeoutToDockUserPreferenceController extends BasePreferenceControl
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
// Is currently user zero. Only non user zero can have this setting.
|
||||
// TODO(b/257333623): Allow the Dock User to be non-SystemUser user in HSUM.
|
||||
if (UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
|
||||
if (Utils.canCurrentUserDream(mContext)) {
|
||||
return DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.DiskInfo;
|
||||
import android.os.storage.StorageManager;
|
||||
@@ -299,4 +300,43 @@ public class UtilsTest {
|
||||
|
||||
assertThat(Utils.isSettingsIntelligence(mContext)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCurrentUserDream_isMainUser_returnTrue() {
|
||||
Context mockContext = mock(Context.class);
|
||||
UserManager mockUserManager = mock(UserManager.class);
|
||||
|
||||
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
|
||||
|
||||
// mock MainUser
|
||||
UserHandle mainUser = new UserHandle(10);
|
||||
when(mockUserManager.getMainUser()).thenReturn(mainUser);
|
||||
when(mockUserManager.isUserForeground()).thenReturn(true);
|
||||
|
||||
when(mockContext.createContextAsUser(mainUser, 0)).thenReturn(mockContext);
|
||||
|
||||
assertThat(Utils.canCurrentUserDream(mockContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCurrentUserDream_nullMainUser_returnFalse() {
|
||||
Context mockContext = mock(Context.class);
|
||||
UserManager mockUserManager = mock(UserManager.class);
|
||||
|
||||
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
|
||||
when(mockUserManager.getMainUser()).thenReturn(null);
|
||||
|
||||
assertThat(Utils.canCurrentUserDream(mockContext)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCurrentUserDream_notMainUser_returnFalse() {
|
||||
Context mockContext = mock(Context.class);
|
||||
UserManager mockUserManager = mock(UserManager.class);
|
||||
|
||||
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
|
||||
when(mockUserManager.isUserForeground()).thenReturn(false);
|
||||
|
||||
assertThat(Utils.canCurrentUserDream(mockContext)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.settings.biometrics.face.FaceEnrollIntroduction;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
||||
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowPackageManager;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowUtils.class,
|
||||
ShadowUserManager.class,
|
||||
ShadowRestrictedLockUtilsInternal.class,
|
||||
ShadowSensorPrivacyManager.class,
|
||||
ShadowLockPatternUtils.class
|
||||
})
|
||||
public class MultiBiometricEnrollHelperTest {
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
private FragmentActivity mActivity;
|
||||
@Mock
|
||||
private FingerprintManager mFingerprintManager;
|
||||
@Mock
|
||||
private FaceManager mFaceManager;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<FingerprintManager.GenerateChallengeCallback> mFingerprintCaptor;
|
||||
|
||||
private final int mUserId = 10;
|
||||
private final long mChallenge = 0L;
|
||||
private final int mSensorId = 0;
|
||||
private final long mGkPwHandle = 0L;
|
||||
|
||||
private MultiBiometricEnrollHelper mMultiBiometricEnrollHelper;
|
||||
private Intent mFingerprintIntent;
|
||||
private Intent mFaceIntent;
|
||||
|
||||
@Before
|
||||
public void setUp() throws RemoteException {
|
||||
mContext = RuntimeEnvironment.application.getApplicationContext();
|
||||
mFingerprintIntent = new Intent(mContext, FingerprintEnrollIntroduction.class);
|
||||
mFaceIntent = new Intent(mContext, FaceEnrollIntroduction.class);
|
||||
mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper(
|
||||
mActivity, mUserId, true /* enrollFace */, true /* enrollFingerprint */,
|
||||
mGkPwHandle, mFingerprintManager, mFaceManager, mFingerprintIntent, mFaceIntent,
|
||||
(challenge) -> null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchFaceAndFingerprintEnroll_testFingerprint() {
|
||||
mMultiBiometricEnrollHelper.startNextStep();
|
||||
|
||||
verify(mFingerprintManager).generateChallenge(anyInt(), mFingerprintCaptor.capture());
|
||||
|
||||
FingerprintManager.GenerateChallengeCallback generateChallengeCallback =
|
||||
mFingerprintCaptor.getValue();
|
||||
generateChallengeCallback.onChallengeGenerated(mSensorId, mUserId, mChallenge);
|
||||
|
||||
assertThat(mFingerprintIntent.hasExtra(
|
||||
MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT)).isTrue();
|
||||
assertThat(mFingerprintIntent.getExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID,
|
||||
-1 /* defaultValue */)).isEqualTo(mSensorId);
|
||||
assertThat(mFingerprintIntent.getExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE,
|
||||
-1 /* defaultValue */)).isEqualTo(mChallenge);
|
||||
assertThat(mFingerprintIntent.getExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
|
||||
-1 /* defaultValue */)).isEqualTo(mGkPwHandle);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchFaceAndFingerprintEnroll_testFace() {
|
||||
mMultiBiometricEnrollHelper.startNextStep();
|
||||
|
||||
verify(mFingerprintManager).generateChallenge(anyInt(), mFingerprintCaptor.capture());
|
||||
|
||||
FingerprintManager.GenerateChallengeCallback fingerprintGenerateChallengeCallback =
|
||||
mFingerprintCaptor.getValue();
|
||||
fingerprintGenerateChallengeCallback.onChallengeGenerated(
|
||||
mSensorId, mUserId, mChallenge);
|
||||
|
||||
assertThat(mFaceIntent.getExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
|
||||
-1 /* defaultValue */)).isEqualTo(mGkPwHandle);
|
||||
assertThat(mFaceIntent.getIntExtra(Intent.EXTRA_USER_ID, -1 /* defaultValue */))
|
||||
.isEqualTo(mUserId);
|
||||
|
||||
final ShadowPackageManager shadowPackageManager = shadowOf(mContext.getPackageManager());
|
||||
shadowPackageManager.setSystemFeature(PackageManager.FEATURE_FACE, true);
|
||||
ShadowUtils.setFaceManager(mFaceManager);
|
||||
ActivityController.of(new FaceEnrollIntroduction(), mFaceIntent)
|
||||
.create(mFaceIntent.getExtras()).get();
|
||||
|
||||
verify(mFaceManager).generateChallenge(eq(mUserId), any());
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,8 @@ import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENT
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -38,9 +37,9 @@ import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.InstallSourceInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
@@ -79,6 +78,8 @@ import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowEntityHeaderController.class, ShadowActivityManager.class})
|
||||
public class AdvancedPowerUsageDetailTest {
|
||||
@@ -116,12 +117,12 @@ public class AdvancedPowerUsageDetailTest {
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private InstallSourceInfo mInstallSourceInfo;
|
||||
@Mock
|
||||
private AppOpsManager mAppOpsManager;
|
||||
@Mock
|
||||
private LoaderManager mLoaderManager;
|
||||
@Mock
|
||||
private BatteryUtils mBatteryUtils;
|
||||
@Mock
|
||||
private BatteryOptimizeUtils mBatteryOptimizeUtils;
|
||||
@Mock
|
||||
private BackupManager mBackupManager;
|
||||
@@ -179,7 +180,6 @@ public class AdvancedPowerUsageDetailTest {
|
||||
|
||||
mFragment.mHeaderPreference = mHeaderPreference;
|
||||
mFragment.mState = mState;
|
||||
mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application);
|
||||
mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
|
||||
mFragment.mBackupManager = mBackupManager;
|
||||
mFragment.mLogStringBuilder = new StringBuilder();
|
||||
@@ -190,10 +190,6 @@ public class AdvancedPowerUsageDetailTest {
|
||||
doReturn(mPackageManager).when(mActivity).getPackageManager();
|
||||
doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE);
|
||||
|
||||
mBatteryUtils = spy(new BatteryUtils(mContext));
|
||||
doReturn(FOREGROUND_SERVICE_TIME_US).when(mBatteryUtils).getForegroundServiceTotalTimeUs(
|
||||
any(BatteryStats.Uid.class), anyLong());
|
||||
|
||||
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
|
||||
Answer<Void> callable = invocation -> {
|
||||
@@ -757,34 +753,46 @@ public class AdvancedPowerUsageDetailTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPause_optimizationModeChanged_logPreference() {
|
||||
public void onPause_optimizationModeChanged_logPreference()
|
||||
throws PackageManager.NameNotFoundException, InterruptedException {
|
||||
final String packageName = "testPackageName";
|
||||
final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
|
||||
mFragment.mOptimizationMode = mode;
|
||||
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
|
||||
when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
|
||||
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
|
||||
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
|
||||
|
||||
mFragment.onRadioButtonClicked(mOptimizePreference);
|
||||
mFragment.onPause();
|
||||
|
||||
TimeUnit.SECONDS.sleep(100);
|
||||
verify(mMetricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.OPEN_APP_BATTERY_USAGE,
|
||||
SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED,
|
||||
SettingsEnums.OPEN_APP_BATTERY_USAGE,
|
||||
/* package name*/ "none",
|
||||
packageName,
|
||||
/* consumed battery */ 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPause_optimizationModeIsNotChanged_notInvokeLogging() {
|
||||
public void onPause_optimizationModeIsNotChanged_notInvokeLogging()
|
||||
throws PackageManager.NameNotFoundException, InterruptedException {
|
||||
final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED;
|
||||
mFragment.mOptimizationMode = mode;
|
||||
when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
|
||||
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
|
||||
mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
|
||||
|
||||
mFragment.onRadioButtonClicked(mOptimizePreference);
|
||||
mFragment.onPause();
|
||||
|
||||
TimeUnit.SECONDS.sleep(100);
|
||||
verifyNoInteractions(mMetricsFeatureProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.inputmethod;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link TrackpadBottomPreferenceController} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TrackpadBottomPreferenceControllerTest {
|
||||
|
||||
private static final String PREFERENCE_KEY = "trackpad_bottom_right_tap";
|
||||
private static final String SETTING_KEY = Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE;
|
||||
|
||||
private Context mContext;
|
||||
private TrackpadBottomPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new TrackpadBottomPreferenceController(mContext, PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_expected() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSliceHighlightMenuRes_expected() {
|
||||
assertThat(mController.getSliceHighlightMenuRes()).isEqualTo(R.string.menu_key_system);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_true_shouldReturn1() {
|
||||
mController.setChecked(true);
|
||||
|
||||
int result = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
assertThat(result).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_false_shouldReturn0() {
|
||||
mController.setChecked(false);
|
||||
|
||||
int result = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
assertThat(result).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_providerPutInt1_returnTrue() {
|
||||
Settings.System.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
1,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
boolean result = mController.isChecked();
|
||||
|
||||
assertThat(result).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_providerPutInt0_returnFalse() {
|
||||
Settings.System.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
boolean result = mController.isChecked();
|
||||
|
||||
assertThat(result).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.inputmethod;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link TrackpadPointerSpeedPreferenceController} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TrackpadPointerSpeedPreferenceControllerTest {
|
||||
|
||||
private static final String PREFERENCE_KEY = "trackpad_pointer_speed";
|
||||
private static final String SETTING_KEY = Settings.System.TOUCHPAD_POINTER_SPEED;
|
||||
|
||||
private Context mContext;
|
||||
private TrackpadPointerSpeedPreferenceController mController;
|
||||
private int mDefaultSpeed;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new TrackpadPointerSpeedPreferenceController(mContext, PREFERENCE_KEY);
|
||||
mDefaultSpeed = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
InputManager.DEFAULT_POINTER_SPEED,
|
||||
UserHandle.USER_CURRENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_expected() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMin_expected() {
|
||||
assertThat(mController.getMin()).isEqualTo(InputManager.MIN_POINTER_SPEED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMax_expected() {
|
||||
assertThat(mController.getMax()).isEqualTo(InputManager.MAX_POINTER_SPEED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSliderPosition_defaultSpeed_return0() {
|
||||
int result = mController.getSliderPosition();
|
||||
|
||||
assertThat(result).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSliderPosition_speedValue1_shouldReturnTrue() {
|
||||
int inputSpeed = 1;
|
||||
|
||||
boolean result = mController.setSliderPosition(inputSpeed);
|
||||
|
||||
assertThat(result).isTrue();
|
||||
assertThat(mController.getSliderPosition()).isEqualTo(inputSpeed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSliderPosition_speedValueOverMaxValue_shouldReturnFalse() {
|
||||
int inputSpeed = InputManager.MAX_POINTER_SPEED + 1;
|
||||
|
||||
boolean result = mController.setSliderPosition(inputSpeed);
|
||||
|
||||
assertThat(result).isFalse();
|
||||
assertThat(mController.getSliderPosition()).isEqualTo(mDefaultSpeed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSliderPosition_speedValueOverMinValue_shouldReturnFalse() {
|
||||
int inputSpeed = InputManager.MIN_POINTER_SPEED - 1;
|
||||
|
||||
boolean result = mController.setSliderPosition(inputSpeed);
|
||||
|
||||
assertThat(result).isFalse();
|
||||
assertThat(mController.getSliderPosition()).isEqualTo(mDefaultSpeed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.inputmethod;
|
||||
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link TrackpadReverseScrollingPreferenceController} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TrackpadReverseScrollingPreferenceControllerTest {
|
||||
|
||||
private static final String PREFERENCE_KEY = "trackpad_reverse_scrolling";
|
||||
private static final String SETTING_KEY = Settings.System.TOUCHPAD_NATURAL_SCROLLING;
|
||||
|
||||
private Context mContext;
|
||||
private TrackpadReverseScrollingPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new TrackpadReverseScrollingPreferenceController(mContext, PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_expected() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSliceHighlightMenuRes_expected() {
|
||||
assertThat(mController.getSliceHighlightMenuRes()).isEqualTo(R.string.menu_key_system);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_true_shouldReturn1() {
|
||||
mController.setChecked(true);
|
||||
|
||||
int result = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
assertThat(result).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_false_shouldReturn0() {
|
||||
mController.setChecked(false);
|
||||
|
||||
int result = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
assertThat(result).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_providerPutInt1_returnTrue() {
|
||||
Settings.System.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
1,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
boolean result = mController.isChecked();
|
||||
|
||||
assertThat(result).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_providerPutInt0_returnFalse() {
|
||||
Settings.System.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
boolean result = mController.isChecked();
|
||||
|
||||
assertThat(result).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.inputmethod;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Tests for {@link TrackpadTapToClickPreferenceController} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TrackpadTapToClickPreferenceControllerTest {
|
||||
|
||||
private static final String PREFERENCE_KEY = "trackpad_tap_to_click";
|
||||
private static final String SETTING_KEY = Settings.System.TOUCHPAD_TAP_TO_CLICK;
|
||||
|
||||
private Context mContext;
|
||||
private TrackpadTapToClickPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new TrackpadTapToClickPreferenceController(mContext, PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_expected() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSliceHighlightMenuRes_expected() {
|
||||
assertThat(mController.getSliceHighlightMenuRes()).isEqualTo(R.string.menu_key_system);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_true_shouldReturn1() {
|
||||
mController.setChecked(true);
|
||||
|
||||
int result = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
assertThat(result).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_false_shouldReturn0() {
|
||||
mController.setChecked(false);
|
||||
|
||||
int result = Settings.System.getIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
assertThat(result).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_providerPutInt1_returnTrue() {
|
||||
Settings.System.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
1,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
boolean result = mController.isChecked();
|
||||
|
||||
assertThat(result).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isChecked_providerPutInt0_returnFalse() {
|
||||
Settings.System.putIntForUser(
|
||||
mContext.getContentResolver(),
|
||||
SETTING_KEY,
|
||||
0,
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
boolean result = mController.isChecked();
|
||||
|
||||
assertThat(result).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import android.provider.Settings;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.fuelgauge.BatteryBackupHelperTest.ShadowUserHandle;
|
||||
import com.android.settings.testutils.shadow.ShadowSecureSettings;
|
||||
@@ -106,15 +107,17 @@ public class TimeoutToDockUserPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_isCurrentlyUserZero_returnDisabledForUser() {
|
||||
ShadowUserHandle.setUid(UserHandle.USER_SYSTEM);
|
||||
public void getAvailabilityStatus_isCurrentlyMainUser_returnDisabledForUser() {
|
||||
when(Utils.canCurrentUserDream(mContext)).thenReturn(true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.DISABLED_FOR_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_featureAndMultiUserEnabledAndNonUserZero_returnAvailable() {
|
||||
public void getAvailabilityStatus_featureAndMultiUserEnabledAndNonMainUser_returnAvailable() {
|
||||
when(Utils.canCurrentUserDream(mContext)).thenReturn(false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(
|
||||
BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.spa.app.appinfo
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.onRoot
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.testutils.delay
|
||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.doNothing
|
||||
import org.mockito.Mockito.eq
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Spy
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AppPermissionPreferenceTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
@get:Rule
|
||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@Test
|
||||
fun title_display() {
|
||||
setContent()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.permissions_label))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenClick_startActivity() {
|
||||
doNothing().`when`(context).startActivityAsUser(any(), any())
|
||||
|
||||
setContent()
|
||||
composeTestRule.onRoot().performClick()
|
||||
composeTestRule.delay()
|
||||
|
||||
val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
|
||||
verify(context).startActivityAsUser(intentCaptor.capture(), eq(APP.userHandle))
|
||||
val intent = intentCaptor.value
|
||||
assertThat(intent.action).isEqualTo(Intent.ACTION_MANAGE_APP_PERMISSIONS)
|
||||
assertThat(intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE_NAME)
|
||||
assertThat(intent.getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)).isEqualTo(true)
|
||||
}
|
||||
|
||||
private fun setContent() {
|
||||
composeTestRule.setContent {
|
||||
CompositionLocalProvider(LocalContext provides context) {
|
||||
AppPermissionPreference(
|
||||
app = APP,
|
||||
summaryLiveData = MutableLiveData(
|
||||
AppPermissionSummaryState(summary = SUMMARY, enabled = true)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
composeTestRule.delay()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val PACKAGE_NAME = "package.name"
|
||||
const val SUMMARY = "Summary"
|
||||
private const val EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"
|
||||
|
||||
val APP = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.os.UserManager;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -41,6 +42,7 @@ public class CommunalPreferenceControllerTest {
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
private Context mContext;
|
||||
private Resources mResources;
|
||||
private CommunalPreferenceController mController;
|
||||
|
||||
@@ -49,33 +51,33 @@ public class CommunalPreferenceControllerTest {
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
final Context context = spy(ApplicationProvider.getApplicationContext());
|
||||
mResources = spy(context.getResources());
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mResources = spy(mContext.getResources());
|
||||
|
||||
mController = new CommunalPreferenceController(context, PREF_KEY);
|
||||
mController = new CommunalPreferenceController(mContext, PREF_KEY);
|
||||
|
||||
when(context.getResources()).thenReturn(mResources);
|
||||
when(context.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_communalEnabled_shouldBeTrueForSystemUser() {
|
||||
public void isAvailable_communalEnabled_shouldBeTrueForDockUser() {
|
||||
setCommunalEnabled(true);
|
||||
when(mUserManager.isSystemUser()).thenReturn(true);
|
||||
when(Utils.canCurrentUserDream(mContext)).thenReturn(true);
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_communalEnabled_shouldBeFalseForNonSystemUser() {
|
||||
public void isAvailable_communalEnabled_shouldBeFalseForNonDockUser() {
|
||||
setCommunalEnabled(true);
|
||||
when(mUserManager.isSystemUser()).thenReturn(false);
|
||||
when(Utils.canCurrentUserDream(mContext)).thenReturn(false);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_communalDisabled_shouldBeFalseForSystemUser() {
|
||||
public void isAvailable_communalDisabled_shouldBeFalseForDockUser() {
|
||||
setCommunalEnabled(false);
|
||||
when(mUserManager.isSystemUser()).thenReturn(true);
|
||||
when(Utils.canCurrentUserDream(mContext)).thenReturn(true);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user