Snap for 13120928 from 6191772de7 to 25Q2-release
Change-Id: I0b03f8283054b80ff5cf36c3de16a7b81e61c149
This commit is contained in:
@@ -12587,12 +12587,20 @@
|
||||
<string name="category_name_how_it_works">How it works</string>
|
||||
<!-- Title for satellite connection guide [CHAR_LIMIT=NONE] -->
|
||||
<string name="title_satellite_connection_guide">When you don\u2019t have a mobile network</string>
|
||||
<!-- Title for satellite connection guide for NTN manual connection type. [CHAR_LIMIT=NONE] -->
|
||||
<string name="title_satellite_connection_guide_for_manual_type">Text a phone number</string>
|
||||
<!-- Summary for satellite connection guide [CHAR_LIMIT=NONE] -->
|
||||
<string name="summary_satellite_connection_guide">Your phone will auto-connect to a satellite. For the best connection, keep a clear view of the sky.</string>
|
||||
<!-- Summary for satellite connection guide for NTN manual connection type. [CHAR_LIMIT=NONE] -->
|
||||
<string name="summary_satellite_connection_guide_for_manual_type">If you don\u2019t have a mobile network, you\u2019ll see an option to use satellite messaging.</string>
|
||||
<!-- Title for satellite supported service [CHAR_LIMIT=NONE] -->
|
||||
<string name="title_supported_service">After your phone connects to a satellite</string>
|
||||
<!-- Title for satellite supported service for NTN manual connection type. [CHAR_LIMIT=NONE] -->
|
||||
<string name="title_supported_service_for_manual_type">Follow steps to connect to the satellite</string>
|
||||
<!-- Summary for satellite supported service [CHAR_LIMIT=NONE] -->
|
||||
<string name="summary_supported_service">You can text anyone, including emergency services. Your phone will reconnect to a mobile network when available.</string>
|
||||
<!-- Summary for satellite supported service for NTN manual connection type. [CHAR_LIMIT=NONE] -->
|
||||
<string name="summary_supported_service_for_manual_type">After your phone is connected, you can text anyone, including emergency services.</string>
|
||||
<!-- learn more text - more about satellite messaging [CHAR_LIMIT=NONE] -->
|
||||
<string name="satellite_setting_summary_more_information"><xliff:g id="subject" example="satellite messaging">%1$s</xliff:g> may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact <xliff:g id="carrier_name" example="T-Mobile">%2$s</xliff:g> for details.</string>
|
||||
<!-- learn more text - more about satellite messaging without emergency messaging support. [CHAR_LIMIT=NONE] -->
|
||||
|
||||
@@ -56,4 +56,27 @@
|
||||
android:key="recs"
|
||||
android:title="@*android:string/recs_notification_channel_label"
|
||||
settings:controller="com.android.settings.notification.BundleTypePreferenceController"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="notification_bundle_excluded_apps_list"
|
||||
android:title="@string/notification_excluded_apps"
|
||||
settings:controller="com.android.settings.notification.AdjustmentExcludedAppsPreferenceController">
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:key="excluded_description"
|
||||
android:title="@string/notification_bundle_excluded_description"/>
|
||||
|
||||
<!-- apps are added here -->
|
||||
|
||||
<Preference
|
||||
android:key="notification_bundle_manage_apps"
|
||||
android:order="1000"
|
||||
android:icon="@drawable/ic_chevron_right_24dp"
|
||||
android:title="@string/notification_summarization_manage_excluded_apps"
|
||||
settings:controller="com.android.settings.notification.BundleManageAppsPreferenceController"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$NotificationExcludeClassificationActivity"/>
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -114,11 +114,10 @@
|
||||
android:summary="@string/oem_unlock_enable_summary"
|
||||
settings:useAdditionalSummary="true" />
|
||||
|
||||
<SwitchPreference
|
||||
<SwitchPreferenceCompat
|
||||
android:key="enable_16k_pages"
|
||||
android:title="@string/enable_16k_pages"
|
||||
android:summary="@string/enable_16k_pages_summary"
|
||||
settings:useAdditionalSummary="true" />
|
||||
android:summary="@string/enable_16k_pages_summary"/>
|
||||
|
||||
<Preference
|
||||
android:key="running_apps"
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:clickable="false" />
|
||||
android:clickable="false"
|
||||
android:focusable="false"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
|
||||
@@ -36,4 +36,29 @@
|
||||
android:key="global_pref"
|
||||
android:title="@string/notification_summarization_main_control_title"
|
||||
settings:controller="com.android.settings.notification.SummarizationGlobalPreferenceController" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="notification_summarization_excluded_apps_list"
|
||||
android:title="@string/notification_excluded_apps"
|
||||
settings:controller="com.android.settings.notification.AdjustmentExcludedAppsPreferenceController">
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:key="excluded_description"
|
||||
android:title="@string/notification_summarization_excluded_description"/>
|
||||
|
||||
<!-- apps are added here -->
|
||||
|
||||
<Preference
|
||||
android:key="notification_summarization_manage_apps"
|
||||
android:order="1000"
|
||||
android:icon="@drawable/ic_chevron_right_24dp"
|
||||
android:title="@string/notification_summarization_manage_excluded_apps"
|
||||
settings:controller="com.android.settings.notification.SummarizationManageAppsPreferenceController"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$NotificationExcludeSummarizationActivity"/>
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.network.GlobalSettingsChangeListener;
|
||||
import com.android.settings.network.ProxySubscriptionManager;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
@@ -162,19 +161,13 @@ public class AirplaneModeEnabler extends GlobalSettingsChangeListener {
|
||||
if (context == null || telephonyManager == null) {
|
||||
return false;
|
||||
}
|
||||
if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
|
||||
try {
|
||||
if (telephonyManager.getEmergencyCallbackMode()) {
|
||||
return true;
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
// Ignore exception, device is not in ECM mode.
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (telephonyManager.getEmergencyCallbackMode()) {
|
||||
return true;
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
// Ignore exception, device is not in ECM mode.
|
||||
}
|
||||
final List<SubscriptionInfo> subInfoList =
|
||||
ProxySubscriptionManager.getInstance(context).getActiveSubscriptionsInfo();
|
||||
@@ -185,18 +178,12 @@ public class AirplaneModeEnabler extends GlobalSettingsChangeListener {
|
||||
final TelephonyManager telephonyManagerForSubId =
|
||||
telephonyManager.createForSubscriptionId(subInfo.getSubscriptionId());
|
||||
if (telephonyManagerForSubId != null) {
|
||||
if (!Flags.enforceTelephonyFeatureMappingForPublicApis()) {
|
||||
try {
|
||||
if (telephonyManagerForSubId.getEmergencyCallbackMode()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (telephonyManagerForSubId.getEmergencyCallbackMode()) {
|
||||
return true;
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Ignore exception, device is not in ECM mode.
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Ignore exception, device is not in ECM mode.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +358,8 @@ public class Settings extends SettingsActivity {
|
||||
public static class AppBubbleNotificationSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NotificationAssistantSettingsActivity extends SettingsActivity{ /* empty */ }
|
||||
public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NotificationExcludeSummarizationActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NotificationExcludeClassificationActivity extends SettingsActivity { /* empty */ }
|
||||
/** Activity to manage Cloned Apps page */
|
||||
public static class ClonedAppsListActivity extends SettingsActivity { /* empty */ }
|
||||
/** Activity to manage Aspect Ratio app list page */
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.settings.accessibility;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settingslib.display.DisplayDensityUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -28,13 +30,17 @@ import java.util.stream.Collectors;
|
||||
/**
|
||||
* Data class for storing the configurations related to the display size.
|
||||
*/
|
||||
class DisplaySizeData extends PreviewSizeData<Integer> {
|
||||
public class DisplaySizeData extends PreviewSizeData<Integer> {
|
||||
private final DisplayDensityUtils mDensity;
|
||||
|
||||
DisplaySizeData(Context context) {
|
||||
this(context, new DisplayDensityUtils(context));
|
||||
}
|
||||
|
||||
public DisplaySizeData(@NonNull Context context, @NonNull DisplayDensityUtils util) {
|
||||
super(context);
|
||||
|
||||
mDensity = new DisplayDensityUtils(getContext());
|
||||
mDensity = util;
|
||||
final int initialIndex = mDensity.getCurrentIndex();
|
||||
if (initialIndex < 0) {
|
||||
// Failed to obtain default density, which means we failed to
|
||||
@@ -54,7 +60,7 @@ class DisplaySizeData extends PreviewSizeData<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
void commit(int currentProgress) {
|
||||
public void commit(int currentProgress) {
|
||||
final int densityDpi = getValues().get(currentProgress);
|
||||
if (densityDpi == getDefaultValue()) {
|
||||
mDensity.clearForcedDisplayDensity();
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
@@ -51,17 +50,12 @@ public class HearingAidCompatibilityPreferenceController extends TogglePreferenc
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
|
||||
try {
|
||||
return mTelephonyManager.isHearingAidCompatibilitySupported() ? AVAILABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return mTelephonyManager.isHearingAidCompatibilitySupported() ? AVAILABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ abstract class PreviewSizeData<T extends Number> {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
List<T> getValues() {
|
||||
@NonNull
|
||||
public List<T> getValues() {
|
||||
return mValues;
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ abstract class PreviewSizeData<T extends Number> {
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
int getInitialIndex() {
|
||||
public int getInitialIndex() {
|
||||
return mInitialIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -270,6 +270,8 @@ public class ManageApplications extends InstrumentedFragment
|
||||
public static final int LIST_TYPE_NFC_TAG_APPS = 18;
|
||||
public static final int LIST_TYPE_TURN_SCREEN_ON = 19;
|
||||
public static final int LIST_TYPE_USER_ASPECT_RATIO_APPS = 20;
|
||||
public static final int LIST_TYPE_NOTIFICATION_EXCLUDE_SUMMARIZATION = 21;
|
||||
public static final int LIST_TYPE_NOTIFICATION_EXCLUDE_CLASSIFICATION = 22;
|
||||
|
||||
// List types that should show instant apps.
|
||||
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
|
||||
|
||||
@@ -31,6 +31,8 @@ import com.android.settings.Settings.ManageExternalSourcesActivity
|
||||
import com.android.settings.Settings.ManageExternalStorageActivity
|
||||
import com.android.settings.Settings.MediaManagementAppsActivity
|
||||
import com.android.settings.Settings.NotificationAppListActivity
|
||||
import com.android.settings.Settings.NotificationExcludeClassificationActivity
|
||||
import com.android.settings.Settings.NotificationExcludeSummarizationActivity
|
||||
import com.android.settings.Settings.NotificationReviewPermissionsActivity
|
||||
import com.android.settings.Settings.OverlaySettingsActivity
|
||||
import com.android.settings.Settings.StorageUseActivity
|
||||
@@ -44,6 +46,8 @@ import com.android.settings.applications.manageapplications.ManageApplications.L
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_USER_ASPECT_RATIO_APPS
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_BATTERY_OPTIMIZATION
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_CLONED_APPS
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION_EXCLUDE_CLASSIFICATION
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION_EXCLUDE_SUMMARIZATION
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_GAMES
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_HIGH_POWER
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_LONG_BACKGROUND_TASKS
|
||||
@@ -99,6 +103,9 @@ object ManageApplicationsUtil {
|
||||
ChangeNfcTagAppsActivity::class to LIST_TYPE_NFC_TAG_APPS,
|
||||
TurnScreenOnSettingsActivity::class to LIST_TYPE_TURN_SCREEN_ON,
|
||||
UserAspectRatioAppListActivity::class to LIST_TYPE_USER_ASPECT_RATIO_APPS,
|
||||
NotificationExcludeSummarizationActivity::class to LIST_TYPE_NOTIFICATION_EXCLUDE_SUMMARIZATION,
|
||||
NotificationExcludeClassificationActivity::class to LIST_TYPE_NOTIFICATION_EXCLUDE_CLASSIFICATION,
|
||||
|
||||
)
|
||||
|
||||
@JvmField
|
||||
@@ -117,7 +124,7 @@ object ManageApplicationsUtil {
|
||||
LIST_TYPE_MEDIA_MANAGEMENT_APPS -> MediaManagementAppsAppListProvider.getAppListRoute()
|
||||
LIST_TYPE_ALARMS_AND_REMINDERS -> AlarmsAndRemindersAppListProvider.getAppListRoute()
|
||||
LIST_TYPE_WIFI_ACCESS -> WifiControlAppListProvider.getAppListRoute()
|
||||
LIST_TYPE_NOTIFICATION -> AppListNotificationsPageProvider.name
|
||||
LIST_TYPE_NOTIFICATION -> AppListNotificationsPageProvider.AllApps.name
|
||||
LIST_TYPE_APPS_LOCALE -> AppLanguagesPageProvider.name
|
||||
LIST_TYPE_MAIN -> AllAppListPageProvider.name
|
||||
LIST_TYPE_NFC_TAG_APPS -> NfcTagAppsSettingsProvider.getAppListRoute()
|
||||
@@ -128,6 +135,8 @@ object ManageApplicationsUtil {
|
||||
//LIST_TYPE_STORAGE -> StorageAppListPageProvider.Apps.name
|
||||
//LIST_TYPE_GAMES -> StorageAppListPageProvider.Games.name
|
||||
LIST_TYPE_BATTERY_OPTIMIZATION -> BatteryOptimizationModeAppListPageProvider.name
|
||||
LIST_TYPE_NOTIFICATION_EXCLUDE_SUMMARIZATION -> AppListNotificationsPageProvider.ExcludeSummarization.name
|
||||
LIST_TYPE_NOTIFICATION_EXCLUDE_CLASSIFICATION -> AppListNotificationsPageProvider.ExcludeClassification.name
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,11 @@ import android.app.Activity;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.window.DesktopExperienceFlags;
|
||||
|
||||
@@ -48,10 +51,12 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragmentBase;
|
||||
import com.android.settings.accessibility.AccessibilitySeekBarPreference;
|
||||
import com.android.settings.accessibility.DisplaySizeData;
|
||||
import com.android.settings.accessibility.TextReadingPreferenceFragment;
|
||||
import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.DisplayListener;
|
||||
import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.Injector;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settingslib.display.DisplayDensityUtils;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.widget.IllustrationPreference;
|
||||
import com.android.settingslib.widget.MainSwitchPreference;
|
||||
@@ -368,7 +373,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
|
||||
@NonNull
|
||||
private AccessibilitySeekBarPreference reuseSizePreference(Context context,
|
||||
PrefRefresh refresh) {
|
||||
PrefRefresh refresh, int displayId) {
|
||||
AccessibilitySeekBarPreference pref =
|
||||
refresh.findUnusedPreference(PrefBasics.EXTERNAL_DISPLAY_SIZE.key);
|
||||
if (pref == null) {
|
||||
@@ -378,11 +383,27 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
pref.setIconEnd(R.drawable.ic_add_24dp);
|
||||
pref.setIconEndContentDescription(R.string.screen_zoom_make_larger_desc);
|
||||
PrefBasics.EXTERNAL_DISPLAY_SIZE.apply(pref);
|
||||
|
||||
setStateForDisplaySizePreference(context, displayId, pref);
|
||||
}
|
||||
refresh.addPreference(pref);
|
||||
return pref;
|
||||
}
|
||||
|
||||
private void setStateForDisplaySizePreference(Context context, int displayId,
|
||||
AccessibilitySeekBarPreference preference) {
|
||||
var displaySizeData = new DisplaySizeData(context,
|
||||
new DisplayDensityUtils(context, (info) -> info.displayId == displayId));
|
||||
ExternalDisplaySizePreferenceStateHandler seekBarChangeHandler =
|
||||
new ExternalDisplaySizePreferenceStateHandler(
|
||||
displaySizeData, preference);
|
||||
|
||||
preference.setMax(displaySizeData.getValues().size() - 1);
|
||||
preference.setProgress(displaySizeData.getInitialIndex());
|
||||
preference.setContinuousUpdates(false);
|
||||
preference.setOnSeekBarChangeListener(seekBarChangeHandler);
|
||||
}
|
||||
|
||||
private void restoreState(@Nullable Bundle savedInstanceState) {
|
||||
if (savedInstanceState == null) {
|
||||
return;
|
||||
@@ -409,7 +430,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
showTextWhenNoDisplaysToShow(screen, context);
|
||||
} else if (displaysToShow.size() == 1
|
||||
&& ((displayId == INVALID_DISPLAY && !mPreviouslyShownListOfDisplays)
|
||||
|| displaysToShow.get(0).getDisplayId() == displayId)) {
|
||||
|| displaysToShow.get(0).getDisplayId() == displayId)) {
|
||||
showDisplaySettings(displaysToShow.get(0), screen, context);
|
||||
if (displayId == INVALID_DISPLAY && isTopologyPaneEnabled(mInjector)) {
|
||||
// Only show the topology pane if the user did not arrive via the displays list.
|
||||
@@ -514,7 +535,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
}
|
||||
}
|
||||
if (isDisplaySizeSettingEnabled(mInjector)) {
|
||||
addSizePreference(context, refresh);
|
||||
addSizePreference(context, refresh, display.getDisplayId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,7 +553,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
}
|
||||
|
||||
private void showDisplaysList(@NonNull List<Display> displaysToShow,
|
||||
@NonNull PrefRefresh screen, @NonNull Context context) {
|
||||
@NonNull PrefRefresh screen, @NonNull Context context) {
|
||||
maybeAddV2Components(context, screen);
|
||||
int order = PrefBasics.BUILTIN_DISPLAY_LIST.order;
|
||||
for (var display : displaysToShow) {
|
||||
@@ -685,8 +706,8 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
pref.setEnabled(isResolutionSettingEnabled(mInjector));
|
||||
}
|
||||
|
||||
private void addSizePreference(final Context context, PrefRefresh refresh) {
|
||||
var pref = reuseSizePreference(context, refresh);
|
||||
private void addSizePreference(final Context context, PrefRefresh refresh, int displayId) {
|
||||
var pref = reuseSizePreference(context, refresh, displayId);
|
||||
pref.setSummary(EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE);
|
||||
pref.setOnPreferenceClickListener(
|
||||
(Preference p) -> {
|
||||
@@ -735,6 +756,54 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExternalDisplaySizePreferenceStateHandler
|
||||
implements SeekBar.OnSeekBarChangeListener {
|
||||
private static final long MIN_COMMIT_INTERVAL_MS = 800;
|
||||
private static final long CHANGE_BY_BUTTON_DELAY_MS = 300;
|
||||
private final DisplaySizeData mDisplaySizeData;
|
||||
private int mLastDisplayProgress;
|
||||
private long mLastCommitTime;
|
||||
private final AccessibilitySeekBarPreference mPreference;
|
||||
ExternalDisplaySizePreferenceStateHandler(DisplaySizeData displaySizeData,
|
||||
AccessibilitySeekBarPreference preference) {
|
||||
mDisplaySizeData = displaySizeData;
|
||||
mPreference = preference;
|
||||
}
|
||||
|
||||
final Choreographer.FrameCallback mCommit = this::tryCommitDisplaySizeConfig;
|
||||
|
||||
private void tryCommitDisplaySizeConfig(long unusedFrameTimeNanos) {
|
||||
final int displayProgress = mPreference.getProgress();
|
||||
if (displayProgress != mLastDisplayProgress) {
|
||||
mDisplaySizeData.commit(displayProgress);
|
||||
mLastDisplayProgress = displayProgress;
|
||||
}
|
||||
mLastCommitTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
private void postCommitDelayed() {
|
||||
var commitDelayMs = CHANGE_BY_BUTTON_DELAY_MS;
|
||||
if (SystemClock.elapsedRealtime() - mLastCommitTime < MIN_COMMIT_INTERVAL_MS) {
|
||||
commitDelayMs += MIN_COMMIT_INTERVAL_MS;
|
||||
}
|
||||
|
||||
final Choreographer choreographer = Choreographer.getInstance();
|
||||
choreographer.removeFrameCallback(mCommit);
|
||||
choreographer.postFrameCallbackDelayed(mCommit, commitDelayMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(@NonNull SeekBar seekBar, int i, boolean b) {
|
||||
postCommitDelayed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(@NonNull SeekBar seekBar) {}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(@NonNull SeekBar seekBar) {}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class DisplayPreference extends TwoTargetPreference
|
||||
implements Preference.OnPreferenceClickListener {
|
||||
|
||||
@@ -39,7 +39,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.preference.SwitchPreferenceCompat;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
@@ -139,7 +139,7 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
|
||||
Settings.Global.ENABLE_16K_PAGES,
|
||||
defaultOptionValue /* default */);
|
||||
|
||||
((SwitchPreference) mPreference).setChecked(optionValue == ENABLE_16K_PAGE_SIZE);
|
||||
((SwitchPreferenceCompat) mPreference).setChecked(optionValue == ENABLE_16K_PAGE_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +150,7 @@ public class Enable16kPagesPreferenceController extends DeveloperOptionsPreferen
|
||||
mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_16K_PAGES,
|
||||
ENABLE_4K_PAGE_SIZE);
|
||||
((SwitchPreference) mPreference).setChecked(false);
|
||||
((SwitchPreferenceCompat) mPreference).setChecked(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,15 +14,39 @@
|
||||
package com.android.settings.display;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.display.ColorDisplayManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class ColorModePreferenceController extends BasePreferenceController {
|
||||
public class ColorModePreferenceController extends BasePreferenceController
|
||||
implements LifecycleObserver {
|
||||
|
||||
public ColorModePreferenceController(Context context, String key) {
|
||||
private Preference mPreference;
|
||||
|
||||
private final ContentObserver mContentObserver = new ContentObserver(
|
||||
new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, @Nullable Uri uri) {
|
||||
if (mPreference != null) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ColorModePreferenceController(@NonNull Context context, @NonNull String key) {
|
||||
super(context, key);
|
||||
}
|
||||
|
||||
@@ -34,13 +58,43 @@ public class ColorModePreferenceController extends BasePreferenceController {
|
||||
AVAILABLE : DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return ColorModeUtils.getColorModeMapping(mContext.getResources()).get(getColorMode());
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
public void onResume() {
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE),
|
||||
/* notifyForDescendants= */ false,
|
||||
mContentObserver);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int getColorMode() {
|
||||
return mContext.getSystemService(ColorDisplayManager.class).getColorMode();
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||
public void onPause() {
|
||||
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return getColorModeName();
|
||||
}
|
||||
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
if (mPreference != null) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(@Nullable Preference preference) {
|
||||
if (preference == null) {
|
||||
return;
|
||||
}
|
||||
super.updateState(preference);
|
||||
preference.setSummary(getSummary());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getColorModeName() {
|
||||
return ColorModeUtils.getActiveColorModeName(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,8 +213,7 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
|
||||
final Map<Integer, String> colorModesToSummaries =
|
||||
ColorModeUtils.getColorModeMapping(mResources);
|
||||
final List<ColorModeCandidateInfo> candidates = new ArrayList<>();
|
||||
for (int colorMode : mResources.getIntArray(
|
||||
com.android.internal.R.array.config_availableColorModes)) {
|
||||
for (int colorMode : ColorModeUtils.getAvailableColorModes(getContext())) {
|
||||
candidates.add(new ColorModeCandidateInfo(
|
||||
colorModesToSummaries.get(colorMode),
|
||||
getKeyForColorMode(colorMode),
|
||||
@@ -390,8 +389,8 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment {
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
final int[] availableColorModes = context.getResources().getIntArray(
|
||||
com.android.internal.R.array.config_availableColorModes);
|
||||
final int[] availableColorModes =
|
||||
ColorModeUtils.getAvailableColorModes(context);
|
||||
return availableColorModes != null && availableColorModes.length > 0
|
||||
&& !ColorDisplayManager.areAccessibilityTransformsEnabled(context);
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.display;
|
||||
|
||||
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_AUTOMATIC;
|
||||
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_BOOSTED;
|
||||
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_NATURAL;
|
||||
import static android.hardware.display.ColorDisplayManager.COLOR_MODE_SATURATED;
|
||||
import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX;
|
||||
import static android.hardware.display.ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
final class ColorModeUtils {
|
||||
|
||||
private ColorModeUtils() {
|
||||
// Do not instantiate.
|
||||
}
|
||||
|
||||
static Map<Integer, String> getColorModeMapping(Resources resources) {
|
||||
final String[] colorModeOptionsStrings = resources.getStringArray(
|
||||
R.array.config_color_mode_options_strings);
|
||||
final int[] colorModeOptionsValues = resources.getIntArray(
|
||||
R.array.config_color_mode_options_values);
|
||||
if (colorModeOptionsStrings.length != colorModeOptionsValues.length) {
|
||||
throw new RuntimeException("Color mode options of unequal length");
|
||||
}
|
||||
|
||||
final Map<Integer, String> colorModesToSummaries = new ArrayMap<>();
|
||||
for (int i = 0; i < colorModeOptionsValues.length; i++) {
|
||||
final int colorMode = colorModeOptionsValues[i];
|
||||
if (colorMode == COLOR_MODE_NATURAL
|
||||
|| colorMode == COLOR_MODE_BOOSTED
|
||||
|| colorMode == COLOR_MODE_SATURATED
|
||||
|| colorMode == COLOR_MODE_AUTOMATIC
|
||||
|| (colorMode >= VENDOR_COLOR_MODE_RANGE_MIN
|
||||
&& colorMode <= VENDOR_COLOR_MODE_RANGE_MAX)) {
|
||||
colorModesToSummaries.put(colorMode, colorModeOptionsStrings[i]);
|
||||
}
|
||||
}
|
||||
return colorModesToSummaries;
|
||||
}
|
||||
}
|
||||
65
src/com/android/settings/display/ColorModeUtils.kt
Normal file
65
src/com/android/settings/display/ColorModeUtils.kt
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.hardware.display.ColorDisplayManager
|
||||
import android.hardware.display.ColorDisplayManager.*
|
||||
import android.util.Log
|
||||
|
||||
import com.android.settings.R
|
||||
|
||||
object ColorModeUtils {
|
||||
|
||||
private val TAG = "ColorModeUtils"
|
||||
|
||||
@JvmStatic
|
||||
fun getColorModeMapping(resources: Resources): Map<Int, String> {
|
||||
val colorModeOptionsStrings = resources.getStringArray(
|
||||
R.array.config_color_mode_options_strings
|
||||
)
|
||||
val colorModeOptionsValues = resources.getIntArray(
|
||||
R.array.config_color_mode_options_values
|
||||
)
|
||||
if (colorModeOptionsStrings.size!= colorModeOptionsValues.size) {
|
||||
throw RuntimeException("Color mode options of unequal length")
|
||||
}
|
||||
|
||||
val colorModesToSummaries = colorModeOptionsValues.zip(colorModeOptionsStrings).toMap().filterKeys { colorMode ->
|
||||
colorMode == COLOR_MODE_NATURAL ||
|
||||
colorMode == COLOR_MODE_BOOSTED ||
|
||||
colorMode == COLOR_MODE_SATURATED ||
|
||||
colorMode == COLOR_MODE_AUTOMATIC ||
|
||||
(colorMode >= VENDOR_COLOR_MODE_RANGE_MIN &&
|
||||
colorMode <= VENDOR_COLOR_MODE_RANGE_MAX)
|
||||
}
|
||||
|
||||
return colorModesToSummaries
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getColorMode(context: Context): Int =
|
||||
context.getSystemService(ColorDisplayManager::class.java).colorMode
|
||||
|
||||
@JvmStatic
|
||||
fun getActiveColorModeName(context: Context): String =
|
||||
getColorModeMapping(context.resources)[getColorMode(context)] ?: ""
|
||||
|
||||
@JvmStatic
|
||||
fun getAvailableColorModes(context: Context): IntArray =
|
||||
context.getResources().getIntArray(com.android.internal.R.array.config_availableColorModes)
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
@@ -164,7 +165,8 @@ public abstract class LocalePickerBaseListPreferenceController extends
|
||||
return getSortedLocaleList(searchItem);
|
||||
}
|
||||
|
||||
private void setupPreference(List<LocaleStore.LocaleInfo> localeInfoList,
|
||||
@VisibleForTesting
|
||||
void setupPreference(List<LocaleStore.LocaleInfo> localeInfoList,
|
||||
Map<String, Preference> existingPreferences) {
|
||||
Log.d(TAG, "setupPreference: isNumberingMode = " + isNumberingMode());
|
||||
if (isNumberingMode() && getPreferenceCategoryKey().contains(KEY_SUPPORTED)) {
|
||||
@@ -255,7 +257,8 @@ public abstract class LocalePickerBaseListPreferenceController extends
|
||||
return localeInfos;
|
||||
}
|
||||
|
||||
private void switchFragment(LocaleStore.LocaleInfo localeInfo) {
|
||||
@VisibleForTesting
|
||||
void switchFragment(LocaleStore.LocaleInfo localeInfo) {
|
||||
boolean shouldShowLocaleEditor = shouldShowLocaleEditor(localeInfo);
|
||||
if (shouldShowLocaleEditor) {
|
||||
List<LocaleStore.LocaleInfo> feedItemList = getUserLocaleList();
|
||||
@@ -281,7 +284,6 @@ public abstract class LocalePickerBaseListPreferenceController extends
|
||||
.setArguments(extra)
|
||||
.launch();
|
||||
}
|
||||
((Activity) mContext).finish();
|
||||
}
|
||||
|
||||
public void setFragmentManager(@NonNull FragmentManager fragmentManager) {
|
||||
@@ -295,7 +297,8 @@ public abstract class LocalePickerBaseListPreferenceController extends
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldShowLocaleEditor(LocaleStore.LocaleInfo localeInfo) {
|
||||
@VisibleForTesting
|
||||
boolean shouldShowLocaleEditor(LocaleStore.LocaleInfo localeInfo) {
|
||||
boolean isSystemLocale = localeInfo.isSystemLocale();
|
||||
boolean isRegionLocale = localeInfo.getParent() != null;
|
||||
boolean mayHaveDifferentNumberingSystem = localeInfo.hasNumberingSystems();
|
||||
|
||||
@@ -162,8 +162,8 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
if (mTelephonyManager == null) {
|
||||
Log.w(LOG_TAG, "Telephony manager not yet initialized");
|
||||
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
|
||||
Log.w(LOG_TAG, "getAvailabilityStatus: Telephony manager not yet initialized");
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
boolean visible =
|
||||
SubscriptionManager.isUsableSubscriptionId(subId)
|
||||
@@ -189,6 +189,10 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mTelephonyManager == null) {
|
||||
Log.w(LOG_TAG, "isChecked: Telephony manager not yet initialized");
|
||||
return false;
|
||||
}
|
||||
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
|
||||
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
|
||||
return (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
|
||||
@@ -214,6 +218,12 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
|
||||
if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mTelephonyManager == null) {
|
||||
Log.w(LOG_TAG, "setChecked: Telephony manager not yet initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
|
||||
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
|
||||
boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
|
||||
|
||||
@@ -911,15 +911,11 @@ public class EnabledNetworkModePreferenceController extends
|
||||
|
||||
// assign current call state so that it helps to show correct preference state even
|
||||
// before first onCallStateChanged() by initial registration.
|
||||
if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
|
||||
try {
|
||||
mCallState = mTelephonyManager.getCallState(subId);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
mCallState = TelephonyManager.CALL_STATE_IDLE;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
mCallState = mTelephonyManager.getCallState(subId);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
mCallState = TelephonyManager.CALL_STATE_IDLE;
|
||||
}
|
||||
mTelephonyManager.registerTelephonyCallback(
|
||||
mContext.getMainExecutor(), mTelephonyCallback);
|
||||
|
||||
@@ -33,7 +33,6 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.network.ims.VolteQueryImsState;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
@@ -233,15 +232,11 @@ public class Enhanced4gBasePreferenceController extends TelephonyTogglePreferenc
|
||||
}
|
||||
// assign current call state so that it helps to show correct preference state even
|
||||
// before first onCallStateChanged() by initial registration.
|
||||
if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
|
||||
try {
|
||||
mCallState = mTelephonyManager.getCallState(subId);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
mCallState = TelephonyManager.CALL_STATE_IDLE;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
mCallState = mTelephonyManager.getCallState(subId);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// Device doesn't support FEATURE_TELEPHONY_CALLING
|
||||
mCallState = TelephonyManager.CALL_STATE_IDLE;
|
||||
}
|
||||
mTelephonyManager.registerTelephonyCallback(
|
||||
mContext.getMainExecutor(), mTelephonyCallback);
|
||||
|
||||
@@ -70,6 +70,9 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
|
||||
private static final String PREF_KEY_YOUR_SATELLITE_DATA_PLAN = "key_your_satellite_data_plan";
|
||||
private static final String PREF_KEY_CATEGORY_ABOUT_SATELLITE = "key_category_about_satellite";
|
||||
private static final String KEY_FOOTER_PREFERENCE = "satellite_setting_extra_info_footer_pref";
|
||||
private static final String KEY_SATELLITE_CONNECTION_GUIDE = "key_satellite_connection_guide";
|
||||
private static final String KEY_SUPPORTED_SERVICE = "key_supported_service";
|
||||
|
||||
|
||||
static final String SUB_ID = "sub_id";
|
||||
static final String EXTRA_IS_SERVICE_DATA_TYPE = "is_service_data_type";
|
||||
@@ -227,6 +230,15 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
|
||||
category.setEnabled(false);
|
||||
category.setShouldDisableView(true);
|
||||
}
|
||||
if (!isCarrierRoamingNtnConnectedTypeManual()) {
|
||||
return;
|
||||
}
|
||||
Preference connectionGuide = findPreference(KEY_SATELLITE_CONNECTION_GUIDE);
|
||||
connectionGuide.setTitle(R.string.title_satellite_connection_guide_for_manual_type);
|
||||
connectionGuide.setSummary(R.string.summary_satellite_connection_guide_for_manual_type);
|
||||
Preference supportedService = findPreference(KEY_SUPPORTED_SERVICE);
|
||||
supportedService.setTitle(R.string.title_supported_service_for_manual_type);
|
||||
supportedService.setSummary(R.string.summary_supported_service_for_manual_type);
|
||||
}
|
||||
|
||||
private void updateFooterContent() {
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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 static android.service.notification.Adjustment.KEY_SUMMARIZATION;
|
||||
import static android.service.notification.Adjustment.KEY_TYPE;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.service.notification.Adjustment;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.text.BidiFormatter;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Adds a preference to the PreferenceCategory for every app excluded from an adjustment key
|
||||
*/
|
||||
public class AdjustmentExcludedAppsPreferenceController extends BasePreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
@NonNull private NotificationBackend mBackend;
|
||||
|
||||
@Nullable String mAdjustmentKey;
|
||||
@Nullable @VisibleForTesting ApplicationsState mApplicationsState;
|
||||
@VisibleForTesting PreferenceCategory mPreferenceCategory;
|
||||
@VisibleForTesting Context mPrefContext;
|
||||
|
||||
private ApplicationsState.Session mAppSession;
|
||||
|
||||
public AdjustmentExcludedAppsPreferenceController(@NonNull Context context,
|
||||
@NonNull String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mBackend = new NotificationBackend();
|
||||
}
|
||||
|
||||
protected void onAttach(@Nullable ApplicationsState appState, @Nullable Fragment host,
|
||||
@NonNull NotificationBackend helperBackend, @Adjustment.Keys String adjustment) {
|
||||
mApplicationsState = appState;
|
||||
mBackend = helperBackend;
|
||||
mAdjustmentKey = adjustment;
|
||||
|
||||
if (mApplicationsState != null && host != null) {
|
||||
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, host.getLifecycle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||
mPreferenceCategory = screen.findPreference(getPreferenceKey());
|
||||
mPrefContext = screen.getContext();
|
||||
updateAppList();
|
||||
super.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (!(Flags.nmSummarization() || Flags.nmSummarizationUi()
|
||||
|| Flags.notificationClassificationUi())) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
if (KEY_SUMMARIZATION.equals(mAdjustmentKey)
|
||||
&& mBackend.isNotificationSummarizationSupported()) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
if (KEY_TYPE.equals(mAdjustmentKey) && mBackend.isNotificationBundlingSupported()) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to trigger the app list to refresh.
|
||||
*/
|
||||
public void updateAppList() {
|
||||
if (mAppSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationsState.AppFilter filter = android.multiuser.Flags.enablePrivateSpaceFeatures()
|
||||
&& android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
|
||||
? ApplicationsState.FILTER_ENABLED_NOT_QUIET
|
||||
: ApplicationsState.FILTER_ALL_ENABLED;
|
||||
mAppSession.rebuild(filter, ApplicationsState.ALPHA_COMPARATOR);
|
||||
}
|
||||
|
||||
// Set the icon for the given preference to the entry icon from cache if available, or look
|
||||
// it up.
|
||||
private void updateIcon(Preference pref, ApplicationsState.AppEntry entry) {
|
||||
synchronized (entry) {
|
||||
final Drawable cachedIcon = AppUtils.getIconFromCache(entry);
|
||||
if (cachedIcon != null && entry.mounted) {
|
||||
pref.setIcon(cachedIcon);
|
||||
} else {
|
||||
ListenableFuture unused = ThreadUtils.postOnBackgroundThread(() -> {
|
||||
final Drawable icon = AppUtils.getIcon(mPrefContext, entry);
|
||||
if (icon != null) {
|
||||
ThreadUtils.postOnMainThread(() -> pref.setIcon(icon));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateAppList(List<ApplicationsState.AppEntry> apps) {
|
||||
if (mPreferenceCategory == null || apps == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> excludedApps = List.of(mBackend.getAdjustmentDeniedPackages(mAdjustmentKey));
|
||||
|
||||
for (ApplicationsState.AppEntry app : apps) {
|
||||
String pkg = app.info.packageName;
|
||||
final String key = getKey(pkg, app.info.uid);
|
||||
boolean doesAppPassCriteria = false;
|
||||
|
||||
if (excludedApps.contains(pkg)) {
|
||||
doesAppPassCriteria = true;
|
||||
}
|
||||
Preference pref = mPreferenceCategory.findPreference(key);
|
||||
if (pref == null) {
|
||||
if (doesAppPassCriteria) {
|
||||
// does not exist but should
|
||||
pref = new Preference(mPrefContext);
|
||||
pref.setKey(key);
|
||||
pref.setTitle(BidiFormatter.getInstance().unicodeWrap(app.label));
|
||||
updateIcon(pref, app);
|
||||
mPreferenceCategory.addPreference(pref);
|
||||
}
|
||||
} else if (!doesAppPassCriteria) {
|
||||
// exists but shouldn't anymore
|
||||
mPreferenceCategory.removePreference(pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a unique key to identify an AppPreference
|
||||
*/
|
||||
static String getKey(String pkg, int uid) {
|
||||
return "all|" + pkg + "|" + uid;
|
||||
}
|
||||
|
||||
private final ApplicationsState.Callbacks mAppSessionCallbacks =
|
||||
new ApplicationsState.Callbacks() {
|
||||
|
||||
@Override
|
||||
public void onRunningStateChanged(boolean running) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageListChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebuildComplete(@NonNull ArrayList<ApplicationsState.AppEntry> apps) {
|
||||
updateAppList(apps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageIconChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageSizeChanged(@NonNull String packageName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllSizesComputed() { }
|
||||
|
||||
@Override
|
||||
public void onLauncherInfoChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
updateAppList();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.Flags;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class BundleManageAppsPreferenceController extends
|
||||
BasePreferenceController {
|
||||
|
||||
NotificationBackend mBackend;
|
||||
|
||||
public BundleManageAppsPreferenceController(@NonNull Context context,
|
||||
@NonNull String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mBackend = new NotificationBackend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (Flags.notificationClassificationUi() && mBackend.isNotificationBundlingSupported()) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.service.notification.Adjustment.KEY_SUMMARIZATION;
|
||||
import static android.service.notification.Adjustment.KEY_TYPE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.app.Flags;
|
||||
@@ -25,6 +30,7 @@ import androidx.lifecycle.Lifecycle;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -49,6 +55,26 @@ public class BundlePreferenceFragment extends DashboardFragment {
|
||||
return "BundlePreferenceFragment";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (use(AdjustmentExcludedAppsPreferenceController.class) != null) {
|
||||
final Activity activity = getActivity();
|
||||
Application app = null;
|
||||
ApplicationsState appState = null;
|
||||
if (activity != null) {
|
||||
app = activity.getApplication();
|
||||
} else {
|
||||
app = null;
|
||||
}
|
||||
if (app != null) {
|
||||
appState = ApplicationsState.getInstance(app);
|
||||
}
|
||||
use(AdjustmentExcludedAppsPreferenceController.class).onAttach(
|
||||
appState, this, new NotificationBackend(), KEY_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.bundle_notifications_settings) {
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.Flags;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
public class SummarizationManageAppsPreferenceController extends
|
||||
BasePreferenceController {
|
||||
|
||||
NotificationBackend mBackend;
|
||||
|
||||
public SummarizationManageAppsPreferenceController(@NonNull Context context,
|
||||
@NonNull String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mBackend = new NotificationBackend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if ((Flags.nmSummarization() || Flags.nmSummarizationUi())
|
||||
&& mBackend.isNotificationSummarizationSupported()) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,19 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.service.notification.Adjustment.KEY_SUMMARIZATION;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.app.Flags;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.notification.app.HeaderPreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
/**
|
||||
@@ -45,6 +51,26 @@ public class SummarizationPreferenceFragment extends DashboardFragment {
|
||||
return "SummarizationPreferenceFragment";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (use(AdjustmentExcludedAppsPreferenceController.class) != null) {
|
||||
final Activity activity = getActivity();
|
||||
Application app = null;
|
||||
ApplicationsState appState = null;
|
||||
if (activity != null) {
|
||||
app = activity.getApplication();
|
||||
} else {
|
||||
app = null;
|
||||
}
|
||||
if (app != null) {
|
||||
appState = ApplicationsState.getInstance(app);
|
||||
}
|
||||
use(AdjustmentExcludedAppsPreferenceController.class).onAttach(
|
||||
appState, this, new NotificationBackend(), KEY_SUMMARIZATION);
|
||||
}
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.summarization_notifications_settings) {
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
@@ -126,6 +127,14 @@ public class ContentProtectionTogglePreferenceController extends TogglePreferenc
|
||||
&& mContentProtectionPolicy
|
||||
!= DevicePolicyManager.CONTENT_PROTECTION_NOT_CONTROLLED_BY_POLICY) {
|
||||
mSwitchBar.setDisabledByAdmin(mEnforcedAdmin);
|
||||
return;
|
||||
}
|
||||
|
||||
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||
if (userManager != null
|
||||
&& userManager.isGuestUser()
|
||||
&& mSwitchBar != null) {
|
||||
mSwitchBar.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,19 @@
|
||||
package com.android.settings.security
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS
|
||||
import android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Settings.LockScreenSettingsActivity
|
||||
import com.android.settings.display.AmbientDisplayAlwaysOnPreference
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.notification.LockScreenNotificationPreferenceController
|
||||
import com.android.settings.utils.makeLaunchIntent
|
||||
import com.android.settingslib.datastore.AbstractKeyedDataObservable
|
||||
import com.android.settingslib.datastore.HandlerExecutor
|
||||
import com.android.settingslib.datastore.KeyedObserver
|
||||
import com.android.settingslib.datastore.SettingsSecureStore
|
||||
import com.android.settingslib.metadata.PreferenceChangeReason
|
||||
import com.android.settingslib.metadata.PreferenceMetadata
|
||||
import com.android.settingslib.metadata.PreferenceSummaryProvider
|
||||
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||
@@ -29,7 +36,12 @@ import com.android.settingslib.metadata.preferenceHierarchy
|
||||
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||
|
||||
@ProvidePreferenceScreen(LockScreenPreferenceScreen.KEY)
|
||||
open class LockScreenPreferenceScreen : PreferenceScreenCreator, PreferenceSummaryProvider {
|
||||
open class LockScreenPreferenceScreen(private val context: Context) :
|
||||
AbstractKeyedDataObservable<String>(), PreferenceScreenCreator, PreferenceSummaryProvider {
|
||||
|
||||
private val observer =
|
||||
KeyedObserver<String> { _, _ -> notifyChange(KEY, PreferenceChangeReason.STATE) }
|
||||
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
@@ -39,6 +51,20 @@ open class LockScreenPreferenceScreen : PreferenceScreenCreator, PreferenceSumma
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_ambient_display_screen
|
||||
|
||||
override fun onFirstObserverAdded() {
|
||||
val store = SettingsSecureStore.get(context)
|
||||
val executor = HandlerExecutor.main
|
||||
// update summary when lock screen notification settings are changed
|
||||
store.addObserver(LOCK_SCREEN_SHOW_NOTIFICATIONS, observer, executor)
|
||||
store.addObserver(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, observer, executor)
|
||||
}
|
||||
|
||||
override fun onLastObserverRemoved() {
|
||||
val store = SettingsSecureStore.get(context)
|
||||
store.removeObserver(LOCK_SCREEN_SHOW_NOTIFICATIONS, observer)
|
||||
store.removeObserver(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, observer)
|
||||
}
|
||||
|
||||
override fun getSummary(context: Context): CharSequence? =
|
||||
context.getString(LockScreenNotificationPreferenceController.getSummaryResource(context))
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
|
||||
import com.android.settings.spa.app.specialaccess.WriteSystemPreferencesAppListProvider
|
||||
import com.android.settings.spa.app.storage.StorageAppListPageProvider
|
||||
import com.android.settings.spa.core.instrumentation.SpaLogMetricsProvider
|
||||
import com.android.settings.spa.core.instrumentation.SpaLogProvider
|
||||
import com.android.settings.spa.development.UsageStatsPageProvider
|
||||
import com.android.settings.spa.development.compat.PlatformCompatAppListPageProvider
|
||||
import com.android.settings.spa.home.HomePageProvider
|
||||
@@ -107,7 +106,9 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
|
||||
AppInfoSettingsProvider,
|
||||
SpecialAppAccessPageProvider,
|
||||
NotificationMainPageProvider,
|
||||
AppListNotificationsPageProvider,
|
||||
AppListNotificationsPageProvider.AllApps,
|
||||
AppListNotificationsPageProvider.ExcludeClassification,
|
||||
AppListNotificationsPageProvider.ExcludeSummarization,
|
||||
SystemMainPageProvider,
|
||||
LanguageAndInputPageProvider,
|
||||
AppLanguagesPageProvider,
|
||||
|
||||
@@ -17,34 +17,72 @@
|
||||
package com.android.settings.spa.notification
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spaprivileged.template.app.AppList
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListInput
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListPage
|
||||
|
||||
object AppListNotificationsPageProvider : SettingsPageProvider {
|
||||
override val name = "AppListNotifications"
|
||||
|
||||
sealed class AppListNotificationsPageProvider(private val type: ListType) : SettingsPageProvider {
|
||||
@Composable
|
||||
override fun Page(arguments: Bundle?) {
|
||||
AppListPage(
|
||||
title = stringResource(R.string.app_notifications_title),
|
||||
listModel = rememberContext(::AppNotificationsListModel),
|
||||
)
|
||||
NotificationsAppListPage(type)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EntryItem() {
|
||||
val summary = stringResource(R.string.app_notification_field_summary)
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = stringResource(R.string.app_notifications_title)
|
||||
override val summary = { summary }
|
||||
override val onClick = navigator(name)
|
||||
})
|
||||
object AllApps : AppListNotificationsPageProvider(ListType.Apps) {
|
||||
override val name = "AppListNotifications"
|
||||
|
||||
@Composable
|
||||
fun EntryItem() {
|
||||
val summary = stringResource(R.string.app_notification_field_summary)
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = stringResource(ListType.Apps.titleResource)
|
||||
override val summary = { summary }
|
||||
override val onClick = navigator(name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
object ExcludeSummarization : AppListNotificationsPageProvider(ListType.ExcludeSummarization) {
|
||||
override val name = "NotificationsExcludeSummarization"
|
||||
}
|
||||
|
||||
object ExcludeClassification : AppListNotificationsPageProvider(ListType.ExcludeClassification) {
|
||||
override val name = "NotificationsExcludeClassification"
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NotificationsAppListPage(
|
||||
type: ListType,
|
||||
appList: @Composable AppListInput<AppNotificationsRecord>.() -> Unit = { AppList() }
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
AppListPage(
|
||||
title = stringResource(type.titleResource),
|
||||
listModel = remember(context) { AppNotificationsListModel(context, type) },
|
||||
appList = appList,
|
||||
)
|
||||
}
|
||||
|
||||
sealed class ListType(
|
||||
@StringRes val titleResource: Int
|
||||
) {
|
||||
object Apps : ListType(
|
||||
titleResource = R.string.app_notifications_title,
|
||||
)
|
||||
object ExcludeSummarization : ListType(
|
||||
titleResource = R.string.notification_summarization_manage_excluded_apps_title,
|
||||
)
|
||||
object ExcludeClassification : ListType(
|
||||
titleResource = R.string.notification_bundle_manage_excluded_apps_title,
|
||||
)
|
||||
}
|
||||
@@ -17,12 +17,16 @@
|
||||
package com.android.settings.spa.notification
|
||||
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.service.notification.Adjustment
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.android.settings.spa.app.storage.StorageAppListModel
|
||||
import com.android.settings.spa.app.storage.StorageType
|
||||
|
||||
class AppNotificationController(
|
||||
private val repository: AppNotificationRepository,
|
||||
private val app: ApplicationInfo,
|
||||
private val listType: ListType,
|
||||
) {
|
||||
val isEnabled: LiveData<Boolean>
|
||||
get() = _isEnabled
|
||||
@@ -47,4 +51,62 @@ class AppNotificationController(
|
||||
postValue(it)
|
||||
}
|
||||
}
|
||||
|
||||
val isAllowed: LiveData<Boolean>
|
||||
get() = _isAllowed
|
||||
|
||||
fun getAllowed() = _isAllowed.get()
|
||||
|
||||
fun setAllowed(enabled: Boolean) {
|
||||
when (listType) {
|
||||
ListType.ExcludeSummarization -> {
|
||||
if (repository.setAdjustmentSupportedForPackage(
|
||||
app, Adjustment.KEY_SUMMARIZATION, enabled)) {
|
||||
_isAllowed.postValue(enabled)
|
||||
}
|
||||
}
|
||||
ListType.ExcludeClassification -> {
|
||||
if (repository.setAdjustmentSupportedForPackage(
|
||||
app, Adjustment.KEY_TYPE, enabled)) {
|
||||
_isAllowed.postValue(enabled)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private val _isAllowed = object : MutableLiveData<Boolean>() {
|
||||
override fun onActive() {
|
||||
when (listType) {
|
||||
ListType.ExcludeSummarization -> {
|
||||
postValue(repository.isAdjustmentSupportedForPackage(
|
||||
app, Adjustment.KEY_SUMMARIZATION))
|
||||
}
|
||||
ListType.ExcludeClassification -> {
|
||||
postValue(repository.isAdjustmentSupportedForPackage(
|
||||
app, Adjustment.KEY_TYPE))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInactive() {
|
||||
}
|
||||
|
||||
fun get(): Boolean = when (listType) {
|
||||
ListType.ExcludeSummarization -> {
|
||||
value ?: repository.isAdjustmentSupportedForPackage(
|
||||
app, Adjustment.KEY_SUMMARIZATION).also {
|
||||
postValue(it)
|
||||
}
|
||||
}
|
||||
ListType.ExcludeClassification -> {
|
||||
value ?: repository.isAdjustmentSupportedForPackage(
|
||||
app, Adjustment.KEY_TYPE).also {
|
||||
postValue(it)
|
||||
}
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,20 @@ class AppNotificationRepository(
|
||||
}
|
||||
}
|
||||
|
||||
fun isAdjustmentSupportedForPackage(app: ApplicationInfo, key: String): Boolean =
|
||||
notificationManager.isAdjustmentSupportedForPackage(key, app.packageName)
|
||||
|
||||
fun setAdjustmentSupportedForPackage(app: ApplicationInfo, key: String, enabled: Boolean):
|
||||
Boolean {
|
||||
return try {
|
||||
notificationManager.setAdjustmentSupportedForPackage(key, app.packageName, enabled)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Error calling INotificationManager", e)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun isUserUnlocked(user: Int): Boolean {
|
||||
return try {
|
||||
userManager.isUserUnlocked(user)
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
import com.android.settingslib.spaprivileged.model.app.userId
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListSwitchItem
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListTwoTargetSwitchItem
|
||||
import com.android.settingslib.utils.StringUtil
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -52,6 +53,7 @@ data class AppNotificationsRecord(
|
||||
|
||||
class AppNotificationsListModel(
|
||||
private val context: Context,
|
||||
private val listType: ListType
|
||||
) : AppListModel<AppNotificationsRecord> {
|
||||
private val repository = AppNotificationRepository(context)
|
||||
private val now = System.currentTimeMillis()
|
||||
@@ -64,7 +66,7 @@ class AppNotificationsListModel(
|
||||
AppNotificationsRecord(
|
||||
app = app,
|
||||
sentState = usageEvents[app.packageName],
|
||||
controller = AppNotificationController(repository, app),
|
||||
controller = AppNotificationController(repository, app, listType),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -129,17 +131,35 @@ class AppNotificationsListModel(
|
||||
|
||||
@Composable
|
||||
override fun AppListItemModel<AppNotificationsRecord>.AppItem() {
|
||||
val changeable by produceState(initialValue = false) {
|
||||
withContext(Dispatchers.Default) {
|
||||
value = repository.isChangeable(record.app)
|
||||
when (listType) {
|
||||
ListType.ExcludeSummarization -> {
|
||||
AppListSwitchItem(
|
||||
checked = record.controller.isAllowed.observeAsCallback(),
|
||||
changeable = { true },
|
||||
onCheckedChange = record.controller::setAllowed,
|
||||
)
|
||||
}
|
||||
ListType.ExcludeClassification -> {
|
||||
AppListSwitchItem(
|
||||
checked = record.controller.isAllowed.observeAsCallback(),
|
||||
changeable = { true },
|
||||
onCheckedChange = record.controller::setAllowed,
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
val changeable by produceState(initialValue = false) {
|
||||
withContext(Dispatchers.Default) {
|
||||
value = repository.isChangeable(record.app)
|
||||
}
|
||||
}
|
||||
AppListTwoTargetSwitchItem(
|
||||
onClick = { navigateToAppNotificationSettings(app = record.app) },
|
||||
checked = record.controller.isEnabled.observeAsCallback(),
|
||||
changeable = { changeable },
|
||||
onCheckedChange = record.controller::setEnabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
AppListTwoTargetSwitchItem(
|
||||
onClick = { navigateToAppNotificationSettings(app = record.app) },
|
||||
checked = record.controller.isEnabled.observeAsCallback(),
|
||||
changeable = { changeable },
|
||||
onCheckedChange = record.controller::setEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
private fun navigateToAppNotificationSettings(app: ApplicationInfo) {
|
||||
|
||||
@@ -41,7 +41,7 @@ object NotificationMainPageProvider : SettingsPageProvider {
|
||||
@Composable
|
||||
override fun Page(arguments: Bundle?) {
|
||||
RegularScaffold(title = getTitle(arguments)) {
|
||||
AppListNotificationsPageProvider.EntryItem()
|
||||
AppListNotificationsPageProvider.AllApps.EntryItem()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public class FactoryResetPreferenceController extends BasePreferenceController {
|
||||
return prepareFactoryResetWizardRequest;
|
||||
}
|
||||
}
|
||||
return prepareFactoryResetWizardRequest;
|
||||
return null;
|
||||
}
|
||||
Log.i(TAG, "Unable to resolve a Factory Reset Handler Activity");
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.database.ContentObserver
|
||||
import android.hardware.display.ColorDisplayManager
|
||||
import android.provider.Settings
|
||||
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
|
||||
import com.android.settingslib.testutils.shadow.ShadowColorDisplayManager
|
||||
import com.android.settings.R
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import org.robolectric.shadow.api.Shadow
|
||||
import org.robolectric.shadows.ShadowContentResolver
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [ShadowColorDisplayManager::class, ShadowContentResolver::class])
|
||||
class ColorModePreferenceControllerTest {
|
||||
private lateinit var context: Context
|
||||
private lateinit var preference: Preference
|
||||
private lateinit var controller: ColorModePreferenceController
|
||||
private lateinit var shadowColorDisplayManager: ShadowColorDisplayManager
|
||||
private lateinit var shadowContentResolver: ShadowContentResolver
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
controller = ColorModePreferenceController(context, "test")
|
||||
preference = Preference(context)
|
||||
val preferenceManager = PreferenceManager(context)
|
||||
val preferenceScreen = preferenceManager.createPreferenceScreen(context)
|
||||
preference.setKey(controller.getPreferenceKey());
|
||||
preferenceScreen.addPreference(preference)
|
||||
|
||||
shadowColorDisplayManager = Shadow.extract(
|
||||
context.getSystemService(ColorDisplayManager::class.java))
|
||||
val contentResolver = context.getContentResolver();
|
||||
shadowContentResolver = Shadow.extract(contentResolver)
|
||||
|
||||
controller.displayPreference(preferenceScreen)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_colorModeAutomatic_shouldSetSummaryToAutomatic() {
|
||||
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC)
|
||||
controller.updateState(preference)
|
||||
val automaticColorModeName = context.getString(R.string.color_mode_option_automatic)
|
||||
assertThat(preference.summary.toString()).isEqualTo(automaticColorModeName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_colorModeSaturated_shouldSetSummaryToSaturated() {
|
||||
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED)
|
||||
controller.updateState(preference)
|
||||
val saturatedColorModeName = context.getString(R.string.color_mode_option_saturated)
|
||||
assertThat(preference.summary.toString()).isEqualTo(saturatedColorModeName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_colorModeBoosted_shouldSetSummaryToBoosted() {
|
||||
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED)
|
||||
controller.updateState(preference)
|
||||
val boostedColorModeName = context.getString(R.string.color_mode_option_boosted)
|
||||
assertThat(preference.summary.toString()).isEqualTo(boostedColorModeName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_colorModeNatural_shouldSetSummaryToNatural() {
|
||||
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL)
|
||||
controller.updateState(preference)
|
||||
val naturalColorModeName = context.getString(R.string.color_mode_option_natural)
|
||||
assertThat(preference.summary.toString()).isEqualTo(naturalColorModeName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onResume_verifyRegisterColorModeObserver() {
|
||||
controller.onResume()
|
||||
assertThat(shadowContentResolver.getContentObservers(
|
||||
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE)))
|
||||
.hasSize(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPause_verifyUnregisterColorModeObserver() {
|
||||
controller.onResume()
|
||||
controller.onPause()
|
||||
assertThat(shadowContentResolver.getContentObservers(
|
||||
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE)))
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun contentObserver_onChange_updatesPreferenceSummary() {
|
||||
controller.onResume()
|
||||
assertThat(shadowContentResolver.getContentObservers(
|
||||
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE)))
|
||||
.hasSize(1)
|
||||
|
||||
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL)
|
||||
triggerOnChangeListener()
|
||||
assertThat(preference.summary).isEqualTo(context.getString(R.string.color_mode_option_natural))
|
||||
|
||||
shadowColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC)
|
||||
triggerOnChangeListener()
|
||||
assertThat(preference.summary).isEqualTo(context.getString(R.string.color_mode_option_automatic))
|
||||
}
|
||||
|
||||
private fun triggerOnChangeListener() {
|
||||
shadowContentResolver.getContentObservers(
|
||||
Settings.System.getUriFor(Settings.System.DISPLAY_COLOR_MODE))
|
||||
.forEach {it.onChange(false, null)};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* Copyright (C) 2025 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.localepicker;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.IActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Looper;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.internal.app.LocaleStore;
|
||||
import com.android.settings.testutils.shadow.ShadowActivityManager;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.shadows.ShadowTelephonyManager;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
ShadowFragment.class,
|
||||
ShadowActivityManager.class,
|
||||
})
|
||||
public class SystemLocaleSuggestedListPreferenceControllerTest {
|
||||
private static final String KEY_CATEGORY_SYSTEM_SUGGESTED_LIST =
|
||||
"system_language_suggested_category";
|
||||
private static final String KEY_SUGGESTED = "system_locale_suggested_list";
|
||||
|
||||
private Context mContext;
|
||||
private PreferenceCategory mPreferenceCategory;
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
private SystemLocaleSuggestedListPreferenceController mController;
|
||||
private List<LocaleStore.LocaleInfo> mLocaleList;
|
||||
private Map<String, Preference> mPreferences = new ArrayMap<>();
|
||||
@Mock
|
||||
private PreferenceManager mPreferenceManager;
|
||||
@Mock
|
||||
private IActivityManager mActivityService;
|
||||
@Mock
|
||||
private LocaleStore.LocaleInfo mSuggestedLocaleInfo_1;
|
||||
@Mock
|
||||
private LocaleStore.LocaleInfo mSuggestedLocaleInfo_2;
|
||||
@Mock
|
||||
private FragmentManager mFragmentManager;
|
||||
@Mock
|
||||
private FragmentTransaction mFragmentTransaction;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
|
||||
ShadowActivityManager.setService(mActivityService);
|
||||
final Configuration config = new Configuration();
|
||||
setUpLocaleConditions();
|
||||
config.setLocales(new LocaleList(mSuggestedLocaleInfo_1.getLocale(),
|
||||
mSuggestedLocaleInfo_2.getLocale()));
|
||||
when(mActivityService.getConfiguration()).thenReturn(config);
|
||||
ShadowTelephonyManager shadowTelephonyManager =
|
||||
Shadows.shadowOf(mContext.getSystemService(TelephonyManager.class));
|
||||
shadowTelephonyManager.setSimCountryIso("us");
|
||||
shadowTelephonyManager.setNetworkCountryIso("us");
|
||||
when(mFragmentManager.beginTransaction()).thenReturn(mFragmentTransaction);
|
||||
mPreferenceScreen = spy(new PreferenceScreen(mContext, null));
|
||||
mPreferenceCategory = spy(new PreferenceCategory(mContext, null));
|
||||
when(mPreferenceScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
|
||||
when(mPreferenceCategory.getPreferenceManager()).thenReturn(mPreferenceManager);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceCategory.setKey(KEY_CATEGORY_SYSTEM_SUGGESTED_LIST);
|
||||
mPreferenceScreen.addPreference(mPreferenceCategory);
|
||||
mController = new SystemLocaleSuggestedListPreferenceController(mContext, KEY_SUGGESTED);
|
||||
}
|
||||
|
||||
private void setUpLocaleConditions() {
|
||||
mLocaleList = new ArrayList<>();
|
||||
when(mSuggestedLocaleInfo_1.getFullNameNative()).thenReturn("English");
|
||||
when(mSuggestedLocaleInfo_1.getLocale()).thenReturn(
|
||||
LocaleList.forLanguageTags("en-US").get(0));
|
||||
mLocaleList.add(mSuggestedLocaleInfo_1);
|
||||
when(mSuggestedLocaleInfo_2.getFullNameNative()).thenReturn("Español (Estados Unidos)");
|
||||
when(mSuggestedLocaleInfo_2.getLocale()).thenReturn(
|
||||
LocaleList.forLanguageTags("es-US").get(0));
|
||||
mLocaleList.add(mSuggestedLocaleInfo_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_hasSuggestedPreference_categoryIsVisible() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.setupPreference(mLocaleList, mPreferences);
|
||||
|
||||
assertTrue(mPreferenceCategory.isVisible());
|
||||
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_noSuggestedPreference_categoryIsGone() {
|
||||
mLocaleList.clear();
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.setupPreference(mLocaleList, mPreferences);
|
||||
|
||||
assertFalse(mPreferenceCategory.isVisible());
|
||||
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchFragment_shouldShowLocaleEditor() {
|
||||
when(mSuggestedLocaleInfo_1.isSuggested()).thenReturn(true);
|
||||
mController.shouldShowLocaleEditor(mSuggestedLocaleInfo_1);
|
||||
mController.switchFragment(mSuggestedLocaleInfo_1);
|
||||
|
||||
verify(mFragmentTransaction, never()).add(any(LocaleListEditor.class),
|
||||
anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void switchFragment_shouldShowRegionNumberingPicker() {
|
||||
Context activityContext = mock(Context.class);
|
||||
mController = new SystemLocaleSuggestedListPreferenceController(activityContext,
|
||||
KEY_SUGGESTED);
|
||||
when(mSuggestedLocaleInfo_1.isSuggested()).thenReturn(false);
|
||||
when(mSuggestedLocaleInfo_1.isSystemLocale()).thenReturn(false);
|
||||
when(mSuggestedLocaleInfo_1.getParent()).thenReturn(null);
|
||||
mController.shouldShowLocaleEditor(mSuggestedLocaleInfo_1);
|
||||
mController.switchFragment(mSuggestedLocaleInfo_1);
|
||||
|
||||
verify(mFragmentTransaction, never()).add(any(RegionAndNumberingSystemPickerFragment.class),
|
||||
anyString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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 static android.service.notification.Adjustment.KEY_SUMMARIZATION;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.app.INotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@EnableFlags({Flags.FLAG_NM_SUMMARIZATION_UI, Flags.FLAG_NM_SUMMARIZATION,
|
||||
Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI})
|
||||
public class AdjustmentExcludedAppsPreferenceControllerTest {
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
@Mock
|
||||
private ApplicationsState mApplicationState;
|
||||
private AdjustmentExcludedAppsPreferenceController mController;
|
||||
private Context mContext;
|
||||
@Mock
|
||||
INotificationManager mInm;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
mController = new AdjustmentExcludedAppsPreferenceController(mContext, "key");
|
||||
mController.onAttach(null, mock(Fragment.class), mBackend, KEY_SUMMARIZATION);
|
||||
PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mController.mPreferenceCategory = new PreferenceCategory(mContext);
|
||||
screen.addPreference(mController.mPreferenceCategory);
|
||||
|
||||
mController.mApplicationsState = mApplicationState;
|
||||
mController.mPrefContext = mContext;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable() {
|
||||
when(mBackend.isNotificationBundlingSupported()).thenReturn(true);
|
||||
when(mBackend.isNotificationSummarizationSupported()).thenReturn(true);
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagEnabledNasDoesNotSupport_shouldReturnFalse() throws Exception {
|
||||
when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of(KEY_SUMMARIZATION));
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAppList() throws Exception {
|
||||
when(mBackend.getAdjustmentDeniedPackages(KEY_SUMMARIZATION)).thenReturn(
|
||||
new String[] {"cannot", "cannot2"});
|
||||
|
||||
// GIVEN there are four apps, and two have KEY_SUMMARIZATION off
|
||||
ApplicationsState.AppEntry canSummarize =
|
||||
mock(ApplicationsState.AppEntry.class);
|
||||
canSummarize.info = new ApplicationInfo();
|
||||
canSummarize.info.packageName = "canSummarize";
|
||||
canSummarize.info.uid = 0;
|
||||
|
||||
ApplicationsState.AppEntry canSummarize2 = mock(ApplicationsState.AppEntry.class);
|
||||
canSummarize2.info = new ApplicationInfo();
|
||||
canSummarize2.info.packageName = "canSummarizeTwo";
|
||||
canSummarize2.info.uid = 0;
|
||||
|
||||
ApplicationsState.AppEntry cannot =
|
||||
mock(ApplicationsState.AppEntry.class);
|
||||
cannot.info = new ApplicationInfo();
|
||||
cannot.info.packageName = "cannot";
|
||||
cannot.info.uid = 0;
|
||||
|
||||
ApplicationsState.AppEntry cannot2 =
|
||||
mock(ApplicationsState.AppEntry.class);
|
||||
cannot2.info = new ApplicationInfo();
|
||||
cannot2.info.packageName = "cannot2";
|
||||
cannot2.info.uid = 0;
|
||||
|
||||
List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(canSummarize);
|
||||
appEntries.add(canSummarize2);
|
||||
appEntries.add(cannot);
|
||||
appEntries.add(cannot2);
|
||||
|
||||
// WHEN the controller updates the app list with the app entries
|
||||
mController.updateAppList(appEntries);
|
||||
|
||||
// THEN only the 'cannot' entries make it to the app list
|
||||
assertThat(mController.mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
|
||||
assertThat((Preference) mController.mPreferenceCategory.findPreference(
|
||||
AdjustmentExcludedAppsPreferenceController.getKey(
|
||||
cannot.info.packageName,cannot.info.uid))).isNotNull();
|
||||
assertThat((Preference) mController.mPreferenceCategory.findPreference(
|
||||
AdjustmentExcludedAppsPreferenceController.getKey(
|
||||
cannot2.info.packageName,cannot2.info.uid))).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAppList_nullApps() {
|
||||
mController.updateAppList(null);
|
||||
assertThat(mController.mPreferenceCategory.getPreferenceCount()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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 static android.service.notification.Adjustment.KEY_SUMMARIZATION;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.app.INotificationManager;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.service.notification.Adjustment;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class BundleManageAppsPreferenceControllerTest {
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String PREFERENCE_KEY = "preference_key";
|
||||
|
||||
private Context mContext;
|
||||
BundleManageAppsPreferenceController mController;
|
||||
@Mock
|
||||
INotificationManager mInm;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI);
|
||||
mController = new BundleManageAppsPreferenceController(mContext, PREFERENCE_KEY);
|
||||
mController.mBackend.setNm(mInm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagEnabledNasSupports_shouldReturnTrue() {
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagEnabledNasDoesNotSupport_shouldReturnFalse() throws Exception {
|
||||
when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of(Adjustment.KEY_TYPE));
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagDisabledNasSupports_shouldReturnFalse() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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 static android.service.notification.Adjustment.KEY_IMPORTANCE;
|
||||
import static android.service.notification.Adjustment.KEY_SUMMARIZATION;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.app.INotificationManager;
|
||||
import android.content.Context;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SummarizationManageAppsPreferenceControllerTest {
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String PREFERENCE_KEY = "preference_key";
|
||||
|
||||
private Context mContext;
|
||||
SummarizationManageAppsPreferenceController mController;
|
||||
@Mock
|
||||
INotificationManager mInm;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mSetFlagsRule.enableFlags(Flags.FLAG_NM_SUMMARIZATION, Flags.FLAG_NM_SUMMARIZATION_UI);
|
||||
mController = new SummarizationManageAppsPreferenceController(mContext, PREFERENCE_KEY);
|
||||
mController.mBackend.setNm(mInm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagEnabledNasSupports_shouldReturnTrue() {
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagEnabledNasDoesNotSupport_shouldReturnFalse() throws Exception {
|
||||
when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of(KEY_SUMMARIZATION));
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_flagDisabledNasSupports_shouldReturnFalse() {
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_NM_SUMMARIZATION);
|
||||
mSetFlagsRule.disableFlags(Flags.FLAG_NM_SUMMARIZATION_UI);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,11 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
@@ -38,6 +41,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settings.widget.SettingsMainSwitchPreference;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
@@ -53,7 +57,8 @@ import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowUtils.class})
|
||||
@Config(shadows = {ShadowUtils.class,
|
||||
ShadowUserManager.class})
|
||||
public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@@ -62,7 +67,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Mock private PreferenceScreen mMockPreferenceScreen;
|
||||
@Mock private PreferenceScreen mMockPreferenceScreen;
|
||||
|
||||
@Mock private SettingsMainSwitchPreference mMockSwitchPreference;
|
||||
|
||||
@@ -74,9 +79,13 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
private TestContentProtectionTogglePreferenceController mController;
|
||||
|
||||
private int mSettingBackupValue;
|
||||
private ShadowUserManager mShadowUserManager;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mShadowUserManager = ShadowUserManager.getShadow();
|
||||
mShadowUserManager.setGuestUser(false);
|
||||
mController = new TestContentProtectionTogglePreferenceController();
|
||||
SettingsMainSwitchPreference switchPreference = new SettingsMainSwitchPreference(mContext);
|
||||
when(mMockPreferenceScreen.findPreference(mController.getPreferenceKey()))
|
||||
@@ -225,6 +234,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,6 +247,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -249,6 +260,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -261,6 +273,30 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_flagEnabled_noEnforcedAdmin_guestUser_switchBarDisabled() {
|
||||
mShadowUserManager.setGuestUser(true);
|
||||
mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
|
||||
mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
|
||||
setupForUpdateState();
|
||||
|
||||
mController.updateState(mMockSwitchPreference);
|
||||
|
||||
verify(mMockSwitchPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_flagEnabled_noEnforcedAdmin_nonGuestUser_switchBarEnabled() {
|
||||
mSetFlagsRule.enableFlags(FLAG_MANAGE_DEVICE_POLICY_ENABLED);
|
||||
mContentProtectionPolicy = DevicePolicyManager.CONTENT_PROTECTION_ENABLED;
|
||||
setupForUpdateState();
|
||||
|
||||
mController.updateState(mMockSwitchPreference);
|
||||
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -273,6 +309,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -286,6 +323,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -299,6 +337,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference).setDisabledByAdmin(mEnforcedAdmin);
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -312,6 +351,7 @@ public class ContentProtectionTogglePreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mCounterGetEnforcedAdmin).isEqualTo(1);
|
||||
verify(mMockSwitchPreference, never()).setDisabledByAdmin(any());
|
||||
verify(mMockSwitchPreference, never()).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.Manifest;
|
||||
@@ -157,4 +158,21 @@ public class FactoryResetPreferenceControllerTest {
|
||||
assertThat(intentArgumentCaptor.getValue().getAction())
|
||||
.isEqualTo(FactoryResetPreferenceController.ACTION_PREPARE_FACTORY_RESET);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(com.android.settings.factory_reset.Flags.FLAG_ENABLE_FACTORY_RESET_WIZARD)
|
||||
public void handlePreference_factoryResetWizardEnabled_noExistingFrwApp()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
PackageInfo info = new PackageInfo();
|
||||
info.requestedPermissions =
|
||||
new String[] {Manifest.permission.PREPARE_FACTORY_RESET};
|
||||
info.requestedPermissionsFlags = new int[] {0};
|
||||
when(mPackageManager.getPackageInfo(anyString(), anyInt()))
|
||||
.thenReturn(info);
|
||||
|
||||
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
|
||||
verify(mPackageManager).getPackageInfo(eq(FACTORY_RESET_APP_PACKAGE),
|
||||
eq(PackageManager.GET_PERMISSIONS));
|
||||
verifyNoMoreInteractions(mFactoryResetLauncher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.display;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.hardware.display.ColorDisplayManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ColorModePreferenceControllerTest {
|
||||
|
||||
private Preference mPreference;
|
||||
private ColorModePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
final Context context = spy(ApplicationProvider.getApplicationContext());
|
||||
mController = spy(new ColorModePreferenceController(context, "test"));
|
||||
mPreference = new Preference(context);
|
||||
final Resources res = spy(context.getResources());
|
||||
when(res.getIntArray(com.android.internal.R.array.config_availableColorModes)).thenReturn(
|
||||
new int[]{
|
||||
ColorDisplayManager.COLOR_MODE_NATURAL,
|
||||
ColorDisplayManager.COLOR_MODE_BOOSTED,
|
||||
ColorDisplayManager.COLOR_MODE_SATURATED,
|
||||
ColorDisplayManager.COLOR_MODE_AUTOMATIC
|
||||
});
|
||||
doReturn(res).when(context).getResources();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void updateState_colorModeAutomatic_shouldSetSummaryToAutomatic() {
|
||||
doReturn(ColorDisplayManager.COLOR_MODE_AUTOMATIC).when(mController).getColorMode();
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo("Adaptive");
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void updateState_colorModeSaturated_shouldSetSummaryToSaturated() {
|
||||
doReturn(ColorDisplayManager.COLOR_MODE_SATURATED).when(mController).getColorMode();
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo("Saturated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_colorModeBoosted_shouldSetSummaryToBoosted() {
|
||||
doReturn(ColorDisplayManager.COLOR_MODE_BOOSTED).when(mController).getColorMode();
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo("Boosted");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_colorModeNatural_shouldSetSummaryToNatural() {
|
||||
doReturn(ColorDisplayManager.COLOR_MODE_NATURAL).when(mController).getColorMode();
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo("Natural");
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ public class ColorModePreferenceFragmentTest {
|
||||
});
|
||||
doReturn(res).when(mContext).getResources();
|
||||
mFragment.onAttach(mContext);
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
|
||||
final List<? extends CandidateInfo> candidates = mFragment.getCandidates();
|
||||
|
||||
@@ -99,6 +100,7 @@ public class ColorModePreferenceFragmentTest {
|
||||
});
|
||||
doReturn(res).when(mContext).getResources();
|
||||
mFragment.onAttach(mContext);
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
|
||||
List<? extends CandidateInfo> candidates = mFragment.getCandidates();
|
||||
|
||||
@@ -116,6 +118,7 @@ public class ColorModePreferenceFragmentTest {
|
||||
});
|
||||
doReturn(res).when(mContext).getResources();
|
||||
mFragment.onAttach(mContext);
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
|
||||
List<? extends CandidateInfo> candidates = mFragment.getCandidates();
|
||||
|
||||
@@ -138,6 +141,7 @@ public class ColorModePreferenceFragmentTest {
|
||||
});
|
||||
doReturn(res).when(mContext).getResources();
|
||||
mFragment.onAttach(mContext);
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
|
||||
List<? extends CandidateInfo> candidates = mFragment.getCandidates();
|
||||
|
||||
|
||||
@@ -83,9 +83,11 @@ public class LocaleDialogFragmentTest {
|
||||
LocaleDialogFragment.LocaleDialogController.DialogContent dialogContent =
|
||||
controller.getDialogContent();
|
||||
|
||||
assertEquals(R.string.button_label_confirmation_of_system_locale_change,
|
||||
dialogContent.mPositiveButton);
|
||||
assertEquals(R.string.cancel, dialogContent.mNegativeButton);
|
||||
assertEquals(ResourcesUtils.getResourcesString(
|
||||
mContext, "button_label_confirmation_of_system_locale_change"),
|
||||
mContext.getString(dialogContent.mPositiveButton));
|
||||
assertEquals(ResourcesUtils.getResourcesString(mContext, "cancel"),
|
||||
mContext.getString(dialogContent.mNegativeButton));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,7 +100,8 @@ public class LocaleDialogFragmentTest {
|
||||
LocaleDialogFragment.LocaleDialogController.DialogContent dialogContent =
|
||||
controller.getDialogContent();
|
||||
|
||||
assertEquals(R.string.okay, dialogContent.mPositiveButton);
|
||||
assertEquals(ResourcesUtils.getResourcesString(mContext, "okay"),
|
||||
mContext.getString(dialogContent.mPositiveButton));
|
||||
assertTrue(dialogContent.mNegativeButton == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (C) 2025 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.localepicker;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.android.internal.app.LocaleStore;
|
||||
import com.android.internal.app.SystemLocaleCollector;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SystemLocaleSuggestedListPreferenceControllerTest {
|
||||
private static final String KEY_CATEGORY_SYSTEM_SUGGESTED_LIST =
|
||||
"system_language_suggested_category";
|
||||
private static final String KEY_SUGGESTED = "system_locale_suggested_list";
|
||||
|
||||
private Context mContext;
|
||||
private PreferenceManager mPreferenceManager;
|
||||
private PreferenceCategory mPreferenceCategory;
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
private Preference mSuggestedPreference;
|
||||
private SystemLocaleSuggestedListPreferenceController mController;
|
||||
private Set<LocaleStore.LocaleInfo> mLocaleList;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
|
||||
SystemLocaleCollector systemLocaleCollector = new SystemLocaleCollector(mContext, null);
|
||||
mLocaleList = systemLocaleCollector.getSupportedLocaleList(null, false, false);
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
|
||||
mPreferenceCategory = new PreferenceCategory(mContext);
|
||||
mPreferenceCategory.setKey(KEY_CATEGORY_SYSTEM_SUGGESTED_LIST);
|
||||
mPreferenceScreen.addPreference(mPreferenceCategory);
|
||||
mController = new SystemLocaleSuggestedListPreferenceController(mContext, KEY_SUGGESTED);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_suggestedLocaleShouldBeInSuggestedCategory() {
|
||||
int count = 0;
|
||||
for (LocaleStore.LocaleInfo localeInfo : mLocaleList) {
|
||||
if (localeInfo.isSuggested()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_hasSuggestedPreference_categoryIsVisible() {
|
||||
int count = 0;
|
||||
for (LocaleStore.LocaleInfo localeInfo : mLocaleList) {
|
||||
if (localeInfo.isSuggested()) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
assertTrue(mPreferenceCategory.isVisible());
|
||||
} else {
|
||||
assertFalse(mPreferenceCategory.isVisible());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user