(TouchMode Permission 2/n) Introduce permission for touch mode

This CL adds caller pid and uid for permission checks in the native
layer when switching touch mode state.

Bug: 198487159
Test: atest FrameworksCoreTests
Test: atest CtsInputMethodTestCases
Test: atest CtsInputTestCases
Test: atest CtsSecurityTestCases
Test: atest CtsWindowManagerDeviceTestCases
Change-Id: I64480c0284481b288ad0950c2e95726b9adb529f
This commit is contained in:
Antonio Kantek
2021-12-20 14:17:12 -08:00
parent d30c9c9992
commit d299b88323
5 changed files with 56 additions and 24 deletions

View File

@@ -376,14 +376,16 @@ public class Instrumentation {
Debug.stopMethodTracing();
}
}
/**
* Force the global system in or out of touch mode. This can be used if
* your instrumentation relies on the UI being in one more or the other
* when it starts.
*
* @param inTouch Set to true to be in touch mode, false to be in
* focus mode.
* Force the global system in or out of touch mode. This can be used if your
* instrumentation relies on the UI being in one more or the other when it starts.
*
* <p><b>Note:</b> Starting from Android {@link Build.VERSION_CODES#TIRAMISU}, this method
* will only have an effect if the calling process is also the focused window owner or has
* {@link android.permission#MODIFY_TOUCH_MODE_STATE} permission granted.
*
* @param inTouch Set to true to be in touch mode, false to be in focus mode.
*/
public void setInTouchMode(boolean inTouch) {
try {
@@ -393,11 +395,11 @@ public class Instrumentation {
// Shouldn't happen!
}
}
/**
* Schedule a callback for when the application's main thread goes idle
* (has no more events to process).
*
*
* @param recipient Called the next time the thread's message queue is
* idle.
*/

View File

@@ -39,6 +39,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE" />
<uses-permission android:name="android.permission.DUMP" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />

View File

@@ -307,7 +307,8 @@ public class InputManagerService extends IInputManager.Stub
private static native void nativeRemoveInputChannel(long ptr, IBinder connectionToken);
private static native void nativePilferPointers(long ptr, IBinder token);
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
private static native void nativeSetInTouchMode(long ptr, boolean inTouchMode);
private static native boolean nativeSetInTouchMode(long ptr, boolean inTouchMode, int pid,
int uid, boolean hasPermission);
private static native void nativeSetMaximumObscuringOpacityForTouch(long ptr, float opacity);
private static native void nativeSetBlockUntrustedTouchesMode(long ptr, int mode);
private static native int nativeInjectInputEvent(long ptr, InputEvent event,
@@ -872,12 +873,16 @@ public class InputManagerService extends IInputManager.Stub
* other apps, when they become focused.
*
* When input dispatches focus to the apps, the touch mode state
* will be sent together with the focus change.
* will be sent together with the focus change (but each one in its own event).
*
* @param inTouchMode true if the device is in touch mode.
* @param inTouchMode true if the device is in touch mode
* @param pid the pid of the process that requested to switch touch mode state
* @param uid the uid of the process that requested to switch touch mode state
* @param hasPermission if set to {@code true} then no further authorization will be performed
* @return {@code true} if the touch mode was successfully changed, {@code false} otherwise
*/
public void setInTouchMode(boolean inTouchMode) {
nativeSetInTouchMode(mPtr, inTouchMode);
public boolean setInTouchMode(boolean inTouchMode, int pid, int uid, boolean hasPermission) {
return nativeSetInTouchMode(mPtr, inTouchMode, pid, uid, hasPermission);
}
@Override // Binder call

View File

@@ -21,6 +21,7 @@ import static android.Manifest.permission.INPUT_CONSUMER;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
@@ -38,6 +39,7 @@ import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
import static android.os.Process.myUid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
@@ -1202,7 +1204,8 @@ public class WindowManagerService extends IWindowManager.Stub
com.android.internal.R.bool.config_hasPermanentDpad);
mInTouchMode = context.getResources().getBoolean(
com.android.internal.R.bool.config_defaultInTouchMode);
inputManager.setInTouchMode(mInTouchMode);
inputManager.setInTouchMode(
mInTouchMode, myPid(), myUid(), /* hasPermission = */ true);
mDrawLockTimeoutMillis = context.getResources().getInteger(
com.android.internal.R.integer.config_drawLockTimeoutMillis);
mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
@@ -2669,7 +2672,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
boolean checkCallingPermission(String permission, String func, boolean printLog) {
// Quick check: if the calling permission is me, it's all okay.
if (Binder.getCallingPid() == myPid()) {
return true;
}
@@ -3703,12 +3705,33 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
@Override
/**
* Sets the touch mode state.
*
* To be able to change touch mode state, the caller must either own the focused window, or must
* have the MODIFY_TOUCH_MODE_STATE permission.
*
* @param mode the touch mode to set
*/
@Override // Binder call
public void setInTouchMode(boolean mode) {
synchronized (mGlobalLock) {
mInTouchMode = mode;
if (mInTouchMode == mode) {
return;
}
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final boolean hasPermission = checkCallingPermission(MODIFY_TOUCH_MODE_STATE,
"setInTouchMode()");
final long token = Binder.clearCallingIdentity();
try {
if (mInputManager.setInTouchMode(mode, pid, uid, hasPermission)) {
mInTouchMode = mode;
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
mInputManager.setInTouchMode(mode);
}
boolean getInTouchMode() {

View File

@@ -1707,7 +1707,6 @@ static void nativePilferPointers(JNIEnv* env, jclass /* clazz */, jlong ptr, job
im->pilferPointers(token);
}
static void nativeSetInputFilterEnabled(JNIEnv* /* env */, jclass /* clazz */,
jlong ptr, jboolean enabled) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1715,11 +1714,13 @@ static void nativeSetInputFilterEnabled(JNIEnv* /* env */, jclass /* clazz */,
im->getInputManager()->getDispatcher().setInputFilterEnabled(enabled);
}
static void nativeSetInTouchMode(JNIEnv* /* env */, jclass /* clazz */,
jlong ptr, jboolean inTouchMode) {
static jboolean nativeSetInTouchMode(JNIEnv* /* env */, jclass /* clazz */, jlong ptr,
jboolean inTouchMode, jint pid, jint uid,
jboolean hasPermission) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->getInputManager()->getDispatcher().setInTouchMode(inTouchMode);
return im->getInputManager()->getDispatcher().setInTouchMode(inTouchMode, pid, uid,
hasPermission);
}
static void nativeSetMaximumObscuringOpacityForTouch(JNIEnv* /* env */, jclass /* clazz */,
@@ -2386,7 +2387,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"nativeRemoveInputChannel", "(JLandroid/os/IBinder;)V", (void*)nativeRemoveInputChannel},
{"nativePilferPointers", "(JLandroid/os/IBinder;)V", (void*)nativePilferPointers},
{"nativeSetInputFilterEnabled", "(JZ)V", (void*)nativeSetInputFilterEnabled},
{"nativeSetInTouchMode", "(JZ)V", (void*)nativeSetInTouchMode},
{"nativeSetInTouchMode", "(JZIIZ)Z", (void*)nativeSetInTouchMode},
{"nativeSetMaximumObscuringOpacityForTouch", "(JF)V",
(void*)nativeSetMaximumObscuringOpacityForTouch},
{"nativeSetBlockUntrustedTouchesMode", "(JI)V", (void*)nativeSetBlockUntrustedTouchesMode},