diff options
Diffstat (limited to 'services')
43 files changed, 863 insertions, 420 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 47aa8f5736bf..aae8879e9199 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -1942,14 +1942,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } public void notifyGesture(AccessibilityGestureEvent gestureEvent) { - if (android.view.accessibility.Flags.copyEventsForGestureDetection()) { - // We will use this event async, so copy it because it contains MotionEvents. - mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, - gestureEvent.copyForAsync()).sendToTarget(); - } else { - mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, - gestureEvent).sendToTarget(); - } + // We will use this event async, so copy it because it contains MotionEvents. + mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, + gestureEvent.copyForAsync()).sendToTarget(); } public void notifySystemActionsChangedLocked() { @@ -2426,9 +2421,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ case MSG_ON_GESTURE: { if (message.obj instanceof AccessibilityGestureEvent gesture) { notifyGestureInternal(gesture); - if (android.view.accessibility.Flags.copyEventsForGestureDetection()) { - gesture.recycle(); - } + gesture.recycle(); } } break; case MSG_CLEAR_ACCESSIBILITY_CACHE: { diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java index 3668eefe293d..62b6b85afa58 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java @@ -336,13 +336,8 @@ public abstract class GestureMatcher { // Recycle the old event first if necessary, to handle duplicate calls to post. recycleEvent(); mTargetState = state; - if (android.view.accessibility.Flags.copyEventsForGestureDetection()) { - mEvent = event.copy(); - mRawEvent = rawEvent.copy(); - } else { - mEvent = event; - mRawEvent = rawEvent; - } + mEvent = event.copy(); + mRawEvent = rawEvent.copy(); mPolicyFlags = policyFlags; mHandler.postDelayed(this, delay); if (DEBUG) { @@ -379,15 +374,13 @@ public abstract class GestureMatcher { } private void recycleEvent() { - if (android.view.accessibility.Flags.copyEventsForGestureDetection()) { - if (mEvent == null || mRawEvent == null) { - return; - } - mEvent.recycle(); - mRawEvent.recycle(); - mEvent = null; - mRawEvent = null; + if (mEvent == null || mRawEvent == null) { + return; } + mEvent.recycle(); + mRawEvent.recycle(); + mEvent = null; + mRawEvent = null; } } diff --git a/services/core/Android.bp b/services/core/Android.bp index decac40d20f8..cf85dd957b3f 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -258,7 +258,6 @@ java_library_static { "dreams_flags_lib", "aconfig_new_storage_flags_lib", "powerstats_flags_lib", - "locksettings_flags_lib", "MmdProperties", "mmd_flags_lib", "profiling_flags_lib", diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 5395d2a914ec..c15915ba39a4 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -790,7 +790,7 @@ public final class ActiveServices { "SHORT_FGS_TIMEOUT"); this.mServiceFGAnrTimer = new ServiceAnrTimer(service, ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, - "SERVICE_FOREGROUND_TIMEOUT"); + "SERVICE_FOREGROUND_TIMEOUT", new AnrTimer.Args().extend(true)); } void systemServicesReady() { @@ -7702,6 +7702,11 @@ public final class ActiveServices { super(Objects.requireNonNull(am).mHandler, msg, label); } + ServiceAnrTimer(ActivityManagerService am, int msg, String label, + @NonNull AnrTimer.Args args) { + super(Objects.requireNonNull(am).mHandler, msg, label, args); + } + @Override public int getPid(@NonNull ServiceRecord service) { return (service.app != null) ? service.app.getPid() : 0; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index a8bb5231d8c0..b1acfe830eed 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -4190,7 +4190,13 @@ public class AudioService extends IAudioService.Stub Log.d(TAG, "adjustStreamVolume postSetHearingAidVolumeIndex index=" + newIndex + " stream=" + streamType); } - mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType); + int haIndex; + final VolumeStreamState vss = getVssForStreamOrDefault(streamType); + synchronized (mVolumeStateLock) { + haIndex = (int) (vss.getMinIndex() + (newIndex - vss.getMinIndex()) + / vss.getIndexStepFactor()); + } + mDeviceBroker.postSetHearingAidVolumeIndex(haIndex, streamType); } } @@ -4460,18 +4466,12 @@ public class AudioService extends IAudioService.Stub private final AudioVolumeChangeHandler mAudioVolumeChangeHandler; /** @see AudioManager#registerVolumeGroupCallback(executor, callback) */ - @android.annotation.EnforcePermission( - android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void registerAudioVolumeCallback(IAudioVolumeChangeDispatcher callback) { - super.registerAudioVolumeCallback_enforcePermission(); mAudioVolumeChangeHandler.registerListener(callback); } /** @see AudioManager#unregisterVolumeGroupCallback(callback) */ - @android.annotation.EnforcePermission( - android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void unregisterAudioVolumeCallback(IAudioVolumeChangeDispatcher callback) { - super.unregisterAudioVolumeCallback_enforcePermission(); mAudioVolumeChangeHandler.unregisterListener(callback); } @@ -5149,7 +5149,13 @@ public class AudioService extends IAudioService.Stub mDeviceBroker.postSetLeAudioVolumeIndex(index * 10, getVssForStreamOrDefault(streamType).getMaxIndex(), streamType); } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) { - mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType); + int haIndex = index * 10; + final VolumeStreamState vss = getVssForStreamOrDefault(streamType); + synchronized (mVolumeStateLock) { + haIndex = (int) (vss.getMinIndex() + + (haIndex - vss.getMinIndex()) / vss.getIndexStepFactor()); + } + mDeviceBroker.postSetHearingAidVolumeIndex(haIndex, streamType); } else if (AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)) { mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index); } else { @@ -5280,7 +5286,13 @@ public class AudioService extends IAudioService.Stub && streamType == getBluetoothContextualVolumeStream()) { Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index + " stream=" + streamType); - mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType); + int haIndex; + final VolumeStreamState vss = getVssForStreamOrDefault(streamType); + synchronized (mVolumeStateLock) { + haIndex = (int) (vss.getMinIndex() + + (index - vss.getMinIndex()) / vss.getIndexStepFactor()); + } + mDeviceBroker.postSetHearingAidVolumeIndex(haIndex, streamType); } synchronized (mHdmiClientLock) { diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java index 60b7fca99e7b..228e6f1c4ddb 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java @@ -130,6 +130,14 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private static final String OVERLAY_DISPLAY_FLAG_FIXED_CONTENT_MODE = "fixed_content_mode"; + /** + * When this flag is set, disables support for moving and resizing the overlay window. + * As the window is made non-touchable, this also makes it possible to directly interact with + * the content underneath. + */ + private static final String OVERLAY_DISPLAY_FLAG_DISABLE_WINDOW_INTERACTION = + "disable_window_interaction"; + // Gravity flags to decide where the overlay should be shown. private static final String GRAVITY_TOP_LEFT = "gravity_top_left"; private static final String GRAVITY_BOTTOM_RIGHT = "gravity_bottom_right"; @@ -571,9 +579,9 @@ final class OverlayDisplayAdapter extends DisplayAdapter { @Override public void run() { OverlayMode mode = mModes.get(mActiveMode); - OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), - mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, - mFlags.mSecure, OverlayDisplayHandle.this); + OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(), mName, + mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, mFlags.mSecure, + mFlags.mDisableWindowInteraction, OverlayDisplayHandle.this); window.show(); synchronized (getSyncRoot()) { @@ -655,6 +663,9 @@ final class OverlayDisplayAdapter extends DisplayAdapter { /** See {@link #OVERLAY_DISPLAY_FLAG_FIXED_CONTENT_MODE}. */ final boolean mFixedContentMode; + /** See {@link #OVERLAY_DISPLAY_FLAG_DISABLE_WINDOW_INTERACTION}. */ + final boolean mDisableWindowInteraction; + final int mGravity; OverlayFlags( @@ -662,11 +673,13 @@ final class OverlayDisplayAdapter extends DisplayAdapter { boolean ownContentOnly, boolean shouldShowSystemDecorations, boolean fixedContentMode, + boolean disableWindowInteraction, int gravity) { mSecure = secure; mOwnContentOnly = ownContentOnly; mShouldShowSystemDecorations = shouldShowSystemDecorations; mFixedContentMode = fixedContentMode; + mDisableWindowInteraction = disableWindowInteraction; mGravity = gravity; } @@ -677,6 +690,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { false /* ownContentOnly */, false /* shouldShowSystemDecorations */, false /* fixedContentMode */, + false /* disableWindowInteraction */, Gravity.NO_GRAVITY); } @@ -684,6 +698,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { boolean ownContentOnly = false; boolean shouldShowSystemDecorations = false; boolean fixedContentMode = false; + boolean disableWindowInteraction = false; int gravity = Gravity.NO_GRAVITY; for (String flag: flagString.split(FLAG_SPLITTER)) { if (OVERLAY_DISPLAY_FLAG_SECURE.equals(flag)) { @@ -694,12 +709,14 @@ final class OverlayDisplayAdapter extends DisplayAdapter { shouldShowSystemDecorations = true; } else if (OVERLAY_DISPLAY_FLAG_FIXED_CONTENT_MODE.equals(flag)) { fixedContentMode = true; + } else if (OVERLAY_DISPLAY_FLAG_DISABLE_WINDOW_INTERACTION.equals(flag)) { + disableWindowInteraction = true; } else { gravity = parseOverlayGravity(flag); } } return new OverlayFlags(secure, ownContentOnly, shouldShowSystemDecorations, - fixedContentMode, gravity); + fixedContentMode, disableWindowInteraction, gravity); } @Override @@ -709,6 +726,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { .append(", ownContentOnly=").append(mOwnContentOnly) .append(", shouldShowSystemDecorations=").append(mShouldShowSystemDecorations) .append(", fixedContentMode=").append(mFixedContentMode) + .append(", disableWindowInteraction=").append(mDisableWindowInteraction) .append(", gravity").append(Gravity.toString(mGravity)) .append("}") .toString(); diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java index 3fd58e8641c3..523bbfa7d69a 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java +++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java @@ -69,6 +69,7 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { private int mDensityDpi; private final int mGravity; private final boolean mSecure; + private final boolean mDisableWindowInteraction; private final Listener mListener; private String mTitle; @@ -96,15 +97,15 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { private float mLiveTranslationY; private float mLiveScale = 1.0f; - public OverlayDisplayWindow(Context context, String name, - int width, int height, int densityDpi, int gravity, boolean secure, - Listener listener) { + OverlayDisplayWindow(Context context, String name, int width, int height, int densityDpi, + int gravity, boolean secure, boolean disableWindowInteraction, Listener listener) { // Workaround device freeze (b/38372997) ThreadedRenderer.disableVsync(); mContext = context; mName = name; mGravity = gravity; mSecure = secure; + mDisableWindowInteraction = disableWindowInteraction; mListener = listener; mDisplayManager = (DisplayManager)context.getSystemService( @@ -226,8 +227,10 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { if (mSecure) { mWindowParams.flags |= WindowManager.LayoutParams.FLAG_SECURE; } - if (DISABLE_MOVE_AND_RESIZE) { + if (DISABLE_MOVE_AND_RESIZE || mDisableWindowInteraction) { mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + mWindowParams.privateFlags |= + WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; } mWindowParams.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED; diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 29e04e744759..6af55300d0b3 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -25,6 +25,7 @@ import static android.view.KeyEvent.KEYCODE_UNKNOWN; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static com.android.hardware.input.Flags.enableCustomizableInputGestures; +import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; import static com.android.hardware.input.Flags.keyEventActivityDetection; import static com.android.hardware.input.Flags.touchpadVisualizer; import static com.android.hardware.input.Flags.useKeyGestureEventHandler; @@ -750,7 +751,8 @@ public class InputManagerService extends IInputManager.Stub * @return True if the lookup was successful, false otherwise. */ @Override // Binder call - public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) { + public boolean hasKeys(int deviceId, int sourceMask, @NonNull int[] keyCodes, + @NonNull boolean[] keyExists) { Objects.requireNonNull(keyCodes, "keyCodes must not be null"); Objects.requireNonNull(keyExists, "keyExists must not be null"); if (keyExists.length < keyCodes.length) { @@ -791,7 +793,7 @@ public class InputManagerService extends IInputManager.Stub * @deprecated Use {@link #transferTouchGesture(IBinder, IBinder)} */ @Deprecated - public boolean transferTouch(IBinder destChannelToken, int displayId) { + public boolean transferTouch(@NonNull IBinder destChannelToken, int displayId) { // TODO(b/162194035): Replace this with a SPY window Objects.requireNonNull(destChannelToken, "destChannelToken must not be null"); return mNative.transferTouch(destChannelToken, displayId); @@ -803,7 +805,7 @@ public class InputManagerService extends IInputManager.Stub * @param displayId Target display id. * @return The input channel. */ - public InputChannel monitorInput(String inputChannelName, int displayId) { + public InputChannel monitorInput(@NonNull String inputChannelName, int displayId) { Objects.requireNonNull(inputChannelName, "inputChannelName not be null"); if (displayId < Display.DEFAULT_DISPLAY) { @@ -835,7 +837,7 @@ public class InputManagerService extends IInputManager.Stub return outInputChannel; } - private void removeSpyWindowGestureMonitor(IBinder inputChannelToken) { + private void removeSpyWindowGestureMonitor(@NonNull IBinder inputChannelToken) { final GestureMonitorSpyWindow monitor; synchronized (mInputMonitors) { monitor = mInputMonitors.remove(inputChannelToken); @@ -854,8 +856,8 @@ public class InputManagerService extends IInputManager.Stub * @return The input channel. */ @Override // Binder call - public InputMonitor monitorGestureInput(IBinder monitorToken, @NonNull String requestedName, - int displayId) { + public InputMonitor monitorGestureInput(@NonNull IBinder monitorToken, + @NonNull String requestedName, int displayId) { if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT, "monitorGestureInput()")) { throw new SecurityException("Requires MONITOR_INPUT permission"); @@ -902,7 +904,7 @@ public class InputManagerService extends IInputManager.Stub * Removes an input channel. * @param connectionToken The input channel to unregister. */ - public void removeInputChannel(IBinder connectionToken) { + public void removeInputChannel(@NonNull IBinder connectionToken) { Objects.requireNonNull(connectionToken, "connectionToken must not be null"); mNative.removeInputChannel(connectionToken); } @@ -977,12 +979,12 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public boolean injectInputEvent(InputEvent event, int mode) { + public boolean injectInputEvent(@NonNull InputEvent event, int mode) { return injectInputEventToTarget(event, mode, Process.INVALID_UID); } @Override // Binder call - public boolean injectInputEventToTarget(InputEvent event, int mode, int targetUid) { + public boolean injectInputEventToTarget(@NonNull InputEvent event, int mode, int targetUid) { if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS, "injectInputEvent()", true /*checkInstrumentationSource*/)) { throw new SecurityException( @@ -1032,7 +1034,7 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public VerifiedInputEvent verifyInputEvent(InputEvent event) { + public VerifiedInputEvent verifyInputEvent(@NonNull InputEvent event) { Objects.requireNonNull(event, "event must not be null"); return mNative.verifyInputEvent(event); } @@ -1106,7 +1108,8 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) { + public void registerInputDevicesChangedListener( + @NonNull IInputDevicesChangedListener listener) { Objects.requireNonNull(listener, "listener must not be null"); synchronized (mInputDevicesLock) { @@ -1176,7 +1179,7 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call & native callback - public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor, + public TouchCalibration getTouchCalibrationForInputDevice(@NonNull String inputDeviceDescriptor, int surfaceRotation) { Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null"); @@ -1186,8 +1189,8 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation, - TouchCalibration calibration) { + public void setTouchCalibrationForInputDevice(@NonNull String inputDeviceDescriptor, + int surfaceRotation, @NonNull TouchCalibration calibration) { if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION, "setTouchCalibrationForInputDevice()")) { throw new SecurityException("Requires SET_INPUT_CALIBRATION permission"); @@ -1225,7 +1228,7 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public void registerTabletModeChangedListener(ITabletModeChangedListener listener) { + public void registerTabletModeChangedListener(@NonNull ITabletModeChangedListener listener) { if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, "registerTabletModeChangedListener()")) { throw new SecurityException("Requires TABLET_MODE_LISTENER permission"); @@ -1341,7 +1344,7 @@ public class InputManagerService extends IInputManager.Stub } @Override - public void requestPointerCapture(IBinder inputChannelToken, boolean enabled) { + public void requestPointerCapture(@NonNull IBinder inputChannelToken, boolean enabled) { Objects.requireNonNull(inputChannelToken, "inputChannelToken must not be null"); mNative.requestPointerCapture(inputChannelToken, enabled); @@ -1664,7 +1667,8 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) { + public boolean registerVibratorStateListener(int deviceId, + @NonNull IVibratorStateListener listener) { Objects.requireNonNull(listener, "listener must not be null"); RemoteCallbackList<IVibratorStateListener> listeners; @@ -1717,8 +1721,8 @@ public class InputManagerService extends IInputManager.Stub // Binder call @Override - public boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId, - IBinder inputToken) { + public boolean setPointerIcon(@NonNull PointerIcon icon, int displayId, int deviceId, + int pointerId, IBinder inputToken) { Objects.requireNonNull(icon); return mNative.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken); } @@ -1896,7 +1900,7 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public boolean registerSensorListener(IInputSensorEventListener listener) { + public boolean registerSensorListener(@NonNull IInputSensorEventListener listener) { if (DEBUG) { Slog.d(TAG, "registerSensorListener: listener=" + listener + " callingPid=" + Binder.getCallingPid()); @@ -1927,7 +1931,7 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - public void unregisterSensorListener(IInputSensorEventListener listener) { + public void unregisterSensorListener(@NonNull IInputSensorEventListener listener) { if (DEBUG) { Slog.d(TAG, "unregisterSensorListener: listener=" + listener + " callingPid=" + Binder.getCallingPid()); @@ -2016,7 +2020,8 @@ public class InputManagerService extends IInputManager.Stub /** * Set specified light state with for a specific input device. */ - private void setLightStateInternal(int deviceId, Light light, LightState lightState) { + private void setLightStateInternal(int deviceId, @NonNull Light light, + @NonNull LightState lightState) { Objects.requireNonNull(light, "light does not exist"); if (DEBUG) { Slog.d(TAG, "setLightStateInternal device " + deviceId + " light " + light @@ -2079,7 +2084,7 @@ public class InputManagerService extends IInputManager.Stub } @Override - public void openLightSession(int deviceId, String opPkg, IBinder token) { + public void openLightSession(int deviceId, String opPkg, @NonNull IBinder token) { Objects.requireNonNull(token); synchronized (mLightLock) { Preconditions.checkState(mLightSessions.get(token) == null, "already registered"); @@ -2098,7 +2103,7 @@ public class InputManagerService extends IInputManager.Stub } @Override - public void closeLightSession(int deviceId, IBinder token) { + public void closeLightSession(int deviceId, @NonNull IBinder token) { Objects.requireNonNull(token); synchronized (mLightLock) { LightSession lightSession = mLightSessions.get(token); @@ -2128,13 +2133,15 @@ public class InputManagerService extends IInputManager.Stub } @Override - public void registerBatteryListener(int deviceId, IInputDeviceBatteryListener listener) { + public void registerBatteryListener(int deviceId, + @NonNull IInputDeviceBatteryListener listener) { Objects.requireNonNull(listener); mBatteryController.registerBatteryListener(deviceId, listener, Binder.getCallingPid()); } @Override - public void unregisterBatteryListener(int deviceId, IInputDeviceBatteryListener listener) { + public void unregisterBatteryListener(int deviceId, + @NonNull IInputDeviceBatteryListener listener) { Objects.requireNonNull(listener); mBatteryController.unregisterBatteryListener(deviceId, listener, Binder.getCallingPid()); } @@ -2155,7 +2162,7 @@ public class InputManagerService extends IInputManager.Stub @EnforcePermission(Manifest.permission.MONITOR_INPUT) @Override - public void pilferPointers(IBinder inputChannelToken) { + public void pilferPointers(@NonNull IBinder inputChannelToken) { super.pilferPointers_enforcePermission(); Objects.requireNonNull(inputChannelToken); @@ -2164,7 +2171,7 @@ public class InputManagerService extends IInputManager.Stub @Override @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT) - public void registerKeyboardBacklightListener(IKeyboardBacklightListener listener) { + public void registerKeyboardBacklightListener(@NonNull IKeyboardBacklightListener listener) { super.registerKeyboardBacklightListener_enforcePermission(); Objects.requireNonNull(listener); mKeyboardBacklightController.registerKeyboardBacklightListener(listener, @@ -2173,7 +2180,7 @@ public class InputManagerService extends IInputManager.Stub @Override @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT) - public void unregisterKeyboardBacklightListener(IKeyboardBacklightListener listener) { + public void unregisterKeyboardBacklightListener(@NonNull IKeyboardBacklightListener listener) { super.unregisterKeyboardBacklightListener_enforcePermission(); Objects.requireNonNull(listener); mKeyboardBacklightController.unregisterKeyboardBacklightListener(listener, @@ -2653,6 +2660,8 @@ public class InputManagerService extends IInputManager.Stub @SuppressWarnings("unused") @VisibleForTesting long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { + final long keyNotConsumedGoFallback = -2; + final long keyConsumed = -1; final long keyNotConsumed = 0; long value = keyNotConsumed; // TODO(b/358569822) Remove below once we have nicer API for listening to shortcuts @@ -2667,6 +2676,16 @@ public class InputManagerService extends IInputManager.Stub value = mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags); } + if (fixSearchModifierFallbacks() && value == keyNotConsumed && event.isMetaPressed()) { + // If the key has not been consumed and includes the meta key, do not send the event + // to the app and attempt to generate a fallback. + final KeyCharacterMap kcm = event.getKeyCharacterMap(); + final KeyCharacterMap.FallbackAction fallbackAction = + kcm.getFallbackAction(event.getKeyCode(), event.getMetaState()); + if (fallbackAction != null) { + return keyNotConsumedGoFallback; + } + } return value; } @@ -3310,9 +3329,10 @@ public class InputManagerService extends IInputManager.Stub * @param token the window token that's about to receive this event * @param event the key event that's being dispatched * @param policyFlags the policy flags - * @return negative value if the key should be skipped (not sent to the app). 0 if the key - * should proceed getting dispatched to the app. positive value to indicate the additional - * time delay, in nanoseconds, to wait before sending this key to the app. + * @return -1 if the key should be skipped (not sent to the app). -2 if the key should not + * be sent to the app, but it should still generate a fallback. + * 0 if the key should proceed getting dispatched to the app. positive value to indicate the + * additional time delay, in nanoseconds, to wait before sending this key to the app. */ long interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags); @@ -3429,7 +3449,7 @@ public class InputManagerService extends IInputManager.Stub } @Override - public void sendInputEvent(InputEvent event, int policyFlags) { + public void sendInputEvent(@NonNull InputEvent event, int policyFlags) { if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS, "sendInputEvent()")) { throw new SecurityException( @@ -3451,9 +3471,9 @@ public class InputManagerService extends IInputManager.Stub * Interface for the system to handle request from InputMonitors. */ private final class InputMonitorHost extends IInputMonitorHost.Stub { - private final IBinder mInputChannelToken; + private final @NonNull IBinder mInputChannelToken; - InputMonitorHost(IBinder inputChannelToken) { + InputMonitorHost(@NonNull IBinder inputChannelToken) { mInputChannelToken = inputChannelToken; } diff --git a/services/core/java/com/android/server/locksettings/Android.bp b/services/core/java/com/android/server/locksettings/Android.bp deleted file mode 100644 index 53f1ac668e49..000000000000 --- a/services/core/java/com/android/server/locksettings/Android.bp +++ /dev/null @@ -1,11 +0,0 @@ -aconfig_declarations { - name: "locksettings_flags", - package: "com.android.server.locksettings", - container: "system", - srcs: ["*.aconfig"], -} - -java_aconfig_library { - name: "locksettings_flags_lib", - aconfig_declarations: "locksettings_flags", -} diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 820c0efcc1cf..4b704d01c3b9 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -428,15 +428,11 @@ class RebootEscrowManager { /** Wrapper function to set error code serialized through handler, */ private void setLoadEscrowDataErrorCode(@RebootEscrowErrorCode int value, Handler handler) { - if (Flags.waitForInternetRor()) { - mInjector.post( - handler, - () -> { - mLoadEscrowDataErrorCode = value; - }); - } else { - mLoadEscrowDataErrorCode = value; - } + mInjector.post( + handler, + () -> { + mLoadEscrowDataErrorCode = value; + }); } /** Wrapper function to compare and set error code serialized through handler. */ @@ -511,23 +507,17 @@ class RebootEscrowManager { mWakeLock.acquire(mInjector.getWakeLockTimeoutMillis()); } - if (Flags.waitForInternetRor()) { - // Timeout to stop retrying same as the wake lock timeout. - mInjector.postDelayed( - retryHandler, - () -> { - mRebootEscrowTimedOut = true; - }, - mInjector.getLoadEscrowTimeoutMillis()); - - mInjector.post( - retryHandler, - () -> loadRebootEscrowDataOnInternet(retryHandler, users, rebootEscrowUsers)); - return; - } + // Timeout to stop retrying same as the wake lock timeout. + mInjector.postDelayed( + retryHandler, + () -> { + mRebootEscrowTimedOut = true; + }, + mInjector.getLoadEscrowTimeoutMillis()); - mInjector.post(retryHandler, () -> loadRebootEscrowDataWithRetry( - retryHandler, 0, users, rebootEscrowUsers)); + mInjector.post( + retryHandler, + () -> loadRebootEscrowDataOnInternet(retryHandler, users, rebootEscrowUsers)); } void scheduleLoadRebootEscrowDataOrFail( @@ -548,27 +538,13 @@ class RebootEscrowManager { return; } - if (Flags.waitForInternetRor()) { - if (mRebootEscrowTimedOut) { - Slog.w(TAG, "Failed to load reboot escrow data within timeout"); - compareAndSetLoadEscrowDataErrorCode( - ERROR_NONE, ERROR_TIMEOUT_EXHAUSTED, retryHandler); - } else { - Slog.w( - TAG, - "Failed to load reboot escrow data after " + attemptNumber + " attempts"); - compareAndSetLoadEscrowDataErrorCode( - ERROR_NONE, ERROR_RETRY_COUNT_EXHAUSTED, retryHandler); - } - onGetRebootEscrowKeyFailed(users, attemptNumber, retryHandler); - return; - } - - Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); - if (mInjector.serverBasedResumeOnReboot() && !mInjector.isNetworkConnected()) { - mLoadEscrowDataErrorCode = ERROR_NO_NETWORK; + if (mRebootEscrowTimedOut) { + Slog.w(TAG, "Failed to load reboot escrow data within timeout"); + compareAndSetLoadEscrowDataErrorCode(ERROR_NONE, ERROR_TIMEOUT_EXHAUSTED, retryHandler); } else { - mLoadEscrowDataErrorCode = ERROR_RETRY_COUNT_EXHAUSTED; + Slog.w(TAG, "Failed to load reboot escrow data after " + attemptNumber + " attempts"); + compareAndSetLoadEscrowDataErrorCode( + ERROR_NONE, ERROR_RETRY_COUNT_EXHAUSTED, retryHandler); } onGetRebootEscrowKeyFailed(users, attemptNumber, retryHandler); } diff --git a/services/core/java/com/android/server/locksettings/flags.aconfig b/services/core/java/com/android/server/locksettings/flags.aconfig deleted file mode 100644 index 6818de91c98e..000000000000 --- a/services/core/java/com/android/server/locksettings/flags.aconfig +++ /dev/null @@ -1,9 +0,0 @@ -package: "com.android.server.locksettings" -container: "system" - -flag { - name: "wait_for_internet_ror" - namespace: "sudo" - description: "Feature flag to wait for internet connectivity before calling resume on reboot server." - bug: "231660348" -}
\ No newline at end of file diff --git a/services/core/java/com/android/server/media/projection/TEST_MAPPING b/services/core/java/com/android/server/media/projection/TEST_MAPPING index b33097c50002..7061044aaeee 100644 --- a/services/core/java/com/android/server/media/projection/TEST_MAPPING +++ b/services/core/java/com/android/server/media/projection/TEST_MAPPING @@ -2,6 +2,34 @@ "presubmit": [ { "name": "MediaProjectionTests" + }, + { + "name": "CtsMediaProjectionTestCases" + }, + { + "name": "CtsMediaProjectionSDK33TestCases" + }, + { + "name": "CtsMediaProjectionSDK34TestCases" + }, + { + "name": "CtsMediaAudioTestCases", + "options": [ + { + "include-filter": "android.media.audio.cts.RemoteSubmixTest" + }, + { + "include-filter": "android.media.audio.cts.AudioPlaybackCaptureTest" + } + ] + }, + { + "name": "CtsStatsdAtomHostTestCases", + "options": [ + { + "include-filter": "android.cts.statsdatom.media.projection.MediaProjectionAtomsTests" + } + ] } ] } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 8d787fe99e3a..651111e431c3 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -985,8 +985,8 @@ public final class OverlayManagerService extends SystemService { final String pkgName = request.overlay.getPackageName(); if (callingUid != Process.ROOT_UID && !ArrayUtils.contains( mPackageManager.getPackagesForUid(callingUid), pkgName)) { - throw new IllegalArgumentException("UID " + callingUid + " does own package" - + "name " + pkgName); + throw new IllegalArgumentException("UID " + callingUid + " does not own " + + "packageName " + pkgName); } } else { // Enforce actor requirements for enabling, disabling, and reordering overlays. diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index b441e9dd561d..7e5ada54c953 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -1994,6 +1994,9 @@ public class ComputerEngine implements Computer { if (Process.isSdkSandboxUid(uid)) { uid = getBaseSdkSandboxUid(); } + if(isKnownIsolatedComputeApp(uid)) { + uid = getIsolatedOwner(uid); + } final int appId = UserHandle.getAppId(uid); return getPackagesForUidInternalBody(callingUid, userId, appId, isCallerInstantApp); } diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index f88681dbcaeb..e98176b0e82b 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -18,6 +18,7 @@ package com.android.server.pm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SpecialUsers.CanBeNULL; import android.annotation.UserIdInt; import android.content.Context; import android.content.pm.LauncherUserInfo; @@ -620,11 +621,17 @@ public abstract class UserManagerInternal { * Returns the user id of the communal profile, or {@link android.os.UserHandle#USER_NULL} * if there is no such user. */ - public abstract @UserIdInt int getCommunalProfileId(); + public abstract @CanBeNULL @UserIdInt int getCommunalProfileId(); /** - * Checks whether to show a notification for sounds (e.g., alarms, timers, etc.) from - * background users. + * Returns the user id of the supervising profile, or {@link android.os.UserHandle#USER_NULL} if + * there is no such user. + */ + public abstract @CanBeNULL @UserIdInt int getSupervisingProfileId(); + + /** + * Checks whether to show a notification for sounds (e.g., alarms, timers, etc.) from background + * users. */ public static boolean shouldShowNotificationForBackgroundUserSounds() { return Flags.addUiForSoundsFromBackgroundUsers() && Resources.getSystem().getBoolean( diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 33a7e7476cf6..053b4aae90dd 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -1530,6 +1530,20 @@ public class UserManagerService extends IUserManager.Stub { return UserHandle.USER_NULL; } + /** Returns the currently-designated supervising profile, or USER_NULL if not present. */ + private @CanBeNULL @UserIdInt int getSupervisingProfileId() { + synchronized (mUsersLock) { + final int userSize = mUsers.size(); + for (int i = 0; i < userSize; i++) { + final UserInfo user = mUsers.valueAt(i).info; + if (user.isSupervisingProfile() && !mRemovingUserIds.get(user.id)) { + return user.id; + } + } + } + return UserHandle.USER_NULL; + } + public @NonNull List<UserInfo> getUsers(boolean excludeDying) { return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */ true); @@ -8348,10 +8362,14 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public @UserIdInt int getCommunalProfileId() { + public @CanBeNULL @UserIdInt int getCommunalProfileId() { return getCommunalProfileIdUnchecked(); } + @Override + public @CanBeNULL @UserIdInt int getSupervisingProfileId() { + return UserManagerService.this.getSupervisingProfileId(); + } } // class LocalService diff --git a/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java b/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java index e989d6875d15..4c14e96e6c98 100644 --- a/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java +++ b/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java @@ -36,6 +36,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.ArrayUtils; import com.android.internal.util.function.DodecFunction; import com.android.internal.util.function.HexConsumer; @@ -141,150 +142,191 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe class AccessCheckDelegateImpl implements AccessCheckDelegate { public static final String SHELL_PKG = "com.android.shell"; + + private final Object mLock = new Object(); + + @GuardedBy("mLock") private int mDelegateAndOwnerUid = INVALID_UID; @Nullable + @GuardedBy("mLock") private String mDelegatePackage; @Nullable + @GuardedBy("mLock") private String[] mDelegatePermissions; + @GuardedBy("mLock") boolean mDelegateAllPermissions; @Nullable + @GuardedBy("mLock") private SparseArray<ArrayMap<String, Integer>> mOverridePermissionStates; @Override public void setShellPermissionDelegate(int uid, @NonNull String packageName, @Nullable String[] permissions) { - mDelegateAndOwnerUid = uid; - mDelegatePackage = packageName; - mDelegatePermissions = permissions; - mDelegateAllPermissions = permissions == null; + synchronized (mLock) { + mDelegateAndOwnerUid = uid; + mDelegatePackage = packageName; + mDelegatePermissions = permissions; + mDelegateAllPermissions = permissions == null; + } PackageManager.invalidatePackageInfoCache(); } @Override public void removeShellPermissionDelegate() { - mDelegatePackage = null; - mDelegatePermissions = null; - mDelegateAllPermissions = false; + synchronized (mLock) { + mDelegatePackage = null; + mDelegatePermissions = null; + mDelegateAllPermissions = false; + } PackageManager.invalidatePackageInfoCache(); } @Override public void addOverridePermissionState(int ownerUid, int uid, @NonNull String permission, int state) { - if (mOverridePermissionStates == null) { - mDelegateAndOwnerUid = ownerUid; - mOverridePermissionStates = new SparseArray<>(); - } + synchronized (mLock) { + if (mOverridePermissionStates == null) { + mDelegateAndOwnerUid = ownerUid; + mOverridePermissionStates = new SparseArray<>(); + } - int uidIdx = mOverridePermissionStates.indexOfKey(uid); - ArrayMap<String, Integer> perUidOverrides; - if (uidIdx < 0) { - perUidOverrides = new ArrayMap<>(); - mOverridePermissionStates.put(uid, perUidOverrides); - } else { - perUidOverrides = mOverridePermissionStates.valueAt(uidIdx); - } + int uidIdx = mOverridePermissionStates.indexOfKey(uid); + ArrayMap<String, Integer> perUidOverrides; + if (uidIdx < 0) { + perUidOverrides = new ArrayMap<>(); + mOverridePermissionStates.put(uid, perUidOverrides); + } else { + perUidOverrides = mOverridePermissionStates.valueAt(uidIdx); + } - perUidOverrides.put(permission, state); + perUidOverrides.put(permission, state); + } PackageManager.invalidatePackageInfoCache(); } @Override public void removeOverridePermissionState(int uid, @NonNull String permission) { - if (mOverridePermissionStates == null) { - return; - } + synchronized (mLock) { + if (mOverridePermissionStates == null) { + return; + } - ArrayMap<String, Integer> perUidOverrides = mOverridePermissionStates.get(uid); + ArrayMap<String, Integer> perUidOverrides = mOverridePermissionStates.get(uid); - if (perUidOverrides == null) { - return; - } + if (perUidOverrides == null) { + return; + } - perUidOverrides.remove(permission); - PackageManager.invalidatePackageInfoCache(); + perUidOverrides.remove(permission); - if (perUidOverrides.isEmpty()) { - mOverridePermissionStates.remove(uid); - } - if (mOverridePermissionStates.size() == 0) { - mOverridePermissionStates = null; + if (perUidOverrides.isEmpty()) { + mOverridePermissionStates.remove(uid); + } + if (mOverridePermissionStates.size() == 0) { + mOverridePermissionStates = null; + } } + PackageManager.invalidatePackageInfoCache(); } @Override public void clearOverridePermissionStates(int uid) { - if (mOverridePermissionStates == null) { - return; - } + synchronized (mLock) { + if (mOverridePermissionStates == null) { + return; + } - mOverridePermissionStates.remove(uid); - PackageManager.invalidatePackageInfoCache(); + mOverridePermissionStates.remove(uid); - if (mOverridePermissionStates.size() == 0) { - mOverridePermissionStates = null; + if (mOverridePermissionStates.size() == 0) { + mOverridePermissionStates = null; + } } + PackageManager.invalidatePackageInfoCache(); } @Override public void clearAllOverridePermissionStates() { - mOverridePermissionStates = null; + synchronized (mLock) { + mOverridePermissionStates = null; + } PackageManager.invalidatePackageInfoCache(); } @Override public List<String> getDelegatedPermissionNames() { - return mDelegatePermissions == null ? null : List.of(mDelegatePermissions); + synchronized (mLock) { + return mDelegatePermissions == null ? null : List.of(mDelegatePermissions); + } } @Override public boolean hasShellPermissionDelegate() { - return mDelegateAllPermissions || mDelegatePermissions != null; + synchronized (mLock) { + return mDelegateAllPermissions || mDelegatePermissions != null; + } } @Override public boolean isDelegatePackage(int uid, @NonNull String packageName) { - return mDelegateAndOwnerUid == uid && TextUtils.equals(mDelegatePackage, packageName); + synchronized (mLock) { + return mDelegateAndOwnerUid == uid + && TextUtils.equals(mDelegatePackage, packageName); + } } @Override public boolean hasOverriddenPermissions() { - return mOverridePermissionStates != null; + synchronized (mLock) { + return mOverridePermissionStates != null; + } } @Override public boolean isDelegateAndOwnerUid(int uid) { - return uid == mDelegateAndOwnerUid; + synchronized (mLock) { + return uid == mDelegateAndOwnerUid; + } } @Override public boolean hasDelegateOrOverrides() { - return hasShellPermissionDelegate() || hasOverriddenPermissions(); + synchronized (mLock) { + return hasShellPermissionDelegate() || hasOverriddenPermissions(); + } } @Override public int checkPermission(@NonNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @UserIdInt int userId, @NonNull QuadFunction<String, String, String, Integer, Integer> superImpl) { - if (TextUtils.equals(mDelegatePackage, packageName) && !SHELL_PKG.equals(packageName)) { - if (isDelegatePermission(permissionName)) { - final long identity = Binder.clearCallingIdentity(); - try { - return checkPermission(SHELL_PKG, permissionName, persistentDeviceId, - userId, superImpl); - } finally { - Binder.restoreCallingIdentity(identity); + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = !SHELL_PKG.equals(packageName) + && TextUtils.equals(mDelegatePackage, packageName) + && isDelegatePermission(permissionName); + + if (!useShellDelegate && mOverridePermissionStates != null) { + int uid = LocalServices.getService(PackageManagerInternal.class) + .getPackageUid(packageName, 0, userId); + if (uid >= 0) { + Map<String, Integer> permissionGrants = mOverridePermissionStates.get(uid); + if (permissionGrants != null + && permissionGrants.containsKey(permissionName)) { + return permissionGrants.get(permissionName); + } } } } - if (mOverridePermissionStates != null) { - int uid = LocalServices.getService(PackageManagerInternal.class) - .getPackageUid(packageName, 0, userId); - if (uid >= 0) { - Map<String, Integer> permissionGrants = mOverridePermissionStates.get(uid); - if (permissionGrants != null && permissionGrants.containsKey(permissionName)) { - return permissionGrants.get(permissionName); - } + + if (useShellDelegate) { + final long identity = Binder.clearCallingIdentity(); + try { + return checkPermission(SHELL_PKG, permissionName, persistentDeviceId, userId, + superImpl); + } finally { + Binder.restoreCallingIdentity(identity); } } return superImpl.apply(packageName, permissionName, persistentDeviceId, userId); @@ -294,21 +336,27 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe public int checkUidPermission(int uid, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull TriFunction<Integer, String, String, Integer> superImpl) { - if (uid == mDelegateAndOwnerUid && uid != Process.SHELL_UID) { - if (isDelegatePermission(permissionName)) { - final long identity = Binder.clearCallingIdentity(); - try { - return checkUidPermission(Process.SHELL_UID, permissionName, - persistentDeviceId, superImpl); - } finally { - Binder.restoreCallingIdentity(identity); + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = uid != Process.SHELL_UID && uid == mDelegateAndOwnerUid + && isDelegatePermission(permissionName); + + if (!useShellDelegate && mOverridePermissionStates != null) { + Map<String, Integer> permissionGrants = mOverridePermissionStates.get(uid); + if (permissionGrants != null && permissionGrants.containsKey(permissionName)) { + return permissionGrants.get(permissionName); } } } - if (mOverridePermissionStates != null) { - Map<String, Integer> permissionGrants = mOverridePermissionStates.get(uid); - if (permissionGrants != null && permissionGrants.containsKey(permissionName)) { - return permissionGrants.get(permissionName); + + if (useShellDelegate) { + final long identity = Binder.clearCallingIdentity(); + try { + return checkUidPermission(Process.SHELL_UID, permissionName, persistentDeviceId, + superImpl); + } finally { + Binder.restoreCallingIdentity(identity); } } return superImpl.apply(uid, permissionName, persistentDeviceId); @@ -319,7 +367,13 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @Nullable String attributionTag, int virtualDeviceId, boolean raw, @NonNull HexFunction<Integer, Integer, String, String, Integer, Boolean, Integer> superImpl) { - if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = uid == mDelegateAndOwnerUid && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); @@ -335,7 +389,13 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @Override public int checkAudioOperation(int code, int usage, int uid, @Nullable String packageName, @NonNull QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) { - if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = uid == mDelegateAndOwnerUid && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); @@ -354,7 +414,13 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @Nullable String message, boolean shouldCollectMessage, int notedCount, @NonNull NonaFunction<Integer, Integer, String, String, Integer, Boolean, String, Boolean, Integer, SyncNotedAppOp> superImpl) { - if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = uid == mDelegateAndOwnerUid && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); @@ -375,21 +441,29 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @Nullable String message, boolean shouldCollectMessage, boolean skiProxyOperation, @NonNull HexFunction<Integer, AttributionSource, Boolean, String, Boolean, Boolean, SyncNotedAppOp> superImpl) { - if (!isDelegateOp(code)) { - return superImpl.apply(code, attributionSource, shouldCollectAsyncNotedOp, - message, shouldCollectMessage, skiProxyOperation); + boolean isDelegateOp; + int delegateAndOwnerUid; + + synchronized (mLock) { + isDelegateOp = isDelegateOp(code); + delegateAndOwnerUid = mDelegateAndOwnerUid; + } + + if (!isDelegateOp) { + return superImpl.apply(code, attributionSource, shouldCollectAsyncNotedOp, message, + shouldCollectMessage, skiProxyOperation); } final int shellUid = UserHandle.getUid( UserHandle.getUserId(attributionSource.getUid()), Process.SHELL_UID); AttributionSource next = attributionSource.getNext(); - if (next != null && next.getUid() == mDelegateAndOwnerUid) { + if (next != null && next.getUid() == delegateAndOwnerUid) { next = new AttributionSource(shellUid, Process.INVALID_PID, SHELL_PKG, next.getAttributionTag(), next.getToken(), /*renouncedPermissions*/ null, next.getDeviceId(), next.getNext()); attributionSource = new AttributionSource(attributionSource, next); } - if (attributionSource.getUid() == mDelegateAndOwnerUid) { + if (attributionSource.getUid() == delegateAndOwnerUid) { attributionSource = new AttributionSource(shellUid, Process.INVALID_PID, SHELL_PKG, attributionSource.getAttributionTag(), attributionSource.getToken(), /*renouncedPermissions*/ null, @@ -397,9 +471,8 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe } final long identity = Binder.clearCallingIdentity(); try { - return superImpl.apply(code, attributionSource, - shouldCollectAsyncNotedOp, message, shouldCollectMessage, - skiProxyOperation); + return superImpl.apply(code, attributionSource, shouldCollectAsyncNotedOp, message, + shouldCollectMessage, skiProxyOperation); } finally { Binder.restoreCallingIdentity(identity); } @@ -413,7 +486,13 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @AttributionFlags int attributionFlags, int attributionChainId, @NonNull DodecFunction<IBinder, Integer, Integer, String, String, Integer, Boolean, Boolean, String, Boolean, Integer, Integer, SyncNotedAppOp> superImpl) { - if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = uid == mDelegateAndOwnerUid && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); @@ -440,7 +519,14 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @NonNull UndecFunction<IBinder, Integer, AttributionSource, Boolean, Boolean, String, Boolean, Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl) { - if (attributionSource.getUid() == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = attributionSource.getUid() == mDelegateAndOwnerUid + && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId( attributionSource.getUid()), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); @@ -467,7 +553,14 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe @NonNull AttributionSource attributionSource, boolean skipProxyOperation, @NonNull QuadFunction<IBinder, Integer, AttributionSource, Boolean, Void> superImpl) { - if (attributionSource.getUid() == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = attributionSource.getUid() == mDelegateAndOwnerUid + && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId( attributionSource.getUid()), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); @@ -490,7 +583,13 @@ public interface AccessCheckDelegate extends CheckPermissionDelegate, CheckOpsDe public void finishOperation(IBinder clientId, int code, int uid, String packageName, String attributionTag, int virtualDeviceId, @NonNull HexConsumer<IBinder, Integer, Integer, String, String, Integer> superImpl) { - if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) { + boolean useShellDelegate; + + synchronized (mLock) { + useShellDelegate = uid == mDelegateAndOwnerUid && isDelegateOp(code); + } + + if (useShellDelegate) { final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 2744721c3a46..e9f522d08328 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -86,6 +86,7 @@ import static android.view.contentprotection.flags.Flags.createAccessibilityOver import static com.android.hardware.input.Flags.enableNew25q2Keycodes; import static com.android.hardware.input.Flags.enableTalkbackAndMagnifierKeyGestures; import static com.android.hardware.input.Flags.enableVoiceAccessKeyGestures; +import static com.android.hardware.input.Flags.fixSearchModifierFallbacks; import static com.android.hardware.input.Flags.inputManagerLifecycleSupport; import static com.android.hardware.input.Flags.keyboardA11yShortcutControl; import static com.android.hardware.input.Flags.modifierShortcutDump; @@ -4181,6 +4182,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } + if (fixSearchModifierFallbacks()) { + // Pass event as unhandled to give other services, e.g. InputManagerService, the + // opportunity to determine if the event can be modified, e.g. generating a fallback for + // meta/search events. + return false; + } + // Reserve all the META modifier combos for system behavior return (metaState & KeyEvent.META_META_ON) != 0; } diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java index 5ee9b7d09fdd..46c497d04f9e 100644 --- a/services/core/java/com/android/server/power/ThermalManagerService.java +++ b/services/core/java/com/android/server/power/ThermalManagerService.java @@ -176,7 +176,9 @@ public class ThermalManagerService extends SystemService { try { final HeadroomCallbackData data; synchronized (mTemperatureWatcher.mSamples) { - Slog.d(TAG, "Updating skin threshold: " + threshold); + if (DEBUG) { + Slog.d(TAG, "Updating skin threshold: " + threshold); + } mTemperatureWatcher.updateTemperatureThresholdLocked(threshold, true); data = mTemperatureWatcher.getHeadroomCallbackDataLocked(); } @@ -454,7 +456,9 @@ public class ThermalManagerService extends SystemService { && temperature.getType() == Temperature.TYPE_SKIN) { final HeadroomCallbackData data; synchronized (mTemperatureWatcher.mSamples) { - Slog.d(TAG, "Updating new temperature: " + temperature); + if (DEBUG) { + Slog.d(TAG, "Updating new temperature: " + temperature); + } mTemperatureWatcher.updateTemperatureSampleLocked(System.currentTimeMillis(), temperature); mTemperatureWatcher.mCachedHeadrooms.clear(); @@ -1878,6 +1882,7 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting long mInactivityThresholdMillis = INACTIVITY_THRESHOLD_MILLIS; + @GuardedBy("mSamples") private final Handler mHandler = BackgroundThread.getHandler(); /** @@ -1900,6 +1905,9 @@ public class ThermalManagerService extends SystemService { @GuardedBy("mSamples") private long mLastForecastCallTimeMillis = 0; + private final Runnable mGetAndUpdateTemperatureSamplesRunnable = + this::getAndUpdateTemperatureSamples; + void getAndUpdateThresholds() { List<TemperatureThreshold> thresholds = mHalWrapper.getTemperatureThresholds(true, Temperature.TYPE_SKIN); @@ -1930,7 +1938,9 @@ public class ThermalManagerService extends SystemService { return; } if (override) { - Slog.d(TAG, "Headroom cache cleared on threshold update " + threshold); + if (DEBUG) { + Slog.d(TAG, "Headroom cache cleared on threshold update " + threshold); + } mCachedHeadrooms.clear(); Arrays.fill(mHeadroomThresholds, Float.NaN); } @@ -1962,7 +1972,7 @@ public class ThermalManagerService extends SystemService { < mInactivityThresholdMillis) { // Trigger this again after a second as long as forecast has been called more // recently than the inactivity timeout - mHandler.postDelayed(this::getAndUpdateTemperatureSamples, 1000); + mHandler.postDelayed(mGetAndUpdateTemperatureSamplesRunnable, 1000); } else { // Otherwise, we've been idle for at least 10 seconds, so we should // shut down @@ -1974,6 +1984,9 @@ public class ThermalManagerService extends SystemService { long now = SystemClock.elapsedRealtime(); final List<Temperature> temperatures = mHalWrapper.getCurrentTemperatures(true, Temperature.TYPE_SKIN); + if (DEBUG) { + Slog.d(TAG, "Thermal HAL getCurrentTemperatures result: " + temperatures); + } for (Temperature temperature : temperatures) { updateTemperatureSampleLocked(now, temperature); } @@ -2080,10 +2093,16 @@ public class ThermalManagerService extends SystemService { } synchronized (mSamples) { mLastForecastCallTimeMillis = SystemClock.elapsedRealtime(); - if (mSamples.isEmpty()) { + if (!mHandler.hasCallbacks(mGetAndUpdateTemperatureSamplesRunnable)) { + if (DEBUG) { + Slog.d(TAG, "No temperature update callback, scheduling one"); + } getAndUpdateTemperatureSamples(); + } else { + if (DEBUG) { + Slog.d(TAG, "Temperature update callback already exists"); + } } - // If somehow things take much longer than expected or there are no temperatures // to sample, return early if (mSamples.isEmpty()) { @@ -2103,8 +2122,11 @@ public class ThermalManagerService extends SystemService { Binder.getCallingUid(), FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__SUCCESS, headroom, forecastSeconds); - Slog.d(TAG, "Headroom forecast in " + forecastSeconds + "s served from cache: " - + headroom); + if (DEBUG) { + Slog.d(TAG, + "Headroom forecast in " + forecastSeconds + "s served from cache: " + + headroom); + } return headroom; } @@ -2133,7 +2155,10 @@ public class ThermalManagerService extends SystemService { Binder.getCallingUid(), FrameworkStatsLog.THERMAL_HEADROOM_CALLED__API_STATUS__SUCCESS, headroom, 0); - Slog.d(TAG, "Headroom forecast in 0s served from cache: " + headroom); + if (DEBUG) { + Slog.d(TAG, + "Headroom forecast in 0s served from cache: " + headroom); + } return headroom; } // Don't try to forecast, just use the latest one we have @@ -2182,7 +2207,9 @@ public class ThermalManagerService extends SystemService { getForecast(DEFAULT_FORECAST_SECONDS), DEFAULT_FORECAST_SECONDS, Arrays.copyOf(mHeadroomThresholds, mHeadroomThresholds.length)); - Slog.d(TAG, "New headroom callback data: " + data); + if (DEBUG) { + Slog.d(TAG, "New headroom callback data: " + data); + } return data; } diff --git a/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionService.java b/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionService.java index 8c3b7c606f04..3ece07c84080 100644 --- a/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionService.java +++ b/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionService.java @@ -17,6 +17,7 @@ package com.android.server.security.advancedprotection; import static android.provider.Settings.Secure.ADVANCED_PROTECTION_MODE; +import static android.provider.Settings.Secure.AAPM_USB_DATA_PROTECTION; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import android.Manifest; @@ -69,6 +70,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** @hide */ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub { @@ -129,7 +131,10 @@ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub Slog.e(TAG, "Failed to initialize DisallowCellular2g", e); } } - if (android.security.Flags.aapmFeatureUsbDataProtection()) { + if (android.security.Flags.aapmFeatureUsbDataProtection() + // Usb data protection is enabled by default + && mStore.retrieveInt(AAPM_USB_DATA_PROTECTION, AdvancedProtectionStore.ON) + == AdvancedProtectionStore.ON) { try { mHooks.add(new UsbDataAdvancedProtectionHook(mContext, enabled)); } catch (Exception e) { @@ -183,7 +188,7 @@ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub // Without permission check private boolean isAdvancedProtectionEnabledInternal() { - return mStore.retrieve(); + return mStore.retrieveAdvancedProtectionModeEnabled(); } @Override @@ -217,7 +222,7 @@ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub try { synchronized (mCallbacks) { if (enabled != isAdvancedProtectionEnabledInternal()) { - mStore.store(enabled); + mStore.storeAdvancedProtectionModeEnabled(enabled); sendModeChanged(enabled); logAdvancedProtectionEnabled(enabled); } @@ -227,6 +232,34 @@ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub } } + public void setUsbDataProtectionEnabled(boolean enabled) { + int value = enabled ? AdvancedProtectionStore.ON + : AdvancedProtectionStore.OFF; + setAdvancedProtectionSubSettingInt(AAPM_USB_DATA_PROTECTION, value); + } + + private void setAdvancedProtectionSubSettingInt(String key, int value) { + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mCallbacks) { + mStore.storeInt(key, value); + Slog.i(TAG, "Advanced protection: subsetting" + key + " is " + value); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public boolean isUsbDataProtectionEnabled() { + final long identity = Binder.clearCallingIdentity(); + try { + return mStore.retrieveInt(AAPM_USB_DATA_PROTECTION, AdvancedProtectionStore.ON) + == AdvancedProtectionStore.ON; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override @EnforcePermission(Manifest.permission.MANAGE_ADVANCED_PROTECTION_MODE) public void logDialogShown(@FeatureId int featureId, @SupportDialogType int type, @@ -419,8 +452,8 @@ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub @VisibleForTesting static class AdvancedProtectionStore { private final Context mContext; - private static final int APM_ON = 1; - private static final int APM_OFF = 0; + static final int ON = 1; + static final int OFF = 0; private final UserManagerInternal mUserManager; AdvancedProtectionStore(@NonNull Context context) { @@ -428,15 +461,26 @@ public class AdvancedProtectionService extends IAdvancedProtectionService.Stub mUserManager = LocalServices.getService(UserManagerInternal.class); } - void store(boolean enabled) { + void storeAdvancedProtectionModeEnabled(boolean enabled) { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + ADVANCED_PROTECTION_MODE, enabled ? ON : OFF, + mUserManager.getMainUserId()); + } + + boolean retrieveAdvancedProtectionModeEnabled() { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + ADVANCED_PROTECTION_MODE, OFF, mUserManager.getMainUserId()) == ON; + } + + void storeInt(String key, int value) { Settings.Secure.putIntForUser(mContext.getContentResolver(), - ADVANCED_PROTECTION_MODE, enabled ? APM_ON : APM_OFF, + key, value, mUserManager.getMainUserId()); } - boolean retrieve() { + int retrieveInt(String key, int defaultValue) { return Settings.Secure.getIntForUser(mContext.getContentResolver(), - ADVANCED_PROTECTION_MODE, APM_OFF, mUserManager.getMainUserId()) == APM_ON; + key, defaultValue, mUserManager.getMainUserId()); } } diff --git a/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionShellCommand.java b/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionShellCommand.java index 42505ad2de3f..ae17a459010b 100644 --- a/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionShellCommand.java +++ b/services/core/java/com/android/server/security/advancedprotection/AdvancedProtectionShellCommand.java @@ -45,6 +45,10 @@ class AdvancedProtectionShellCommand extends ShellCommand { return setProtectionEnabled(); case "is-protection-enabled": return isProtectionEnabled(pw); + case "set-usb-data-protection-enabled": + return setUsbDataProtectedEnabled(); + case "is-usb-data-protection-enabled": + return isUsbDataProtectedEnabled(pw); } } catch (RemoteException e) { pw.println("Remote exception: " + e); @@ -64,6 +68,10 @@ class AdvancedProtectionShellCommand extends ShellCommand { pw.println(" Print this help text."); pw.println(" set-protection-enabled [true|false]"); pw.println(" is-protection-enabled"); + if(android.security.Flags.aapmFeatureUsbDataProtection()) { + pw.println(" set-usb-data-protection-enabled [true|false]"); + pw.println(" is-usb-data-protection-enabled"); + } } @SuppressLint("AndroidFrameworkRequiresPermission") @@ -79,4 +87,22 @@ class AdvancedProtectionShellCommand extends ShellCommand { pw.println(protectionMode); return 0; } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private int setUsbDataProtectedEnabled() throws RemoteException { + if(android.security.Flags.aapmFeatureUsbDataProtection()) { + String protectionMode = getNextArgRequired(); + mService.setUsbDataProtectionEnabled(Boolean.parseBoolean(protectionMode)); + } + return 0; + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private int isUsbDataProtectedEnabled(@NonNull PrintWriter pw) throws RemoteException { + if(android.security.Flags.aapmFeatureUsbDataProtection()) { + boolean protectionMode = mService.isUsbDataProtectionEnabled(); + pw.println(protectionMode); + } + return 0; + } } diff --git a/services/core/java/com/android/server/wm/AppCompatCameraOverrides.java b/services/core/java/com/android/server/wm/AppCompatCameraOverrides.java index cb82f480d73b..d152a1dbe17d 100644 --- a/services/core/java/com/android/server/wm/AppCompatCameraOverrides.java +++ b/services/core/java/com/android/server/wm/AppCompatCameraOverrides.java @@ -35,6 +35,7 @@ import static com.android.server.wm.AppCompatUtils.isChangeEnabled; import android.annotation.NonNull; import android.annotation.Nullable; +import android.window.DesktopModeFlags; import com.android.server.wm.utils.OptPropFactory; import com.android.window.flags.Flags; @@ -177,7 +178,7 @@ class AppCompatCameraOverrides { * </ul> */ boolean shouldApplyFreeformTreatmentForCameraCompat() { - return Flags.enableCameraCompatForDesktopWindowing() + return DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue() && (shouldEnableCameraCompatFreeformTreatmentForApp() || shouldEnableCameraCompatFreeformTreatmentForAllApps()); } diff --git a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java index 276c7d2cbaa0..e7a0803df916 100644 --- a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +++ b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java @@ -26,9 +26,9 @@ import android.app.CameraCompatTaskInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.widget.Toast; +import android.window.DesktopModeFlags; import com.android.internal.annotations.VisibleForTesting; -import com.android.window.flags.Flags; /** * Encapsulate policy logic related to app compat display rotation. @@ -53,7 +53,7 @@ class AppCompatCameraPolicy { final boolean needsDisplayRotationCompatPolicy = wmService.mAppCompatConfiguration.isCameraCompatTreatmentEnabledAtBuildTime(); final boolean needsCameraCompatFreeformPolicy = - Flags.enableCameraCompatForDesktopWindowing() + DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue() && DesktopModeHelper.canEnterDesktopMode(wmService.mContext); if (needsDisplayRotationCompatPolicy || needsCameraCompatFreeformPolicy) { mCameraStateMonitor = new CameraStateMonitor(displayContent, wmService.mH); diff --git a/services/core/java/com/android/server/wm/DeviceStateAutoRotateSettingIssueLogger.java b/services/core/java/com/android/server/wm/DeviceStateAutoRotateSettingIssueLogger.java index 937039d838e5..a7d03485058f 100644 --- a/services/core/java/com/android/server/wm/DeviceStateAutoRotateSettingIssueLogger.java +++ b/services/core/java/com/android/server/wm/DeviceStateAutoRotateSettingIssueLogger.java @@ -29,13 +29,13 @@ import java.util.function.LongSupplier; /** * Logs potential race conditions that lead to incorrect auto-rotate setting. * - * Before go/auto-rotate-refactor, there is a race condition that happen during device state + * <p>Before go/auto-rotate-refactor, there is a race condition that happen during device state * changes, as a result, incorrect auto-rotate setting are written for a device state in * DEVICE_STATE_ROTATION_LOCK. Realistically, users shouldn’t be able to change * DEVICE_STATE_ROTATION_LOCK while the device folds/unfolds. * - * This class monitors the time between a device state change and a subsequent change to the device - * state based auto-rotate setting. If the duration is less than a threshold + * <p>This class monitors the time between a device state change and a subsequent change to the + * device state based auto-rotate setting. If the duration is less than a threshold * (DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_THRESHOLD), a potential issue is logged. The logging of * the atom is not expected to occur often, realistically estimated once a month on few devices. * But the number could be bigger, as that's what this metric is set to reveal. @@ -72,23 +72,33 @@ public class DeviceStateAutoRotateSettingIssueLogger { } private void onStateChange() { - // Only move forward if both of the events have occurred already - if (mLastDeviceStateChangeTime != TIME_NOT_SET - && mLastDeviceStateAutoRotateSettingChangeTime != TIME_NOT_SET) { - final long duration = - mLastDeviceStateAutoRotateSettingChangeTime - mLastDeviceStateChangeTime; - boolean isDeviceStateChangeFirst = duration > 0; + // Only move forward if both of the events have occurred already. + if (mLastDeviceStateChangeTime == TIME_NOT_SET + || mLastDeviceStateAutoRotateSettingChangeTime == TIME_NOT_SET) { + return; + } + final long duration = + mLastDeviceStateAutoRotateSettingChangeTime - mLastDeviceStateChangeTime; + boolean isDeviceStateChangeFirst = duration > 0; - if (abs(duration) - < DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_THRESHOLD_MILLIS) { - FrameworkStatsLog.write( - FrameworkStatsLog.DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_REPORTED, - (int) abs(duration), - isDeviceStateChangeFirst); - } + if (abs(duration) + < DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_THRESHOLD_MILLIS) { + FrameworkStatsLog.write( + FrameworkStatsLog.DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_REPORTED, + (int) abs(duration), + isDeviceStateChangeFirst); + // This pair is logged, reset both timestamps. mLastDeviceStateAutoRotateSettingChangeTime = TIME_NOT_SET; mLastDeviceStateChangeTime = TIME_NOT_SET; + } else { + // This pair was not logged, reset the earlier timestamp. + if (isDeviceStateChangeFirst) { + mLastDeviceStateChangeTime = TIME_NOT_SET; + } else { + mLastDeviceStateAutoRotateSettingChangeTime = TIME_NOT_SET; + } } + } } diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 51c3da098020..02b53b0106b8 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -512,9 +512,14 @@ class TransitionController { return false; } + /** Returns {@code true} if the display contains a collecting transition. */ + boolean isCollectingTransitionOnDisplay(@NonNull DisplayContent dc) { + return mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc); + } + /** Returns {@code true} if the display contains a running or pending transition. */ boolean isTransitionOnDisplay(@NonNull DisplayContent dc) { - if (mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc)) { + if (isCollectingTransitionOnDisplay(dc)) { return true; } for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a9bb690d4e53..3ccbc868377e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1845,9 +1845,12 @@ public class WindowManagerService extends IWindowManager.Stub // Only a presentation window needs a transition because its visibility affets the // lifecycle of apps below (b/390481865). if (enablePresentationForConnectedDisplays() && win.isPresentation()) { - Transition transition = null; + final boolean wasTransitionOnDisplay = + win.mTransitionController.isCollectingTransitionOnDisplay(displayContent); + Transition newlyCreatedTransition = null; if (!win.mTransitionController.isCollecting()) { - transition = win.mTransitionController.createAndStartCollecting(TRANSIT_OPEN); + newlyCreatedTransition = + win.mTransitionController.createAndStartCollecting(TRANSIT_OPEN); } win.mTransitionController.collect(win.mToken); res |= addWindowInner(win, displayPolicy, activity, displayContent, outInsetsState, @@ -1856,9 +1859,14 @@ public class WindowManagerService extends IWindowManager.Stub // A presentation hides all activities behind on the same display. win.mDisplayContent.ensureActivitiesVisible(/*starting=*/ null, /*notifyClients=*/ true); - win.mTransitionController.getCollectingTransition().setReady(win.mToken, true); - if (transition != null) { - win.mTransitionController.requestStartTransition(transition, null, + if (!wasTransitionOnDisplay && win.mTransitionController + .isCollectingTransitionOnDisplay(displayContent)) { + // Set the display ready only when the display gets added to the collecting + // transition in this operation. + win.mTransitionController.setReady(win.mToken); + } + if (newlyCreatedTransition != null) { + win.mTransitionController.requestStartTransition(newlyCreatedTransition, null, null /* remoteTransition */, null /* displayChange */); } } else { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 22ddd5f39b24..d43aba0d218d 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2365,9 +2365,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Only a presentation window needs a transition because its visibility affets the // lifecycle of apps below (b/390481865). if (enablePresentationForConnectedDisplays() && isPresentation()) { - Transition transition = null; + final boolean wasTransitionOnDisplay = + mTransitionController.isCollectingTransitionOnDisplay(displayContent); + Transition newlyCreatedTransition = null; if (!mTransitionController.isCollecting()) { - transition = mTransitionController.createAndStartCollecting(TRANSIT_CLOSE); + newlyCreatedTransition = + mTransitionController.createAndStartCollecting(TRANSIT_CLOSE); } mTransitionController.collect(mToken); mAnimatingExit = true; @@ -2376,9 +2379,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // A presentation hides all activities behind on the same display. mDisplayContent.ensureActivitiesVisible(/*starting=*/ null, /*notifyClients=*/ true); - mTransitionController.getCollectingTransition().setReady(mToken, true); - if (transition != null) { - mTransitionController.requestStartTransition(transition, null, + if (!wasTransitionOnDisplay && mTransitionController + .isCollectingTransitionOnDisplay(displayContent)) { + // Set the display ready only when the display gets added to the collecting + // transition in this operation. + mTransitionController.setReady(mToken); + } + if (newlyCreatedTransition != null) { + mTransitionController.requestStartTransition(newlyCreatedTransition, null, null /* remoteTransition */, null /* displayChange */); } } else { diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index ec8794f8073f..017284cded8e 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -1978,6 +1978,11 @@ NativeInputManager::interceptKeyBeforeDispatching(const sp<IBinder>& token, return inputdispatcher::KeyEntry::InterceptKeyResult::SKIP; } + // -2 : Skip sending even to application and go directly to post processing e.g. fallbacks. + if (delayMillis == -2) { + return inputdispatcher::KeyEntry::InterceptKeyResult::FALLBACK; + } + return milliseconds_to_nanoseconds(delayMillis); } diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java index bb6339c79502..0b5a95b0e888 100644 --- a/services/supervision/java/com/android/server/supervision/SupervisionService.java +++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java @@ -27,6 +27,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.UserIdInt; +import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.supervision.ISupervisionManager; @@ -147,9 +148,21 @@ public class SupervisionService extends ISupervisionManager.Stub { @Override @Nullable public Intent createConfirmSupervisionCredentialsIntent() { - // TODO(b/392961554): (1) Return null if supervision is not enabled. - // (2) check if PIN exists before return a valid intent. enforceAnyPermission(QUERY_USERS, MANAGE_USERS); + if (!isSupervisionEnabledForUser(mContext.getUserId())) { + return null; + } + // Verify the supervising user profile exists and has a secure credential set. + final int supervisingUserId = mInjector.getUserManagerInternal().getSupervisingProfileId(); + final long token = Binder.clearCallingIdentity(); + try { + if (supervisingUserId == UserHandle.USER_NULL + || !mInjector.getKeyguardManager().isDeviceSecure(supervisingUserId)) { + return null; + } + } finally { + Binder.restoreCallingIdentity(token); + } final Intent intent = new Intent(ACTION_CONFIRM_SUPERVISION_CREDENTIALS); // explicitly set the package for security intent.setPackage("com.android.settings"); @@ -277,6 +290,7 @@ public class SupervisionService extends ISupervisionManager.Stub { static class Injector { private final Context mContext; private DevicePolicyManagerInternal mDpmInternal; + private KeyguardManager mKeyguardManager; private PackageManager mPackageManager; private UserManagerInternal mUserManagerInternal; @@ -292,6 +306,13 @@ public class SupervisionService extends ISupervisionManager.Stub { return mDpmInternal; } + KeyguardManager getKeyguardManager() { + if (mKeyguardManager == null) { + mKeyguardManager = mContext.getSystemService(KeyguardManager.class); + } + return mKeyguardManager; + } + PackageManager getPackageManager() { if (mPackageManager == null) { mPackageManager = mContext.getPackageManager(); diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java index 554b5b4297f2..740424813c2a 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/UserDataPreparerTest.java @@ -98,9 +98,9 @@ public class UserDataPreparerTest { File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID); systemDeDir.mkdirs(); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_DE); - verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), + verify(mStorageManagerMock).prepareUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_DE)); - verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), + verify(mInstaller).createUserData(isNull(), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE)); int serialNumber = UserDataPreparer.getSerialNumber(userDeDir); assertEquals(TEST_USER_SERIAL, serialNumber); @@ -115,9 +115,9 @@ public class UserDataPreparerTest { File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID); systemCeDir.mkdirs(); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); - verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), + verify(mStorageManagerMock).prepareUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); - verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID), + verify(mInstaller).createUserData(isNull(), eq(TEST_USER_ID), eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE)); int serialNumber = UserDataPreparer.getSerialNumber(userCeDir); assertEquals(TEST_USER_SERIAL, serialNumber); @@ -129,10 +129,10 @@ public class UserDataPreparerTest { public void testPrepareUserData_forNewUser_destroysOnFailure() throws Exception { TEST_USER.lastLoggedInTime = 0; doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock) - .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), + .prepareUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); - verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID), + verify(mStorageManagerMock).destroyUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); } @@ -140,10 +140,10 @@ public class UserDataPreparerTest { public void testPrepareUserData_forExistingUser_doesNotDestroyOnFailure() throws Exception { TEST_USER.lastLoggedInTime = System.currentTimeMillis(); doThrow(new IllegalStateException("expected exception for test")).when(mStorageManagerMock) - .prepareUserStorage(isNull(String.class), eq(TEST_USER_ID), + .prepareUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); mUserDataPreparer.prepareUserData(TEST_USER, StorageManager.FLAG_STORAGE_CE); - verify(mStorageManagerMock, never()).destroyUserStorage(isNull(String.class), + verify(mStorageManagerMock, never()).destroyUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); } @@ -171,9 +171,9 @@ public class UserDataPreparerTest { mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_DE); - verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID), + verify(mInstaller).destroyUserData(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_DE)); - verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID), + verify(mStorageManagerMock).destroyUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_DE)); // systemDir (normal path: /data/system/users/$userId) should have been deleted. @@ -195,9 +195,9 @@ public class UserDataPreparerTest { mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_CE); - verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID), + verify(mInstaller).destroyUserData(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); - verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID), + verify(mStorageManagerMock).destroyUserStorage(isNull(), eq(TEST_USER_ID), eq(StorageManager.FLAG_STORAGE_CE)); // systemCeDir (normal path: /data/system_ce/$userId) should still exist but be empty, since @@ -225,7 +225,7 @@ public class UserDataPreparerTest { .reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL, Arrays.asList(u1, u2), Arrays.asList(dir1, dir2, dir3)); // Verify that user 3 data is removed - verify(mInstaller).destroyUserData(isNull(String.class), eq(3), + verify(mInstaller).destroyUserData(isNull(), eq(3), eq(StorageManager.FLAG_STORAGE_DE|StorageManager.FLAG_STORAGE_CE)); } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java index 3289d70b89ac..fe4baeb80ee7 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationStartInfoTest.java @@ -79,7 +79,8 @@ import java.util.ArrayList; public class ApplicationStartInfoTest { private static final String TAG = ApplicationStartInfoTest.class.getSimpleName(); - private static final ComponentName COMPONENT = new ComponentName("com.android.test", ".Foo"); + private static final ComponentName COMPONENT = + new ComponentName("com.android.test", "com.android.test.Foo"); private static final int APP_1_UID = 10123; private static final int APP_1_PID_1 = 12345; diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 067fba9893e5..64e6d323bdfd 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -93,7 +93,6 @@ android_test { "net_flags_lib", "CtsVirtualDeviceCommonLib", "com_android_server_accessibility_flags_lib", - "locksettings_flags_lib", ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), { "true": ["service-crashrecovery-pre-jarjar"], default: [], diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java index e0bc3e76f31d..457d8a96fea4 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -87,6 +87,9 @@ import android.content.res.XmlResourceParser; import android.graphics.drawable.Icon; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; +import android.hardware.input.IInputManager; +import android.hardware.input.InputManager; +import android.hardware.input.InputManagerGlobal; import android.hardware.input.KeyGestureEvent; import android.net.Uri; import android.os.Build; @@ -237,6 +240,9 @@ public class AccessibilityManagerServiceTest { @Mock private HearingDevicePhoneCallNotificationController mMockHearingDevicePhoneCallNotificationController; + @Mock + private IInputManager mMockInputManagerService; + private InputManagerGlobal.TestSession mInputManagerTestSession; @Spy private IUserInitializationCompleteCallback mUserInitializationCompleteCallback; @Captor private ArgumentCaptor<Intent> mIntentArgumentCaptor; private IAccessibilityManager mA11yManagerServiceOnDevice; @@ -270,6 +276,10 @@ public class AccessibilityManagerServiceTest { mInputFilter = mock(FakeInputFilter.class); mTestableContext.addMockSystemService(DevicePolicyManager.class, mDevicePolicyManager); + mInputManagerTestSession = InputManagerGlobal.createTestSession(mMockInputManagerService); + InputManager mockInputManager = new InputManager(mTestableContext); + mTestableContext.addMockSystemService(InputManager.class, mockInputManager); + when(mMockPackageManagerInternal.getSystemUiServiceComponent()).thenReturn( new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); when(mMockPackageManagerInternal.getPackageUid(eq("com.android.systemui"), anyLong(), @@ -334,6 +344,9 @@ public class AccessibilityManagerServiceTest { FieldSetter.setField( am, AccessibilityManager.class.getDeclaredField("mService"), mA11yManagerServiceOnDevice); + if (mInputManagerTestSession != null) { + mInputManagerTestSession.close(); + } } private void setupAccessibilityServiceConnection(int serviceInfoFlag) { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java index d94faec4cf01..49eb63b2c261 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java @@ -28,10 +28,6 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.graphics.PointF; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.view.Display; import android.view.MotionEvent; import android.view.ViewConfiguration; @@ -54,9 +50,6 @@ import java.util.List; */ public class TwoFingersDownOrSwipeTest { - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - private static final float DEFAULT_X = 100f; private static final float DEFAULT_Y = 100f; @@ -94,22 +87,6 @@ public class TwoFingersDownOrSwipeTest { } @Test - @RequiresFlagsDisabled(android.view.accessibility.Flags.FLAG_COPY_EVENTS_FOR_GESTURE_DETECTION) - public void sendTwoFingerDownEvent_onGestureCompleted_withoutCopiedEvents() { - final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY, - new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10)); - - for (MotionEvent event : downEvents) { - mGesturesObserver.onMotionEvent(event, event, 0); - } - - verify(mListener, timeout(sTimeoutMillis)).onGestureCompleted( - MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE, downEvents.get(1), - downEvents.get(1), 0); - } - - @Test - @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_COPY_EVENTS_FOR_GESTURE_DETECTION) public void sendTwoFingerDownEvent_onGestureCompleted() { final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY, new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10)); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index c50c62323212..a1f73170e549 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -816,14 +816,14 @@ public class DevicePolicyManagerTest extends DpmTestBase { MockUtils.checkIntentAction( DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED), MockUtils.checkUserHandle(CALLER_USER_HANDLE), - isNull(String.class), + isNull(), eq(AppOpsManager.OP_NONE), any(Bundle.class), any(BroadcastReceiver.class), eq(dpms.mHandler), eq(Activity.RESULT_OK), - isNull(String.class), - isNull(Bundle.class)); + isNull(), + isNull()); assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse(); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( @@ -873,14 +873,14 @@ public class DevicePolicyManagerTest extends DpmTestBase { MockUtils.checkIntentAction( DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED), MockUtils.checkUserHandle(CALLER_USER_HANDLE), - isNull(String.class), + isNull(), eq(AppOpsManager.OP_NONE), any(Bundle.class), any(BroadcastReceiver.class), eq(dpms.mHandler), eq(Activity.RESULT_OK), - isNull(String.class), - isNull(Bundle.class)); + isNull(), + isNull()); assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse(); verify(getServices().usageStatsManagerInternal).setActiveAdminApps( diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java index ae781dcb834a..52c7c48cc8b7 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -60,10 +60,6 @@ import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.UserManager; import android.platform.test.annotations.Presubmit; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -74,7 +70,6 @@ import com.android.server.locksettings.ResumeOnRebootServiceProvider.ResumeOnReb import com.android.server.pm.UserManagerInternal; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -113,9 +108,6 @@ public class RebootEscrowManagerTests { 0x26, 0x52, 0x72, 0x63, 0x63, 0x61, 0x78, 0x23, }; - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - private Context mContext; private UserManager mUserManager; private UserManagerInternal mUserManagerInternal; @@ -847,53 +839,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsDisabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) - public void loadRebootEscrowDataIfAvailable_ServerBasedIoError_RetryFailure() throws Exception { - setServerBasedRebootEscrowProvider(); - - when(mInjected.getBootCount()).thenReturn(0); - RebootEscrowListener mockListener = mock(RebootEscrowListener.class); - mService.setRebootEscrowListener(mockListener); - mService.prepareRebootEscrow(); - - clearInvocations(mServiceConnection); - callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID); - verify(mockListener).onPreparedForReboot(eq(true)); - verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong()); - - // Use x -> x for both wrap & unwrap functions. - when(mServiceConnection.wrapBlob(any(), anyLong(), anyLong())) - .thenAnswer(invocation -> invocation.getArgument(0)); - assertEquals(ARM_REBOOT_ERROR_NONE, mService.armRebootEscrowIfNeeded()); - verify(mServiceConnection).wrapBlob(any(), anyLong(), anyLong()); - assertTrue(mStorage.hasRebootEscrowServerBlob()); - - // pretend reboot happens here - when(mInjected.getBootCount()).thenReturn(1); - ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - ArgumentCaptor<Integer> metricsErrorCodeCaptor = ArgumentCaptor.forClass(Integer.class); - doNothing() - .when(mInjected) - .reportMetric( - metricsSuccessCaptor.capture(), - metricsErrorCodeCaptor.capture(), - eq(2) /* Server based */, - eq(2) /* attempt count */, - anyInt(), - eq(0) /* vbmeta status */, - anyInt()); - when(mServiceConnection.unwrap(any(), anyLong())).thenThrow(IOException.class); - - mService.loadRebootEscrowDataIfAvailable(mHandler); - // Sleep 5s for the retry to complete - Thread.sleep(5 * 1000); - assertFalse(metricsSuccessCaptor.getValue()); - assertEquals( - Integer.valueOf(RebootEscrowManager.ERROR_NO_NETWORK), - metricsErrorCodeCaptor.getValue()); - } - - @Test public void loadRebootEscrowDataIfAvailable_ServerBased_RetrySuccess() throws Exception { setServerBasedRebootEscrowProvider(); @@ -941,7 +886,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsEnabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) public void loadRebootEscrowDataIfAvailable_waitForInternet_networkUnavailable() throws Exception { setServerBasedRebootEscrowProvider(); @@ -989,7 +933,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsEnabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) public void loadRebootEscrowDataIfAvailable_waitForInternet_networkLost() throws Exception { setServerBasedRebootEscrowProvider(); @@ -1044,7 +987,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsEnabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) public void loadRebootEscrowDataIfAvailable_waitForInternet_networkAvailableWithDelay() throws Exception { setServerBasedRebootEscrowProvider(); @@ -1103,7 +1045,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsEnabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) public void loadRebootEscrowDataIfAvailable_waitForInternet_timeoutExhausted() throws Exception { setServerBasedRebootEscrowProvider(); @@ -1163,7 +1104,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsEnabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) public void loadRebootEscrowDataIfAvailable_serverBasedWaitForNetwork_retryCountExhausted() throws Exception { setServerBasedRebootEscrowProvider(); @@ -1219,7 +1159,6 @@ public class RebootEscrowManagerTests { } @Test - @RequiresFlagsEnabled(Flags.FLAG_WAIT_FOR_INTERNET_ROR) public void loadRebootEscrowDataIfAvailable_ServerBasedWaitForInternet_RetrySuccess() throws Exception { setServerBasedRebootEscrowProvider(); diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java index 88395a4889c4..071bd739072b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java @@ -306,9 +306,9 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { // This method is always called, even with PI == null. if (resultIntent == null) { - verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(isNull()); } else { - verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(notNull()); } runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { @@ -619,7 +619,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { makeResultIntent())); // The intent should be sent right away. - verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(notNull()); }); // Already pinned. @@ -661,7 +661,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertTrue(request.accept()); // The intent is only sent once, so times(1). - verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(isNull()); }); // Still pinned. @@ -698,7 +698,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { makeResultIntent())); // The intent should be sent right away. - verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(notNull()); }); // Already pinned. @@ -742,7 +742,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertTrue(request.accept()); // The intent is only sent once, so times(1). - verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); + verify(mServiceContext, times(1)).sendIntentSender(isNull()); }); // Still pinned. diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java index 952d8fa47a34..09acfddacf03 100644 --- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java @@ -51,6 +51,7 @@ import android.os.IThermalStatusListener; import android.os.PowerManager; import android.os.RemoteException; import android.os.Temperature; +import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; @@ -78,6 +79,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; /** * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server @@ -117,7 +119,8 @@ public class ThermalManagerServiceTest { */ private class ThermalHalFake extends ThermalHalWrapper { private static final int INIT_STATUS = Temperature.THROTTLING_NONE; - private List<Temperature> mTemperatureList = new ArrayList<>(); + private final List<Temperature> mTemperatureList = new ArrayList<>(); + private AtomicInteger mGetCurrentTemperaturesCalled = new AtomicInteger(); private List<CoolingDevice> mCoolingDeviceList = new ArrayList<>(); private List<TemperatureThreshold> mTemperatureThresholdList = initializeThresholds(); @@ -173,6 +176,7 @@ public class ThermalManagerServiceTest { mTemperatureList.add(mUsbPort); mCoolingDeviceList.add(mCpu); mCoolingDeviceList.add(mGpu); + mGetCurrentTemperaturesCalled.set(0); } void enableForecastSkinTemperature() { @@ -188,14 +192,24 @@ public class ThermalManagerServiceTest { mForecastSkinTemperaturesError = true; } + void updateTemperatureList(Temperature... temperatures) { + synchronized (mTemperatureList) { + mTemperatureList.clear(); + mTemperatureList.addAll(Arrays.asList(temperatures)); + } + } + @Override protected List<Temperature> getCurrentTemperatures(boolean shouldFilter, int type) { List<Temperature> ret = new ArrayList<>(); - for (Temperature temperature : mTemperatureList) { - if (shouldFilter && type != temperature.getType()) { - continue; + synchronized (mTemperatureList) { + mGetCurrentTemperaturesCalled.incrementAndGet(); + for (Temperature temperature : mTemperatureList) { + if (shouldFilter && type != temperature.getType()) { + continue; + } + ret.add(temperature); } - ret.add(temperature); } return ret; } @@ -407,7 +421,7 @@ public class ThermalManagerServiceTest { Thread.sleep(CALLBACK_TIMEOUT_MILLI_SEC); resetListenerMock(); int status = Temperature.THROTTLING_SEVERE; - mFakeHal.mTemperatureList = new ArrayList<>(); + mFakeHal.updateTemperatureList(); // Should not notify on non-skin type Temperature newBattery = new Temperature(37, Temperature.TYPE_BATTERY, "batt", status); @@ -537,6 +551,42 @@ public class ThermalManagerServiceTest { } @Test + @DisableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST}) + public void testGetThermalHeadroom_handlerUpdateTemperatures() + throws RemoteException, InterruptedException { + // test that handler will at least enqueue one message to periodically read temperatures + // even if there is sample seeded from HAL temperature callback + String temperatureName = "skin1"; + Temperature temperature = new Temperature(100, Temperature.TYPE_SKIN, temperatureName, + Temperature.THROTTLING_NONE); + mFakeHal.mCallback.onTemperatureChanged(temperature); + float headroom = mService.mService.getThermalHeadroom(0); + // the callback temperature 100C (headroom > 1.0f) sample should have been appended by the + // immediately scheduled fake HAL current temperatures read (mSkin1, mSkin2), and because + // there are less samples for prediction, the latest temperature mSkin1 is used to calculate + // headroom (mSkin2 has no threshold), which is 0.6f (28C vs threshold 40C). + assertEquals(0.6f, headroom, 0.01f); + // one called by service onActivityManagerReady, one called by handler on headroom call + assertEquals(2, mFakeHal.mGetCurrentTemperaturesCalled.get()); + // periodic read should update the samples history, so the headroom should increase 0.1f + // as current temperature goes up by 3C every 1100ms. + for (int i = 1; i < 5; i++) { + Temperature newTemperature = new Temperature(mFakeHal.mSkin1.getValue() + 3 * i, + Temperature.TYPE_SKIN, + temperatureName, + Temperature.THROTTLING_NONE); + mFakeHal.updateTemperatureList(newTemperature); + // wait for handler to update temperature + Thread.sleep(1100); + // assert that only one callback was scheduled to query HAL when making multiple + // headroom calls + assertEquals(2 + i, mFakeHal.mGetCurrentTemperaturesCalled.get()); + headroom = mService.mService.getThermalHeadroom(0); + assertEquals(0.6f + 0.1f * i, headroom, 0.01f); + } + } + + @Test @EnableFlags({Flags.FLAG_ALLOW_THERMAL_HAL_SKIN_FORECAST}) public void testGetThermalHeadroom_halForecast() throws RemoteException { mFakeHal.mForecastSkinTemperaturesCalled = 0; diff --git a/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java b/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java index 339bac4f768b..d6b3fecb487c 100644 --- a/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java @@ -45,6 +45,8 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.List; +import java.util.Map; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicBoolean; @SuppressLint("VisibleForTests") @@ -66,17 +68,28 @@ public class AdvancedProtectionServiceTest { mPermissionEnforcer.grant(Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE); mStore = new AdvancedProtectionService.AdvancedProtectionStore(mContext) { + private Map<String, Integer> mStoredValues = new HashMap<>(); private boolean mEnabled = false; @Override - boolean retrieve() { + boolean retrieveAdvancedProtectionModeEnabled() { return mEnabled; } @Override - void store(boolean enabled) { + void storeAdvancedProtectionModeEnabled(boolean enabled) { this.mEnabled = enabled; } + + @Override + void storeInt(String key, int value) { + mStoredValues.put(key, value); + } + + @Override + int retrieveInt(String key, int defaultValue) { + return mStoredValues.getOrDefault(key, defaultValue); + } }; mLooper = new TestLooper(); @@ -316,6 +329,18 @@ public class AdvancedProtectionServiceTest { } @Test + public void testUsbDataProtection_withoutPermission() { + mPermissionEnforcer.revoke(Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE); + assertThrows(SecurityException.class, () -> mService.isUsbDataProtectionEnabled()); + } + + @Test + public void testSetUsbDataProtection_withoutPermission() { + mPermissionEnforcer.revoke(Manifest.permission.MANAGE_ADVANCED_PROTECTION_MODE); + assertThrows(SecurityException.class, () -> mService.setUsbDataProtectionEnabled(true)); + } + + @Test public void testRegisterCallback_withoutPermission() { mPermissionEnforcer.revoke(Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE); assertThrows(SecurityException.class, () -> mService.registerAdvancedProtectionCallback( diff --git a/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java b/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java index 4a97b4670289..291d0ec8fbfc 100644 --- a/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java @@ -85,7 +85,7 @@ public class DiskStatsLoggingServiceTest extends AndroidTestCase { mDownloads = new TemporaryFolder(); mDownloads.create(); mStorageStats = new ExternalStorageStats(); - when(mSsm.queryExternalStatsForUser(isNull(String.class), any(UserHandle.class))) + when(mSsm.queryExternalStatsForUser((String)isNull(), any(UserHandle.class))) .thenReturn(mStorageStats); when(mJobService.getSystemService(anyString())).thenReturn(mSsm); } diff --git a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt index fbf906586e8b..c59f0a05c619 100644 --- a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt +++ b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt @@ -17,6 +17,7 @@ package com.android.server.supervision import android.app.Activity +import android.app.KeyguardManager import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManagerInternal import android.app.supervision.flags.Flags @@ -61,6 +62,9 @@ class SupervisionServiceTest { @get:Rule val mocks: MockitoRule = MockitoJUnit.rule() @Mock private lateinit var mockDpmInternal: DevicePolicyManagerInternal + + @Mock + private lateinit var mockKeyguardManager: KeyguardManager @Mock private lateinit var mockPackageManager: PackageManager @Mock private lateinit var mockUserManagerInternal: UserManagerInternal @@ -71,7 +75,7 @@ class SupervisionServiceTest { @Before fun setUp() { context = InstrumentationRegistry.getInstrumentation().context - context = SupervisionContextWrapper(context, mockPackageManager) + context = SupervisionContextWrapper(context, mockKeyguardManager, mockPackageManager) LocalServices.removeServiceForTest(DevicePolicyManagerInternal::class.java) LocalServices.addService(DevicePolicyManagerInternal::class.java, mockDpmInternal) @@ -250,11 +254,41 @@ class SupervisionServiceTest { @Test fun createConfirmSupervisionCredentialsIntent() { + service.mInternal.setSupervisionEnabledForUser(context.getUserId(), true) + whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(SUPERVISING_USER_ID) + whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true) + val intent = checkNotNull(service.createConfirmSupervisionCredentialsIntent()) assertThat(intent.action).isEqualTo(ACTION_CONFIRM_SUPERVISION_CREDENTIALS) assertThat(intent.getPackage()).isEqualTo("com.android.settings") } + @Test + fun createConfirmSupervisionCredentialsIntent_supervisionNotEnabled_returnsNull() { + service.mInternal.setSupervisionEnabledForUser(context.getUserId(), false) + whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(SUPERVISING_USER_ID) + whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true) + + assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull() + } + + @Test + fun createConfirmSupervisionCredentialsIntent_noSupervisingUser_returnsNull() { + service.mInternal.setSupervisionEnabledForUser(context.getUserId(), true) + whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(UserHandle.USER_NULL) + + assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull() + } + + @Test + fun createConfirmSupervisionCredentialsIntent_supervisingUserMissingSecureLock_returnsNull() { + service.mInternal.setSupervisionEnabledForUser(context.getUserId(), true) + whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(SUPERVISING_USER_ID) + whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(false) + + assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull() + } + private val systemSupervisionPackage: String get() = context.getResources().getString(R.string.config_systemSupervision) @@ -279,6 +313,7 @@ class SupervisionServiceTest { private companion object { const val USER_ID = 100 const val APP_UID = USER_ID * UserHandle.PER_USER_RANGE + const val SUPERVISING_USER_ID = 10 } } @@ -286,10 +321,19 @@ class SupervisionServiceTest { * A context wrapper that allows broadcast intents to immediately invoke the receivers without * performing checks on the sending user. */ -private class SupervisionContextWrapper(val context: Context, val pkgManager: PackageManager) : - ContextWrapper(context) { +private class SupervisionContextWrapper( + val context: Context, + val keyguardManager: KeyguardManager, + val pkgManager: PackageManager, +) : ContextWrapper(context) { val interceptors = mutableListOf<Pair<BroadcastReceiver, IntentFilter>>() + override fun getSystemService(name: String): Any = + when (name) { + Context.KEYGUARD_SERVICE -> keyguardManager + else -> super.getSystemService(name) + } + override fun getPackageManager() = pkgManager override fun registerReceiverForAllUsers( diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java index f3d5e39ec127..8d164e1acf74 100644 --- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java @@ -53,14 +53,16 @@ import android.app.AppOpsManager; import android.content.Context; import android.hardware.input.InputManager; import android.os.Bundle; +import android.os.IBinder; import android.os.PowerManager; import android.os.PowerManagerInternal; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.service.dreams.DreamManagerInternal; import android.testing.TestableContext; -import android.view.contentprotection.flags.Flags; +import android.view.KeyEvent; import androidx.test.filters.SmallTest; @@ -102,6 +104,8 @@ public class PhoneWindowManagerTests { public final TestableContext mContext = spy( new TestableContext(getInstrumentation().getContext())); + @Mock private IBinder mInputToken; + PhoneWindowManager mPhoneWindowManager; @Mock private ActivityTaskManagerInternal mAtmInternal; @@ -125,6 +129,8 @@ public class PhoneWindowManagerTests { @Mock private LockPatternUtils mLockPatternUtils; + private static final int INTERCEPT_SYSTEM_KEY_NOT_CONSUMED_DELAY = 0; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -216,7 +222,7 @@ public class PhoneWindowManagerTests { @Test public void testCheckAddPermission_withoutAccessibilityOverlay_noAccessibilityAppOpLogged() { - mSetFlagsRule.enableFlags(Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED); + mSetFlagsRule.enableFlags(android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED); int[] outAppOp = new int[1]; assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_WALLPAPER, /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY)); @@ -225,7 +231,7 @@ public class PhoneWindowManagerTests { @Test public void testCheckAddPermission_withAccessibilityOverlay() { - mSetFlagsRule.enableFlags(Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED); + mSetFlagsRule.enableFlags(android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED); int[] outAppOp = new int[1]; assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY, /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY)); @@ -234,7 +240,7 @@ public class PhoneWindowManagerTests { @Test public void testCheckAddPermission_withAccessibilityOverlay_flagDisabled() { - mSetFlagsRule.disableFlags(Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED); + mSetFlagsRule.disableFlags(android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED); int[] outAppOp = new int[1]; assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY, /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY)); @@ -401,6 +407,35 @@ public class PhoneWindowManagerTests { verify(mDreamManagerInternal).requestDream(); } + @EnableFlags(com.android.hardware.input.Flags.FLAG_FIX_SEARCH_MODIFIER_FALLBACKS) + public void testInterceptKeyBeforeDispatching() { + // Handle sub-tasks of init(). + doNothing().when(mPhoneWindowManager).updateSettings(any()); + doNothing().when(mPhoneWindowManager).initializeHdmiState(); + final DisplayPolicy displayPolicy = mock(DisplayPolicy.class); + mPhoneWindowManager.mDefaultDisplayPolicy = displayPolicy; + mPhoneWindowManager.mDefaultDisplayRotation = mock(DisplayRotation.class); + final PowerManager pm = mock(PowerManager.class); + doReturn(true).when(pm).isInteractive(); + doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE)); + + mContext.getMainThreadHandler().runWithScissors(() -> mPhoneWindowManager.init( + new PhoneWindowManager.Injector(mContext, + mock(WindowManagerPolicy.WindowManagerFuncs.class))), 0); + + // Case: KeyNotConsumed with meta key. + KeyEvent keyEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, + KeyEvent.KEYCODE_A, 0, KeyEvent.META_META_ON); + long result = mPhoneWindowManager.interceptKeyBeforeDispatching(mInputToken, keyEvent, 0); + assertEquals(INTERCEPT_SYSTEM_KEY_NOT_CONSUMED_DELAY, result); + + // Case: KeyNotConsumed without meta key. + KeyEvent keyEvent1 = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, + KeyEvent.KEYCODE_ESCAPE, 0, 0); + long result1 = mPhoneWindowManager.interceptKeyBeforeDispatching(mInputToken, keyEvent1, 0); + assertEquals(INTERCEPT_SYSTEM_KEY_NOT_CONSUMED_DELAY, result1); + } + private void initPhoneWindowManager() { mPhoneWindowManager.mDefaultDisplayPolicy = mDisplayPolicy; mPhoneWindowManager.mDefaultDisplayRotation = mock(DisplayRotation.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/DeviceStateAutoRotateSettingIssueLoggerTests.java b/services/tests/wmtests/src/com/android/server/wm/DeviceStateAutoRotateSettingIssueLoggerTests.java index f76a9cdbb894..ba9bf1bf8045 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DeviceStateAutoRotateSettingIssueLoggerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DeviceStateAutoRotateSettingIssueLoggerTests.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import android.platform.test.annotations.Presubmit; @@ -143,4 +144,46 @@ public class DeviceStateAutoRotateSettingIssueLoggerTests { anyInt(), anyBoolean()), never()); } + + @Test + public void onStateChange_issueOccurredSettingChangedTwice_reportOnlyOnce() { + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateAutoRotateSettingChange(); + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateChange(); + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateAutoRotateSettingChange(); + + verify(() -> + FrameworkStatsLog.write( + eq(FrameworkStatsLog.DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_REPORTED), + anyInt(), + anyBoolean()), times(1)); + } + + @Test + public void onStateChange_issueOccurredDeviceStateChangedTwice_reportOnlyOnce() { + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateChange(); + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateAutoRotateSettingChange(); + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateChange(); + + verify(() -> + FrameworkStatsLog.write( + eq(FrameworkStatsLog.DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_REPORTED), + anyInt(), + anyBoolean()), times(1)); + } + + @Test + public void onStateChange_issueOccurredAfterDelay_reportOnce() { + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateAutoRotateSettingChange(); + mTestTimeSupplier.delay( + DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_THRESHOLD_MILLIS + DELAY); + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateChange(); + mTestTimeSupplier.delay(DELAY); + mDeviceStateAutoRotateSettingIssueLogger.onDeviceStateAutoRotateSettingChange(); + + verify(() -> + FrameworkStatsLog.write( + eq(FrameworkStatsLog.DEVICE_STATE_AUTO_ROTATE_SETTING_ISSUE_REPORTED), + eq(DELAY), + anyBoolean()), times(1)); + } } |