Merge "Extracting VotesStorage to separate class with local locking" into udc-dev
diff --git a/core/java/android/app/admin/LockTaskPolicy.java b/core/java/android/app/admin/LockTaskPolicy.java
index f5d1cb4..b671d57 100644
--- a/core/java/android/app/admin/LockTaskPolicy.java
+++ b/core/java/android/app/admin/LockTaskPolicy.java
@@ -38,6 +38,7 @@
/**
* @hide
*/
+ // We default on the power button menu, in order to be consistent with pre-P behaviour
public static final int DEFAULT_LOCK_TASK_FLAG =
DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
@@ -72,18 +73,28 @@
/**
* @hide
*/
- public LockTaskPolicy(@NonNull Set<String> packages) {
- Objects.requireNonNull(packages);
- mPackages.addAll(packages);
+ public LockTaskPolicy(@Nullable Set<String> packages) {
+ if (packages != null) {
+ mPackages.addAll(packages);
+ }
setValue(this);
}
/**
* @hide
*/
- public LockTaskPolicy(@NonNull Set<String> packages, int flags) {
- Objects.requireNonNull(packages);
- mPackages = new HashSet<>(packages);
+ public LockTaskPolicy(int flags) {
+ mFlags = flags;
+ setValue(this);
+ }
+
+ /**
+ * @hide
+ */
+ public LockTaskPolicy(@Nullable Set<String> packages, int flags) {
+ if (packages != null) {
+ mPackages.addAll(packages);
+ }
mFlags = flags;
setValue(this);
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index e31adcf..f2373fb 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -341,6 +341,9 @@
@Nullable
public DisplayShape displayShape;
+ /**
+ * Refresh rate range limitation based on the current device layout
+ */
@Nullable
public SurfaceControl.RefreshRateRange layoutLimitedRefreshRate;
@@ -354,7 +357,7 @@
* RefreshRateRange limitation for @Temperature.ThrottlingStatus
*/
@NonNull
- public SparseArray<SurfaceControl.RefreshRateRange> refreshRateThermalThrottling =
+ public SparseArray<SurfaceControl.RefreshRateRange> thermalRefreshRateThrottling =
new SparseArray<>();
public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
@@ -434,7 +437,7 @@
&& Objects.equals(displayShape, other.displayShape)
&& Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate)
&& BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)
- && refreshRateThermalThrottling.contentEquals(other.refreshRateThermalThrottling);
+ && thermalRefreshRateThrottling.contentEquals(other.thermalRefreshRateThrottling);
}
@Override
@@ -491,7 +494,7 @@
displayShape = other.displayShape;
layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
hdrSdrRatio = other.hdrSdrRatio;
- refreshRateThermalThrottling = other.refreshRateThermalThrottling;
+ thermalRefreshRateThrottling = other.thermalRefreshRateThrottling;
}
public void readFromParcel(Parcel source) {
@@ -554,7 +557,7 @@
displayShape = source.readTypedObject(DisplayShape.CREATOR);
layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
hdrSdrRatio = source.readFloat();
- refreshRateThermalThrottling = source.readSparseArray(null,
+ thermalRefreshRateThrottling = source.readSparseArray(null,
SurfaceControl.RefreshRateRange.class);
}
@@ -616,7 +619,7 @@
dest.writeTypedObject(displayShape, flags);
dest.writeTypedObject(layoutLimitedRefreshRate, flags);
dest.writeFloat(hdrSdrRatio);
- dest.writeSparseArray(refreshRateThermalThrottling);
+ dest.writeSparseArray(thermalRefreshRateThrottling);
}
@Override
@@ -884,8 +887,8 @@
} else {
sb.append(hdrSdrRatio);
}
- sb.append(", refreshRateThermalThrottling ");
- sb.append(refreshRateThermalThrottling);
+ sb.append(", thermalRefreshRateThrottling ");
+ sb.append(thermalRefreshRateThrottling);
sb.append("}");
return sb.toString();
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index dab00d8..0b6d1c8 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -181,6 +181,19 @@
*/
private String mThermalBrightnessThrottlingDataId;
+ /**
+ * Refresh rate range limitation based on the current device layout
+ */
+ @Nullable
+ private SurfaceControl.RefreshRateRange mLayoutLimitedRefreshRate;
+
+ /**
+ * RefreshRateRange limitation for @Temperature.ThrottlingStatus
+ */
+ @NonNull
+ private SparseArray<SurfaceControl.RefreshRateRange> mThermalRefreshRateThrottling =
+ new SparseArray<>();
+
public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
mDisplayId = displayId;
mLayerStack = layerStack;
@@ -339,24 +352,24 @@
*/
public void updateLayoutLimitedRefreshRateLocked(
@Nullable SurfaceControl.RefreshRateRange layoutLimitedRefreshRate) {
- if (!Objects.equals(layoutLimitedRefreshRate, mBaseDisplayInfo.layoutLimitedRefreshRate)) {
- mBaseDisplayInfo.layoutLimitedRefreshRate = layoutLimitedRefreshRate;
- mInfo.set(null);
+ if (!Objects.equals(layoutLimitedRefreshRate, mLayoutLimitedRefreshRate)) {
+ mLayoutLimitedRefreshRate = layoutLimitedRefreshRate;
+ mDirty = true;
}
}
/**
- * Updates refreshRateThermalThrottling
+ * Updates thermalRefreshRateThrottling
*
- * @param refreshRanges new refreshRateThermalThrottling ranges limited by layout or default
+ * @param refreshRanges new thermalRefreshRateThrottling ranges limited by layout or default
*/
public void updateThermalRefreshRateThrottling(
@Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) {
if (refreshRanges == null) {
refreshRanges = new SparseArray<>();
}
- if (!mBaseDisplayInfo.refreshRateThermalThrottling.contentEquals(refreshRanges)) {
- mBaseDisplayInfo.refreshRateThermalThrottling = refreshRanges;
- mInfo.set(null);
+ if (!mThermalRefreshRateThrottling.contentEquals(refreshRanges)) {
+ mThermalRefreshRateThrottling = refreshRanges;
+ mDirty = true;
}
}
@@ -499,6 +512,9 @@
mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
}
+ mBaseDisplayInfo.layoutLimitedRefreshRate = mLayoutLimitedRefreshRate;
+ mBaseDisplayInfo.thermalRefreshRateThrottling = mThermalRefreshRateThrottling;
+
mPrimaryDisplayDeviceInfo = deviceInfo;
mInfo.set(null);
mDirty = false;
@@ -952,6 +968,8 @@
pw.println("mDisplayGroupName=" + mDisplayGroupName);
pw.println("mThermalBrightnessThrottlingDataId=" + mThermalBrightnessThrottlingDataId);
pw.println("mLeadDisplayId=" + mLeadDisplayId);
+ pw.println("mLayoutLimitedRefreshRate=" + mLayoutLimitedRefreshRate);
+ pw.println("mThermalRefreshRateThrottling=" + mThermalRefreshRateThrottling);
}
@Override
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 86ba1dd..fd94be9 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -1393,14 +1393,13 @@
}
public void observe() {
- DisplayManager dm = mContext.getSystemService(DisplayManager.class);
- dm.registerDisplayListener(this, mHandler);
+ mInjector.registerDisplayListener(this, mHandler);
// Populate existing displays
SparseArray<Display.Mode[]> modes = new SparseArray<>();
SparseArray<Display.Mode> defaultModes = new SparseArray<>();
DisplayInfo info = new DisplayInfo();
- Display[] displays = dm.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ Display[] displays = mInjector.getDisplays();
for (Display d : displays) {
final int displayId = d.getDisplayId();
d.getDisplayInfo(info);
@@ -1441,16 +1440,9 @@
@Nullable
private DisplayInfo getDisplayInfo(int displayId) {
- Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
- if (d == null) {
- // We can occasionally get a display added or changed event for a display that was
- // subsequently removed, which means this returns null. Check this case and bail
- // out early; if it gets re-attached we'll eventually get another call back for it.
- return null;
- }
DisplayInfo info = new DisplayInfo();
- d.getDisplayInfo(info);
- return info;
+ // Display info might be invalid, in this case return null
+ return mInjector.getDisplayInfo(displayId, info) ? info : null;
}
private void updateLayoutLimitedFrameRate(int displayId, @Nullable DisplayInfo info) {
@@ -2121,8 +2113,7 @@
}
private void updateDefaultDisplayState() {
- Display display = mContext.getSystemService(DisplayManager.class)
- .getDisplay(Display.DEFAULT_DISPLAY);
+ Display display = mInjector.getDisplay(Display.DEFAULT_DISPLAY);
if (display == null) {
return;
}
@@ -2439,8 +2430,7 @@
sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
synchronized (mSensorObserverLock) {
- for (Display d : mDisplayManager.getDisplays(
- DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) {
+ for (Display d : mInjector.getDisplays()) {
mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
}
}
@@ -2451,8 +2441,7 @@
}
private void recalculateVotesLocked() {
- final Display[] displays = mDisplayManager.getDisplays(
- DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ final Display[] displays = mInjector.getDisplays();
for (Display d : displays) {
int displayId = d.getDisplayId();
Vote vote = null;
@@ -2483,7 +2472,7 @@
@Override
public void onDisplayAdded(int displayId) {
- boolean isDozeState = mInjector.isDozeState(mDisplayManager.getDisplay(displayId));
+ boolean isDozeState = mInjector.isDozeState(mInjector.getDisplay(displayId));
synchronized (mSensorObserverLock) {
mDozeStateByDisplay.put(displayId, isDozeState);
recalculateVotesLocked();
@@ -2495,7 +2484,7 @@
boolean wasDozeState = mDozeStateByDisplay.get(displayId);
synchronized (mSensorObserverLock) {
mDozeStateByDisplay.put(displayId,
- mInjector.isDozeState(mDisplayManager.getDisplay(displayId)));
+ mInjector.isDozeState(mInjector.getDisplay(displayId)));
if (wasDozeState != mDozeStateByDisplay.get(displayId)) {
recalculateVotesLocked();
}
@@ -2865,8 +2854,13 @@
@NonNull ContentObserver observer);
void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
+ Handler handler);
+
+ void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
Handler handler, long flags);
+ Display getDisplay(int displayId);
+
Display[] getDisplays();
boolean getDisplayInfo(int displayId, DisplayInfo displayInfo);
@@ -2911,11 +2905,22 @@
@Override
public void registerDisplayListener(DisplayManager.DisplayListener listener,
+ Handler handler) {
+ getDisplayManager().registerDisplayListener(listener, handler);
+ }
+
+ @Override
+ public void registerDisplayListener(DisplayManager.DisplayListener listener,
Handler handler, long flags) {
getDisplayManager().registerDisplayListener(listener, handler, flags);
}
@Override
+ public Display getDisplay(int displayId) {
+ return getDisplayManager().getDisplay(displayId);
+ }
+
+ @Override
public Display[] getDisplays() {
return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
}
@@ -2923,10 +2928,13 @@
@Override
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
Display display = getDisplayManager().getDisplay(displayId);
- if (display != null) {
- return display.getDisplayInfo(displayInfo);
+ if (display == null) {
+ // We can occasionally get a display added or changed event for a display that was
+ // subsequently removed, which means this returns null. Check this case and bail
+ // out early; if it gets re-attached we'll eventually get another call back for it.
+ return false;
}
- return false;
+ return display.getDisplayInfo(displayInfo);
}
@Override
diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
index d2822ca..58e1550 100644
--- a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
+++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
@@ -138,7 +138,7 @@
for (Display d : displays) {
final int displayId = d.getDisplayId();
d.getDisplayInfo(info);
- localMap.put(displayId, info.refreshRateThermalThrottling);
+ localMap.put(displayId, info.thermalRefreshRateThrottling);
}
synchronized (mThermalObserverLock) {
for (int i = 0; i < size; i++) {
@@ -154,7 +154,7 @@
DisplayInfo displayInfo = new DisplayInfo();
mInjector.getDisplayInfo(displayId, displayInfo);
SparseArray<SurfaceControl.RefreshRateRange> throttlingMap =
- displayInfo.refreshRateThermalThrottling;
+ displayInfo.thermalRefreshRateThrottling;
synchronized (mThermalObserverLock) {
mThermalThrottlingByDisplay.put(displayId, throttlingMap);
diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java
index 048308e..48c346a 100644
--- a/services/core/java/com/android/server/input/KeyboardBacklightController.java
+++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java
@@ -199,8 +199,11 @@
}
if (brightness.isPresent()) {
int brightnessValue = Math.max(0, Math.min(MAX_BRIGHTNESS, brightness.getAsInt()));
- int brightnessLevel = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
- updateBacklightState(inputDevice.getId(), keyboardBacklight, brightnessLevel,
+ int index = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
+ if (index < 0) {
+ index = Math.min(NUM_BRIGHTNESS_CHANGE_STEPS, -(index + 1));
+ }
+ updateBacklightState(inputDevice.getId(), keyboardBacklight, index,
false /* isTriggeredByKeyPress */);
if (DEBUG) {
Slog.d(TAG, "Restoring brightness level " + brightness.getAsInt());
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 72c7dad..d8716b3 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -16,6 +16,8 @@
package com.android.server.input;
+import android.annotation.AnyThread;
+import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -99,6 +101,7 @@
private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
+ private static final int MSG_CURRENT_IME_INFO_CHANGED = 5;
private final Context mContext;
private final NativeInputManagerService mNative;
@@ -108,16 +111,17 @@
private final Handler mHandler;
// Connected keyboards with associated keyboard layouts (either auto-detected or manually
- // selected layout). If the mapped value is null/empty, it means that no layout has been
- // configured for the keyboard and user might need to manually configure it from the Settings.
- private final SparseArray<Set<String>> mConfiguredKeyboards = new SparseArray<>();
+ // selected layout).
+ private final SparseArray<KeyboardConfiguration> mConfiguredKeyboards = new SparseArray<>();
private Toast mSwitchedKeyboardLayoutToast;
// This cache stores "best-matched" layouts so that we don't need to run the matching
// algorithm repeatedly.
@GuardedBy("mKeyboardLayoutCache")
private final Map<String, String> mKeyboardLayoutCache = new ArrayMap<>();
+ private final Object mImeInfoLock = new Object();
@Nullable
+ @GuardedBy("mImeInfoLock")
private ImeInfo mCurrentImeInfo;
KeyboardLayoutManager(Context context, NativeInputManagerService nativeService,
@@ -155,26 +159,32 @@
}
@Override
+ @MainThread
public void onInputDeviceAdded(int deviceId) {
onInputDeviceChanged(deviceId);
- if (useNewSettingsUi()) {
- // Force native callback to set up keyboard layout overlay for newly added keyboards
- reloadKeyboardLayouts();
- }
}
@Override
+ @MainThread
public void onInputDeviceRemoved(int deviceId) {
mConfiguredKeyboards.remove(deviceId);
maybeUpdateNotification();
}
@Override
+ @MainThread
public void onInputDeviceChanged(int deviceId) {
final InputDevice inputDevice = getInputDevice(deviceId);
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return;
}
+ KeyboardConfiguration config = mConfiguredKeyboards.get(deviceId);
+ if (config == null) {
+ config = new KeyboardConfiguration();
+ mConfiguredKeyboards.put(deviceId, config);
+ }
+
+ boolean needToShowNotification = false;
if (!useNewSettingsUi()) {
synchronized (mDataStore) {
String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
@@ -182,54 +192,66 @@
layout = getDefaultKeyboardLayout(inputDevice);
if (layout != null) {
setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
- } else {
- mConfiguredKeyboards.put(inputDevice.getId(), new HashSet<>());
}
}
+ config.setCurrentLayout(layout);
+ if (layout == null) {
+ // In old settings show notification always until user manually selects a
+ // layout in the settings.
+ needToShowNotification = true;
+ }
}
} else {
final InputDeviceIdentifier identifier = inputDevice.getIdentifier();
final String key = getLayoutDescriptor(identifier);
Set<String> selectedLayouts = new HashSet<>();
- boolean needToShowMissingLayoutNotification = false;
for (ImeInfo imeInfo : getImeInfoListForLayoutMapping()) {
// Check if the layout has been previously configured
String layout = getKeyboardLayoutForInputDeviceInternal(identifier,
new ImeInfo(imeInfo.mUserId, imeInfo.mImeSubtypeHandle,
imeInfo.mImeSubtype));
if (layout == null) {
- needToShowMissingLayoutNotification = true;
- continue;
+ // If even one layout not configured properly, we need to ask user to configure
+ // the keyboard properly from the Settings.
+ selectedLayouts.clear();
+ break;
}
selectedLayouts.add(layout);
}
- if (needToShowMissingLayoutNotification) {
- // If even one layout not configured properly we will show configuration
- // notification allowing user to set the keyboard layout.
- selectedLayouts.clear();
- }
-
if (DEBUG) {
Slog.d(TAG,
"Layouts selected for input device: " + identifier + " -> selectedLayouts: "
+ selectedLayouts);
}
- mConfiguredKeyboards.set(inputDevice.getId(), selectedLayouts);
+
+ config.setConfiguredLayouts(selectedLayouts);
+
+ // Update current layout: If there is a change then need to reload.
+ synchronized (mImeInfoLock) {
+ String layout = getKeyboardLayoutForInputDeviceInternal(
+ inputDevice.getIdentifier(), mCurrentImeInfo);
+ if (!Objects.equals(layout, config.getCurrentLayout())) {
+ config.setCurrentLayout(layout);
+ mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
+ }
+ }
synchronized (mDataStore) {
try {
- if (!mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
- // No need to show the notification only if layout selection didn't change
+ if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
+ // Need to show the notification only if layout selection changed
// from the previous configuration
- return;
+ needToShowNotification = true;
}
} finally {
mDataStore.saveIfNeeded();
}
}
}
- maybeUpdateNotification();
+ if (needToShowNotification) {
+ maybeUpdateNotification();
+ }
}
private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
@@ -323,12 +345,14 @@
reloadKeyboardLayouts();
}
+ @AnyThread
public KeyboardLayout[] getKeyboardLayouts() {
final ArrayList<KeyboardLayout> list = new ArrayList<>();
visitAllKeyboardLayouts((resources, keyboardLayoutResId, layout) -> list.add(layout));
return list.toArray(new KeyboardLayout[0]);
}
+ @AnyThread
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
final InputDeviceIdentifier identifier) {
if (useNewSettingsUi()) {
@@ -375,6 +399,7 @@
KeyboardLayout[]::new);
}
+ @AnyThread
@Nullable
public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
Objects.requireNonNull(keyboardLayoutDescriptor,
@@ -543,6 +568,7 @@
return key.toString();
}
+ @AnyThread
@Nullable
public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
if (useNewSettingsUi()) {
@@ -566,6 +592,7 @@
}
}
+ @AnyThread
public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (useNewSettingsUi()) {
@@ -592,6 +619,7 @@
}
}
+ @AnyThread
public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
if (useNewSettingsUi()) {
Slog.e(TAG, "getEnabledKeyboardLayoutsForInputDevice API not supported");
@@ -608,6 +636,7 @@
}
}
+ @AnyThread
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (useNewSettingsUi()) {
@@ -635,6 +664,7 @@
}
}
+ @AnyThread
public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (useNewSettingsUi()) {
@@ -667,6 +697,7 @@
}
}
+ @AnyThread
public void switchKeyboardLayout(int deviceId, int direction) {
if (useNewSettingsUi()) {
Slog.e(TAG, "switchKeyboardLayout API not supported");
@@ -675,7 +706,7 @@
mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
}
- // Must be called on handler.
+ @MainThread
private void handleSwitchKeyboardLayout(int deviceId, int direction) {
final InputDevice device = getInputDevice(deviceId);
if (device != null) {
@@ -713,23 +744,14 @@
}
@Nullable
+ @AnyThread
public String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
String keyboardLayoutDescriptor;
if (useNewSettingsUi()) {
- InputDevice inputDevice = getInputDevice(identifier);
- if (inputDevice == null) {
- // getKeyboardLayoutOverlay() called before input device added completely. Need
- // to wait till the device is added which will call reloadKeyboardLayouts()
- return null;
+ synchronized (mImeInfoLock) {
+ keyboardLayoutDescriptor = getKeyboardLayoutForInputDeviceInternal(identifier,
+ mCurrentImeInfo);
}
- if (mCurrentImeInfo == null) {
- // Haven't received onInputMethodSubtypeChanged() callback from IMMS. Will reload
- // keyboard layouts once we receive the callback.
- return null;
- }
-
- keyboardLayoutDescriptor = getKeyboardLayoutForInputDeviceInternal(identifier,
- mCurrentImeInfo);
} else {
keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
}
@@ -755,6 +777,7 @@
return result;
}
+ @AnyThread
@Nullable
public String getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@@ -773,6 +796,7 @@
return layout;
}
+ @AnyThread
public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@Nullable InputMethodSubtype imeSubtype,
@@ -783,8 +807,8 @@
}
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
- String key = createLayoutKey(identifier, userId,
- InputMethodSubtypeHandle.of(imeInfo, imeSubtype));
+ String key = createLayoutKey(identifier,
+ new ImeInfo(userId, InputMethodSubtypeHandle.of(imeInfo, imeSubtype), imeSubtype));
synchronized (mDataStore) {
try {
// Key for storing into data store = <device descriptor>,<userId>,<subtypeHandle>
@@ -803,6 +827,7 @@
}
}
+ @AnyThread
public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@Nullable InputMethodSubtype imeSubtype) {
@@ -815,8 +840,8 @@
}
private KeyboardLayout[] getKeyboardLayoutListForInputDeviceInternal(
- InputDeviceIdentifier identifier, ImeInfo imeInfo) {
- String key = createLayoutKey(identifier, imeInfo.mUserId, imeInfo.mImeSubtypeHandle);
+ InputDeviceIdentifier identifier, @Nullable ImeInfo imeInfo) {
+ String key = createLayoutKey(identifier, imeInfo);
// Fetch user selected layout and always include it in layout list.
String userSelectedLayout;
@@ -826,7 +851,7 @@
final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<>();
String imeLanguageTag;
- if (imeInfo.mImeSubtype == null) {
+ if (imeInfo == null || imeInfo.mImeSubtype == null) {
imeLanguageTag = "";
} else {
ULocale imeLocale = imeInfo.mImeSubtype.getPhysicalKeyboardHintLanguageTag();
@@ -866,6 +891,7 @@
return potentialLayouts.toArray(new KeyboardLayout[0]);
}
+ @AnyThread
public void onInputMethodSubtypeChanged(@UserIdInt int userId,
@Nullable InputMethodSubtypeHandle subtypeHandle,
@Nullable InputMethodSubtype subtype) {
@@ -879,25 +905,45 @@
}
return;
}
- if (mCurrentImeInfo == null || !subtypeHandle.equals(mCurrentImeInfo.mImeSubtypeHandle)
- || mCurrentImeInfo.mUserId != userId) {
- mCurrentImeInfo = new ImeInfo(userId, subtypeHandle, subtype);
- mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
- if (DEBUG) {
- Slog.d(TAG, "InputMethodSubtype changed: userId=" + userId
- + " subtypeHandle=" + subtypeHandle);
+ synchronized (mImeInfoLock) {
+ if (mCurrentImeInfo == null || !subtypeHandle.equals(mCurrentImeInfo.mImeSubtypeHandle)
+ || mCurrentImeInfo.mUserId != userId) {
+ mCurrentImeInfo = new ImeInfo(userId, subtypeHandle, subtype);
+ mHandler.sendEmptyMessage(MSG_CURRENT_IME_INFO_CHANGED);
+ if (DEBUG) {
+ Slog.d(TAG, "InputMethodSubtype changed: userId=" + userId
+ + " subtypeHandle=" + subtypeHandle);
+ }
+ }
+ }
+ }
+
+ @MainThread
+ private void onCurrentImeInfoChanged() {
+ synchronized (mImeInfoLock) {
+ for (int i = 0; i < mConfiguredKeyboards.size(); i++) {
+ InputDevice inputDevice = Objects.requireNonNull(
+ getInputDevice(mConfiguredKeyboards.keyAt(i)));
+ String layout = getKeyboardLayoutForInputDeviceInternal(inputDevice.getIdentifier(),
+ mCurrentImeInfo);
+ KeyboardConfiguration config = mConfiguredKeyboards.valueAt(i);
+ if (!Objects.equals(layout, config.getCurrentLayout())) {
+ config.setCurrentLayout(layout);
+ mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
+ return;
+ }
}
}
}
@Nullable
private String getKeyboardLayoutForInputDeviceInternal(InputDeviceIdentifier identifier,
- ImeInfo imeInfo) {
+ @Nullable ImeInfo imeInfo) {
InputDevice inputDevice = getInputDevice(identifier);
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return null;
}
- String key = createLayoutKey(identifier, imeInfo.mUserId, imeInfo.mImeSubtypeHandle);
+ String key = createLayoutKey(identifier, imeInfo);
String layout;
synchronized (mDataStore) {
layout = mDataStore.getKeyboardLayout(getLayoutDescriptor(identifier), key);
@@ -923,11 +969,7 @@
@Nullable
private static String getDefaultKeyboardLayoutBasedOnImeInfo(InputDevice inputDevice,
- ImeInfo imeInfo, KeyboardLayout[] layoutList) {
- if (imeInfo.mImeSubtypeHandle == null) {
- return null;
- }
-
+ @Nullable ImeInfo imeInfo, KeyboardLayout[] layoutList) {
Arrays.sort(layoutList);
// Check <VendorID, ProductID> matching for explicitly declared custom KCM files.
@@ -961,12 +1003,12 @@
}
}
- InputMethodSubtype subtype = imeInfo.mImeSubtype;
- // Can't auto select layout based on IME if subtype or language tag is null
- if (subtype == null) {
+ if (imeInfo == null || imeInfo.mImeSubtypeHandle == null || imeInfo.mImeSubtype == null) {
+ // Can't auto select layout based on IME info is null
return null;
}
+ InputMethodSubtype subtype = imeInfo.mImeSubtype;
// Check layout type, language tag information from IME for matching
ULocale pkLocale = subtype.getPhysicalKeyboardHintLanguageTag();
String pkLanguageTag =
@@ -1043,6 +1085,7 @@
mNative.reloadKeyboardLayouts();
}
+ @MainThread
private void maybeUpdateNotification() {
if (mConfiguredKeyboards.size() == 0) {
hideKeyboardLayoutNotification();
@@ -1051,7 +1094,7 @@
for (int i = 0; i < mConfiguredKeyboards.size(); i++) {
// If we have a keyboard with no selected layouts, we should always show missing
// layout notification even if there are other keyboards that are configured properly.
- if (mConfiguredKeyboards.valueAt(i).isEmpty()) {
+ if (!mConfiguredKeyboards.valueAt(i).hasConfiguredLayouts()) {
showMissingKeyboardLayoutNotification();
return;
}
@@ -1059,7 +1102,7 @@
showConfiguredKeyboardLayoutNotification();
}
- // Must be called on handler.
+ @MainThread
private void showMissingKeyboardLayoutNotification() {
final Resources r = mContext.getResources();
final String missingKeyboardLayoutNotificationContent = r.getString(
@@ -1084,6 +1127,7 @@
}
}
+ @MainThread
private void showKeyboardLayoutNotification(@NonNull String intentTitle,
@NonNull String intentContent, @Nullable InputDevice targetDevice) {
final NotificationManager notificationManager = mContext.getSystemService(
@@ -1119,7 +1163,7 @@
notification, UserHandle.ALL);
}
- // Must be called on handler.
+ @MainThread
private void hideKeyboardLayoutNotification() {
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
@@ -1132,6 +1176,7 @@
UserHandle.ALL);
}
+ @MainThread
private void showConfiguredKeyboardLayoutNotification() {
final Resources r = mContext.getResources();
@@ -1144,8 +1189,8 @@
}
final InputDevice inputDevice = getInputDevice(mConfiguredKeyboards.keyAt(0));
- final Set<String> selectedLayouts = mConfiguredKeyboards.valueAt(0);
- if (inputDevice == null || selectedLayouts == null || selectedLayouts.isEmpty()) {
+ final KeyboardConfiguration config = mConfiguredKeyboards.valueAt(0);
+ if (inputDevice == null || !config.hasConfiguredLayouts()) {
return;
}
@@ -1153,10 +1198,11 @@
r.getString(
R.string.keyboard_layout_notification_selected_title,
inputDevice.getName()),
- createConfiguredNotificationText(mContext, selectedLayouts),
+ createConfiguredNotificationText(mContext, config.getConfiguredLayouts()),
inputDevice);
}
+ @MainThread
private String createConfiguredNotificationText(@NonNull Context context,
@NonNull Set<String> selectedLayouts) {
final Resources r = context.getResources();
@@ -1199,6 +1245,9 @@
case MSG_UPDATE_KEYBOARD_LAYOUTS:
updateKeyboardLayouts();
return true;
+ case MSG_CURRENT_IME_INFO_CHANGED:
+ onCurrentImeInfoChanged();
+ return true;
default:
return false;
}
@@ -1252,17 +1301,19 @@
return imeInfoList;
}
- private String createLayoutKey(InputDeviceIdentifier identifier, int userId,
- @NonNull InputMethodSubtypeHandle subtypeHandle) {
- Objects.requireNonNull(subtypeHandle, "subtypeHandle must not be null");
- return "layoutDescriptor:" + getLayoutDescriptor(identifier) + ",userId:" + userId
- + ",subtypeHandle:" + subtypeHandle.toStringHandle();
+ private String createLayoutKey(InputDeviceIdentifier identifier, @Nullable ImeInfo imeInfo) {
+ if (imeInfo == null) {
+ return getLayoutDescriptor(identifier);
+ }
+ Objects.requireNonNull(imeInfo.mImeSubtypeHandle, "subtypeHandle must not be null");
+ return "layoutDescriptor:" + getLayoutDescriptor(identifier) + ",userId:" + imeInfo.mUserId
+ + ",subtypeHandle:" + imeInfo.mImeSubtypeHandle.toStringHandle();
}
private static boolean isLayoutCompatibleWithLanguageTag(KeyboardLayout layout,
@NonNull String languageTag) {
LocaleList layoutLocales = layout.getLocales();
- if (layoutLocales.isEmpty()) {
+ if (layoutLocales.isEmpty() || TextUtils.isEmpty(languageTag)) {
// KCM file doesn't have an associated language tag. This can be from
// a 3rd party app so need to include it as a potential layout.
return true;
@@ -1350,6 +1401,39 @@
}
}
+ private static class KeyboardConfiguration {
+ // If null or empty, it means no layout is configured for the device. And user needs to
+ // manually set up the device.
+ @Nullable
+ private Set<String> mConfiguredLayouts;
+
+ // If null, it means no layout is selected for the device.
+ @Nullable
+ private String mCurrentLayout;
+
+ private boolean hasConfiguredLayouts() {
+ return mConfiguredLayouts != null && !mConfiguredLayouts.isEmpty();
+ }
+
+ @Nullable
+ private Set<String> getConfiguredLayouts() {
+ return mConfiguredLayouts;
+ }
+
+ private void setConfiguredLayouts(Set<String> configuredLayouts) {
+ mConfiguredLayouts = configuredLayouts;
+ }
+
+ @Nullable
+ private String getCurrentLayout() {
+ return mCurrentLayout;
+ }
+
+ private void setCurrentLayout(String currentLayout) {
+ mCurrentLayout = currentLayout;
+ }
+ }
+
private interface KeyboardLayoutVisitor {
void visitKeyboardLayout(Resources resources,
int keyboardLayoutResId, KeyboardLayout layout);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0532a79..247a5c0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2987,6 +2987,7 @@
}
break;
case KeyEvent.KEYCODE_H:
+ case KeyEvent.KEYCODE_ENTER:
if (event.isMetaPressed()) {
return handleHomeShortcuts(displayId, focusedToken, event);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f6bc93a..ee75f84 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -14744,24 +14744,24 @@
synchronized (getLockObject()) {
enforcingAdmin = enforceCanCallLockTaskLocked(who, caller.getPackageName());
}
- if (packages.length == 0) {
+ LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicySetByAdmin(
+ PolicyDefinition.LOCK_TASK,
+ enforcingAdmin,
+ caller.getUserId());
+ LockTaskPolicy policy;
+ if (currentPolicy == null) {
+ policy = new LockTaskPolicy(Set.of(packages));
+ } else {
+ policy = new LockTaskPolicy(currentPolicy);
+ policy.setPackages(Set.of(packages));
+ }
+ if (policy.getPackages().isEmpty()
+ && policy.getFlags() == DevicePolicyManager.LOCK_TASK_FEATURE_NONE) {
mDevicePolicyEngine.removeLocalPolicy(
PolicyDefinition.LOCK_TASK,
enforcingAdmin,
caller.getUserId());
} else {
- LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicySetByAdmin(
- PolicyDefinition.LOCK_TASK,
- enforcingAdmin,
- caller.getUserId());
- LockTaskPolicy policy;
- if (currentPolicy == null) {
- policy = new LockTaskPolicy(Set.of(packages));
- } else {
- policy = new LockTaskPolicy(currentPolicy);
- policy.setPackages(Set.of(packages));
- }
-
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.LOCK_TASK,
enforcingAdmin,
@@ -14876,18 +14876,26 @@
PolicyDefinition.LOCK_TASK,
enforcingAdmin,
caller.getUserId());
+ LockTaskPolicy policy;
if (currentPolicy == null) {
- throw new IllegalArgumentException("Can't set a lock task flags without setting "
- + "lock task packages first.");
+ policy = new LockTaskPolicy(flags);
+ } else {
+ policy = new LockTaskPolicy(currentPolicy);
+ policy.setFlags(flags);
}
- LockTaskPolicy policy = new LockTaskPolicy(currentPolicy);
- policy.setFlags(flags);
-
- mDevicePolicyEngine.setLocalPolicy(
- PolicyDefinition.LOCK_TASK,
- enforcingAdmin,
- policy,
- caller.getUserId());
+ if (policy.getPackages().isEmpty()
+ && policy.getFlags() == DevicePolicyManager.LOCK_TASK_FEATURE_NONE) {
+ mDevicePolicyEngine.removeLocalPolicy(
+ PolicyDefinition.LOCK_TASK,
+ enforcingAdmin,
+ caller.getUserId());
+ } else {
+ mDevicePolicyEngine.setLocalPolicy(
+ PolicyDefinition.LOCK_TASK,
+ enforcingAdmin,
+ policy,
+ caller.getUserId());
+ }
} else {
Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java
index 0f6f3c5..20bd2d7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicySerializer.java
@@ -42,10 +42,6 @@
void saveToXml(PolicyKey policyKey, TypedXmlSerializer serializer,
@NonNull LockTaskPolicy value) throws IOException {
Objects.requireNonNull(value);
- if (value.getPackages() == null || value.getPackages().isEmpty()) {
- throw new IllegalArgumentException("Error saving LockTaskPolicy to file, lock task "
- + "packages must be present");
- }
serializer.attribute(
/* namespace= */ null,
ATTR_PACKAGES,
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index ff89be7..5ea3029 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -17,6 +17,8 @@
package com.android.server.display;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -26,6 +28,7 @@
import android.app.PropertyInvalidatedCache;
import android.graphics.Point;
+import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -47,6 +50,7 @@
private static final int LAYER_STACK = 0;
private static final int DISPLAY_WIDTH = 100;
private static final int DISPLAY_HEIGHT = 200;
+ private static final int MODE_ID = 1;
private LogicalDisplay mLogicalDisplay;
private DisplayDevice mDisplayDevice;
@@ -65,6 +69,9 @@
mDisplayDeviceInfo.height = DISPLAY_HEIGHT;
mDisplayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
+ mDisplayDeviceInfo.modeId = MODE_ID;
+ mDisplayDeviceInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT, /* refreshRate= */ 60)};
when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(mDisplayDeviceInfo);
// Disable binder caches in this process.
@@ -168,14 +175,34 @@
}
@Test
- public void testLayoutLimitedRefreshRateNotClearedAfterUpdate() {
- SurfaceControl.RefreshRateRange refreshRateRange = new SurfaceControl.RefreshRateRange(1,
- 2);
- mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(refreshRateRange);
- mLogicalDisplay.updateDisplayGroupIdLocked(1);
+ public void testUpdateLayoutLimitedRefreshRate() {
+ SurfaceControl.RefreshRateRange layoutLimitedRefreshRate =
+ new SurfaceControl.RefreshRateRange(0, 120);
+ DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked();
+ mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(layoutLimitedRefreshRate);
+ DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked();
+ // Display info should only be updated when updateLocked is called
+ assertEquals(info2, info1);
- DisplayInfo result = mLogicalDisplay.getDisplayInfoLocked();
+ mLogicalDisplay.updateLocked(mDeviceRepo);
+ DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked();
+ assertNotEquals(info3, info2);
+ assertEquals(layoutLimitedRefreshRate, info3.layoutLimitedRefreshRate);
+ }
- assertEquals(refreshRateRange, result.layoutLimitedRefreshRate);
+ @Test
+ public void testUpdateRefreshRateThermalThrottling() {
+ SparseArray<SurfaceControl.RefreshRateRange> refreshRanges = new SparseArray<>();
+ refreshRanges.put(0, new SurfaceControl.RefreshRateRange(0, 120));
+ DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked();
+ mLogicalDisplay.updateThermalRefreshRateThrottling(refreshRanges);
+ DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked();
+ // Display info should only be updated when updateLocked is called
+ assertEquals(info2, info1);
+
+ mLogicalDisplay.updateLocked(mDeviceRepo);
+ DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked();
+ assertNotEquals(info3, info2);
+ assertTrue(refreshRanges.contentEquals(info3.thermalRefreshRateThrottling));
}
}
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 1d47b32..e492252 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
@@ -126,7 +126,8 @@
private static final String TAG = "DisplayModeDirectorTest";
private static final boolean DEBUG = false;
private static final float FLOAT_TOLERANCE = 0.01f;
- private static final int DISPLAY_ID = 0;
+ private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
+ private static final int MODE_ID = 1;
private static final float TRANSITION_POINT = 0.763f;
private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
@@ -2642,6 +2643,53 @@
assertNull(vote);
}
+ @Test
+ public void testUpdateLayoutLimitedRefreshRate_validDisplayInfo() {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
+ director.start(createMockSensorManager());
+
+ ArgumentCaptor<DisplayListener> displayListenerCaptor =
+ ArgumentCaptor.forClass(DisplayListener.class);
+ verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
+ any(Handler.class));
+ DisplayListener displayListener = displayListenerCaptor.getValue();
+
+ float refreshRate = 60;
+ mInjector.mDisplayInfo.layoutLimitedRefreshRate =
+ new RefreshRateRange(refreshRate, refreshRate);
+ displayListener.onDisplayChanged(DISPLAY_ID);
+
+ Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE);
+ assertVoteForPhysicalRefreshRate(vote, /* refreshRate= */ refreshRate);
+
+ mInjector.mDisplayInfo.layoutLimitedRefreshRate = null;
+ displayListener.onDisplayChanged(DISPLAY_ID);
+
+ vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE);
+ assertNull(vote);
+ }
+
+ @Test
+ public void testUpdateLayoutLimitedRefreshRate_invalidDisplayInfo() {
+ DisplayModeDirector director =
+ createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
+ director.start(createMockSensorManager());
+
+ ArgumentCaptor<DisplayListener> displayListenerCaptor =
+ ArgumentCaptor.forClass(DisplayListener.class);
+ verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
+ any(Handler.class));
+ DisplayListener displayListener = displayListenerCaptor.getValue();
+
+ mInjector.mDisplayInfo.layoutLimitedRefreshRate = new RefreshRateRange(10, 10);
+ mInjector.mDisplayInfoValid = false;
+ displayListener.onDisplayChanged(DISPLAY_ID);
+
+ Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE);
+ assertNull(vote);
+ }
+
private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
}
@@ -2848,12 +2896,20 @@
public static class FakesInjector implements DisplayModeDirector.Injector {
private final FakeDeviceConfig mDeviceConfig;
+ private final DisplayInfo mDisplayInfo;
+ private final Display mDisplay;
+ private boolean mDisplayInfoValid = true;
private ContentObserver mBrightnessObserver;
private ContentObserver mSmoothDisplaySettingObserver;
private ContentObserver mForcePeakRefreshRateSettingObserver;
FakesInjector() {
mDeviceConfig = new FakeDeviceConfig();
+ mDisplayInfo = new DisplayInfo();
+ mDisplayInfo.defaultModeId = MODE_ID;
+ mDisplayInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID,
+ 800, 600, /* refreshRate= */ 60)};
+ mDisplay = createDisplay(DISPLAY_ID);
}
@NonNull
@@ -2874,16 +2930,25 @@
}
@Override
+ public void registerDisplayListener(DisplayListener listener, Handler handler) {}
+
+ @Override
public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {}
@Override
+ public Display getDisplay(int displayId) {
+ return mDisplay;
+ }
+
+ @Override
public Display[] getDisplays() {
- return new Display[] { createDisplay(DISPLAY_ID) };
+ return new Display[] { mDisplay };
}
@Override
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
- return false;
+ displayInfo.copyFrom(mDisplayInfo);
+ return mDisplayInfoValid;
}
@Override
@@ -2907,7 +2972,7 @@
}
protected Display createDisplay(int id) {
- return new Display(DisplayManagerGlobal.getInstance(), id, new DisplayInfo(),
+ return new Display(DisplayManagerGlobal.getInstance(), id, mDisplayInfo,
ApplicationProvider.getApplicationContext().getResources());
}
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
index 487d752..9ab6ee5 100644
--- a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
@@ -255,7 +255,7 @@
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
SparseArray<SurfaceControl.RefreshRateRange> config = mOverriddenConfig.get(displayId);
if (config != null) {
- displayInfo.refreshRateThermalThrottling = config;
+ displayInfo.thermalRefreshRateThrottling = config;
return true;
}
return false;
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index 0f4d4e8..64c05dc 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -250,20 +250,24 @@
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
- dataStore.setKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID,
- MAX_BRIGHTNESS
- )
+ for (level in 1 until BRIGHTNESS_VALUE_FOR_LEVEL.size) {
+ dataStore.setKeyboardBacklightBrightness(
+ keyboardWithBacklight.descriptor,
+ LIGHT_ID,
+ BRIGHTNESS_VALUE_FOR_LEVEL[level] - 1
+ )
- keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- keyboardBacklightController.notifyUserActivity()
- testLooper.dispatchNext()
- assertEquals(
- "Keyboard backlight level should be restored to the level saved in the data store",
- Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchNext()
+ assertEquals(
+ "Keyboard backlight level should be restored to the level saved in the data " +
+ "store",
+ Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
+ lightColorMap[LIGHT_ID]
+ )
+ keyboardBacklightController.onInputDeviceRemoved(DEVICE_ID)
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index ea3f3bc..d0d28c3 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -633,6 +633,30 @@
0,
keyboardLayouts.size
)
+
+ // If IME doesn't have a corresponding language tag, then should show all available
+ // layouts no matter the script code.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, null
+ )
+ assertNotEquals(
+ "New UI: getKeyboardLayoutListForInputDevice API should return all layouts if" +
+ "language tag or subtype not provided",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Latin " +
+ "layouts if language tag or subtype not provided",
+ containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
+ "layouts if language tag or subtype not provided",
+ containsLayout(
+ keyboardLayouts,
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ )
}
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 8f0a5e6..bf6901e 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -21,6 +21,8 @@
import static android.view.KeyEvent.KEYCODE_C;
import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
import static android.view.KeyEvent.KEYCODE_E;
+import static android.view.KeyEvent.KEYCODE_ENTER;
+import static android.view.KeyEvent.KEYCODE_H;
import static android.view.KeyEvent.KEYCODE_K;
import static android.view.KeyEvent.KEYCODE_M;
import static android.view.KeyEvent.KEYCODE_META_LEFT;
@@ -164,4 +166,24 @@
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ALT_LEFT}, 0);
mPhoneWindowManager.assertToggleCapsLock();
}
+
+ /**
+ * META + H to go to homescreen
+ */
+ @Test
+ public void testMetaH() {
+ mPhoneWindowManager.overrideLaunchHome();
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_H}, 0);
+ mPhoneWindowManager.assertGoToHomescreen();
+ }
+
+ /**
+ * META + ENTER to go to homescreen
+ */
+ @Test
+ public void testMetaEnter() {
+ mPhoneWindowManager.overrideLaunchHome();
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ENTER}, 0);
+ mPhoneWindowManager.assertGoToHomescreen();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
index 6368f47..676bfb0 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -117,9 +117,9 @@
throw new RuntimeException(e);
}
- for (KeyEvent event: events) {
+ for (int i = count - 1; i >= 0; i--) {
final long eventTime = SystemClock.uptimeMillis();
- final int keyCode = event.getKeyCode();
+ final int keyCode = keyCodes[i];
final KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, keyCode,
0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
InputDevice.SOURCE_KEYBOARD);
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index a2ee8a4..2665e19 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -353,6 +353,10 @@
() -> LocalServices.getService(eq(StatusBarManagerInternal.class)));
}
+ void overrideLaunchHome() {
+ doNothing().when(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
+ }
+
/**
* Below functions will check the policy behavior could be invoked.
*/
@@ -480,4 +484,9 @@
transitionCaptor.getValue().onAppTransitionFinishedLocked(any());
verify(mPhoneWindowManager).lockNow(null);
}
+
+ void assertGoToHomescreen() {
+ waitForIdle();
+ verify(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
+ }
}