Merge "[Safety Labels] Enable safety label change notifications flag by default in PackageManager code" into udc-dev am: c1e42bd0ce
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22748343
Change-Id: Idf0c11896093f690611c5a5926031e4c01a1d188
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2efb265..3487b01 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4677,22 +4677,16 @@
"display_color_mode_vendor_hint";
/**
- * The user selected min refresh rate in frames per second.
- *
- * If this isn't set, 0 will be used.
+ * Whether or not the peak refresh rate should be forced. 0=no, 1=yes
* @hide
*/
- @Readable
- public static final String MIN_REFRESH_RATE = "min_refresh_rate";
+ public static final String FORCE_PEAK_REFRESH_RATE = "force_peak_refresh_rate";
/**
- * The user selected peak refresh rate in frames per second.
- *
- * If this isn't set, the system falls back to a device specific default.
+ * Whether or not the peak refresh rate should be used for some content. 0=no, 1=yes
* @hide
*/
- @Readable
- public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
+ public static final String SMOOTH_DISPLAY = "smooth_display";
/**
* The amount of time in milliseconds before the device goes to sleep or begins
diff --git a/core/java/com/android/internal/display/RefreshRateSettingsUtils.java b/core/java/com/android/internal/display/RefreshRateSettingsUtils.java
new file mode 100644
index 0000000..39d8380
--- /dev/null
+++ b/core/java/com/android/internal/display/RefreshRateSettingsUtils.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.display;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Display;
+
+/**
+ * Constants and utility methods for refresh rate settings.
+ */
+public class RefreshRateSettingsUtils {
+
+ private static final String TAG = "RefreshRateSettingsUtils";
+
+ public static final float DEFAULT_REFRESH_RATE = 60f;
+
+ /**
+ * Find the highest refresh rate among all the modes of the default display.
+ * @param context The context
+ * @return The highest refresh rate
+ */
+ public static float findHighestRefreshRateForDefaultDisplay(Context context) {
+ final DisplayManager dm = context.getSystemService(DisplayManager.class);
+ final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+
+ if (display == null) {
+ Log.w(TAG, "No valid default display device");
+ return DEFAULT_REFRESH_RATE;
+ }
+
+ float maxRefreshRate = DEFAULT_REFRESH_RATE;
+ for (Display.Mode mode : display.getSupportedModes()) {
+ if (Math.round(mode.getRefreshRate()) > maxRefreshRate) {
+ maxRefreshRate = mode.getRefreshRate();
+ }
+ }
+ return maxRefreshRate;
+ }
+
+ /**
+ * Get the min refresh rate which is determined by
+ * {@link Settings.System.FORCE_PEAK_REFRESH_RATE}.
+ * @param context The context
+ * @return The min refresh rate
+ */
+ public static float getMinRefreshRate(Context context) {
+ final ContentResolver cr = context.getContentResolver();
+ int forcePeakRefreshRateSetting = Settings.System.getIntForUser(cr,
+ Settings.System.FORCE_PEAK_REFRESH_RATE, -1, cr.getUserId());
+ return forcePeakRefreshRateSetting == 1
+ ? findHighestRefreshRateForDefaultDisplay(context)
+ : 0;
+ }
+
+ /**
+ * Get the peak refresh rate which is determined by {@link Settings.System.SMOOTH_DISPLAY}.
+ * @param context The context
+ * @param defaultPeakRefreshRate The refresh rate to return if the setting doesn't have a value
+ * @return The peak refresh rate
+ */
+ public static float getPeakRefreshRate(Context context, float defaultPeakRefreshRate) {
+ final ContentResolver cr = context.getContentResolver();
+ int smoothDisplaySetting = Settings.System.getIntForUser(cr,
+ Settings.System.SMOOTH_DISPLAY, -1, cr.getUserId());
+ switch (smoothDisplaySetting) {
+ case 0:
+ return DEFAULT_REFRESH_RATE;
+ case 1:
+ return findHighestRefreshRateForDefaultDisplay(context);
+ default:
+ return defaultPeakRefreshRate;
+ }
+ }
+}
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b7df6a4..bf5e6dc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5003,7 +5003,8 @@
<java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" />
<java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
-
+
+
<java-symbol name="materialColorOnSecondaryFixedVariant" type="attr"/>
<java-symbol name="materialColorOnTertiaryFixedVariant" type="attr"/>
<java-symbol name="materialColorSurfaceContainerLowest" type="attr"/>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 058065e..bac6306 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -519,12 +519,9 @@
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Daugiau laiko."</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Mažiau laiko."</string>
<string name="cancel" msgid="5665114069455378395">"Atšaukti"</string>
- <!-- no translation found for next (2699398661093607009) -->
- <skip />
- <!-- no translation found for back (5554327870352703710) -->
- <skip />
- <!-- no translation found for save (3745809743277153149) -->
- <skip />
+ <string name="next" msgid="2699398661093607009">"Kitas"</string>
+ <string name="back" msgid="5554327870352703710">"Atgal"</string>
+ <string name="save" msgid="3745809743277153149">"Išsaugoti"</string>
<string name="okay" msgid="949938843324579502">"Gerai"</string>
<string name="done" msgid="381184316122520313">"Atlikta"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Signalai ir priminimai"</string>
@@ -579,12 +576,9 @@
<string name="user_add_user_title" msgid="5457079143694924885">"Pridėti naują naudotoją?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"Galite bendrinti šį įrenginį su kitais žmonėmis sukūrę papildomų naudotojų. Kiekvienam naudotojui suteikiama atskira erdvė, kurią jie gali tinkinti naudodami programas, ekrano foną ir kt. Be to, naudotojai gali koreguoti įrenginio nustatymus, pvz., „Wi‑Fi“, kurie taikomi visiems.\n\nKai pridedate naują naudotoją, šis asmuo turi nusistatyti savo erdvę.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas. Pasiekiamumo nustatymai ir paslaugos gali nebūti perkeltos naujam naudotojui."</string>
<string name="user_add_user_message_short" msgid="3295959985795716166">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo vietą.\n\nBet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>
- <!-- no translation found for user_grant_admin_title (5157031020083343984) -->
- <skip />
- <!-- no translation found for user_grant_admin_message (1673791931033486709) -->
- <skip />
- <!-- no translation found for user_grant_admin_button (5441486731331725756) -->
- <skip />
+ <string name="user_grant_admin_title" msgid="5157031020083343984">"Nustatyti šį naudotoją kaip administratorių?"</string>
+ <string name="user_grant_admin_message" msgid="1673791931033486709">"Administratoriai turi specialių privilegijų, kurių kiti naudotojai neturi. Administratorius gali tvarkyti visus naudotojus, atnaujinti ar iš naujo nustatyti šį įrenginį, keisti nustatymus, peržiūrėti visas įdiegtas programas ir suteikti administratoriaus privilegijas kitiems naudotojams arba jas panaikinti."</string>
+ <string name="user_grant_admin_button" msgid="5441486731331725756">"Nustatyti kaip administratorių"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"Nustatyti naudotoją dabar?"</string>
<string name="user_setup_dialog_message" msgid="269931619868102841">"Įsitikinkite, kad asmuo gali paimti įrenginį ir nustatyti savo vietą"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Nustatyti profilį dabar?"</string>
@@ -616,10 +610,8 @@
<string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"Bus pradėta nauja svečio sesija ir iš esamos sesijos bus ištrintos visos programos ir duomenys"</string>
<string name="guest_exit_dialog_title" msgid="1846494656849381804">"Išeiti iš svečio režimo?"</string>
<string name="guest_exit_dialog_message" msgid="1743218864242719783">"Bus ištrintos esamos svečio sesijos programos ir duomenys"</string>
- <!-- no translation found for grant_admin (4323199171790522574) -->
- <skip />
- <!-- no translation found for not_grant_admin (3557849576157702485) -->
- <skip />
+ <string name="grant_admin" msgid="4323199171790522574">"Taip, nustatyti kaip administratorių"</string>
+ <string name="not_grant_admin" msgid="3557849576157702485">"Ne, nenustatyti kaip administratoriaus"</string>
<string name="guest_exit_dialog_button" msgid="1736401897067442044">"Išeiti"</string>
<string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"Išsaugoti svečio veiklą?"</string>
<string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"Galite išsaugoti esamos sesijos veiklą arba ištrinti visas programas ir duomenis"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 7cf8968..052840d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -519,12 +519,9 @@
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"增加时间。"</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"减少时间。"</string>
<string name="cancel" msgid="5665114069455378395">"取消"</string>
- <!-- no translation found for next (2699398661093607009) -->
- <skip />
- <!-- no translation found for back (5554327870352703710) -->
- <skip />
- <!-- no translation found for save (3745809743277153149) -->
- <skip />
+ <string name="next" msgid="2699398661093607009">"继续"</string>
+ <string name="back" msgid="5554327870352703710">"返回"</string>
+ <string name="save" msgid="3745809743277153149">"保存"</string>
<string name="okay" msgid="949938843324579502">"确定"</string>
<string name="done" msgid="381184316122520313">"完成"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"闹钟和提醒"</string>
@@ -579,12 +576,9 @@
<string name="user_add_user_title" msgid="5457079143694924885">"要添加新用户吗?"</string>
<string name="user_add_user_message_long" msgid="1527434966294733380">"创建新用户后,您就能够与其他人共用此设备。每位用户都有自己的专属空间,而且在自己的个人空间内还可以自行安装自己想要的应用、设置壁纸等。此外,用户还可以调整会影响所有用户的设备设置(例如 WLAN 设置)。\n\n当您添加新用户后,该用户需要自行设置个人空间。\n\n任何用户都可以为所有其他用户更新应用。无障碍功能设置和服务可能无法转移给新用户。"</string>
<string name="user_add_user_message_short" msgid="3295959985795716166">"当您添加新用户后,该用户需要自行设置个人空间。\n\n任何用户都可以为所有其他用户更新应用。"</string>
- <!-- no translation found for user_grant_admin_title (5157031020083343984) -->
- <skip />
- <!-- no translation found for user_grant_admin_message (1673791931033486709) -->
- <skip />
- <!-- no translation found for user_grant_admin_button (5441486731331725756) -->
- <skip />
+ <string name="user_grant_admin_title" msgid="5157031020083343984">"将此用户设为管理员?"</string>
+ <string name="user_grant_admin_message" msgid="1673791931033486709">"管理员拥有其他用户没有的特殊权限。管理员可以管理所有用户、更新或重置此设备、修改设置、查看所有已安装的应用,以及授予或撤消其他用户的管理员权限。"</string>
+ <string name="user_grant_admin_button" msgid="5441486731331725756">"设为管理员"</string>
<string name="user_setup_dialog_title" msgid="8037342066381939995">"要现在设置该用户吗?"</string>
<string name="user_setup_dialog_message" msgid="269931619868102841">"请让相应用户操作设备并设置他们自己的空间。"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"要立即设置个人资料吗?"</string>
@@ -616,10 +610,8 @@
<string name="guest_reset_and_restart_dialog_message" msgid="2764425635305200790">"此操作会开始新的访客会话,并删除当前会话中的所有应用和数据"</string>
<string name="guest_exit_dialog_title" msgid="1846494656849381804">"要退出访客模式吗?"</string>
<string name="guest_exit_dialog_message" msgid="1743218864242719783">"此操作会删除当前访客会话中的所有应用和数据"</string>
- <!-- no translation found for grant_admin (4323199171790522574) -->
- <skip />
- <!-- no translation found for not_grant_admin (3557849576157702485) -->
- <skip />
+ <string name="grant_admin" msgid="4323199171790522574">"是,将其设为管理员"</string>
+ <string name="not_grant_admin" msgid="3557849576157702485">"不,不要将其设为管理员"</string>
<string name="guest_exit_dialog_button" msgid="1736401897067442044">"退出"</string>
<string name="guest_exit_dialog_title_non_ephemeral" msgid="7675327443743162986">"要保存访客活动记录吗?"</string>
<string name="guest_exit_dialog_message_non_ephemeral" msgid="223385323235719442">"您可以保存当前会话中的活动记录,也可以删除所有应用和数据"</string>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 6a5535d..e4cc9f1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -100,5 +100,6 @@
Settings.System.CAMERA_FLASH_NOTIFICATION,
Settings.System.SCREEN_FLASH_NOTIFICATION,
Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
+ Settings.System.SMOOTH_DISPLAY
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 85623b2..4b72063 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -226,5 +226,6 @@
VALIDATORS.put(System.CAMERA_FLASH_NOTIFICATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.SCREEN_FLASH_NOTIFICATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.SCREEN_FLASH_NOTIFICATION_COLOR, ANY_INTEGER_VALIDATOR);
+ VALIDATORS.put(System.SMOOTH_DISPLAY, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 284b06b..d1bd5e6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -34,6 +34,7 @@
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.internal.accessibility.util.AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM;
+import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
import static com.android.providers.settings.SettingsState.FALLBACK_FILE_SUFFIX;
import static com.android.providers.settings.SettingsState.getTypeFromKey;
import static com.android.providers.settings.SettingsState.getUserIdFromKey;
@@ -3748,7 +3749,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 218;
+ private static final int SETTINGS_VERSION = 219;
private final int mUserId;
@@ -5673,7 +5674,7 @@
providers.addAll(Arrays.asList(resources.getStringArray(resourceId)));
} catch (Resources.NotFoundException e) {
Slog.w(LOG_TAG,
- "Get default array Cred Provider not found: " + e.toString());
+ "Get default array Cred Provider not found: " + e.toString());
}
try {
final String storedValue = resources.getString(resourceId);
@@ -5682,7 +5683,7 @@
}
} catch (Resources.NotFoundException e) {
Slog.w(LOG_TAG,
- "Get default Cred Provider not found: " + e.toString());
+ "Get default Cred Provider not found: " + e.toString());
}
if (!providers.isEmpty()) {
@@ -5731,8 +5732,8 @@
final Setting currentSetting = secureSettings
.getSettingLocked(Settings.Secure.CREDENTIAL_SERVICE);
if (currentSetting.isNull()) {
- final int resourceId =
- com.android.internal.R.array.config_defaultCredentialProviderService;
+ final int resourceId = com.android.internal.R.array
+ .config_defaultCredentialProviderService;
final Resources resources = getContext().getResources();
// If the config has not be defined we might get an exception.
final List<String> providers = new ArrayList<>();
@@ -5740,7 +5741,7 @@
providers.addAll(Arrays.asList(resources.getStringArray(resourceId)));
} catch (Resources.NotFoundException e) {
Slog.w(LOG_TAG,
- "Get default array Cred Provider not found: " + e.toString());
+ "Get default array Cred Provider not found: " + e.toString());
}
if (!providers.isEmpty()) {
@@ -5839,6 +5840,47 @@
currentVersion = 218;
}
+ // v218: Convert Smooth Display and Force Peak Refresh Rate to a boolean
+ if (currentVersion == 218) {
+ final String peakRefreshRateSettingName = "peak_refresh_rate";
+ final String minRefreshRateSettingName = "min_refresh_rate";
+
+ final SettingsState systemSettings = getSystemSettingsLocked(userId);
+ final Setting peakRefreshRateSetting =
+ systemSettings.getSettingLocked(peakRefreshRateSettingName);
+ final Setting minRefreshRateSetting =
+ systemSettings.getSettingLocked(minRefreshRateSettingName);
+
+ float peakRefreshRate = DEFAULT_REFRESH_RATE;
+ float minRefreshRate = 0;
+ try {
+ if (!peakRefreshRateSetting.isNull()) {
+ peakRefreshRate = Float.parseFloat(peakRefreshRateSetting.getValue());
+ }
+ } catch (NumberFormatException e) {
+ // Do nothing. Overwrite with default value.
+ }
+ try {
+ if (!minRefreshRateSetting.isNull()) {
+ minRefreshRate = Float.parseFloat(minRefreshRateSetting.getValue());
+ }
+ } catch (NumberFormatException e) {
+ // Do nothing. Overwrite with default value.
+ }
+
+ systemSettings.deleteSettingLocked(peakRefreshRateSettingName);
+ systemSettings.deleteSettingLocked(minRefreshRateSettingName);
+
+ systemSettings.insertSettingLocked(Settings.System.SMOOTH_DISPLAY,
+ peakRefreshRate > DEFAULT_REFRESH_RATE ? "1" : "0", /* tag= */ null,
+ /* makeDefault= */ false, SettingsState.SYSTEM_PACKAGE_NAME);
+ systemSettings.insertSettingLocked(Settings.System.FORCE_PEAK_REFRESH_RATE,
+ minRefreshRate > 0 ? "1" : "0", /* tag= */ null,
+ /* makeDefault= */ false, SettingsState.SYSTEM_PACKAGE_NAME);
+
+ currentVersion = 219;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 706666c..36aa2ac 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -97,8 +97,7 @@
Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
Settings.System.DESKTOP_MODE, // developer setting for internal prototyping
- Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities
- Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities
+ Settings.System.FORCE_PEAK_REFRESH_RATE, // depends on hardware capabilities
Settings.System.SCREEN_BRIGHTNESS_FLOAT,
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 0189294..03b49f0 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -65,6 +65,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.display.RefreshRateSettingsUtils;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.display.DisplayDeviceConfig;
@@ -1171,7 +1172,7 @@
public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 2;
// SETTING_MIN_RENDER_FRAME_RATE is used to propose a lower bound of the render frame rate.
- // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
+ // It votes [minRefreshRate, Float.POSITIVE_INFINITY]
public static final int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3;
// APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render
@@ -1376,10 +1377,10 @@
@VisibleForTesting
final class SettingsObserver extends ContentObserver {
- private final Uri mPeakRefreshRateSetting =
- Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
- private final Uri mMinRefreshRateSetting =
- Settings.System.getUriFor(Settings.System.MIN_REFRESH_RATE);
+ private final Uri mSmoothDisplaySetting =
+ Settings.System.getUriFor(Settings.System.SMOOTH_DISPLAY);
+ private final Uri mForcePeakRefreshRateSetting =
+ Settings.System.getUriFor(Settings.System.FORCE_PEAK_REFRESH_RATE);
private final Uri mLowPowerModeSetting =
Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE);
private final Uri mMatchContentFrameRateSetting =
@@ -1415,9 +1416,8 @@
public void observe() {
final ContentResolver cr = mContext.getContentResolver();
- mInjector.registerPeakRefreshRateObserver(cr, this);
- cr.registerContentObserver(mMinRefreshRateSetting, false /*notifyDescendants*/, this,
- UserHandle.USER_SYSTEM);
+ mInjector.registerSmoothDisplayObserver(cr, this);
+ mInjector.registerForcePeakRefreshRateObserver(cr, this);
cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
UserHandle.USER_SYSTEM);
cr.registerContentObserver(mMatchContentFrameRateSetting, false /*notifyDescendants*/,
@@ -1459,8 +1459,8 @@
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
synchronized (mLock) {
- if (mPeakRefreshRateSetting.equals(uri)
- || mMinRefreshRateSetting.equals(uri)) {
+ if (mSmoothDisplaySetting.equals(uri)
+ || mForcePeakRefreshRateSetting.equals(uri)) {
updateRefreshRateSettingLocked();
} else if (mLowPowerModeSetting.equals(uri)) {
updateLowPowerModeSettingLocked();
@@ -1515,12 +1515,9 @@
}
private void updateRefreshRateSettingLocked() {
- final ContentResolver cr = mContext.getContentResolver();
- float minRefreshRate = Settings.System.getFloatForUser(cr,
- Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId());
- float peakRefreshRate = Settings.System.getFloatForUser(cr,
- Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId());
- updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate);
+ updateRefreshRateSettingLocked(RefreshRateSettingsUtils.getMinRefreshRate(mContext),
+ RefreshRateSettingsUtils.getPeakRefreshRate(mContext, mDefaultPeakRefreshRate),
+ mDefaultRefreshRate);
}
private void updateRefreshRateSettingLocked(
@@ -3165,12 +3162,17 @@
}
interface Injector {
- Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
+ Uri SMOOTH_DISPLAY_URI = Settings.System.getUriFor(Settings.System.SMOOTH_DISPLAY);
+ Uri FORCE_PEAK_REFRESH_RATE_URI =
+ Settings.System.getUriFor(Settings.System.FORCE_PEAK_REFRESH_RATE);
@NonNull
DeviceConfigInterface getDeviceConfig();
- void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
+ void registerSmoothDisplayObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer);
+
+ void registerForcePeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
@@ -3205,9 +3207,16 @@
}
@Override
- public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
+ public void registerSmoothDisplayObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
- cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/,
+ cr.registerContentObserver(SMOOTH_DISPLAY_URI, false /*notifyDescendants*/,
+ observer, UserHandle.USER_SYSTEM);
+ }
+
+ @Override
+ public void registerForcePeakRefreshRateObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ cr.registerContentObserver(FORCE_PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/,
observer, UserHandle.USER_SYSTEM);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java b/services/tests/mockingservicestests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java
new file mode 100644
index 0000000..17fba9f
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import android.hardware.display.DisplayManager;
+import android.provider.Settings;
+import android.testing.TestableContext;
+import android.view.Display;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.display.RefreshRateSettingsUtils;
+
+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;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RefreshRateSettingsUtilsTest {
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getContext());
+
+ @Mock
+ private DisplayManager mDisplayManagerMock;
+ @Mock
+ private Display mDisplayMock;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext.addMockSystemService(DisplayManager.class, mDisplayManagerMock);
+
+ Display.Mode[] modes = new Display.Mode[] {
+ new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
+ /* refreshRate= */ 60),
+ new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
+ /* refreshRate= */ 120),
+ new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600,
+ /* refreshRate= */ 90)
+ };
+
+ when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock);
+ when(mDisplayMock.getSupportedModes()).thenReturn(modes);
+ }
+
+ @Test
+ public void testFindHighestRefreshRateForDefaultDisplay() {
+ when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(null);
+ assertEquals(DEFAULT_REFRESH_RATE,
+ RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext),
+ /* delta= */ 0);
+
+ when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock);
+ assertEquals(120,
+ RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext),
+ /* delta= */ 0);
+ }
+
+ @Test
+ public void testGetMinRefreshRate() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.FORCE_PEAK_REFRESH_RATE, -1);
+ assertEquals(0, RefreshRateSettingsUtils.getMinRefreshRate(mContext), /* delta= */ 0);
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.FORCE_PEAK_REFRESH_RATE, 0);
+ assertEquals(0, RefreshRateSettingsUtils.getMinRefreshRate(mContext), /* delta= */ 0);
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.FORCE_PEAK_REFRESH_RATE, 1);
+ assertEquals(120, RefreshRateSettingsUtils.getMinRefreshRate(mContext), /* delta= */ 0);
+ }
+
+ @Test
+ public void testGetPeakRefreshRate() {
+ float defaultPeakRefreshRate = 100;
+
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, -1);
+ assertEquals(defaultPeakRefreshRate,
+ RefreshRateSettingsUtils.getPeakRefreshRate(mContext, defaultPeakRefreshRate),
+ /* delta= */ 0);
+
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, 0);
+ assertEquals(DEFAULT_REFRESH_RATE,
+ RefreshRateSettingsUtils.getPeakRefreshRate(mContext, defaultPeakRefreshRate),
+ /* delta= */ 0);
+
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, 1);
+ assertEquals(120,
+ RefreshRateSettingsUtils.getPeakRefreshRate(mContext, defaultPeakRefreshRate),
+ /* delta= */ 0);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 6907145..42c1fd9 100644
--- a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -84,6 +84,7 @@
import com.android.internal.R;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.display.RefreshRateSettingsUtils;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider;
@@ -158,6 +159,9 @@
LocalServices.addService(SensorManagerInternal.class, mSensorManagerInternalMock);
LocalServices.removeServiceForTest(DisplayManagerInternal.class);
LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+
+ clearSmoothDisplaySetting();
+ clearForcePeakRefreshRateSetting();
}
private DisplayModeDirector createDirectorFromRefreshRateArray(
@@ -919,7 +923,6 @@
public void testLockFpsForLowZone() throws Exception {
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
- setPeakRefreshRate(90);
director.getSettingsObserver().setDefaultRefreshRate(90);
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
@@ -927,6 +930,7 @@
config.setRefreshRateInLowZone(90);
config.setLowDisplayBrightnessThresholds(new int[] { 10 });
config.setLowAmbientBrightnessThresholds(new int[] { 20 });
+ config.setDefaultPeakRefreshRate(90);
Sensor lightSensor = createLightSensor();
SensorManager sensorManager = createMockSensorManager(lightSensor);
@@ -977,7 +981,6 @@
public void testLockFpsForHighZone() throws Exception {
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
- setPeakRefreshRate(90 /*fps*/);
director.getSettingsObserver().setDefaultRefreshRate(90);
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
@@ -985,6 +988,7 @@
config.setRefreshRateInHighZone(60);
config.setHighDisplayBrightnessThresholds(new int[] { 255 });
config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
+ config.setDefaultPeakRefreshRate(90);
Sensor lightSensor = createLightSensor();
SensorManager sensorManager = createMockSensorManager(lightSensor);
@@ -1032,16 +1036,123 @@
}
@Test
+ public void testSmoothDisplay() {
+ float defaultRefreshRate = 60;
+ int defaultPeakRefreshRate = 100;
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
+ director.getSettingsObserver().setDefaultRefreshRate(defaultRefreshRate);
+ director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
+
+ final FakeDeviceConfig config = mInjector.getDeviceConfig();
+ config.setDefaultPeakRefreshRate(defaultPeakRefreshRate);
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+ director.start(sensorManager);
+
+ // Default value of the setting
+
+ Vote vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ defaultPeakRefreshRate);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ Float.POSITIVE_INFINITY);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ defaultRefreshRate);
+
+ setSmoothDisplayEnabled(false);
+
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ Float.POSITIVE_INFINITY);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ defaultRefreshRate);
+
+ setSmoothDisplayEnabled(true);
+
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext));
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ Float.POSITIVE_INFINITY);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ defaultRefreshRate);
+ }
+
+ @Test
+ public void testForcePeakRefreshRate() {
+ float defaultRefreshRate = 60;
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
+ director.getSettingsObserver().setDefaultRefreshRate(defaultRefreshRate);
+ director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
+
+ Sensor lightSensor = createLightSensor();
+ SensorManager sensorManager = createMockSensorManager(lightSensor);
+ director.start(sensorManager);
+
+ setForcePeakRefreshRateEnabled(false);
+ setSmoothDisplayEnabled(false);
+
+ Vote vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0,
+ /* frameRateHigh= */ Float.POSITIVE_INFINITY);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ defaultRefreshRate);
+
+ setForcePeakRefreshRateEnabled(true);
+
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext));
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */
+ RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext),
+ /* frameRateHigh= */ Float.POSITIVE_INFINITY);
+ vote = director.getVote(Display.DEFAULT_DISPLAY,
+ Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE);
+ assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */
+ defaultRefreshRate);
+ }
+
+ @Test
public void testSensorRegistration() {
// First, configure brightness zones or DMD won't register for sensor data.
final FakeDeviceConfig config = mInjector.getDeviceConfig();
config.setRefreshRateInHighZone(60);
config.setHighDisplayBrightnessThresholds(new int[] { 255 });
config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
+ config.setDefaultPeakRefreshRate(90);
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
- setPeakRefreshRate(90 /*fps*/);
director.getSettingsObserver().setDefaultRefreshRate(90);
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
@@ -2417,10 +2528,10 @@
config.setRefreshRateInHighZone(60);
config.setHighDisplayBrightnessThresholds(new int[] { 255 });
config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
+ config.setDefaultPeakRefreshRate(90);
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
- setPeakRefreshRate(90 /*fps*/);
director.getSettingsObserver().setDefaultRefreshRate(90);
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
@@ -2671,10 +2782,30 @@
listener.onDisplayChanged(DISPLAY_ID);
}
- private void setPeakRefreshRate(float fps) {
- Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE,
- fps);
- mInjector.notifyPeakRefreshRateChanged();
+ private void setSmoothDisplayEnabled(boolean enabled) {
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY,
+ enabled ? 1 : 0);
+ mInjector.notifySmoothDisplaySettingChanged();
+ waitForIdleSync();
+ }
+
+ private void clearSmoothDisplaySetting() {
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, -1);
+ mInjector.notifySmoothDisplaySettingChanged();
+ waitForIdleSync();
+ }
+
+ private void setForcePeakRefreshRateEnabled(boolean enabled) {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.FORCE_PEAK_REFRESH_RATE, enabled ? 1 : 0);
+ mInjector.notifyForcePeakRefreshRateSettingChanged();
+ waitForIdleSync();
+ }
+
+ private void clearForcePeakRefreshRateSetting() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.FORCE_PEAK_REFRESH_RATE, -1);
+ mInjector.notifySmoothDisplaySettingChanged();
waitForIdleSync();
}
@@ -2720,7 +2851,8 @@
public static class FakesInjector implements DisplayModeDirector.Injector {
private final FakeDeviceConfig mDeviceConfig;
private ContentObserver mBrightnessObserver;
- private ContentObserver mPeakRefreshRateObserver;
+ private ContentObserver mSmoothDisplaySettingObserver;
+ private ContentObserver mForcePeakRefreshRateSettingObserver;
FakesInjector() {
mDeviceConfig = new FakeDeviceConfig();
@@ -2732,9 +2864,15 @@
}
@Override
- public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
+ public void registerSmoothDisplayObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
- mPeakRefreshRateObserver = observer;
+ mSmoothDisplaySettingObserver = observer;
+ }
+
+ @Override
+ public void registerForcePeakRefreshRateObserver(@NonNull ContentResolver cr,
+ @NonNull ContentObserver observer) {
+ mForcePeakRefreshRateSettingObserver = observer;
}
@Override
@@ -2775,10 +2913,17 @@
ApplicationProvider.getApplicationContext().getResources());
}
- void notifyPeakRefreshRateChanged() {
- if (mPeakRefreshRateObserver != null) {
- mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
- PEAK_REFRESH_RATE_URI);
+ void notifySmoothDisplaySettingChanged() {
+ if (mSmoothDisplaySettingObserver != null) {
+ mSmoothDisplaySettingObserver.dispatchChange(false /*selfChange*/,
+ SMOOTH_DISPLAY_URI);
+ }
+ }
+
+ void notifyForcePeakRefreshRateSettingChanged() {
+ if (mForcePeakRefreshRateSettingObserver != null) {
+ mForcePeakRefreshRateSettingObserver.dispatchChange(false /*selfChange*/,
+ FORCE_PEAK_REFRESH_RATE_URI);
}
}
}