Snap for 12587146 from 2977bc7825
to 25Q1-release
Change-Id: Iafb0e27e4472861e6dde58785800d1141e11274a
This commit is contained in:
@@ -79,6 +79,7 @@ android_library {
|
|||||||
"BiometricsSharedLib",
|
"BiometricsSharedLib",
|
||||||
"SystemUIUnfoldLib",
|
"SystemUIUnfoldLib",
|
||||||
"WifiTrackerLib",
|
"WifiTrackerLib",
|
||||||
|
"android.hardware.biometrics.flags-aconfig-java",
|
||||||
"android.hardware.dumpstate-V1-java",
|
"android.hardware.dumpstate-V1-java",
|
||||||
"android.hardware.dumpstate-V1.0-java",
|
"android.hardware.dumpstate-V1.0-java",
|
||||||
"android.hardware.dumpstate-V1.1-java",
|
"android.hardware.dumpstate-V1.1-java",
|
||||||
|
@@ -3365,6 +3365,21 @@
|
|||||||
android:value="@string/menu_key_battery"/>
|
android:value="@string/menu_key_battery"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="Settings$PowerUsageAdvancedActivity"
|
||||||
|
android:label="@string/advanced_battery_title"
|
||||||
|
android:exported="true"
|
||||||
|
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize">
|
||||||
|
<intent-filter android:priority="1">
|
||||||
|
<action android:name="com.android.settings.battery.action.POWER_USAGE_ADVANCED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||||
|
android:value="com.android.settings.fuelgauge.batteryusage.PowerUsageAdvanced" />
|
||||||
|
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
|
||||||
|
android:value="@string/menu_key_battery"/>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".fuelgauge.batteryusage.BatteryUsageContentProvider"
|
android:name=".fuelgauge.batteryusage.BatteryUsageContentProvider"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
@@ -15,3 +15,9 @@ flag {
|
|||||||
bug: "323791114"
|
bug: "323791114"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flag {
|
||||||
|
name: "catalyst_my_device_info_pref_screen"
|
||||||
|
namespace: "android_settings"
|
||||||
|
description: "Flag for About phone"
|
||||||
|
bug: "323791114"
|
||||||
|
}
|
||||||
|
@@ -22,6 +22,13 @@ flag {
|
|||||||
bug: "323791114"
|
bug: "323791114"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flag {
|
||||||
|
name: "catalyst_tether_settings"
|
||||||
|
namespace: "android_settings"
|
||||||
|
description: "Flag for Hotspot & tethering"
|
||||||
|
bug: "323791114"
|
||||||
|
}
|
||||||
|
|
||||||
flag {
|
flag {
|
||||||
name: "catalyst_adaptive_connectivity"
|
name: "catalyst_adaptive_connectivity"
|
||||||
namespace: "android_settings"
|
namespace: "android_settings"
|
||||||
|
@@ -1234,6 +1234,16 @@
|
|||||||
<string name="security_settings_fingerprint_bad_calibration_title">Can\u2019t use fingerprint sensor</string>
|
<string name="security_settings_fingerprint_bad_calibration_title">Can\u2019t use fingerprint sensor</string>
|
||||||
<!-- Text shown during fingerprint enrollment to indicate bad sensor calibration. [CHAR LIMIT=100] -->
|
<!-- Text shown during fingerprint enrollment to indicate bad sensor calibration. [CHAR LIMIT=100] -->
|
||||||
<string name="security_settings_fingerprint_bad_calibration">Visit a repair provider.</string>
|
<string name="security_settings_fingerprint_bad_calibration">Visit a repair provider.</string>
|
||||||
|
|
||||||
|
<!-- Key for screen off udfps unlock feature. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="security_settings_screen_off_unlock_udfps_key" translatable="false">security_settings_screen_off_unlock_udfps</string>
|
||||||
|
<!-- Title for Key for screen off udfps unlock feature. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="security_settings_screen_off_unlock_udfps_title">Screen-off Fingerprint Unlock</string>
|
||||||
|
<!-- Description for screen off udfps unlock feature. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="security_settings_screen_off_unlock_udfps_description">Use Fingerprint Unlock even when the screen is off</string>
|
||||||
|
<!-- Description for screen off udfps unlock feature. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="security_settings_screen_off_unlock_udfps_keywords">Screen-off, Unlock</string>
|
||||||
|
|
||||||
<!-- Title for the section that has additional security settings. [CHAR LIMIT=60] -->
|
<!-- Title for the section that has additional security settings. [CHAR LIMIT=60] -->
|
||||||
<string name="security_advanced_settings">More security settings</string>
|
<string name="security_advanced_settings">More security settings</string>
|
||||||
<!-- String for the "More security settings" summary when a work profile is on the device. [CHAR_LIMIT=NONE] -->
|
<!-- String for the "More security settings" summary when a work profile is on the device. [CHAR_LIMIT=NONE] -->
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
<com.android.settingslib.RestrictedPreference
|
<com.android.settingslib.RestrictedPreference
|
||||||
android:key="@string/preference_key_brightness_level"
|
android:key="@string/preference_key_brightness_level"
|
||||||
android:title="@string/brightness"
|
android:title="@string/brightness"
|
||||||
|
android:persistent="false"
|
||||||
settings:keywords="@string/keywords_display_brightness_level"
|
settings:keywords="@string/keywords_display_brightness_level"
|
||||||
settings:useAdminDisabledSummary="true"
|
settings:useAdminDisabledSummary="true"
|
||||||
settings:userRestriction="no_config_brightness"/>
|
settings:userRestriction="no_config_brightness"/>
|
||||||
|
@@ -56,7 +56,7 @@
|
|||||||
settings:controller="com.android.settings.network.MobileNetworkSummaryController" />
|
settings:controller="com.android.settings.network.MobileNetworkSummaryController" />
|
||||||
|
|
||||||
<com.android.settingslib.RestrictedSwitchPreference
|
<com.android.settingslib.RestrictedSwitchPreference
|
||||||
android:key="airplane_mode"
|
android:key="airplane_mode_on"
|
||||||
android:title="@string/airplane_mode"
|
android:title="@string/airplane_mode"
|
||||||
android:icon="@drawable/ic_airplanemode_active"
|
android:icon="@drawable/ic_airplanemode_active"
|
||||||
android:order="-5"
|
android:order="-5"
|
||||||
|
@@ -40,7 +40,16 @@
|
|||||||
android:title="@string/security_settings_require_screen_on_to_auth_title"
|
android:title="@string/security_settings_require_screen_on_to_auth_title"
|
||||||
android:summary="@string/security_settings_require_screen_on_to_auth_description"
|
android:summary="@string/security_settings_require_screen_on_to_auth_description"
|
||||||
settings:keywords="@string/security_settings_require_screen_on_to_auth_keywords"
|
settings:keywords="@string/security_settings_require_screen_on_to_auth_keywords"
|
||||||
settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController" />
|
settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController"
|
||||||
|
settings:isPreferenceVisible="false"/>
|
||||||
|
|
||||||
|
<com.android.settingslib.RestrictedSwitchPreference
|
||||||
|
android:key="@string/security_settings_screen_off_unlock_udfps_key"
|
||||||
|
android:title="@string/security_settings_screen_off_unlock_udfps_title"
|
||||||
|
android:summary="@string/security_settings_screen_off_unlock_udfps_description"
|
||||||
|
settings:keywords="@string/security_settings_screen_off_unlock_udfps_keywords"
|
||||||
|
settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsScreenOffUnlockUdfpsPreferenceController"
|
||||||
|
settings:isPreferenceVisible="false"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
|
|
||||||
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
@@ -25,6 +27,7 @@ import android.app.admin.FactoryResetProtectionPolicy;
|
|||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -33,6 +36,7 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.service.oemlock.OemLockManager;
|
import android.service.oemlock.OemLockManager;
|
||||||
import android.service.persistentdata.PersistentDataBlockManager;
|
import android.service.persistentdata.PersistentDataBlockManager;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -42,6 +46,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
|
|
||||||
import com.android.settings.core.InstrumentedFragment;
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
|
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
|
||||||
|
import com.android.settings.network.telephony.SubscriptionActionDialogActivity;
|
||||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||||
|
|
||||||
import com.google.android.setupcompat.template.FooterBarMixin;
|
import com.google.android.setupcompat.template.FooterBarMixin;
|
||||||
@@ -90,7 +95,7 @@ public class MainClearConfirm extends InstrumentedFragment {
|
|||||||
} else {
|
} else {
|
||||||
pdbManager = null;
|
pdbManager = null;
|
||||||
}
|
}
|
||||||
|
setSimDialogProgressState();
|
||||||
if (shouldWipePersistentDataBlock(pdbManager)) {
|
if (shouldWipePersistentDataBlock(pdbManager)) {
|
||||||
|
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@@ -128,6 +133,17 @@ public class MainClearConfirm extends InstrumentedFragment {
|
|||||||
} else {
|
} else {
|
||||||
doMainClear();
|
doMainClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSimDialogProgressState() {
|
||||||
|
if (getActivity() != null) {
|
||||||
|
final SharedPreferences prefs = getActivity().getSharedPreferences(
|
||||||
|
SubscriptionActionDialogActivity.SIM_ACTION_DIALOG_PREFS, MODE_PRIVATE);
|
||||||
|
prefs.edit().putInt(SubscriptionActionDialogActivity.KEY_PROGRESS_STATE,
|
||||||
|
SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING).apply();
|
||||||
|
Log.d(TAG, "SIM dialog setProgressState: 1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProgressDialog getProgressDialog() {
|
private ProgressDialog getProgressDialog() {
|
||||||
|
@@ -484,6 +484,7 @@ public class Settings extends SettingsActivity {
|
|||||||
public static class NetworkDashboardActivity extends SettingsActivity {}
|
public static class NetworkDashboardActivity extends SettingsActivity {}
|
||||||
public static class ConnectedDeviceDashboardActivity extends SettingsActivity {}
|
public static class ConnectedDeviceDashboardActivity extends SettingsActivity {}
|
||||||
public static class PowerUsageSummaryActivity extends SettingsActivity { /* empty */ }
|
public static class PowerUsageSummaryActivity extends SettingsActivity { /* empty */ }
|
||||||
|
public static class PowerUsageAdvancedActivity extends SettingsActivity { /* empty */ }
|
||||||
public static class StorageDashboardActivity extends SettingsActivity {}
|
public static class StorageDashboardActivity extends SettingsActivity {}
|
||||||
public static class AccountDashboardActivity extends SettingsActivity {}
|
public static class AccountDashboardActivity extends SettingsActivity {}
|
||||||
public static class SystemDashboardActivity extends SettingsActivity {}
|
public static class SystemDashboardActivity extends SettingsActivity {}
|
||||||
|
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
|
import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
@@ -45,6 +47,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
|
import com.android.settings.flags.Flags;
|
||||||
import com.android.settings.support.actionbar.HelpResourceProvider;
|
import com.android.settings.support.actionbar.HelpResourceProvider;
|
||||||
import com.android.settings.widget.HighlightablePreferenceGroupAdapter;
|
import com.android.settings.widget.HighlightablePreferenceGroupAdapter;
|
||||||
import com.android.settings.widget.LoadingViewController;
|
import com.android.settings.widget.LoadingViewController;
|
||||||
@@ -367,9 +370,13 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
|
|||||||
@Override
|
@Override
|
||||||
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||||
final Bundle arguments = getArguments();
|
final Bundle arguments = getArguments();
|
||||||
mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen,
|
String key = arguments == null ? null : arguments.getString(EXTRA_FRAGMENT_ARG_KEY);
|
||||||
arguments == null
|
if (Flags.catalyst() && key == null) {
|
||||||
? null : arguments.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY),
|
Activity activity = getActivity();
|
||||||
|
Intent intent = activity != null ? activity.getIntent() : null;
|
||||||
|
key = intent != null ? intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY) : null;
|
||||||
|
}
|
||||||
|
mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen, key,
|
||||||
mPreferenceHighlighted);
|
mPreferenceHighlighted);
|
||||||
return mAdapter;
|
return mAdapter;
|
||||||
}
|
}
|
||||||
|
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.settings.applications;
|
package com.android.settings.applications;
|
||||||
|
|
||||||
import static android.webkit.Flags.updateServiceV2;
|
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -173,12 +171,10 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep WebView default package enabled.
|
// Keep WebView default package enabled.
|
||||||
if (updateServiceV2()) {
|
|
||||||
String packageName = mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName();
|
String packageName = mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName();
|
||||||
if (packageName != null) {
|
if (packageName != null) {
|
||||||
keepEnabledPackages.add(packageName);
|
keepEnabledPackages.add(packageName);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
keepEnabledPackages.addAll(getEnabledPackageAllowlist());
|
keepEnabledPackages.addAll(getEnabledPackageAllowlist());
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ package com.android.settings.biometrics.fingerprint;
|
|||||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED_EXPLANATION;
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.FINGERPRINT_UNLOCK_DISABLED_EXPLANATION;
|
||||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_FINGERPRINT_LAST_DELETE_MESSAGE;
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_FINGERPRINT_LAST_DELETE_MESSAGE;
|
||||||
import static android.app.admin.DevicePolicyResources.UNDEFINED;
|
import static android.app.admin.DevicePolicyResources.UNDEFINED;
|
||||||
|
import static android.hardware.biometrics.Flags.screenOffUnlockUdfps;
|
||||||
|
|
||||||
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
||||||
import static com.android.settings.Utils.isPrivateProfile;
|
import static com.android.settings.Utils.isPrivateProfile;
|
||||||
@@ -207,6 +208,17 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
context,
|
context,
|
||||||
KEY_REQUIRE_SCREEN_ON_TO_AUTH
|
KEY_REQUIRE_SCREEN_ON_TO_AUTH
|
||||||
));
|
));
|
||||||
|
} else if (screenOffUnlockUdfps()) {
|
||||||
|
controllers.add(
|
||||||
|
new FingerprintUnlockCategoryController(
|
||||||
|
context,
|
||||||
|
KEY_FINGERPRINT_UNLOCK_CATEGORY
|
||||||
|
));
|
||||||
|
controllers.add(
|
||||||
|
new FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(
|
||||||
|
context,
|
||||||
|
KEY_SCREEN_OFF_FINGERPRINT_UNLOCK
|
||||||
|
));
|
||||||
}
|
}
|
||||||
controllers.add(new FingerprintsEnrolledCategoryPreferenceController(context,
|
controllers.add(new FingerprintsEnrolledCategoryPreferenceController(context,
|
||||||
KEY_FINGERPRINTS_ENROLLED_CATEGORY));
|
KEY_FINGERPRINTS_ENROLLED_CATEGORY));
|
||||||
@@ -233,6 +245,9 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String KEY_REQUIRE_SCREEN_ON_TO_AUTH =
|
static final String KEY_REQUIRE_SCREEN_ON_TO_AUTH =
|
||||||
"security_settings_require_screen_on_to_auth";
|
"security_settings_require_screen_on_to_auth";
|
||||||
|
@VisibleForTesting
|
||||||
|
static final String KEY_SCREEN_OFF_FINGERPRINT_UNLOCK =
|
||||||
|
"security_settings_screen_off_unlock_udfps";
|
||||||
private static final String KEY_FINGERPRINTS_ENROLLED_CATEGORY =
|
private static final String KEY_FINGERPRINTS_ENROLLED_CATEGORY =
|
||||||
"security_settings_fingerprints_enrolled";
|
"security_settings_fingerprints_enrolled";
|
||||||
private static final String KEY_FINGERPRINT_UNLOCK_CATEGORY =
|
private static final String KEY_FINGERPRINT_UNLOCK_CATEGORY =
|
||||||
@@ -263,8 +278,11 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
mFingerprintUnlockCategoryPreferenceController;
|
mFingerprintUnlockCategoryPreferenceController;
|
||||||
private FingerprintSettingsRequireScreenOnToAuthPreferenceController
|
private FingerprintSettingsRequireScreenOnToAuthPreferenceController
|
||||||
mRequireScreenOnToAuthPreferenceController;
|
mRequireScreenOnToAuthPreferenceController;
|
||||||
|
private FingerprintSettingsScreenOffUnlockUdfpsPreferenceController
|
||||||
|
mScreenOffUnlockUdfpsPreferenceController;
|
||||||
private Preference mAddFingerprintPreference;
|
private Preference mAddFingerprintPreference;
|
||||||
private RestrictedSwitchPreference mRequireScreenOnToAuthPreference;
|
private RestrictedSwitchPreference mRequireScreenOnToAuthPreference;
|
||||||
|
private RestrictedSwitchPreference mScreenOffUnlockUdfpsPreference;
|
||||||
private PreferenceCategory mFingerprintsEnrolledCategory;
|
private PreferenceCategory mFingerprintsEnrolledCategory;
|
||||||
private PreferenceCategory mFingerprintUnlockCategory;
|
private PreferenceCategory mFingerprintUnlockCategory;
|
||||||
private PreferenceCategory mFingerprintUnlockFooter;
|
private PreferenceCategory mFingerprintUnlockFooter;
|
||||||
@@ -621,7 +639,7 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
// This needs to be after setting ids, otherwise
|
// This needs to be after setting ids, otherwise
|
||||||
// |mRequireScreenOnToAuthPreferenceController.isChecked| is always checking the primary
|
// |mRequireScreenOnToAuthPreferenceController.isChecked| is always checking the primary
|
||||||
// user instead of the user with |mUserId|.
|
// user instead of the user with |mUserId|.
|
||||||
if (isSfps()) {
|
if (isSfps() || screenOffUnlockUdfps()) {
|
||||||
scrollToPreference(fpPrefKey);
|
scrollToPreference(fpPrefKey);
|
||||||
addFingerprintUnlockCategory();
|
addFingerprintUnlockCategory();
|
||||||
}
|
}
|
||||||
@@ -671,7 +689,8 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
|
|
||||||
private void addFingerprintUnlockCategory() {
|
private void addFingerprintUnlockCategory() {
|
||||||
mFingerprintUnlockCategory = findPreference(KEY_FINGERPRINT_UNLOCK_CATEGORY);
|
mFingerprintUnlockCategory = findPreference(KEY_FINGERPRINT_UNLOCK_CATEGORY);
|
||||||
setupFingerprintUnlockCategoryPreferences();
|
if (isSfps()) {
|
||||||
|
// For both SFPS "screen on to auth" and "rest to unlock"
|
||||||
final Preference restToUnlockPreference = FeatureFactory.getFeatureFactory()
|
final Preference restToUnlockPreference = FeatureFactory.getFeatureFactory()
|
||||||
.getFingerprintFeatureProvider()
|
.getFingerprintFeatureProvider()
|
||||||
.getSfpsRestToUnlockFeature(getContext())
|
.getSfpsRestToUnlockFeature(getContext())
|
||||||
@@ -679,25 +698,37 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
if (restToUnlockPreference != null) {
|
if (restToUnlockPreference != null) {
|
||||||
// Use custom featured preference if any.
|
// Use custom featured preference if any.
|
||||||
mRequireScreenOnToAuthPreference.setTitle(restToUnlockPreference.getTitle());
|
mRequireScreenOnToAuthPreference.setTitle(restToUnlockPreference.getTitle());
|
||||||
mRequireScreenOnToAuthPreference.setSummary(restToUnlockPreference.getSummary());
|
mRequireScreenOnToAuthPreference.setSummary(
|
||||||
|
restToUnlockPreference.getSummary());
|
||||||
mRequireScreenOnToAuthPreference.setChecked(
|
mRequireScreenOnToAuthPreference.setChecked(
|
||||||
((TwoStatePreference) restToUnlockPreference).isChecked());
|
((TwoStatePreference) restToUnlockPreference).isChecked());
|
||||||
mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
|
mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
|
||||||
restToUnlockPreference.getOnPreferenceChangeListener());
|
restToUnlockPreference.getOnPreferenceChangeListener());
|
||||||
}
|
}
|
||||||
|
setupFingerprintUnlockCategoryPreferencesForScreenOnToAuth();
|
||||||
|
} else if (screenOffUnlockUdfps()) {
|
||||||
|
setupFingerprintUnlockCategoryPreferencesForScreenOffUnlock();
|
||||||
|
}
|
||||||
updateFingerprintUnlockCategoryVisibility();
|
updateFingerprintUnlockCategoryVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFingerprintUnlockCategoryVisibility() {
|
private void updateFingerprintUnlockCategoryVisibility() {
|
||||||
final boolean mFingerprintUnlockCategoryAvailable =
|
final boolean fingerprintUnlockCategoryAvailable =
|
||||||
mFingerprintUnlockCategoryPreferenceController.isAvailable();
|
mFingerprintUnlockCategoryPreferenceController.isAvailable();
|
||||||
if (mFingerprintUnlockCategory.isVisible() != mFingerprintUnlockCategoryAvailable) {
|
if (mFingerprintUnlockCategory.isVisible() != fingerprintUnlockCategoryAvailable) {
|
||||||
mFingerprintUnlockCategory.setVisible(
|
mFingerprintUnlockCategory.setVisible(fingerprintUnlockCategoryAvailable);
|
||||||
mFingerprintUnlockCategoryAvailable);
|
}
|
||||||
|
if (mRequireScreenOnToAuthPreferenceController != null) {
|
||||||
|
mRequireScreenOnToAuthPreference.setVisible(
|
||||||
|
mRequireScreenOnToAuthPreferenceController.isAvailable());
|
||||||
|
}
|
||||||
|
if (mScreenOffUnlockUdfpsPreferenceController != null) {
|
||||||
|
mScreenOffUnlockUdfpsPreference.setVisible(
|
||||||
|
mScreenOffUnlockUdfpsPreferenceController.isAvailable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupFingerprintUnlockCategoryPreferences() {
|
private void setupFingerprintUnlockCategoryPreferencesForScreenOnToAuth() {
|
||||||
mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
|
mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
|
||||||
mRequireScreenOnToAuthPreference.setChecked(
|
mRequireScreenOnToAuthPreference.setChecked(
|
||||||
mRequireScreenOnToAuthPreferenceController.isChecked());
|
mRequireScreenOnToAuthPreferenceController.isChecked());
|
||||||
@@ -709,9 +740,21 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupFingerprintUnlockCategoryPreferencesForScreenOffUnlock() {
|
||||||
|
mScreenOffUnlockUdfpsPreference = findPreference(KEY_SCREEN_OFF_FINGERPRINT_UNLOCK);
|
||||||
|
mScreenOffUnlockUdfpsPreference.setChecked(
|
||||||
|
mScreenOffUnlockUdfpsPreferenceController.isChecked());
|
||||||
|
mScreenOffUnlockUdfpsPreference.setOnPreferenceChangeListener(
|
||||||
|
(preference, newValue) -> {
|
||||||
|
final boolean isChecked = ((TwoStatePreference) preference).isChecked();
|
||||||
|
mScreenOffUnlockUdfpsPreferenceController.setChecked(!isChecked);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void updatePreferencesAfterFingerprintRemoved() {
|
private void updatePreferencesAfterFingerprintRemoved() {
|
||||||
updateAddPreference();
|
updateAddPreference();
|
||||||
if (isSfps()) {
|
if (isSfps() || screenOffUnlockUdfps()) {
|
||||||
updateFingerprintUnlockCategoryVisibility();
|
updateFingerprintUnlockCategoryVisibility();
|
||||||
}
|
}
|
||||||
updatePreferences();
|
updatePreferences();
|
||||||
@@ -954,6 +997,18 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
controller;
|
controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (screenOffUnlockUdfps()) {
|
||||||
|
for (AbstractPreferenceController controller : controllers) {
|
||||||
|
if (controller.getPreferenceKey() == KEY_FINGERPRINT_UNLOCK_CATEGORY) {
|
||||||
|
mFingerprintUnlockCategoryPreferenceController =
|
||||||
|
(FingerprintUnlockCategoryController) controller;
|
||||||
|
} else if (controller.getPreferenceKey() == KEY_SCREEN_OFF_FINGERPRINT_UNLOCK) {
|
||||||
|
mScreenOffUnlockUdfpsPreferenceController =
|
||||||
|
(FingerprintSettingsScreenOffUnlockUdfpsPreferenceController)
|
||||||
|
controller;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return controllers;
|
return controllers;
|
||||||
@@ -1070,7 +1125,8 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||||
mBiometricsAuthenticationRequested = false;
|
mBiometricsAuthenticationRequested = false;
|
||||||
if (resultCode != RESULT_OK) {
|
if (resultCode != RESULT_OK) {
|
||||||
if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
|
if (resultCode
|
||||||
|
== ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
|
||||||
IdentityCheckBiometricErrorDialog
|
IdentityCheckBiometricErrorDialog
|
||||||
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
|
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
|
||||||
Utils.BiometricStatus.LOCKOUT);
|
Utils.BiometricStatus.LOCKOUT);
|
||||||
|
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fingerprint;
|
||||||
|
|
||||||
|
import static android.hardware.biometrics.Flags.screenOffUnlockUdfps;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.settings.Utils;
|
||||||
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
|
import com.android.settingslib.search.SearchIndexable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preference controller that controls whether show screen off UDFPS unlock toggle for users to
|
||||||
|
* turn this feature ON or OFF
|
||||||
|
*/
|
||||||
|
@SearchIndexable
|
||||||
|
public class FingerprintSettingsScreenOffUnlockUdfpsPreferenceController
|
||||||
|
extends FingerprintSettingsPreferenceController {
|
||||||
|
private static final String TAG =
|
||||||
|
"FingerprintSettingsScreenOffUnlockUdfpsPreferenceController";
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected FingerprintManager mFingerprintManager;
|
||||||
|
|
||||||
|
public FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(
|
||||||
|
@NonNull Context context, @NonNull String prefKey) {
|
||||||
|
super(context, prefKey);
|
||||||
|
mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChecked() {
|
||||||
|
if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
|
||||||
|
return false;
|
||||||
|
} else if (getRestrictingAdmin() != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final boolean defEnabled = mContext.getResources().getBoolean(
|
||||||
|
com.android.internal.R.bool.config_screen_off_udfps_enabled);
|
||||||
|
final int value = Settings.Secure.getIntForUser(
|
||||||
|
mContext.getContentResolver(),
|
||||||
|
Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED,
|
||||||
|
defEnabled ? 1 : 0 /* config_screen_off_udfps_enabled */,
|
||||||
|
getUserHandle());
|
||||||
|
return value == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setChecked(boolean isChecked) {
|
||||||
|
Settings.Secure.putIntForUser(
|
||||||
|
mContext.getContentResolver(),
|
||||||
|
Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED,
|
||||||
|
isChecked ? 1 : 0,
|
||||||
|
getUserHandle());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateState(@NonNull Preference preference) {
|
||||||
|
super.updateState(preference);
|
||||||
|
if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
|
||||||
|
preference.setEnabled(false);
|
||||||
|
} else if (!mFingerprintManager.hasEnrolledTemplates(getUserId())) {
|
||||||
|
preference.setEnabled(false);
|
||||||
|
} else if (getRestrictingAdmin() != null) {
|
||||||
|
preference.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
preference.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
if (mFingerprintManager != null
|
||||||
|
&& mFingerprintManager.isHardwareDetected()
|
||||||
|
&& screenOffUnlockUdfps()
|
||||||
|
&& !mFingerprintManager.isPowerbuttonFps()) {
|
||||||
|
return mFingerprintManager.hasEnrolledTemplates(getUserId())
|
||||||
|
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||||
|
} else {
|
||||||
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getUserHandle() {
|
||||||
|
return UserHandle.of(getUserId()).getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This feature is not directly searchable.
|
||||||
|
*/
|
||||||
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
|
new BaseSearchIndexProvider() {};
|
||||||
|
|
||||||
|
}
|
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint;
|
package com.android.settings.biometrics.fingerprint;
|
||||||
|
|
||||||
|
import static android.hardware.biometrics.Flags.screenOffUnlockUdfps;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ public class FingerprintUnlockCategoryController extends BasePreferenceControlle
|
|||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
if (mFingerprintManager != null
|
if (mFingerprintManager != null
|
||||||
&& mFingerprintManager.isHardwareDetected()
|
&& mFingerprintManager.isHardwareDetected()
|
||||||
&& mFingerprintManager.isPowerbuttonFps()) {
|
&& (mFingerprintManager.isPowerbuttonFps() || screenOffUnlockUdfps())) {
|
||||||
return mFingerprintManager.hasEnrolledTemplates(getUserId())
|
return mFingerprintManager.hasEnrolledTemplates(getUserId())
|
||||||
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -117,6 +117,7 @@ import com.android.settings.enterprise.EnterprisePrivacySettings;
|
|||||||
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
|
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
|
||||||
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleSettings;
|
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleSettings;
|
||||||
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
|
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
|
||||||
|
import com.android.settings.fuelgauge.batteryusage.PowerUsageAdvanced;
|
||||||
import com.android.settings.fuelgauge.batteryusage.PowerUsageSummary;
|
import com.android.settings.fuelgauge.batteryusage.PowerUsageSummary;
|
||||||
import com.android.settings.gestures.ButtonNavigationSettingsFragment;
|
import com.android.settings.gestures.ButtonNavigationSettingsFragment;
|
||||||
import com.android.settings.gestures.DoubleTapPowerSettings;
|
import com.android.settings.gestures.DoubleTapPowerSettings;
|
||||||
@@ -276,6 +277,7 @@ public class SettingsGateway {
|
|||||||
DevelopmentSettingsDashboardFragment.class.getName(),
|
DevelopmentSettingsDashboardFragment.class.getName(),
|
||||||
WifiDisplaySettings.class.getName(),
|
WifiDisplaySettings.class.getName(),
|
||||||
PowerUsageSummary.class.getName(),
|
PowerUsageSummary.class.getName(),
|
||||||
|
PowerUsageAdvanced.class.getName(),
|
||||||
AccountSyncSettings.class.getName(),
|
AccountSyncSettings.class.getName(),
|
||||||
FaceSettings.class.getName(),
|
FaceSettings.class.getName(),
|
||||||
FingerprintSettings.FingerprintSettingsFragment.class.getName(),
|
FingerprintSettings.FingerprintSettingsFragment.class.getName(),
|
||||||
@@ -415,6 +417,7 @@ public class SettingsGateway {
|
|||||||
Settings.SoundSettingsActivity.class.getName(),
|
Settings.SoundSettingsActivity.class.getName(),
|
||||||
Settings.StorageDashboardActivity.class.getName(),
|
Settings.StorageDashboardActivity.class.getName(),
|
||||||
Settings.PowerUsageSummaryActivity.class.getName(),
|
Settings.PowerUsageSummaryActivity.class.getName(),
|
||||||
|
Settings.PowerUsageAdvancedActivity.class.getName(),
|
||||||
Settings.AccountDashboardActivity.class.getName(),
|
Settings.AccountDashboardActivity.class.getName(),
|
||||||
Settings.PrivacySettingsActivity.class.getName(),
|
Settings.PrivacySettingsActivity.class.getName(),
|
||||||
Settings.SecurityDashboardActivity.class.getName(),
|
Settings.SecurityDashboardActivity.class.getName(),
|
||||||
|
@@ -25,6 +25,9 @@ import android.os.Bundle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
@@ -211,6 +214,11 @@ public class MyDeviceInfoFragment extends DashboardFragment
|
|||||||
controller.updateDeviceName(confirm);
|
controller.updateDeviceName(confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
|
||||||
|
return MyDeviceInfoScreen.KEY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For Search.
|
* For Search.
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.deviceinfo.aboutphone
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.flags.Flags
|
||||||
|
import com.android.settingslib.metadata.PreferenceIconProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceSummaryProvider
|
||||||
|
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||||
|
import com.android.settingslib.metadata.preferenceHierarchy
|
||||||
|
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||||
|
|
||||||
|
@ProvidePreferenceScreen
|
||||||
|
class MyDeviceInfoScreen :
|
||||||
|
PreferenceScreenCreator, PreferenceSummaryProvider, PreferenceIconProvider {
|
||||||
|
override val key: String
|
||||||
|
get() = KEY
|
||||||
|
|
||||||
|
override val title: Int
|
||||||
|
get() = R.string.about_settings
|
||||||
|
|
||||||
|
override fun getSummary(context: Context): CharSequence? {
|
||||||
|
return Settings.Global.getString(context.contentResolver, Settings.Global.DEVICE_NAME)
|
||||||
|
?: Build.MODEL
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIcon(context: Context): Int {
|
||||||
|
return when (Flags.homepageRevamp()) {
|
||||||
|
true -> R.drawable.ic_settings_about_device_filled
|
||||||
|
false -> R.drawable.ic_settings_about_device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isFlagEnabled(context: Context) = Flags.catalystMyDeviceInfoPrefScreen()
|
||||||
|
|
||||||
|
override fun fragmentClass() = MyDeviceInfoFragment::class.java
|
||||||
|
|
||||||
|
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
|
||||||
|
|
||||||
|
override fun hasCompleteHierarchy() = false
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY = "my_device_info_pref_screen"
|
||||||
|
}
|
||||||
|
}
|
@@ -57,6 +57,7 @@ import java.text.NumberFormat;
|
|||||||
/**
|
/**
|
||||||
* The top-level preference controller that updates the adaptive brightness level.
|
* The top-level preference controller that updates the adaptive brightness level.
|
||||||
*/
|
*/
|
||||||
|
// LINT.IfChange
|
||||||
public class BrightnessLevelPreferenceController extends BasePreferenceController implements
|
public class BrightnessLevelPreferenceController extends BasePreferenceController implements
|
||||||
PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
|
PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
|
||||||
private static final Uri BRIGHTNESS_ADJ_URI;
|
private static final Uri BRIGHTNESS_ADJ_URI;
|
||||||
@@ -187,3 +188,4 @@ public class BrightnessLevelPreferenceController extends BasePreferenceControlle
|
|||||||
return (value - min) / (max - min);
|
return (value - min) / (max - min);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// LINT.ThenChange(BrightnessLevelRestrictedPreference.kt)
|
||||||
|
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.display
|
||||||
|
|
||||||
|
import android.app.ActivityOptions
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.Intent.ACTION_SHOW_BRIGHTNESS_DIALOG
|
||||||
|
import android.content.Intent.EXTRA_BRIGHTNESS_DIALOG_IS_FULL_WIDTH
|
||||||
|
import android.hardware.display.BrightnessInfo
|
||||||
|
import android.hardware.display.DisplayManager
|
||||||
|
import android.hardware.display.DisplayManager.DisplayListener
|
||||||
|
import android.os.Process
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.os.UserManager
|
||||||
|
import android.provider.Settings.System
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.Utils
|
||||||
|
import com.android.settings.core.SettingsBaseActivity
|
||||||
|
import com.android.settingslib.RestrictedLockUtilsInternal
|
||||||
|
import com.android.settingslib.RestrictedPreference
|
||||||
|
import com.android.settingslib.datastore.HandlerExecutor
|
||||||
|
import com.android.settingslib.datastore.KeyedObserver
|
||||||
|
import com.android.settingslib.datastore.SettingsSystemStore
|
||||||
|
import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX
|
||||||
|
import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN
|
||||||
|
import com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat
|
||||||
|
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
||||||
|
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceMetadata
|
||||||
|
import com.android.settingslib.metadata.PreferenceRestrictionProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceSummaryProvider
|
||||||
|
import com.android.settingslib.preference.PreferenceBinding
|
||||||
|
import com.android.settingslib.transition.SettingsTransitionHelper
|
||||||
|
import java.text.NumberFormat
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
|
class BrightnessLevelRestrictedPreference :
|
||||||
|
PreferenceMetadata,
|
||||||
|
PreferenceBinding,
|
||||||
|
PreferenceRestrictionProvider,
|
||||||
|
PreferenceSummaryProvider,
|
||||||
|
PreferenceLifecycleProvider,
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
|
||||||
|
private var brightnessObserver: KeyedObserver<String>? = null
|
||||||
|
private var displayListener: DisplayListener? = null
|
||||||
|
|
||||||
|
override val key: String
|
||||||
|
get() = "brightness"
|
||||||
|
|
||||||
|
override val title: Int
|
||||||
|
get() = R.string.brightness
|
||||||
|
|
||||||
|
override val keywords: Int
|
||||||
|
get() = R.string.keywords_display_brightness_level
|
||||||
|
|
||||||
|
override fun getSummary(context: Context) =
|
||||||
|
NumberFormat.getPercentInstance().format(getCurrentBrightness(context))
|
||||||
|
|
||||||
|
override fun isEnabled(context: Context) =
|
||||||
|
!UserManager.get(context)
|
||||||
|
.hasBaseUserRestriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, Process.myUserHandle())
|
||||||
|
|
||||||
|
override fun isRestricted(context: Context) =
|
||||||
|
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
|
||||||
|
context,
|
||||||
|
UserManager.DISALLOW_CONFIG_BRIGHTNESS,
|
||||||
|
UserHandle.myUserId(),
|
||||||
|
) != null
|
||||||
|
|
||||||
|
override fun createWidget(context: Context) = RestrictedPreference(context)
|
||||||
|
|
||||||
|
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||||
|
super.bind(preference, metadata)
|
||||||
|
if (preference is RestrictedPreference) preference.useAdminDisabledSummary(true)
|
||||||
|
preference.onPreferenceClickListener = this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart(context: PreferenceLifecycleContext) {
|
||||||
|
val observer =
|
||||||
|
object : KeyedObserver<String> {
|
||||||
|
override fun onKeyChanged(key: String, reason: Int) {
|
||||||
|
context.notifyPreferenceChange(this@BrightnessLevelRestrictedPreference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
brightnessObserver = observer
|
||||||
|
SettingsSystemStore.get(context)
|
||||||
|
.addObserver(System.SCREEN_AUTO_BRIGHTNESS_ADJ, observer, HandlerExecutor.main)
|
||||||
|
|
||||||
|
val listener =
|
||||||
|
object : DisplayListener {
|
||||||
|
override fun onDisplayAdded(displayId: Int) {}
|
||||||
|
|
||||||
|
override fun onDisplayRemoved(displayId: Int) {}
|
||||||
|
|
||||||
|
override fun onDisplayChanged(displayId: Int) {
|
||||||
|
context.notifyPreferenceChange(this@BrightnessLevelRestrictedPreference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayListener = listener
|
||||||
|
context
|
||||||
|
.getSystemService(DisplayManager::class.java)
|
||||||
|
.registerDisplayListener(
|
||||||
|
listener,
|
||||||
|
HandlerExecutor.main,
|
||||||
|
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop(context: PreferenceLifecycleContext) {
|
||||||
|
brightnessObserver?.let {
|
||||||
|
SettingsSystemStore.get(context).removeObserver(System.SCREEN_AUTO_BRIGHTNESS_ADJ, it)
|
||||||
|
brightnessObserver = null
|
||||||
|
}
|
||||||
|
|
||||||
|
displayListener?.let {
|
||||||
|
context.getSystemService(DisplayManager::class.java).unregisterDisplayListener(it)
|
||||||
|
displayListener = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPreferenceClick(preference: Preference): Boolean {
|
||||||
|
val context = preference.context
|
||||||
|
val intent =
|
||||||
|
Intent(ACTION_SHOW_BRIGHTNESS_DIALOG)
|
||||||
|
.setPackage(Utils.SYSTEMUI_PACKAGE_NAME)
|
||||||
|
.putExtra(
|
||||||
|
SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
|
||||||
|
SettingsTransitionHelper.TransitionType.TRANSITION_NONE,
|
||||||
|
)
|
||||||
|
.putExtra(EXTRA_BRIGHTNESS_DIALOG_IS_FULL_WIDTH, true)
|
||||||
|
val options =
|
||||||
|
ActivityOptions.makeCustomAnimation(
|
||||||
|
context,
|
||||||
|
android.R.anim.fade_in,
|
||||||
|
android.R.anim.fade_out,
|
||||||
|
)
|
||||||
|
context.startActivityForResult(preference.key, intent, 0, options.toBundle())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCurrentBrightness(context: Context): Double {
|
||||||
|
val info: BrightnessInfo? = context.display.brightnessInfo
|
||||||
|
val value =
|
||||||
|
info?.run {
|
||||||
|
convertLinearToGammaFloat(brightness, brightnessMinimum, brightnessMaximum)
|
||||||
|
}
|
||||||
|
return getPercentage(value?.toDouble() ?: 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPercentage(value: Double): Double =
|
||||||
|
when {
|
||||||
|
value > GAMMA_SPACE_MAX -> 1.0
|
||||||
|
value < GAMMA_SPACE_MIN -> 0.0
|
||||||
|
else -> (value - GAMMA_SPACE_MIN) / (GAMMA_SPACE_MAX - GAMMA_SPACE_MIN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LINT.ThenChange(BrightnessLevelPreferenceController.java)
|
@@ -18,10 +18,13 @@ package com.android.settings.display
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.settings.DisplaySettings
|
import com.android.settings.DisplaySettings
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
|
import com.android.settings.Settings.DisplaySettingsActivity
|
||||||
import com.android.settings.display.darkmode.DarkModeScreen
|
import com.android.settings.display.darkmode.DarkModeScreen
|
||||||
import com.android.settings.flags.Flags
|
import com.android.settings.flags.Flags
|
||||||
|
import com.android.settings.utils.makeLaunchIntent
|
||||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||||
import com.android.settingslib.metadata.PreferenceIconProvider
|
import com.android.settingslib.metadata.PreferenceIconProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceMetadata
|
||||||
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||||
import com.android.settingslib.metadata.preferenceHierarchy
|
import com.android.settingslib.metadata.preferenceHierarchy
|
||||||
import com.android.settingslib.preference.PreferenceScreenCreator
|
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||||
@@ -48,10 +51,14 @@ class DisplayScreen :
|
|||||||
override fun fragmentClass() = DisplaySettings::class.java
|
override fun fragmentClass() = DisplaySettings::class.java
|
||||||
|
|
||||||
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
|
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
|
||||||
|
+BrightnessLevelRestrictedPreference()
|
||||||
+DarkModeScreen.KEY
|
+DarkModeScreen.KEY
|
||||||
+PeakRefreshRateSwitchPreference()
|
+PeakRefreshRateSwitchPreference()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLaunchIntent(context: Context, metadata: PreferenceMetadata?) =
|
||||||
|
makeLaunchIntent(context, DisplaySettingsActivity::class.java, metadata?.key)
|
||||||
|
|
||||||
override fun isAvailable(context: Context) =
|
override fun isAvailable(context: Context) =
|
||||||
context.resources.getBoolean(R.bool.config_show_top_level_display)
|
context.resources.getBoolean(R.bool.config_show_top_level_display)
|
||||||
|
|
||||||
|
@@ -18,53 +18,51 @@ package com.android.settings.display
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
import android.provider.DeviceConfig
|
import android.provider.DeviceConfig
|
||||||
import android.util.Log
|
import android.provider.Settings.System.PEAK_REFRESH_RATE
|
||||||
import com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE
|
import com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE
|
||||||
import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays
|
import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays
|
||||||
import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay
|
import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay
|
||||||
import com.android.server.display.feature.flags.Flags
|
import com.android.server.display.feature.flags.Flags
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settingslib.datastore.HandlerExecutor
|
import com.android.settingslib.datastore.HandlerExecutor
|
||||||
|
import com.android.settingslib.datastore.KeyValueStore
|
||||||
|
import com.android.settingslib.datastore.KeyedObservableDelegate
|
||||||
|
import com.android.settingslib.datastore.SettingsStore
|
||||||
import com.android.settingslib.datastore.SettingsSystemStore
|
import com.android.settingslib.datastore.SettingsSystemStore
|
||||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||||
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
import com.android.settingslib.metadata.PreferenceLifecycleContext
|
||||||
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
import com.android.settingslib.metadata.PreferenceLifecycleProvider
|
||||||
import com.android.settingslib.metadata.PreferenceSummaryProvider
|
import com.android.settingslib.metadata.PreferenceSummaryProvider
|
||||||
import com.android.settingslib.metadata.SwitchPreference
|
import com.android.settingslib.metadata.SwitchPreference
|
||||||
import com.android.settingslib.preference.SwitchPreferenceBinding
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
// LINT.IfChange
|
// LINT.IfChange
|
||||||
class PeakRefreshRateSwitchPreference :
|
class PeakRefreshRateSwitchPreference :
|
||||||
SwitchPreference("peak_refresh_rate", R.string.peak_refresh_rate_title),
|
SwitchPreference(PEAK_REFRESH_RATE, R.string.peak_refresh_rate_title),
|
||||||
SwitchPreferenceBinding,
|
|
||||||
PreferenceAvailabilityProvider,
|
PreferenceAvailabilityProvider,
|
||||||
PreferenceSummaryProvider,
|
PreferenceSummaryProvider,
|
||||||
PreferenceLifecycleProvider {
|
PreferenceLifecycleProvider {
|
||||||
|
|
||||||
private var propertiesChangedListener: DeviceConfig.OnPropertiesChangedListener? = null
|
private var propertiesChangedListener: DeviceConfig.OnPropertiesChangedListener? = null
|
||||||
|
|
||||||
override fun storage(context: Context) = SettingsSystemStore.get(context)
|
override fun storage(context: Context): KeyValueStore =
|
||||||
|
PeakRefreshRateStore(context, SettingsSystemStore.get(context))
|
||||||
|
|
||||||
override fun isAvailable(context: Context) =
|
override fun isAvailable(context: Context) =
|
||||||
context.resources.getBoolean(R.bool.config_show_smooth_display) &&
|
context.resources.getBoolean(R.bool.config_show_smooth_display) &&
|
||||||
(getPeakRefreshRate(context) > DEFAULT_REFRESH_RATE)
|
context.peakRefreshRate > DEFAULT_REFRESH_RATE
|
||||||
|
|
||||||
override fun getSummary(context: Context) =
|
override fun getSummary(context: Context): CharSequence? =
|
||||||
context.getString(
|
context.getString(R.string.peak_refresh_rate_summary, context.peakRefreshRate.roundToInt())
|
||||||
R.string.peak_refresh_rate_summary,
|
|
||||||
getPeakRefreshRate(context).roundToInt(),
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun onStart(context: PreferenceLifecycleContext) {
|
override fun onStart(context: PreferenceLifecycleContext) {
|
||||||
val listener =
|
val listener =
|
||||||
object : DeviceConfig.OnPropertiesChangedListener {
|
DeviceConfig.OnPropertiesChangedListener {
|
||||||
// Got notified if any property has been changed in NAMESPACE_DISPLAY_MANAGER. The
|
// Got notified if any property has been changed in NAMESPACE_DISPLAY_MANAGER. The
|
||||||
// KEY_PEAK_REFRESH_RATE_DEFAULT value could be added, changed, removed or
|
// KEY_PEAK_REFRESH_RATE_DEFAULT value could be added, changed, removed or
|
||||||
// unchanged.
|
// unchanged.
|
||||||
// Just force a UI update for any case.
|
// Just force a UI update for any case.
|
||||||
override fun onPropertiesChanged(properties: DeviceConfig.Properties) =
|
context.notifyPreferenceChange(this)
|
||||||
context.notifyPreferenceChange(this@PeakRefreshRateSwitchPreference)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesChangedListener = listener
|
propertiesChangedListener = listener
|
||||||
@@ -83,38 +81,74 @@ class PeakRefreshRateSwitchPreference :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPeakRefreshRate(context: Context): Float =
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private class PeakRefreshRateStore(
|
||||||
|
private val context: Context,
|
||||||
|
private val settingsStore: SettingsStore,
|
||||||
|
) : KeyedObservableDelegate<String>(settingsStore), KeyValueStore {
|
||||||
|
|
||||||
|
override fun contains(key: String) = settingsStore.contains(key)
|
||||||
|
|
||||||
|
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>): T? {
|
||||||
|
if (key != PEAK_REFRESH_RATE) return super.getDefaultValue(key, valueType)
|
||||||
|
return context.defaultPeakRefreshRate.refreshRateAsBoolean(context) as T
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> getValue(key: String, valueType: Class<T>): T? {
|
||||||
|
if (key != PEAK_REFRESH_RATE) return null
|
||||||
|
val refreshRate =
|
||||||
|
settingsStore.getFloat(PEAK_REFRESH_RATE) ?: context.defaultPeakRefreshRate
|
||||||
|
return refreshRate.refreshRateAsBoolean(context) as T
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Float.refreshRateAsBoolean(context: Context) =
|
||||||
|
this.isInfinite() || roundToInt() == context.peakRefreshRate.roundToInt()
|
||||||
|
|
||||||
|
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) =
|
||||||
|
when {
|
||||||
|
key != PEAK_REFRESH_RATE -> {}
|
||||||
|
value == null -> settingsStore.setFloat(PEAK_REFRESH_RATE, null)
|
||||||
|
else -> {
|
||||||
|
val peakRefreshRate =
|
||||||
|
if (value as Boolean) context.refreshRateIfON() else DEFAULT_REFRESH_RATE
|
||||||
|
settingsStore.setFloat(PEAK_REFRESH_RATE, peakRefreshRate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Context.refreshRateIfON() =
|
||||||
|
when {
|
||||||
|
Flags.backUpSmoothDisplayAndForcePeakRefreshRate() -> Float.POSITIVE_INFINITY
|
||||||
|
else -> peakRefreshRate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val INVALIDATE_REFRESH_RATE: Float = -1f
|
||||||
|
|
||||||
|
private val Context.peakRefreshRate: Float
|
||||||
|
get() =
|
||||||
Math.round(
|
Math.round(
|
||||||
when {
|
when {
|
||||||
Flags.backUpSmoothDisplayAndForcePeakRefreshRate() ->
|
Flags.backUpSmoothDisplayAndForcePeakRefreshRate() ->
|
||||||
findHighestRefreshRateAmongAllDisplays(context)
|
findHighestRefreshRateAmongAllDisplays(this)
|
||||||
else -> findHighestRefreshRateForDefaultDisplay(context)
|
else -> findHighestRefreshRateForDefaultDisplay(this)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.toFloat()
|
.toFloat()
|
||||||
|
|
||||||
private fun getDefaultPeakRefreshRate(context: Context): Float {
|
private val Context.defaultPeakRefreshRate: Float
|
||||||
var defaultPeakRefreshRate =
|
get() {
|
||||||
|
val defaultPeakRefreshRate =
|
||||||
DeviceConfig.getFloat(
|
DeviceConfig.getFloat(
|
||||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT,
|
DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT,
|
||||||
INVALIDATE_REFRESH_RATE,
|
INVALIDATE_REFRESH_RATE,
|
||||||
)
|
)
|
||||||
|
if (defaultPeakRefreshRate != INVALIDATE_REFRESH_RATE) return defaultPeakRefreshRate
|
||||||
if (defaultPeakRefreshRate == INVALIDATE_REFRESH_RATE) {
|
return resources
|
||||||
defaultPeakRefreshRate =
|
|
||||||
context.resources
|
|
||||||
.getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate)
|
.getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate)
|
||||||
.toFloat()
|
.toFloat()
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : $defaultPeakRefreshRate")
|
|
||||||
return defaultPeakRefreshRate
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG: String = "PeakRefreshRateSwitchPreference"
|
|
||||||
private const val INVALIDATE_REFRESH_RATE: Float = -1f
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// LINT.ThenChange(PeakRefreshRatePreferenceController.java)
|
// LINT.ThenChange(PeakRefreshRatePreferenceController.java)
|
||||||
|
42
src/com/android/settings/network/AirplaneModePreference.kt
Normal file
42
src/com/android/settings/network/AirplaneModePreference.kt
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.provider.Settings.Global.AIRPLANE_MODE_ON
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settingslib.datastore.SettingsGlobalStore
|
||||||
|
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||||
|
import com.android.settingslib.metadata.SwitchPreference
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
|
class AirplaneModePreference :
|
||||||
|
SwitchPreference(AIRPLANE_MODE_ON, R.string.airplane_mode),
|
||||||
|
PreferenceAvailabilityProvider {
|
||||||
|
|
||||||
|
override val icon: Int
|
||||||
|
@DrawableRes get() = R.drawable.ic_airplanemode_active
|
||||||
|
|
||||||
|
override fun storage(context: Context) = SettingsGlobalStore.get(context)
|
||||||
|
|
||||||
|
override fun isAvailable(context: Context) =
|
||||||
|
(context.resources.getBoolean(R.bool.config_show_toggle_airplane)
|
||||||
|
&& !context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
|
||||||
|
}
|
||||||
|
// LINT.ThenChange(AirplaneModePreferenceController.java)
|
@@ -52,6 +52,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
public class AirplaneModePreferenceController extends TogglePreferenceController
|
public class AirplaneModePreferenceController extends TogglePreferenceController
|
||||||
implements LifecycleObserver, OnStart, OnResume, OnStop, OnDestroy,
|
implements LifecycleObserver, OnStart, OnResume, OnStop, OnDestroy,
|
||||||
AirplaneModeEnabler.OnAirplaneModeChangedListener {
|
AirplaneModeEnabler.OnAirplaneModeChangedListener {
|
||||||
@@ -217,3 +218,4 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// LINT.ThenChange(AirplaneModePreference.kt)
|
||||||
|
@@ -26,7 +26,6 @@ import android.net.VpnManager;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.SettingsSlicesContract;
|
|
||||||
import android.security.Credentials;
|
import android.security.Credentials;
|
||||||
import android.security.LegacyVpnProfileStore;
|
import android.security.LegacyVpnProfileStore;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -39,7 +38,6 @@ import com.android.internal.net.LegacyVpnInfo;
|
|||||||
import com.android.internal.net.VpnConfig;
|
import com.android.internal.net.VpnConfig;
|
||||||
import com.android.internal.net.VpnProfile;
|
import com.android.internal.net.VpnProfile;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
|
||||||
import com.android.settings.core.PreferenceControllerMixin;
|
import com.android.settings.core.PreferenceControllerMixin;
|
||||||
import com.android.settings.vpn2.VpnInfoPreference;
|
import com.android.settings.vpn2.VpnInfoPreference;
|
||||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||||
@@ -50,7 +48,6 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
|
|||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class VpnPreferenceController extends AbstractPreferenceController
|
public class VpnPreferenceController extends AbstractPreferenceController
|
||||||
@@ -87,7 +84,7 @@ public class VpnPreferenceController extends AbstractPreferenceController
|
|||||||
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
|
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
|
||||||
// Manually set dependencies for Wifi when not toggleable.
|
// Manually set dependencies for Wifi when not toggleable.
|
||||||
if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIFI)) {
|
if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIFI)) {
|
||||||
preference.setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
|
preference.setDependency(Settings.Global.AIRPLANE_MODE_ON);
|
||||||
}
|
}
|
||||||
return preference;
|
return preference;
|
||||||
}
|
}
|
||||||
|
63
src/com/android/settings/network/tether/TetherScreen.kt
Normal file
63
src/com/android/settings/network/tether/TetherScreen.kt
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.network.tether
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.TetheringManager
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.flags.Flags
|
||||||
|
import com.android.settings.network.TetherPreferenceController
|
||||||
|
import com.android.settingslib.TetherUtil
|
||||||
|
import com.android.settingslib.Utils
|
||||||
|
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||||
|
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||||
|
import com.android.settingslib.metadata.preferenceHierarchy
|
||||||
|
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||||
|
|
||||||
|
@ProvidePreferenceScreen
|
||||||
|
class TetherScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider {
|
||||||
|
|
||||||
|
override val key: String
|
||||||
|
get() = KEY
|
||||||
|
|
||||||
|
override val icon: Int
|
||||||
|
get() = R.drawable.ic_wifi_tethering
|
||||||
|
|
||||||
|
override val keywords: Int
|
||||||
|
get() = R.string.keywords_hotspot_tethering
|
||||||
|
|
||||||
|
override fun getPreferenceTitle(context: Context): CharSequence? =
|
||||||
|
if (TetherPreferenceController.isTetherConfigDisallowed(context)) {
|
||||||
|
context.getText(R.string.tether_settings_title_all)
|
||||||
|
} else {
|
||||||
|
val tetheringManager = context.getSystemService(TetheringManager::class.java)!!
|
||||||
|
context.getText(Utils.getTetheringLabel(tetheringManager))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAvailable(context: Context) = TetherUtil.isTetherAvailable(context)
|
||||||
|
|
||||||
|
override fun isFlagEnabled(context: Context) = Flags.catalystTetherSettings()
|
||||||
|
|
||||||
|
override fun hasCompleteHierarchy() = false
|
||||||
|
|
||||||
|
override fun fragmentClass() = TetherSettings::class.java
|
||||||
|
|
||||||
|
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY = "tether_settings"
|
||||||
|
}
|
||||||
|
}
|
@@ -48,6 +48,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -731,4 +732,9 @@ public class TetherSettings extends RestrictedDashboardFragment
|
|||||||
}
|
}
|
||||||
updateBluetoothAndEthernetState();
|
updateBluetoothAndEthernetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
|
||||||
|
return TetherScreen.KEY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
118
src/com/android/settings/notification/MediaVolumePreference.kt
Normal file
118
src/com/android/settings/notification/MediaVolumePreference.kt
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.AudioManager.STREAM_MUSIC
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.os.UserManager
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settingslib.RestrictedLockUtilsInternal
|
||||||
|
import com.android.settingslib.datastore.KeyValueStore
|
||||||
|
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||||
|
import com.android.settingslib.metadata.*
|
||||||
|
import com.android.settingslib.preference.PreferenceBinding
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
|
open class MediaVolumePreference :
|
||||||
|
PreferenceMetadata,
|
||||||
|
PreferenceBinding,
|
||||||
|
PersistentPreference<Int>,
|
||||||
|
RangeValue,
|
||||||
|
PreferenceAvailabilityProvider,
|
||||||
|
PreferenceIconProvider,
|
||||||
|
PreferenceRestrictionProvider {
|
||||||
|
override val key: String
|
||||||
|
get() = KEY
|
||||||
|
|
||||||
|
override val title: Int
|
||||||
|
get() = R.string.media_volume_option_title
|
||||||
|
|
||||||
|
override fun getIcon(context: Context) =
|
||||||
|
when {
|
||||||
|
VolumeHelper.isMuted(context, STREAM_MUSIC) -> R.drawable.ic_media_stream_off
|
||||||
|
else -> R.drawable.ic_media_stream
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAvailable(context: Context) =
|
||||||
|
context.resources.getBoolean(R.bool.config_show_media_volume)
|
||||||
|
|
||||||
|
override fun isRestricted(context: Context) =
|
||||||
|
RestrictedLockUtilsInternal.hasBaseUserRestriction(
|
||||||
|
context,
|
||||||
|
UserManager.DISALLOW_ADJUST_VOLUME,
|
||||||
|
UserHandle.myUserId(),
|
||||||
|
) ||
|
||||||
|
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
|
||||||
|
context,
|
||||||
|
UserManager.DISALLOW_ADJUST_VOLUME,
|
||||||
|
UserHandle.myUserId(),
|
||||||
|
) != null
|
||||||
|
|
||||||
|
override fun storage(context: Context): KeyValueStore {
|
||||||
|
val helper = createAudioHelper(context)
|
||||||
|
return object : NoOpKeyedObservable<String>(), KeyValueStore {
|
||||||
|
override fun contains(key: String) = key == KEY
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
|
||||||
|
helper.getStreamVolume(STREAM_MUSIC) as T
|
||||||
|
|
||||||
|
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
|
||||||
|
helper.setStreamVolume(STREAM_MUSIC, value as Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMinValue(context: Context) =
|
||||||
|
createAudioHelper(context).getMinVolume(STREAM_MUSIC)
|
||||||
|
|
||||||
|
override fun getMaxValue(context: Context) =
|
||||||
|
createAudioHelper(context).getMaxVolume(STREAM_MUSIC)
|
||||||
|
|
||||||
|
override fun createWidget(context: Context) = VolumeSeekBarPreference(context)
|
||||||
|
|
||||||
|
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||||
|
super.bind(preference, metadata)
|
||||||
|
(preference as VolumeSeekBarPreference).apply {
|
||||||
|
setStream(STREAM_MUSIC)
|
||||||
|
setMuteIcon(R.drawable.ic_media_stream_off)
|
||||||
|
setListener { updateContentDescription(this) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun createAudioHelper(context: Context) = AudioHelper(context)
|
||||||
|
|
||||||
|
fun updateContentDescription(preference: VolumeSeekBarPreference) {
|
||||||
|
when {
|
||||||
|
preference.isMuted() ->
|
||||||
|
preference.updateContentDescription(
|
||||||
|
preference.context.getString(
|
||||||
|
R.string.volume_content_description_silent_mode,
|
||||||
|
preference.title,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else -> preference.updateContentDescription(preference.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY = "media_volume"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LINT.ThenChange(MediaVolumePreferenceController.java)
|
@@ -42,6 +42,7 @@ import com.android.settingslib.media.BluetoothMediaDevice;
|
|||||||
import com.android.settingslib.media.MediaDevice;
|
import com.android.settingslib.media.MediaDevice;
|
||||||
import com.android.settingslib.media.MediaOutputConstants;
|
import com.android.settingslib.media.MediaOutputConstants;
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceController {
|
public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceController {
|
||||||
private static final String TAG = "MediaVolumePreCtrl";
|
private static final String TAG = "MediaVolumePreCtrl";
|
||||||
private static final String KEY_MEDIA_VOLUME = "media_volume";
|
private static final String KEY_MEDIA_VOLUME = "media_volume";
|
||||||
@@ -204,3 +205,4 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
|||||||
return MediaOutputIndicatorWorker.class;
|
return MediaOutputIndicatorWorker.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// LINT.ThenChange(MediaVolumePreference.kt)
|
||||||
|
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification
|
||||||
|
|
||||||
|
import android.app.INotificationManager
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.AudioManager.RINGER_MODE_NORMAL
|
||||||
|
import android.media.AudioManager.RINGER_MODE_SILENT
|
||||||
|
import android.media.AudioManager.RINGER_MODE_VIBRATE
|
||||||
|
import android.media.AudioManager.STREAM_RING
|
||||||
|
import android.os.ServiceManager
|
||||||
|
import android.os.UserHandle
|
||||||
|
import android.os.UserManager.DISALLOW_ADJUST_VOLUME
|
||||||
|
import android.os.Vibrator
|
||||||
|
import android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS
|
||||||
|
import android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settingslib.RestrictedLockUtilsInternal
|
||||||
|
import com.android.settingslib.datastore.KeyValueStore
|
||||||
|
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||||
|
import com.android.settingslib.metadata.PersistentPreference
|
||||||
|
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceIconProvider
|
||||||
|
import com.android.settingslib.metadata.PreferenceMetadata
|
||||||
|
import com.android.settingslib.metadata.PreferenceRestrictionProvider
|
||||||
|
import com.android.settingslib.metadata.RangeValue
|
||||||
|
import com.android.settingslib.preference.PreferenceBinding
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
|
open class SeparateRingVolumePreference :
|
||||||
|
PreferenceMetadata,
|
||||||
|
PreferenceBinding,
|
||||||
|
PersistentPreference<Int>,
|
||||||
|
RangeValue,
|
||||||
|
PreferenceAvailabilityProvider,
|
||||||
|
PreferenceIconProvider,
|
||||||
|
PreferenceRestrictionProvider {
|
||||||
|
override val key: String
|
||||||
|
get() = KEY
|
||||||
|
|
||||||
|
override val title: Int
|
||||||
|
get() = R.string.separate_ring_volume_option_title
|
||||||
|
|
||||||
|
override fun getIcon(context: Context) =
|
||||||
|
when {
|
||||||
|
VolumeHelper.isMuted(context, STREAM_RING) -> getMuteIcon(context)
|
||||||
|
else -> R.drawable.ic_ring_volume
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAvailable(context: Context) = !createAudioHelper(context).isSingleVolume()
|
||||||
|
|
||||||
|
override fun isEnabled(context: Context) =
|
||||||
|
!RestrictedLockUtilsInternal.hasBaseUserRestriction(
|
||||||
|
context,
|
||||||
|
DISALLOW_ADJUST_VOLUME,
|
||||||
|
UserHandle.myUserId(),
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun isRestricted(context: Context) =
|
||||||
|
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
|
||||||
|
context,
|
||||||
|
DISALLOW_ADJUST_VOLUME,
|
||||||
|
UserHandle.myUserId(),
|
||||||
|
) != null
|
||||||
|
|
||||||
|
override fun storage(context: Context): KeyValueStore {
|
||||||
|
val helper = createAudioHelper(context)
|
||||||
|
return object : NoOpKeyedObservable<String>(), KeyValueStore {
|
||||||
|
override fun contains(key: String) = key == KEY
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
|
||||||
|
helper.getStreamVolume(STREAM_RING) as T
|
||||||
|
|
||||||
|
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
|
||||||
|
helper.setStreamVolume(STREAM_RING, value as Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMinValue(context: Context) =
|
||||||
|
createAudioHelper(context).getMinVolume(STREAM_RING)
|
||||||
|
|
||||||
|
override fun getMaxValue(context: Context) =
|
||||||
|
createAudioHelper(context).getMaxVolume(STREAM_RING)
|
||||||
|
|
||||||
|
override fun createWidget(context: Context) = VolumeSeekBarPreference(context)
|
||||||
|
|
||||||
|
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
|
||||||
|
super.bind(preference, metadata)
|
||||||
|
(preference as VolumeSeekBarPreference).apply {
|
||||||
|
setStream(STREAM_RING)
|
||||||
|
setMuteIcon(getMuteIcon(preference.context))
|
||||||
|
setListener { updateContentDescription(this) }
|
||||||
|
setSuppressionText(getSuppressionText(preference.context))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun createAudioHelper(context: Context) = AudioHelper(context)
|
||||||
|
|
||||||
|
fun updateContentDescription(preference: VolumeSeekBarPreference) {
|
||||||
|
val context = preference.context
|
||||||
|
val ringerMode = getEffectiveRingerMode(context)
|
||||||
|
when (ringerMode) {
|
||||||
|
RINGER_MODE_VIBRATE ->
|
||||||
|
preference.updateContentDescription(
|
||||||
|
context.getString(R.string.ringer_content_description_vibrate_mode)
|
||||||
|
)
|
||||||
|
RINGER_MODE_SILENT ->
|
||||||
|
preference.updateContentDescription(
|
||||||
|
context.getString(R.string.ringer_content_description_silent_mode)
|
||||||
|
)
|
||||||
|
else -> preference.updateContentDescription(preference.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMuteIcon(context: Context): Int {
|
||||||
|
val ringerMode = getEffectiveRingerMode(context)
|
||||||
|
return when (ringerMode) {
|
||||||
|
RINGER_MODE_NORMAL -> R.drawable.ic_ring_volume
|
||||||
|
RINGER_MODE_VIBRATE -> R.drawable.ic_volume_ringer_vibrate
|
||||||
|
else -> R.drawable.ic_ring_volume_off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEffectiveRingerMode(context: Context): Int {
|
||||||
|
val hasVibrator = context.getSystemService(Vibrator::class.java)?.hasVibrator() ?: false
|
||||||
|
val ringerMode = createAudioHelper(context).ringerModeInternal
|
||||||
|
return when {
|
||||||
|
!hasVibrator && ringerMode == RINGER_MODE_VIBRATE -> RINGER_MODE_SILENT
|
||||||
|
else -> ringerMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSuppressionText(context: Context): String? {
|
||||||
|
val suppressor = NotificationManager.from(context).getEffectsSuppressor()
|
||||||
|
val notificationManager =
|
||||||
|
INotificationManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NOTIFICATION_SERVICE)
|
||||||
|
)
|
||||||
|
val hints = notificationManager.getHintsFromListenerNoToken()
|
||||||
|
return when {
|
||||||
|
hintsMatch(hints) -> SuppressorHelper.getSuppressionText(context, suppressor)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hintsMatch(hints: Int) =
|
||||||
|
(hints and HINT_HOST_DISABLE_CALL_EFFECTS) != 0 ||
|
||||||
|
(hints and HINT_HOST_DISABLE_EFFECTS) != 0
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY = "separate_ring_volume"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LINT.ThenChange(SeparateRingVolumePreferenceController.java)
|
@@ -35,6 +35,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
|
|||||||
/**
|
/**
|
||||||
* This slider is used to represent ring volume when ring is separated from notification
|
* This slider is used to represent ring volume when ring is separated from notification
|
||||||
*/
|
*/
|
||||||
|
// LINT.IfChange
|
||||||
public class SeparateRingVolumePreferenceController extends
|
public class SeparateRingVolumePreferenceController extends
|
||||||
RingerModeAffectedVolumePreferenceController {
|
RingerModeAffectedVolumePreferenceController {
|
||||||
|
|
||||||
@@ -149,3 +150,4 @@ public class SeparateRingVolumePreferenceController extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// LINT.ThenChange(SeparateRingVolumePreference.kt)
|
||||||
|
@@ -49,7 +49,9 @@ class SoundScreen : PreferenceScreenCreator, PreferenceIconProvider {
|
|||||||
|
|
||||||
override fun getPreferenceHierarchy(context: Context) =
|
override fun getPreferenceHierarchy(context: Context) =
|
||||||
preferenceHierarchy(this) {
|
preferenceHierarchy(this) {
|
||||||
|
+MediaVolumePreference() order -180
|
||||||
+CallVolumePreference() order -170
|
+CallVolumePreference() order -170
|
||||||
|
+SeparateRingVolumePreference() order -155
|
||||||
+DialPadTonePreference() order -50
|
+DialPadTonePreference() order -50
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
src/com/android/settings/notification/VolumeHelper.kt
Normal file
62
src/com/android/settings/notification/VolumeHelper.kt
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification
|
||||||
|
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
|
||||||
|
import android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.media.AudioManager.*
|
||||||
|
import android.provider.Settings.Global.ZEN_MODE_ALARMS
|
||||||
|
import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
|
||||||
|
import android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
|
||||||
|
import android.service.notification.ZenModeConfig
|
||||||
|
|
||||||
|
class VolumeHelper {
|
||||||
|
companion object {
|
||||||
|
fun isMuted(context: Context, streamType: Int): Boolean {
|
||||||
|
val audioManager = context.getSystemService(AudioManager::class.java)
|
||||||
|
return audioManager.isStreamMute(streamType) && !isZenMuted(context, streamType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isZenMuted(context: Context, streamType: Int): Boolean {
|
||||||
|
val notificationManager = context.getSystemService(NotificationManager::class.java)
|
||||||
|
val zenMode = notificationManager.getZenMode()
|
||||||
|
val notificationPolicy = notificationManager.getConsolidatedNotificationPolicy()
|
||||||
|
val isAllowAlarms =
|
||||||
|
(notificationPolicy.priorityCategories and PRIORITY_CATEGORY_ALARMS) != 0
|
||||||
|
val isAllowMedia =
|
||||||
|
(notificationPolicy.priorityCategories and PRIORITY_CATEGORY_MEDIA) != 0
|
||||||
|
val isAllowRinger =
|
||||||
|
!ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(notificationPolicy)
|
||||||
|
return isNotificationOrRingStream(streamType)
|
||||||
|
&& zenMode == ZEN_MODE_ALARMS || zenMode == ZEN_MODE_NO_INTERRUPTIONS
|
||||||
|
|| (zenMode == ZEN_MODE_IMPORTANT_INTERRUPTIONS
|
||||||
|
&& (!isAllowRinger && isNotificationOrRingStream(streamType)
|
||||||
|
|| !isAllowMedia && isMediaStream(streamType)
|
||||||
|
|| !isAllowAlarms && isAlarmStream(streamType)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isNotificationOrRingStream(streamType: Int) =
|
||||||
|
streamType == STREAM_RING || streamType == STREAM_NOTIFICATION
|
||||||
|
|
||||||
|
private fun isAlarmStream(streamType: Int) = streamType == STREAM_ALARM
|
||||||
|
|
||||||
|
private fun isMediaStream(streamType: Int) = streamType == STREAM_MUSIC
|
||||||
|
}
|
||||||
|
}
|
@@ -377,7 +377,14 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
|||||||
setBiometricPromptPropertiesForPrivateProfile(promptInfo);
|
setBiometricPromptPropertiesForPrivateProfile(promptInfo);
|
||||||
showBiometricPrompt(promptInfo, effectiveUserId);
|
showBiometricPrompt(promptInfo, effectiveUserId);
|
||||||
launchedBiometric = true;
|
launchedBiometric = true;
|
||||||
|
} else if (Flags.privateSpaceBp()) {
|
||||||
|
promptInfo.setAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL);
|
||||||
|
setBiometricPromptPropertiesForPrivateProfile(promptInfo);
|
||||||
|
showBiometricPrompt(promptInfo, mUserId);
|
||||||
|
launchedBiometric = true;
|
||||||
} else {
|
} else {
|
||||||
|
// TODO(b/376328272): Remove custom private space behavior
|
||||||
|
mDetails = Utils.getConfirmCredentialStringForUser(this, mUserId, credentialType);
|
||||||
showConfirmCredentials();
|
showConfirmCredentials();
|
||||||
launchedCDC = true;
|
launchedCDC = true;
|
||||||
}
|
}
|
||||||
|
34
src/com/android/settings/utils/IntentUtils.kt
Normal file
34
src/com/android/settings/utils/IntentUtils.kt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import com.android.settings.SettingsActivity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the [Intent] to start given settings activity and locate the preference.
|
||||||
|
*
|
||||||
|
* @param context context
|
||||||
|
* @param activityClass activity to start
|
||||||
|
* @param key preference key to locate
|
||||||
|
*/
|
||||||
|
fun makeLaunchIntent(context: Context, activityClass: Class<out Activity>, key: String?) =
|
||||||
|
Intent(context, activityClass).apply {
|
||||||
|
if (key != null) putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key)
|
||||||
|
}
|
@@ -30,6 +30,7 @@ import android.util.TypedValue;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.preference.PreferenceGroup;
|
import androidx.preference.PreferenceGroup;
|
||||||
import androidx.preference.PreferenceGroupAdapter;
|
import androidx.preference.PreferenceGroupAdapter;
|
||||||
@@ -64,7 +65,7 @@ public class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter
|
|||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final int mNormalBackgroundRes;
|
private final int mNormalBackgroundRes;
|
||||||
private final String mHighlightKey;
|
private final @Nullable String mHighlightKey;
|
||||||
private boolean mHighlightRequested;
|
private boolean mHighlightRequested;
|
||||||
private int mHighlightPosition = RecyclerView.NO_POSITION;
|
private int mHighlightPosition = RecyclerView.NO_POSITION;
|
||||||
|
|
||||||
@@ -101,7 +102,8 @@ public class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter
|
|||||||
screen.setInitialExpandedChildrenCount(initialCount);
|
screen.setInitialExpandedChildrenCount(initialCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup, String key,
|
public HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup,
|
||||||
|
@Nullable String key,
|
||||||
boolean highlightRequested) {
|
boolean highlightRequested) {
|
||||||
super(preferenceGroup);
|
super(preferenceGroup);
|
||||||
mHighlightKey = key;
|
mHighlightKey = key;
|
||||||
|
@@ -38,11 +38,8 @@ import android.os.Build;
|
|||||||
import android.os.SystemConfigManager;
|
import android.os.SystemConfigManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
|
||||||
import android.platform.test.annotations.RequiresFlagsEnabled;
|
|
||||||
import android.platform.test.flag.junit.CheckFlagsRule;
|
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||||
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||||
import android.webkit.Flags;
|
|
||||||
|
|
||||||
import com.android.settings.testutils.ApplicationTestUtils;
|
import com.android.settings.testutils.ApplicationTestUtils;
|
||||||
import com.android.settings.webview.WebViewUpdateServiceWrapper;
|
import com.android.settings.webview.WebViewUpdateServiceWrapper;
|
||||||
@@ -373,7 +370,6 @@ public final class ApplicationFeatureProviderImplTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@RequiresFlagsEnabled(Flags.FLAG_UPDATE_SERVICE_V2)
|
|
||||||
public void getKeepEnabledPackages_shouldContainWebViewPackage() {
|
public void getKeepEnabledPackages_shouldContainWebViewPackage() {
|
||||||
final String testWebViewPackageName = "com.android.webview";
|
final String testWebViewPackageName = "com.android.webview";
|
||||||
when(mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName())
|
when(mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName())
|
||||||
@@ -382,16 +378,6 @@ public final class ApplicationFeatureProviderImplTest {
|
|||||||
assertThat(allowlist).contains(testWebViewPackageName);
|
assertThat(allowlist).contains(testWebViewPackageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@RequiresFlagsDisabled(Flags.FLAG_UPDATE_SERVICE_V2)
|
|
||||||
public void getKeepEnabledPackages_shouldNotContainWebViewPackageIfFlagDisabled() {
|
|
||||||
final String testWebViewPackageName = "com.android.webview";
|
|
||||||
when(mWebViewUpdateServiceWrapper.getDefaultWebViewPackageName())
|
|
||||||
.thenReturn(testWebViewPackageName);
|
|
||||||
final Set<String> allowlist = mProvider.getKeepEnabledPackages();
|
|
||||||
assertThat(allowlist).doesNotContain(testWebViewPackageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
|
@Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
|
||||||
public void getKeepEnabledPackages_shouldContainPackageInstaller() {
|
public void getKeepEnabledPackages_shouldContainPackageInstaller() {
|
||||||
|
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fingerprint;
|
||||||
|
|
||||||
|
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||||
|
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||||
|
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.eq;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.platform.test.annotations.EnableFlags;
|
||||||
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||||
|
import com.android.settingslib.RestrictedSwitchPreference;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = {ShadowUtils.class})
|
||||||
|
public class FingerprintSettingsScreenOffUnlockUdfpsPreferenceControllerTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||||
|
@Mock
|
||||||
|
private FingerprintManager mFingerprintManager;
|
||||||
|
@Mock
|
||||||
|
private PackageManager mPackageManager;
|
||||||
|
@Mock
|
||||||
|
private RestrictedSwitchPreference mPreference;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private FingerprintSettingsScreenOffUnlockUdfpsPreferenceController mController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
when(mContext.getSystemService(eq(Context.FINGERPRINT_SERVICE))).thenReturn(
|
||||||
|
mFingerprintManager);
|
||||||
|
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||||
|
|
||||||
|
mController = spy(new FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(mContext,
|
||||||
|
"test_key"));
|
||||||
|
ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowUtils.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPreferenceChange_settingIsUpdated() {
|
||||||
|
boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||||
|
Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED, 1) != 0;
|
||||||
|
|
||||||
|
assertThat(mController.isChecked()).isFalse();
|
||||||
|
assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
|
||||||
|
boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||||
|
Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED, 1) != 0;
|
||||||
|
assertThat(newState).isEqualTo(!state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isAvailable_isEnabled_whenUdfpsHardwareDetected_AndHasEnrolledFingerprints() {
|
||||||
|
assertThat(mController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
|
||||||
|
true /* isHardwareDetected */,
|
||||||
|
false /* isPowerbuttonFps false implies udfps */,
|
||||||
|
true /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mController.isAvailable()).isEqualTo(true);
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isUnavailable_isDisabled_whenUdfpsHardwareDetected_AndNoEnrolledFingerprints() {
|
||||||
|
assertThat(mController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
|
||||||
|
true /* isHardwareDetected */,
|
||||||
|
false /* isPowerbuttonFps false implies udfps */,
|
||||||
|
false /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isUnavailable_whenHardwareNotDetected() {
|
||||||
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
|
||||||
|
false /* isHardwareDetected */,
|
||||||
|
false /* isPowerbuttonFps false implies udfps */,
|
||||||
|
true /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isUnavailable_onNonUdfpsDevice() {
|
||||||
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
|
||||||
|
true /* isHardwareDetected */,
|
||||||
|
true /* isPowerbuttonFps false implies udfps */,
|
||||||
|
true /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
|
||||||
|
boolean isHardwareDetected, boolean isPowerbuttonFps, boolean hasEnrolledTemplates) {
|
||||||
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(isHardwareDetected);
|
||||||
|
when(mFingerprintManager.isPowerbuttonFps()).thenReturn(isPowerbuttonFps);
|
||||||
|
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(hasEnrolledTemplates);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -30,12 +30,15 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.platform.test.annotations.EnableFlags;
|
||||||
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
|
|
||||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||||
import com.android.settingslib.RestrictedSwitchPreference;
|
import com.android.settingslib.RestrictedSwitchPreference;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@@ -49,6 +52,8 @@ import org.robolectric.util.ReflectionHelpers;
|
|||||||
@Config(shadows = {ShadowUtils.class})
|
@Config(shadows = {ShadowUtils.class})
|
||||||
public class FingerprintSettingsUnlockCategoryControllerTest {
|
public class FingerprintSettingsUnlockCategoryControllerTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||||
@Mock
|
@Mock
|
||||||
private FingerprintManager mFingerprintManager;
|
private FingerprintManager mFingerprintManager;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -59,6 +64,8 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private FingerprintSettingsRequireScreenOnToAuthPreferenceController mController;
|
private FingerprintSettingsRequireScreenOnToAuthPreferenceController mController;
|
||||||
|
|
||||||
|
private FingerprintSettingsScreenOffUnlockUdfpsPreferenceController mScreenOffUnlockController;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
@@ -69,7 +76,12 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
|
|||||||
|
|
||||||
mController = spy(new FingerprintSettingsRequireScreenOnToAuthPreferenceController(mContext,
|
mController = spy(new FingerprintSettingsRequireScreenOnToAuthPreferenceController(mContext,
|
||||||
"test_key"));
|
"test_key"));
|
||||||
|
mScreenOffUnlockController = spy(
|
||||||
|
new FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(mContext,
|
||||||
|
"screen_off_unlock_test_key"));
|
||||||
ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
|
ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
|
||||||
|
ReflectionHelpers.setField(mScreenOffUnlockController, "mFingerprintManager",
|
||||||
|
mFingerprintManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -89,6 +101,20 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
|
|||||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isAvailable_isEnabled_whenUdfpsHardwareDetected_AndHasEnrolledFingerprints() {
|
||||||
|
assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
|
||||||
|
true /* isHardwareDetected */,
|
||||||
|
false /* isPowerbuttonFps false implies udfps */,
|
||||||
|
true /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(true);
|
||||||
|
assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isUnavailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
|
public void isUnavailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
|
||||||
assertThat(mController.isAvailable()).isEqualTo(false);
|
assertThat(mController.isAvailable()).isEqualTo(false);
|
||||||
@@ -102,7 +128,22 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isUnavailable_whenHardwareNotDetected() {
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isUnavailable_isDisabled_whenUdfpsHardwareDetected_AndNoEnrolledFingerprints() {
|
||||||
|
assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
|
||||||
|
true /* isHardwareDetected */,
|
||||||
|
false /* isPowerbuttonFps false implies udfps */,
|
||||||
|
false /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
CONDITIONALLY_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isUnavailable_whenHardwareNotDetected_onSfpsDevice() {
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
|
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
|
||||||
@@ -113,6 +154,21 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
|
|||||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
|
||||||
|
public void isUnavailable_whenHardwareNotDetected_onUdfpsDevice() {
|
||||||
|
assertThat(mScreenOffUnlockController.isAvailable()).isFalse();
|
||||||
|
assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
UNSUPPORTED_ON_DEVICE);
|
||||||
|
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
|
||||||
|
false /* isHardwareDetected */,
|
||||||
|
false /* isPowerbuttonFps false implies udfps */,
|
||||||
|
true /* hasEnrolledTemplates */);
|
||||||
|
assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
|
||||||
|
assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
|
||||||
|
UNSUPPORTED_ON_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isUnavailable_onNonSfpsDevice() {
|
public void isUnavailable_onNonSfpsDevice() {
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.deviceinfo.aboutphone
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings.Global
|
||||||
|
import com.android.settings.flags.Flags
|
||||||
|
import com.android.settingslib.preference.CatalystScreenTestCase
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.robolectric.RuntimeEnvironment
|
||||||
|
|
||||||
|
class MyDeviceInfoScreenTest : CatalystScreenTestCase() {
|
||||||
|
private lateinit var context: Context
|
||||||
|
|
||||||
|
override val preferenceScreenCreator = MyDeviceInfoScreen()
|
||||||
|
override val flagName: String
|
||||||
|
get() = Flags.FLAG_CATALYST_MY_DEVICE_INFO_PREF_SCREEN
|
||||||
|
|
||||||
|
override fun migration() {}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
context = RuntimeEnvironment.getApplication()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun key() {
|
||||||
|
assertThat(preferenceScreenCreator.key).isEqualTo(MyDeviceInfoScreen.KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getSummary_deviceNameNotSet_shouldReturnDeviceModel() {
|
||||||
|
assertThat(preferenceScreenCreator.getSummary(context)?.toString()).isEqualTo(Build.MODEL)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getSummary_deviceNameSet_shouldReturnDeviceName() {
|
||||||
|
Global.putString(context.contentResolver, Global.DEVICE_NAME, "Test")
|
||||||
|
assertThat(preferenceScreenCreator.getSummary(context)?.toString()).isEqualTo("Test")
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.network
|
||||||
|
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.PackageManager.FEATURE_LEANBACK
|
||||||
|
import android.content.res.Resources
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class AirplaneModePreferenceTest {
|
||||||
|
|
||||||
|
private val mockPackageManager = mock<PackageManager>()
|
||||||
|
private val mockResources = mock<Resources>()
|
||||||
|
|
||||||
|
private val context =
|
||||||
|
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||||
|
override fun getPackageManager(): PackageManager = mockPackageManager
|
||||||
|
|
||||||
|
override fun getResources(): Resources = mockResources
|
||||||
|
}
|
||||||
|
|
||||||
|
private val airplaneModePreference = AirplaneModePreference()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_hasConfigAndNoFeatureLeanback_shouldReturnTrue() {
|
||||||
|
mockResources.stub { on { getBoolean(anyInt()) } doReturn true }
|
||||||
|
mockPackageManager.stub { on { hasSystemFeature(FEATURE_LEANBACK) } doReturn false }
|
||||||
|
|
||||||
|
assertThat(airplaneModePreference.isAvailable(context)).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_noConfig_shouldReturnFalse() {
|
||||||
|
mockResources.stub { on { getBoolean(anyInt()) } doReturn false }
|
||||||
|
mockPackageManager.stub { on { hasSystemFeature(FEATURE_LEANBACK) } doReturn false }
|
||||||
|
|
||||||
|
assertThat(airplaneModePreference.isAvailable(context)).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_hasFeatureLeanback_shouldReturnFalse() {
|
||||||
|
mockResources.stub { on { getBoolean(anyInt()) } doReturn true }
|
||||||
|
mockPackageManager.stub { on { hasSystemFeature(FEATURE_LEANBACK) } doReturn true }
|
||||||
|
|
||||||
|
assertThat(airplaneModePreference.isAvailable(context)).isFalse()
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.network.tether
|
||||||
|
|
||||||
|
import android.net.TetheringManager
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.flags.Flags
|
||||||
|
import com.android.settings.testutils.shadow.ShadowConnectivityManager
|
||||||
|
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal
|
||||||
|
import com.android.settingslib.Utils
|
||||||
|
import com.android.settingslib.preference.CatalystScreenTestCase
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
import org.robolectric.annotation.Implementation
|
||||||
|
import org.robolectric.annotation.Implements
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@Config(shadows = [ShadowConnectivityManager::class, ShadowRestrictedLockUtilsInternal::class,
|
||||||
|
ShadowTetheringManager::class])
|
||||||
|
class TetherScreenTest : CatalystScreenTestCase() {
|
||||||
|
override val preferenceScreenCreator = TetherScreen()
|
||||||
|
|
||||||
|
override val flagName: String
|
||||||
|
get() = Flags.FLAG_CATALYST_TETHER_SETTINGS
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
ShadowConnectivityManager.getShadow().setTetheringSupported(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun key() {
|
||||||
|
assertThat(preferenceScreenCreator.key).isEqualTo(TetherScreen.KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getPreferenceTitle_tetherConfigDisallowed_shouldShowAll() {
|
||||||
|
ShadowRestrictedLockUtilsInternal.setRestricted(true)
|
||||||
|
|
||||||
|
assertThat(preferenceScreenCreator.getPreferenceTitle(appContext)).isEqualTo(
|
||||||
|
appContext.getString(R.string.tether_settings_title_all))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getPreferenceTitle_tetherConfigAllowed_shouldShowTetheringLabel() {
|
||||||
|
ShadowRestrictedLockUtilsInternal.setRestricted(false)
|
||||||
|
val tm = appContext.getSystemService(TetheringManager::class.java)
|
||||||
|
|
||||||
|
assertThat(preferenceScreenCreator.getPreferenceTitle(appContext)).isEqualTo(
|
||||||
|
appContext.getText(Utils.getTetheringLabel(tm)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_tetherIsAvailable_shouldReturnTrue() {
|
||||||
|
ShadowRestrictedLockUtilsInternal.setRestricted(false)
|
||||||
|
|
||||||
|
assertThat(preferenceScreenCreator.isAvailable(appContext)).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_tetherIsUnavailable_shouldReturnFalse() {
|
||||||
|
ShadowRestrictedLockUtilsInternal.setRestricted(true)
|
||||||
|
|
||||||
|
assertThat(preferenceScreenCreator.isAvailable(appContext)).isFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Implements(TetheringManager::class)
|
||||||
|
class ShadowTetheringManager {
|
||||||
|
private val emptyArray = arrayOf<String>()
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
fun getTetheredIfaces() = emptyArray
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
fun getTetherableIfaces() = emptyArray
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
fun getTetherableWifiRegexs() = emptyArray
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
fun getTetherableUsbRegexs() = emptyArray
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
fun getTetherableBluetoothRegexs() = emptyArray
|
||||||
|
}
|
@@ -58,6 +58,7 @@ import org.robolectric.annotation.Config;
|
|||||||
import org.robolectric.annotation.Implementation;
|
import org.robolectric.annotation.Implementation;
|
||||||
import org.robolectric.annotation.Implements;
|
import org.robolectric.annotation.Implements;
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = MediaVolumePreferenceControllerTest.ShadowSliceBackgroundWorker.class)
|
@Config(shadows = MediaVolumePreferenceControllerTest.ShadowSliceBackgroundWorker.class)
|
||||||
public class MediaVolumePreferenceControllerTest {
|
public class MediaVolumePreferenceControllerTest {
|
||||||
@@ -269,3 +270,4 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// LINT.ThenChange(MediaVolumePreference.kt)
|
||||||
|
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification
|
||||||
|
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.content.res.Resources
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class MediaVolumePreferenceTest {
|
||||||
|
private val mockResources = mock<Resources>()
|
||||||
|
|
||||||
|
private val mediaVolumePreference = MediaVolumePreference()
|
||||||
|
private val context =
|
||||||
|
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||||
|
override fun getResources(): Resources = mockResources
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_configTrue_shouldReturnTrue() {
|
||||||
|
mockResources.stub { on { getBoolean(anyInt()) } doReturn true }
|
||||||
|
|
||||||
|
assertThat(mediaVolumePreference.isAvailable(context)).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_configFalse_shouldReturnFalse() {
|
||||||
|
mockResources.stub { on { getBoolean(anyInt()) } doReturn false }
|
||||||
|
|
||||||
|
assertThat(mediaVolumePreference.isAvailable(context)).isFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LINT.ThenChange(MediaVolumePreferenceControllerTest.java)
|
@@ -41,6 +41,7 @@ import org.robolectric.RuntimeEnvironment;
|
|||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.shadows.ShadowApplication;
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowDeviceConfig.class})
|
@Config(shadows = {ShadowDeviceConfig.class})
|
||||||
public class SeparateRingVolumePreferenceControllerTest {
|
public class SeparateRingVolumePreferenceControllerTest {
|
||||||
@@ -108,3 +109,4 @@ public class SeparateRingVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// LINT.ThenChange(SeparateRingVolumePreferenceTest.kt)
|
||||||
|
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification
|
||||||
|
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.media.AudioManager.RINGER_MODE_NORMAL
|
||||||
|
import android.media.AudioManager.RINGER_MODE_SILENT
|
||||||
|
import android.media.AudioManager.RINGER_MODE_VIBRATE
|
||||||
|
import android.os.Vibrator
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.spy
|
||||||
|
import org.mockito.kotlin.stub
|
||||||
|
|
||||||
|
// LINT.IfChange
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class SeparateRingVolumePreferenceTest {
|
||||||
|
private var audioHelper = mock<AudioHelper>()
|
||||||
|
private var vibrator: Vibrator? = null
|
||||||
|
private var ringVolumePreference = SeparateRingVolumePreference()
|
||||||
|
|
||||||
|
private val context =
|
||||||
|
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||||
|
override fun getSystemService(name: String): Any? =
|
||||||
|
when {
|
||||||
|
name == getSystemServiceName(Vibrator::class.java) -> vibrator
|
||||||
|
else -> super.getSystemService(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_singleVolume_shouldReturnFalse() {
|
||||||
|
audioHelper = mock { on { isSingleVolume } doReturn true }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.isAvailable(context)).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isAvailable_noSingleVolume_shouldReturnTrue() {
|
||||||
|
audioHelper = mock { on { isSingleVolume } doReturn false }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.isAvailable(context)).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getEffectiveRingerMode_noVibratorAndVibrateMode_shouldReturnSilentMode() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn false }
|
||||||
|
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.getEffectiveRingerMode(context))
|
||||||
|
.isEqualTo(RINGER_MODE_SILENT)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getEffectiveRingerMode_hasVibratorAndVibrateMode_shouldReturnVibrateMode() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
|
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.getEffectiveRingerMode(context))
|
||||||
|
.isEqualTo(RINGER_MODE_VIBRATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getEffectiveRingerMode_hasVibratorAndNormalMode_shouldReturnNormalMode() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
|
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_NORMAL }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.getEffectiveRingerMode(context))
|
||||||
|
.isEqualTo(RINGER_MODE_NORMAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMuteIcon_normalMode_shouldReturnRingVolumeIcon() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
|
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_NORMAL }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.getMuteIcon(context)).isEqualTo(R.drawable.ic_ring_volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMuteIcon_vibrateMode_shouldReturnVibrateIcon() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn true }
|
||||||
|
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.getMuteIcon(context))
|
||||||
|
.isEqualTo(R.drawable.ic_volume_ringer_vibrate)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getMuteIcon_silentMode_shouldReturnSilentIcon() {
|
||||||
|
vibrator = mock { on { hasVibrator() } doReturn false }
|
||||||
|
audioHelper = mock { on { ringerModeInternal } doReturn RINGER_MODE_VIBRATE }
|
||||||
|
ringVolumePreference =
|
||||||
|
spy(ringVolumePreference).stub {
|
||||||
|
onGeneric { createAudioHelper(context) } doReturn audioHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(ringVolumePreference.getMuteIcon(context))
|
||||||
|
.isEqualTo(R.drawable.ic_ring_volume_off)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// LINT.ThenChange(SeparateRingVolumePreferenceControllerTest.java)
|
@@ -34,7 +34,6 @@ import android.net.VpnManager;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.SettingsSlicesContract;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -102,7 +101,7 @@ public class VpnPreferenceControllerTest {
|
|||||||
|
|
||||||
controller.displayPreference(mScreen);
|
controller.displayPreference(mScreen);
|
||||||
|
|
||||||
verify(mPreference).setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
|
verify(mPreference).setDependency(Settings.Global.AIRPLANE_MODE_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Reference in New Issue
Block a user