diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index b57409867f..372cecd63c 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -53,6 +53,7 @@ message SurfaceChange { ReparentChildrenChange reparent_children = 20; BackgroundBlurRadiusChange background_blur_radius = 21; ShadowRadiusChange shadow_radius = 22; + TrustedOverlayChange trusted_overlay = 23; } } @@ -208,4 +209,8 @@ message DetachChildrenChange { message ShadowRadiusChange { required float radius = 1; +} + +message TrustedOverlayChange { + required float is_trusted_overlay = 1; } \ No newline at end of file diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 2dac5b62a7..bbf793e62b 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -108,7 +108,6 @@ struct InputWindowInfo { TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, - TYPE_TRUSTED_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 42, LAST_SYSTEM_WINDOW = 2999, }; @@ -116,6 +115,7 @@ struct InputWindowInfo { INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001, INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002, INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004, + INPUT_FEATURE_DROP_INPUT = 0x00000008, }; /* These values are filled in by the WM and passed through SurfaceFlinger @@ -163,6 +163,12 @@ struct InputWindowInfo { bool hasFocus = false; bool hasWallpaper = false; bool paused = false; + /* This flag is set when the window is of a trusted type that is allowed to silently + * overlay other windows for the purpose of implementing the secure views feature. + * Trusted overlays, such as IME windows, can partly obscure other windows without causing + * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. + */ + bool trustedOverlay = false; int32_t ownerPid = -1; int32_t ownerUid = -1; int32_t inputFeatures = 0; @@ -175,20 +181,15 @@ struct InputWindowInfo { void addTouchableRegion(const Rect& region); bool touchableRegionContainsPoint(int32_t x, int32_t y) const; - bool frameContainsPoint(int32_t x, int32_t y) const; - /* Returns true if the window is of a trusted type that is allowed to silently - * overlay other windows for the purpose of implementing the secure views feature. - * Trusted overlays, such as IME windows, can partly obscure other windows without causing - * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. - */ - bool isTrustedOverlay() const; + bool frameContainsPoint(int32_t x, int32_t y) const; bool supportsSplitTouch() const; bool overlaps(const InputWindowInfo* other) const; status_t write(Parcel& output) const; + static InputWindowInfo read(const Parcel& from); }; diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index a9f2d73951..218970a1b2 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -215,7 +215,8 @@ sp ServiceManagerShim::getService(const String16& name) const const bool isVendorService = strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; - const long timeout = uptimeMillis() + 5000; + const long timeout = 5000; + int64_t startTime = uptimeMillis(); // Vendor code can't access system properties if (!gSystemBootCompleted && !isVendorService) { #ifdef __ANDROID__ @@ -230,7 +231,7 @@ sp ServiceManagerShim::getService(const String16& name) const const long sleepTime = gSystemBootCompleted ? 1000 : 100; int n = 0; - while (uptimeMillis() < timeout) { + while (uptimeMillis() - startTime < timeout) { n++; ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), ProcessState::self()->getDriverName().c_str()); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 64a4f9bf6d..f790b88e8d 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -2334,12 +2334,14 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, type == BINDER_TYPE_FD)) { // We should never receive other types (eg BINDER_TYPE_FDA) as long as we don't support // them in libbinder. If we do receive them, it probably means a kernel bug; try to - // recover gracefully by clearing out the objects, and releasing the objects we do - // know about. + // recover gracefully by clearing out the objects. android_errorWriteLog(0x534e4554, "135930648"); + android_errorWriteLog(0x534e4554, "203847542"); ALOGE("%s: unsupported type object (%" PRIu32 ") at offset %" PRIu64 "\n", __func__, type, (uint64_t)offset); - releaseObjects(); + + // WARNING: callers of ipcSetDataReference need to make sure they + // don't rely on mObjectsSize in their release_func. mObjectsSize = 0; break; } diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 98f0868bca..9caad451d8 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -83,7 +83,7 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, BINDER_LIB_TEST_GETPID, BINDER_LIB_TEST_ECHO_VECTOR, - BINDER_LIB_TEST_REJECT_BUF, + BINDER_LIB_TEST_REJECT_OBJECTS, }; pid_t start_server_process(int arg2, bool usePoll = false) @@ -1116,14 +1116,53 @@ TEST_F(BinderLibTest, BufRejected) { // And now, overwrite it with the buffer object memcpy(parcelData, &obj, sizeof(obj)); data.setDataSize(sizeof(obj)); + EXPECT_EQ(data.objectsCount(), 1); + + status_t ret = server->transact(BINDER_LIB_TEST_REJECT_OBJECTS, data, &reply); - status_t ret = server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply); // Either the kernel should reject this transaction (if it's correct), but // if it's not, the server implementation should return an error if it // finds an object in the received Parcel. EXPECT_NE(NO_ERROR, ret); } +TEST_F(BinderLibTest, WeakRejected) { + Parcel data, reply; + sp server = addServer(); + ASSERT_TRUE(server != nullptr); + + sp binder = new BBinder(); + wp wpBinder(binder); + flat_binder_object obj{ + .hdr = {.type = BINDER_TYPE_WEAK_BINDER}, + .flags = 0, + .binder = reinterpret_cast(wpBinder.get_refs()), + .cookie = reinterpret_cast(wpBinder.unsafe_get()), + }; + data.setDataCapacity(1024); + // Write a bogus object at offset 0 to get an entry in the offset table + data.writeFileDescriptor(0); + EXPECT_EQ(data.objectsCount(), 1); + uint8_t *parcelData = const_cast(data.data()); + // And now, overwrite it with the weak binder + memcpy(parcelData, &obj, sizeof(obj)); + data.setDataSize(sizeof(obj)); + + // a previous bug caused other objects to be released an extra time, so we + // test with an object that libbinder will actually try to release + EXPECT_EQ(OK, data.writeStrongBinder(new BBinder())); + + EXPECT_EQ(data.objectsCount(), 2); + + // send it many times, since previous error was memory corruption, make it + // more likely that the server crashes + for (size_t i = 0; i < 100; i++) { + EXPECT_EQ(BAD_VALUE, server->transact(BINDER_LIB_TEST_REJECT_OBJECTS, data, &reply)); + } + + EXPECT_EQ(NO_ERROR, server->pingBinder()); +} + class BinderLibTestService : public BBinder { public: @@ -1422,7 +1461,7 @@ class BinderLibTestService : public BBinder reply->writeUint64Vector(vector); return NO_ERROR; } - case BINDER_LIB_TEST_REJECT_BUF: { + case BINDER_LIB_TEST_REJECT_OBJECTS: { return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR; } default: diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index f14cd7a8a5..bacd93e9b1 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -30,6 +30,14 @@ cc_library_headers { min_sdk_version: "29", } +// AIDL files that should be exposed to java +filegroup { + name: "guiconstants_aidl", + srcs: [ + "android/gui/DropInputMode.aidl", + ], +} + cc_defaults { name: "libgui_defaults", @@ -38,6 +46,7 @@ cc_defaults { defaults: ["libgui_bufferqueue-defaults"], srcs: [ + ":guiconstants_aidl", ":framework_native_aidl", ":libgui_bufferqueue_sources", diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e43446ac8c..a76a21c5c4 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -117,6 +117,8 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(frameRate); output.writeByte(frameRateCompatibility); output.writeUint32(fixedTransformHint); + output.writeBool(isTrustedOverlay); + output.writeUint32(static_cast(dropInputMode)); return NO_ERROR; } @@ -200,6 +202,11 @@ status_t layer_state_t::read(const Parcel& input) frameRate = input.readFloat(); frameRateCompatibility = input.readByte(); fixedTransformHint = static_cast(input.readUint32()); + isTrustedOverlay = input.readBool(); + + uint32_t mode; + mode = input.readUint32(); + dropInputMode = static_cast(mode); return NO_ERROR; } @@ -269,6 +276,27 @@ void DisplayState::merge(const DisplayState& other) { } } +void DisplayState::sanitize(bool privileged) { + if (what & DisplayState::eLayerStackChanged) { + if (!privileged) { + what &= ~DisplayState::eLayerStackChanged; + ALOGE("Stripped attempt to set eLayerStackChanged in sanitize"); + } + } + if (what & DisplayState::eDisplayProjectionChanged) { + if (!privileged) { + what &= ~DisplayState::eDisplayProjectionChanged; + ALOGE("Stripped attempt to set eDisplayProjectionChanged in sanitize"); + } + } + if (what & DisplayState::eSurfaceChanged) { + if (!privileged) { + what &= ~DisplayState::eSurfaceChanged; + ALOGE("Stripped attempt to set eSurfaceChanged in sanitize"); + } + } +} + void layer_state_t::merge(const layer_state_t& other) { if (other.what & ePositionChanged) { what |= ePositionChanged; @@ -439,6 +467,14 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; } + if (other.what & eTrustedOverlayChanged) { + what |= eTrustedOverlayChanged; + isTrustedOverlay = other.isTrustedOverlay; + } + if (other.what & eDropInputModeChanged) { + what |= eDropInputModeChanged; + dropInputMode = other.dropInputMode; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 83bc06997a..d2c96218f4 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1484,6 +1484,34 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedOverlay( + const sp& sc, bool isTrustedOverlay) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eTrustedOverlayChanged; + s->isTrustedOverlay = isTrustedOverlay; + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDropInputMode( + const sp& sc, gui::DropInputMode mode) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eDropInputModeChanged; + s->dropInputMode = mode; + + registerSurfaceControlForCallback(sc); + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/android/gui/DropInputMode.aidl b/libs/gui/android/gui/DropInputMode.aidl new file mode 100644 index 0000000000..248a0318b7 --- /dev/null +++ b/libs/gui/android/gui/DropInputMode.aidl @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2022, 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.gui; + + +/** + * Input event drop modes: Input event drop options for windows and its children. + * + * @hide + */ +@Backing(type="int") +enum DropInputMode { + /** + * Default mode, input events are sent to the target as usual. + */ + NONE, + + /** + * Window and its children will not receive any input even if it has a valid input channel. + * Touches and keys will be dropped. If a window is focused, it will remain focused but will + * not receive any keys. If the window has a touchable region and is the target of an input + * event, the event will be dropped and will not go to the window behind. ref: b/197296414 + */ + ALL, +} + diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e60f6777ae..b73bb89791 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -25,6 +25,7 @@ #include #include +#include #ifndef NO_INPUT #include