Loading apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +264 −1 Original line number Diff line number Diff line Loading @@ -145,7 +145,9 @@ public class UserLifecycleTests { Intent.ACTION_USER_STARTED, Intent.ACTION_MEDIA_MOUNTED, Intent.ACTION_USER_UNLOCKED, Intent.ACTION_USER_STOPPED); Intent.ACTION_USER_STOPPED, Intent.ACTION_PROFILE_AVAILABLE, Intent.ACTION_PROFILE_UNAVAILABLE); mUserSwitchWaiter = new UserSwitchWaiter(TAG, TIMEOUT_IN_SECOND); removeAnyPreviousTestUsers(); if (mAm.getCurrentUser() != UserHandle.USER_SYSTEM) { Loading Loading @@ -1230,6 +1232,255 @@ public class UserLifecycleTests { } } /** Tests creating a private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void createPrivateProfile() throws RemoteException { while (mRunner.keepRunning()) { Log.i(TAG, "Starting timer"); final int userId = createPrivateProfileUser(); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** * Tests creating and starting a newly created private profile. This test waits for the * {@link Intent.ACTION_USER_STARTED} to be received. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void createAndStartPrivateProfile_realistic() throws RemoteException { while (mRunner.keepRunning()) { Log.i(TAG, "Starting timer"); final int userId = createPrivateProfileUser(); // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until // ACTION_USER_STARTED. runThenWaitForBroadcasts(userId, () -> { mIam.startUserInBackground(userId); }, Intent.ACTION_USER_STARTED); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** Tests for stopping the private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileStopped() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); runThenWaitForBroadcasts(userId, () -> { startUserInBackgroundAndWaitForUnlock(userId); }, Intent.ACTION_MEDIA_MOUNTED); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); stopUser(userId); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests unlocking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileUnlock() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); waitCoolDownPeriod(); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); mUm.requestQuietModeEnabled(false, UserHandle.of(userId)); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests unlocking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api and waiting for the * {@link Intent.ACTION_PROFILE_AVAILABLE} to be received. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileUnlock_realistic() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); waitCoolDownPeriod(); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mUm.requestQuietModeEnabled(false, UserHandle.of(userId)); }, Intent.ACTION_PROFILE_AVAILABLE); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests locking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileLock() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests locking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api and waiting for the * {@link Intent.ACTION_PROFILE_UNAVAILABLE} to be received. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileLock_realistic() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); }, Intent.ACTION_PROFILE_UNAVAILABLE); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** Tests removing a newly-created private profile */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileRemove() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); removeUser(userId); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); mRunner.resumeTimingForNextIteration(); } } /** Tests installing a pre-existing app in a private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileInstall() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); installPreexistingApp(userId, DUMMY_PACKAGE_NAME); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** * Tests creating a new private profile, starting it, installing an app, and launching that app * in it. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileCreateStartInstallAndLaunchApp() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); installPreexistingApp(userId, DUMMY_PACKAGE_NAME); startApp(userId, DUMMY_PACKAGE_NAME); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** * Tests starting & launching an already-installed app in a private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileStartAndLaunchApp() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null); installPreexistingApp(userId, DUMMY_PACKAGE_NAME); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); startUserInBackgroundAndWaitForUnlock(userId); startApp(userId, DUMMY_PACKAGE_NAME); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** Creates a new user, returning its userId. */ private int createUserNoFlags() { return createUserWithFlags(/* flags= */ 0); Loading @@ -1252,6 +1503,18 @@ public class UserLifecycleTests { return userInfo.id; } /** Creates a private profile under the current user, returning its userId. */ private int createPrivateProfileUser() { final UserInfo userInfo = mUm.createProfileForUser(TEST_USER_NAME, UserManager.USER_TYPE_PROFILE_PRIVATE, /* flags */ 0, mAm.getCurrentUser()); attestFalse( "Creating a private profile failed. Most likely there is already a pre-existing " + "private profile on the device.", userInfo == null); mUsersToRemove.add(userInfo.id); return userInfo.id; } /** * Start user in background and wait for it to unlock by waiting for * UserState.mUnlockProgress.finish(). Loading api/coverage/tools/ExtractFlaggedApis.kt +3 −3 Original line number Diff line number Diff line Loading @@ -75,10 +75,10 @@ fun addFlaggedApi(builder: FlagApiMap.Builder, api: JavaMethod.Builder, flag: St fun getClassFlag(classItem: ClassItem): String? { var classFlag = getFlagAnnotation(classItem) var cur = classItem // If a class is not an inner class, use its @FlaggedApi annotation value. // If a class is not a nested class, use its @FlaggedApi annotation value. // Otherwise, use the flag value of the closest outer class that is annotated by @FlaggedApi. while (cur.isInnerClass() && classFlag == null) { cur = cur.parent() as ClassItem while (classFlag == null) { cur = cur.containingClass() ?: break classFlag = getFlagAnnotation(cur) } return classFlag Loading core/java/android/hardware/input/IInputManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.hardware.input.TouchCalibration; import android.os.CombinedVibration; import android.hardware.input.IInputSensorEventListener; import android.hardware.input.InputSensorInfo; import android.hardware.input.KeyGlyphMap; import android.hardware.lights.Light; import android.hardware.lights.LightState; import android.os.IBinder; Loading Loading @@ -236,4 +237,6 @@ interface IInputManager { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " + "android.Manifest.permission.MONITOR_STICKY_MODIFIER_STATE)") void unregisterStickyModifierStateListener(IStickyModifierStateListener listener); KeyGlyphMap getKeyGlyphMap(int deviceId); } core/java/android/hardware/input/InputManager.java +46 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.hardware.input; import static com.android.input.flags.Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API; import static com.android.input.flags.Flags.FLAG_DEVICE_ASSOCIATIONS; import static com.android.hardware.input.Flags.keyboardLayoutPreviewFlag; import static com.android.hardware.input.Flags.keyboardGlyphMap; import android.Manifest; import android.annotation.FlaggedApi; Loading Loading @@ -157,6 +158,34 @@ public final class InputManager { public static final String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; /** * Broadcast Action: Query available keyboard glyph maps. * <p> * The input manager service locates available keyboard glyph maps * by querying broadcast receivers that are registered for this action. * An application can offer additional keyboard glyph maps to the user * by declaring a suitable broadcast receiver in its manifest. * </p> * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_QUERY_KEYBOARD_GLYPH_MAPS = "android.hardware.input.action.QUERY_KEYBOARD_GLYPH_MAPS"; /** * Metadata Key: Keyboard glyph map metadata associated with * {@link #ACTION_QUERY_KEYBOARD_GLYPH_MAPS}. * <p> * Specifies the resource id of a XML resource that describes the keyboard * glyph maps that are provided by the application. * </p> * * @hide */ public static final String META_DATA_KEYBOARD_GLYPH_MAPS = "android.hardware.input.metadata.KEYBOARD_GLYPH_MAPS"; /** * Prevent touches from being consumed by apps if these touches passed through a non-trusted * window from a different UID and are considered unsafe. Loading Loading @@ -897,6 +926,23 @@ public final class InputManager { return new KeyboardLayoutPreviewDrawable(mContext, keyLayout, width, height); } /** * Provides associated glyph map for the keyboard device (if available) * * @hide */ @Nullable public KeyGlyphMap getKeyGlyphMap(int deviceId) { if (!keyboardGlyphMap()) { return null; } try { return mIm.getKeyGlyphMap(deviceId); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Injects an input event into the event system, targeting windows owned by the provided uid. * Loading core/java/android/hardware/input/KeyGlyphMap.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /** * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.input; parcelable KeyGlyphMap; No newline at end of file Loading
apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +264 −1 Original line number Diff line number Diff line Loading @@ -145,7 +145,9 @@ public class UserLifecycleTests { Intent.ACTION_USER_STARTED, Intent.ACTION_MEDIA_MOUNTED, Intent.ACTION_USER_UNLOCKED, Intent.ACTION_USER_STOPPED); Intent.ACTION_USER_STOPPED, Intent.ACTION_PROFILE_AVAILABLE, Intent.ACTION_PROFILE_UNAVAILABLE); mUserSwitchWaiter = new UserSwitchWaiter(TAG, TIMEOUT_IN_SECOND); removeAnyPreviousTestUsers(); if (mAm.getCurrentUser() != UserHandle.USER_SYSTEM) { Loading Loading @@ -1230,6 +1232,255 @@ public class UserLifecycleTests { } } /** Tests creating a private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void createPrivateProfile() throws RemoteException { while (mRunner.keepRunning()) { Log.i(TAG, "Starting timer"); final int userId = createPrivateProfileUser(); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** * Tests creating and starting a newly created private profile. This test waits for the * {@link Intent.ACTION_USER_STARTED} to be received. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void createAndStartPrivateProfile_realistic() throws RemoteException { while (mRunner.keepRunning()) { Log.i(TAG, "Starting timer"); final int userId = createPrivateProfileUser(); // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until // ACTION_USER_STARTED. runThenWaitForBroadcasts(userId, () -> { mIam.startUserInBackground(userId); }, Intent.ACTION_USER_STARTED); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** Tests for stopping the private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileStopped() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); runThenWaitForBroadcasts(userId, () -> { startUserInBackgroundAndWaitForUnlock(userId); }, Intent.ACTION_MEDIA_MOUNTED); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); stopUser(userId); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests unlocking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileUnlock() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); waitCoolDownPeriod(); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); mUm.requestQuietModeEnabled(false, UserHandle.of(userId)); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests unlocking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api and waiting for the * {@link Intent.ACTION_PROFILE_AVAILABLE} to be received. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileUnlock_realistic() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); waitCoolDownPeriod(); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mUm.requestQuietModeEnabled(false, UserHandle.of(userId)); }, Intent.ACTION_PROFILE_AVAILABLE); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests locking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileLock() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** * Tests locking a newly-created private profile using the * {@link UserManager#requestQuietModeEnabled} api and waiting for the * {@link Intent.ACTION_PROFILE_UNAVAILABLE} to be received. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileLock_realistic() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); runThenWaitForBroadcasts(userId, () -> { mUm.requestQuietModeEnabled(true, UserHandle.of(userId)); }, Intent.ACTION_PROFILE_UNAVAILABLE); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); mRunner.resumeTimingForNextIteration(); } } /** Tests removing a newly-created private profile */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileRemove() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); removeUser(userId); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); mRunner.resumeTimingForNextIteration(); } } /** Tests installing a pre-existing app in a private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileInstall() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); installPreexistingApp(userId, DUMMY_PACKAGE_NAME); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** * Tests creating a new private profile, starting it, installing an app, and launching that app * in it. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileCreateStartInstallAndLaunchApp() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); final int userId = createPrivateProfileUser(); startUserInBackgroundAndWaitForUnlock(userId); installPreexistingApp(userId, DUMMY_PACKAGE_NAME); startApp(userId, DUMMY_PACKAGE_NAME); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** * Tests starting & launching an already-installed app in a private profile. */ @Test(timeout = TIMEOUT_MAX_TEST_TIME_MS) public void privateProfileStartAndLaunchApp() throws RemoteException { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int userId = createPrivateProfileUser(); WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null); installPreexistingApp(userId, DUMMY_PACKAGE_NAME); mRunner.resumeTiming(); Log.i(TAG, "Starting timer"); startUserInBackgroundAndWaitForUnlock(userId); startApp(userId, DUMMY_PACKAGE_NAME); mRunner.pauseTiming(); Log.i(TAG, "Stopping timer"); removeUser(userId); waitCoolDownPeriod(); mRunner.resumeTimingForNextIteration(); } } /** Creates a new user, returning its userId. */ private int createUserNoFlags() { return createUserWithFlags(/* flags= */ 0); Loading @@ -1252,6 +1503,18 @@ public class UserLifecycleTests { return userInfo.id; } /** Creates a private profile under the current user, returning its userId. */ private int createPrivateProfileUser() { final UserInfo userInfo = mUm.createProfileForUser(TEST_USER_NAME, UserManager.USER_TYPE_PROFILE_PRIVATE, /* flags */ 0, mAm.getCurrentUser()); attestFalse( "Creating a private profile failed. Most likely there is already a pre-existing " + "private profile on the device.", userInfo == null); mUsersToRemove.add(userInfo.id); return userInfo.id; } /** * Start user in background and wait for it to unlock by waiting for * UserState.mUnlockProgress.finish(). Loading
api/coverage/tools/ExtractFlaggedApis.kt +3 −3 Original line number Diff line number Diff line Loading @@ -75,10 +75,10 @@ fun addFlaggedApi(builder: FlagApiMap.Builder, api: JavaMethod.Builder, flag: St fun getClassFlag(classItem: ClassItem): String? { var classFlag = getFlagAnnotation(classItem) var cur = classItem // If a class is not an inner class, use its @FlaggedApi annotation value. // If a class is not a nested class, use its @FlaggedApi annotation value. // Otherwise, use the flag value of the closest outer class that is annotated by @FlaggedApi. while (cur.isInnerClass() && classFlag == null) { cur = cur.parent() as ClassItem while (classFlag == null) { cur = cur.containingClass() ?: break classFlag = getFlagAnnotation(cur) } return classFlag Loading
core/java/android/hardware/input/IInputManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.hardware.input.TouchCalibration; import android.os.CombinedVibration; import android.hardware.input.IInputSensorEventListener; import android.hardware.input.InputSensorInfo; import android.hardware.input.KeyGlyphMap; import android.hardware.lights.Light; import android.hardware.lights.LightState; import android.os.IBinder; Loading Loading @@ -236,4 +237,6 @@ interface IInputManager { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = " + "android.Manifest.permission.MONITOR_STICKY_MODIFIER_STATE)") void unregisterStickyModifierStateListener(IStickyModifierStateListener listener); KeyGlyphMap getKeyGlyphMap(int deviceId); }
core/java/android/hardware/input/InputManager.java +46 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.hardware.input; import static com.android.input.flags.Flags.FLAG_INPUT_DEVICE_VIEW_BEHAVIOR_API; import static com.android.input.flags.Flags.FLAG_DEVICE_ASSOCIATIONS; import static com.android.hardware.input.Flags.keyboardLayoutPreviewFlag; import static com.android.hardware.input.Flags.keyboardGlyphMap; import android.Manifest; import android.annotation.FlaggedApi; Loading Loading @@ -157,6 +158,34 @@ public final class InputManager { public static final String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; /** * Broadcast Action: Query available keyboard glyph maps. * <p> * The input manager service locates available keyboard glyph maps * by querying broadcast receivers that are registered for this action. * An application can offer additional keyboard glyph maps to the user * by declaring a suitable broadcast receiver in its manifest. * </p> * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_QUERY_KEYBOARD_GLYPH_MAPS = "android.hardware.input.action.QUERY_KEYBOARD_GLYPH_MAPS"; /** * Metadata Key: Keyboard glyph map metadata associated with * {@link #ACTION_QUERY_KEYBOARD_GLYPH_MAPS}. * <p> * Specifies the resource id of a XML resource that describes the keyboard * glyph maps that are provided by the application. * </p> * * @hide */ public static final String META_DATA_KEYBOARD_GLYPH_MAPS = "android.hardware.input.metadata.KEYBOARD_GLYPH_MAPS"; /** * Prevent touches from being consumed by apps if these touches passed through a non-trusted * window from a different UID and are considered unsafe. Loading Loading @@ -897,6 +926,23 @@ public final class InputManager { return new KeyboardLayoutPreviewDrawable(mContext, keyLayout, width, height); } /** * Provides associated glyph map for the keyboard device (if available) * * @hide */ @Nullable public KeyGlyphMap getKeyGlyphMap(int deviceId) { if (!keyboardGlyphMap()) { return null; } try { return mIm.getKeyGlyphMap(deviceId); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } /** * Injects an input event into the event system, targeting windows owned by the provided uid. * Loading
core/java/android/hardware/input/KeyGlyphMap.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /** * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.input; parcelable KeyGlyphMap; No newline at end of file