| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2018 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | #include <gtest/gtest.h> | 
 | 18 | #include <stdlib.h> | 
 | 19 | #include <unistd.h> | 
 | 20 | #include <sys/time.h> | 
 | 21 | #include <sys/types.h> | 
 | 22 | #include <stdio.h> | 
 | 23 | #include <poll.h> | 
 | 24 |  | 
 | 25 | #include <memory> | 
 | 26 |  | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 27 | #include <android/keycodes.h> | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 28 | #include <android/native_window.h> | 
 | 29 |  | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 30 | #include <binder/Binder.h> | 
 | 31 | #include <binder/IServiceManager.h> | 
 | 32 | #include <binder/Parcel.h> | 
 | 33 | #include <binder/ProcessState.h> | 
 | 34 |  | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 35 | #include <gui/ISurfaceComposer.h> | 
 | 36 | #include <gui/Surface.h> | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 37 | #include <gui/SurfaceComposerClient.h> | 
 | 38 | #include <gui/SurfaceControl.h> | 
 | 39 |  | 
| Chris Ye | 0783e99 | 2020-06-02 21:34:49 -0700 | [diff] [blame] | 40 | #include <android/os/IInputFlinger.h> | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 41 | #include <gui/WindowInfo.h> | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 42 | #include <input/Input.h> | 
| Chris Ye | 0783e99 | 2020-06-02 21:34:49 -0700 | [diff] [blame] | 43 | #include <input/InputTransport.h> | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 44 |  | 
| Marin Shalamanov | a7fe304 | 2021-01-29 21:02:08 +0100 | [diff] [blame] | 45 | #include <ui/DisplayMode.h> | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 46 | #include <ui/Rect.h> | 
 | 47 | #include <ui/Region.h> | 
 | 48 |  | 
| Chris Ye | 0783e99 | 2020-06-02 21:34:49 -0700 | [diff] [blame] | 49 | using android::os::IInputFlinger; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 50 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 51 | using android::hardware::graphics::common::V1_1::BufferUsage; | 
 | 52 |  | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 53 | using android::gui::FocusRequest; | 
 | 54 | using android::gui::InputApplicationInfo; | 
 | 55 | using android::gui::TouchOcclusionMode; | 
 | 56 | using android::gui::WindowInfo; | 
 | 57 |  | 
| Vishnu Nair | 958da93 | 2020-08-21 17:12:37 -0700 | [diff] [blame] | 58 | namespace android::test { | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 59 |  | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 60 | using Transaction = SurfaceComposerClient::Transaction; | 
 | 61 |  | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 62 | sp<IInputFlinger> getInputFlinger() { | 
 | 63 |    sp<IBinder> input(defaultServiceManager()->getService( | 
 | 64 |             String16("inputflinger"))); | 
 | 65 |     if (input == nullptr) { | 
 | 66 |         ALOGE("Failed to link to input service"); | 
 | 67 |     } else { ALOGE("Linked to input"); } | 
 | 68 |     return interface_cast<IInputFlinger>(input); | 
 | 69 | } | 
 | 70 |  | 
 | 71 | // We use the top 10 layers as a way to haphazardly place ourselves above anything else. | 
 | 72 | static const int LAYER_BASE = INT32_MAX - 10; | 
| Chris Ye | 6c4243b | 2020-07-22 12:07:12 -0700 | [diff] [blame] | 73 | static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 74 |  | 
 | 75 | class InputSurface { | 
 | 76 | public: | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 77 |     InputSurface(const sp<SurfaceControl> &sc, int width, int height) { | 
 | 78 |         mSurfaceControl = sc; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 79 |  | 
 | 80 |         mInputFlinger = getInputFlinger(); | 
| Garfield Tan | 1560166 | 2020-09-22 15:32:38 -0700 | [diff] [blame] | 81 |         mClientChannel = std::make_shared<InputChannel>(); | 
 | 82 |         mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 83 |  | 
 | 84 |         populateInputInfo(width, height); | 
 | 85 |  | 
 | 86 |         mInputConsumer = new InputConsumer(mClientChannel); | 
 | 87 |     } | 
 | 88 |  | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 89 |     static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient> &scc, | 
 | 90 |                                                                int width, int height) { | 
 | 91 |         sp<SurfaceControl> surfaceControl = | 
 | 92 |                 scc->createSurface(String8("Test Surface"), 0 /* bufHeight */, 0 /* bufWidth */, | 
| Vishnu Nair | fa247b1 | 2020-02-11 08:58:26 -0800 | [diff] [blame] | 93 |                                    PIXEL_FORMAT_RGBA_8888, | 
 | 94 |                                    ISurfaceComposerClient::eFXSurfaceEffect); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 95 |         return std::make_unique<InputSurface>(surfaceControl, width, height); | 
 | 96 |     } | 
 | 97 |  | 
 | 98 |     static std::unique_ptr<InputSurface> makeBufferInputSurface( | 
 | 99 |             const sp<SurfaceComposerClient> &scc, int width, int height) { | 
 | 100 |         sp<SurfaceControl> surfaceControl = | 
 | 101 |                 scc->createSurface(String8("Test Buffer Surface"), width, height, | 
 | 102 |                                    PIXEL_FORMAT_RGBA_8888, 0 /* flags */); | 
 | 103 |         return std::make_unique<InputSurface>(surfaceControl, width, height); | 
 | 104 |     } | 
 | 105 |  | 
 | 106 |     static std::unique_ptr<InputSurface> makeContainerInputSurface( | 
 | 107 |             const sp<SurfaceComposerClient> &scc, int width, int height) { | 
 | 108 |         sp<SurfaceControl> surfaceControl = | 
 | 109 |                 scc->createSurface(String8("Test Container Surface"), 0 /* bufHeight */, | 
 | 110 |                                    0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, | 
 | 111 |                                    ISurfaceComposerClient::eFXSurfaceContainer); | 
 | 112 |         return std::make_unique<InputSurface>(surfaceControl, width, height); | 
 | 113 |     } | 
 | 114 |  | 
| arthurhung | b4a0f85 | 2020-06-16 11:02:50 +0800 | [diff] [blame] | 115 |     static std::unique_ptr<InputSurface> makeCursorInputSurface( | 
 | 116 |             const sp<SurfaceComposerClient> &scc, int width, int height) { | 
 | 117 |         sp<SurfaceControl> surfaceControl = | 
 | 118 |                 scc->createSurface(String8("Test Cursor Surface"), 0 /* bufHeight */, | 
 | 119 |                                    0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, | 
 | 120 |                                    ISurfaceComposerClient::eCursorWindow); | 
 | 121 |         return std::make_unique<InputSurface>(surfaceControl, width, height); | 
 | 122 |     } | 
 | 123 |  | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 124 |     InputEvent *consumeEvent(int timeoutMs = 3000) { | 
 | 125 |         waitForEventAvailable(timeoutMs); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 126 |  | 
 | 127 |         InputEvent *ev; | 
 | 128 |         uint32_t seqId; | 
 | 129 |         status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev); | 
 | 130 |         if (consumed != OK) { | 
 | 131 |             return nullptr; | 
 | 132 |         } | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 133 |         status_t status = mInputConsumer->sendFinishedSignal(seqId, true); | 
 | 134 |         EXPECT_EQ(OK, status) << "Could not send finished signal"; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 135 |         return ev; | 
 | 136 |     } | 
 | 137 |  | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 138 |     void assertFocusChange(bool hasFocus) { | 
 | 139 |         InputEvent *ev = consumeEvent(); | 
 | 140 |         ASSERT_NE(ev, nullptr); | 
 | 141 |         ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, ev->getType()); | 
 | 142 |         FocusEvent *focusEvent = static_cast<FocusEvent *>(ev); | 
 | 143 |         EXPECT_EQ(hasFocus, focusEvent->getHasFocus()); | 
 | 144 |     } | 
 | 145 |  | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 146 |     void expectTap(int x, int y) { | 
 | 147 |         InputEvent* ev = consumeEvent(); | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 148 |         ASSERT_NE(ev, nullptr); | 
 | 149 |         ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 150 |         MotionEvent* mev = static_cast<MotionEvent*>(ev); | 
 | 151 |         EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); | 
 | 152 |         EXPECT_EQ(x, mev->getX(0)); | 
 | 153 |         EXPECT_EQ(y, mev->getY(0)); | 
| arthurhung | b4a0f85 | 2020-06-16 11:02:50 +0800 | [diff] [blame] | 154 |         EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 155 |  | 
 | 156 |         ev = consumeEvent(); | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 157 |         ASSERT_NE(ev, nullptr); | 
 | 158 |         ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 159 |         mev = static_cast<MotionEvent*>(ev); | 
 | 160 |         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); | 
| arthurhung | b4a0f85 | 2020-06-16 11:02:50 +0800 | [diff] [blame] | 161 |         EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 162 |     } | 
 | 163 |  | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 164 |     void expectTapWithFlag(int x, int y, int32_t flags) { | 
 | 165 |         InputEvent *ev = consumeEvent(); | 
 | 166 |         ASSERT_NE(ev, nullptr); | 
 | 167 |         ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); | 
 | 168 |         MotionEvent *mev = static_cast<MotionEvent *>(ev); | 
 | 169 |         EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); | 
 | 170 |         EXPECT_EQ(x, mev->getX(0)); | 
 | 171 |         EXPECT_EQ(y, mev->getY(0)); | 
 | 172 |         EXPECT_EQ(flags, mev->getFlags() & flags); | 
 | 173 |  | 
 | 174 |         ev = consumeEvent(); | 
 | 175 |         ASSERT_NE(ev, nullptr); | 
 | 176 |         ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, ev->getType()); | 
 | 177 |         mev = static_cast<MotionEvent *>(ev); | 
 | 178 |         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); | 
 | 179 |         EXPECT_EQ(flags, mev->getFlags() & flags); | 
 | 180 |     } | 
 | 181 |  | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 182 |     void expectKey(uint32_t keycode) { | 
 | 183 |         InputEvent *ev = consumeEvent(); | 
 | 184 |         ASSERT_NE(ev, nullptr); | 
 | 185 |         ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); | 
 | 186 |         KeyEvent *keyEvent = static_cast<KeyEvent *>(ev); | 
 | 187 |         EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, keyEvent->getAction()); | 
 | 188 |         EXPECT_EQ(keycode, keyEvent->getKeyCode()); | 
 | 189 |         EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); | 
 | 190 |  | 
 | 191 |         ev = consumeEvent(); | 
 | 192 |         ASSERT_NE(ev, nullptr); | 
 | 193 |         ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, ev->getType()); | 
 | 194 |         keyEvent = static_cast<KeyEvent *>(ev); | 
 | 195 |         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, keyEvent->getAction()); | 
 | 196 |         EXPECT_EQ(keycode, keyEvent->getKeyCode()); | 
 | 197 |         EXPECT_EQ(0, keyEvent->getFlags() & VERIFIED_KEY_EVENT_FLAGS); | 
 | 198 |     } | 
 | 199 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 200 |     virtual ~InputSurface() { | 
 | 201 |         mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); | 
 | 202 |     } | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 203 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 204 |     virtual void doTransaction( | 
 | 205 |             std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)> | 
 | 206 |                     transactionBody) { | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 207 |         SurfaceComposerClient::Transaction t; | 
 | 208 |         transactionBody(t, mSurfaceControl); | 
 | 209 |         t.apply(true); | 
 | 210 |     } | 
 | 211 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 212 |     virtual void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) { | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 213 |         SurfaceComposerClient::Transaction t; | 
 | 214 |         t.show(mSurfaceControl); | 
 | 215 |         t.setInputWindowInfo(mSurfaceControl, mInputInfo); | 
 | 216 |         t.setLayer(mSurfaceControl, LAYER_BASE); | 
 | 217 |         t.setPosition(mSurfaceControl, x, y); | 
| chaviw | 2571450 | 2021-02-11 10:01:08 -0800 | [diff] [blame] | 218 |         t.setCrop(mSurfaceControl, crop); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 219 |         t.setAlpha(mSurfaceControl, 1); | 
 | 220 |         t.apply(true); | 
 | 221 |     } | 
 | 222 |  | 
| Vishnu Nair | 958da93 | 2020-08-21 17:12:37 -0700 | [diff] [blame] | 223 |     void requestFocus() { | 
 | 224 |         SurfaceComposerClient::Transaction t; | 
| Vishnu Nair | 9ad0146 | 2021-01-15 12:55:14 -0800 | [diff] [blame] | 225 |         FocusRequest request; | 
 | 226 |         request.token = mInputInfo.token; | 
 | 227 |         request.windowName = mInputInfo.name; | 
 | 228 |         request.focusedToken = nullptr; | 
 | 229 |         request.focusedWindowName = ""; | 
 | 230 |         request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); | 
 | 231 |         request.displayId = 0; | 
 | 232 |         t.setFocusedWindow(request); | 
| Vishnu Nair | 958da93 | 2020-08-21 17:12:37 -0700 | [diff] [blame] | 233 |         t.apply(true); | 
 | 234 |     } | 
 | 235 |  | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 236 | private: | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 237 |     void waitForEventAvailable(int timeoutMs) { | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 238 |         struct pollfd fd; | 
 | 239 |  | 
 | 240 |         fd.fd = mClientChannel->getFd(); | 
 | 241 |         fd.events = POLLIN; | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 242 |         poll(&fd, 1, timeoutMs); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 243 |     } | 
 | 244 |  | 
 | 245 |     void populateInputInfo(int width, int height) { | 
| Garfield Tan | 1560166 | 2020-09-22 15:32:38 -0700 | [diff] [blame] | 246 |         mInputInfo.token = mClientChannel->getConnectionToken(); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 247 |         mInputInfo.name = "Test info"; | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 248 |         mInputInfo.flags = WindowInfo::Flag::NOT_TOUCH_MODAL; | 
 | 249 |         mInputInfo.type = WindowInfo::Type::BASE_APPLICATION; | 
| Siarhei Vishniakou | c1ae556 | 2020-06-30 14:22:57 -0500 | [diff] [blame] | 250 |         mInputInfo.dispatchingTimeout = 5s; | 
| Robert Carr | e07e103 | 2018-11-26 12:55:53 -0800 | [diff] [blame] | 251 |         mInputInfo.globalScaleFactor = 1.0; | 
| Vishnu Nair | 47074b8 | 2020-08-14 11:54:47 -0700 | [diff] [blame] | 252 |         mInputInfo.focusable = true; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 253 |         mInputInfo.hasWallpaper = false; | 
 | 254 |         mInputInfo.paused = false; | 
 | 255 |  | 
 | 256 |         mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); | 
 | 257 |  | 
 | 258 |         // TODO: Fill in from SF? | 
 | 259 |         mInputInfo.ownerPid = 11111; | 
 | 260 |         mInputInfo.ownerUid = 11111; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 261 |         mInputInfo.displayId = 0; | 
| Robert Carr | 740167f | 2018-10-11 19:03:41 -0700 | [diff] [blame] | 262 |  | 
 | 263 |         InputApplicationInfo aInfo; | 
 | 264 |         aInfo.token = new BBinder(); | 
 | 265 |         aInfo.name = "Test app info"; | 
| Siarhei Vishniakou | 7062295 | 2020-07-30 11:17:23 -0500 | [diff] [blame] | 266 |         aInfo.dispatchingTimeoutMillis = | 
 | 267 |                 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count(); | 
| Robert Carr | 740167f | 2018-10-11 19:03:41 -0700 | [diff] [blame] | 268 |  | 
 | 269 |         mInputInfo.applicationInfo = aInfo; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 270 |     } | 
 | 271 | public: | 
 | 272 |     sp<SurfaceControl> mSurfaceControl; | 
| Siarhei Vishniakou | ce5ab08 | 2020-07-09 17:03:21 -0500 | [diff] [blame] | 273 |     std::shared_ptr<InputChannel> mClientChannel; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 274 |     sp<IInputFlinger> mInputFlinger; | 
 | 275 |  | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 276 |     WindowInfo mInputInfo; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 277 |  | 
 | 278 |     PreallocatedInputEventFactory mInputEventFactory; | 
 | 279 |     InputConsumer* mInputConsumer; | 
 | 280 | }; | 
 | 281 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 282 | class BlastInputSurface : public InputSurface { | 
 | 283 | public: | 
 | 284 |     BlastInputSurface(const sp<SurfaceControl> &sc, const sp<SurfaceControl> &parentSc, int width, | 
 | 285 |                       int height) | 
 | 286 |           : InputSurface(sc, width, height) { | 
 | 287 |         mParentSurfaceControl = parentSc; | 
 | 288 |     } | 
 | 289 |  | 
 | 290 |     ~BlastInputSurface() = default; | 
 | 291 |  | 
 | 292 |     static std::unique_ptr<BlastInputSurface> makeBlastInputSurface( | 
 | 293 |             const sp<SurfaceComposerClient> &scc, int width, int height) { | 
 | 294 |         sp<SurfaceControl> parentSc = | 
 | 295 |                 scc->createSurface(String8("Test Parent Surface"), 0 /* bufHeight */, | 
 | 296 |                                    0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888, | 
 | 297 |                                    ISurfaceComposerClient::eFXSurfaceContainer); | 
 | 298 |  | 
 | 299 |         sp<SurfaceControl> surfaceControl = | 
 | 300 |                 scc->createSurface(String8("Test Buffer Surface"), width, height, | 
 | 301 |                                    PIXEL_FORMAT_RGBA_8888, | 
 | 302 |                                    ISurfaceComposerClient::eFXSurfaceBufferState, | 
 | 303 |                                    parentSc->getHandle()); | 
 | 304 |         return std::make_unique<BlastInputSurface>(surfaceControl, parentSc, width, height); | 
 | 305 |     } | 
 | 306 |  | 
 | 307 |     void doTransaction( | 
 | 308 |             std::function<void(SurfaceComposerClient::Transaction &, const sp<SurfaceControl> &)> | 
 | 309 |                     transactionBody) override { | 
 | 310 |         SurfaceComposerClient::Transaction t; | 
 | 311 |         transactionBody(t, mParentSurfaceControl); | 
 | 312 |         t.apply(true); | 
 | 313 |     } | 
 | 314 |  | 
 | 315 |     void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) override { | 
 | 316 |         SurfaceComposerClient::Transaction t; | 
 | 317 |         t.show(mParentSurfaceControl); | 
 | 318 |         t.setLayer(mParentSurfaceControl, LAYER_BASE); | 
 | 319 |         t.setPosition(mParentSurfaceControl, x, y); | 
 | 320 |         t.setCrop(mParentSurfaceControl, crop); | 
 | 321 |  | 
 | 322 |         t.show(mSurfaceControl); | 
 | 323 |         t.setInputWindowInfo(mSurfaceControl, mInputInfo); | 
 | 324 |         t.setCrop(mSurfaceControl, crop); | 
 | 325 |         t.setAlpha(mSurfaceControl, 1); | 
 | 326 |         t.apply(true); | 
 | 327 |     } | 
 | 328 |  | 
 | 329 | private: | 
 | 330 |     sp<SurfaceControl> mParentSurfaceControl; | 
 | 331 | }; | 
 | 332 |  | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 333 | class InputSurfacesTest : public ::testing::Test { | 
 | 334 | public: | 
 | 335 |     InputSurfacesTest() { | 
 | 336 |         ProcessState::self()->startThreadPool(); | 
 | 337 |     } | 
 | 338 |  | 
 | 339 |     void SetUp() { | 
 | 340 |         mComposerClient = new SurfaceComposerClient; | 
 | 341 |         ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 342 |  | 
| Dominik Laskowski | dcb38bb | 2019-01-25 02:35:50 -0800 | [diff] [blame] | 343 |         const auto display = mComposerClient->getInternalDisplayToken(); | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 344 |         ASSERT_NE(display, nullptr); | 
| Dominik Laskowski | dcb38bb | 2019-01-25 02:35:50 -0800 | [diff] [blame] | 345 |  | 
| Marin Shalamanov | a7fe304 | 2021-01-29 21:02:08 +0100 | [diff] [blame] | 346 |         ui::DisplayMode mode; | 
 | 347 |         ASSERT_EQ(NO_ERROR, mComposerClient->getActiveDisplayMode(display, &mode)); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 348 |  | 
 | 349 |         // After a new buffer is queued, SurfaceFlinger is notified and will | 
 | 350 |         // latch the new buffer on next vsync.  Let's heuristically wait for 3 | 
 | 351 |         // vsyncs. | 
| Marin Shalamanov | a7fe304 | 2021-01-29 21:02:08 +0100 | [diff] [blame] | 352 |         mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 353 |     } | 
 | 354 |  | 
 | 355 |     void TearDown() { | 
 | 356 |         mComposerClient->dispose(); | 
 | 357 |     } | 
 | 358 |  | 
 | 359 |     std::unique_ptr<InputSurface> makeSurface(int width, int height) { | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 360 |         return InputSurface::makeColorInputSurface(mComposerClient, width, height); | 
 | 361 |     } | 
 | 362 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 363 |     void postBuffer(const sp<SurfaceControl> &layer, int32_t w, int32_t h) { | 
 | 364 |         int64_t usageFlags = BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | | 
 | 365 |                 BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE; | 
 | 366 |         sp<GraphicBuffer> buffer = | 
 | 367 |                 new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888, 1, usageFlags, "test"); | 
 | 368 |         Transaction().setBuffer(layer, buffer).apply(true); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 369 |         usleep(mBufferPostDelay); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 370 |     } | 
 | 371 |  | 
 | 372 |     sp<SurfaceComposerClient> mComposerClient; | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 373 |     int32_t mBufferPostDelay; | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 374 | }; | 
 | 375 |  | 
 | 376 | void injectTap(int x, int y) { | 
 | 377 |     char *buf1, *buf2; | 
 | 378 |     asprintf(&buf1, "%d", x); | 
 | 379 |     asprintf(&buf2, "%d", y); | 
 | 380 |     if (fork() == 0) { | 
 | 381 |         execlp("input", "input", "tap", buf1, buf2, NULL); | 
 | 382 |     } | 
 | 383 | } | 
 | 384 |  | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 385 | void injectKey(uint32_t keycode) { | 
 | 386 |     char *buf1; | 
 | 387 |     asprintf(&buf1, "%d", keycode); | 
 | 388 |     if (fork() == 0) { | 
 | 389 |         execlp("input", "input", "keyevent", buf1, NULL); | 
 | 390 |     } | 
 | 391 | } | 
 | 392 |  | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 393 | TEST_F(InputSurfacesTest, can_receive_input) { | 
 | 394 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 395 |     surface->showAt(100, 100); | 
 | 396 |  | 
 | 397 |     injectTap(101, 101); | 
 | 398 |  | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 399 |     EXPECT_NE(surface->consumeEvent(), nullptr); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 400 | } | 
 | 401 |  | 
| Siarhei Vishniakou | f1035d4 | 2019-09-20 16:32:01 +0100 | [diff] [blame] | 402 | /** | 
 | 403 |  * Set up two surfaces side-by-side. Tap each surface. | 
 | 404 |  * Next, swap the positions of the two surfaces. Inject tap into the two | 
 | 405 |  * original locations. Ensure that the tap is received by the surfaces in the | 
 | 406 |  * reverse order. | 
 | 407 |  */ | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 408 | TEST_F(InputSurfacesTest, input_respects_positioning) { | 
 | 409 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 410 |     surface->showAt(100, 100); | 
 | 411 |  | 
 | 412 |     std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100); | 
 | 413 |     surface2->showAt(200, 200); | 
 | 414 |  | 
 | 415 |     injectTap(201, 201); | 
 | 416 |     surface2->expectTap(1, 1); | 
 | 417 |  | 
 | 418 |     injectTap(101, 101); | 
 | 419 |     surface->expectTap(1, 1); | 
 | 420 |  | 
 | 421 |     surface2->doTransaction([](auto &t, auto &sc) { | 
 | 422 |          t.setPosition(sc, 100, 100); | 
 | 423 |     }); | 
 | 424 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 425 |          t.setPosition(sc, 200, 200); | 
 | 426 |     }); | 
 | 427 |  | 
 | 428 |     injectTap(101, 101); | 
 | 429 |     surface2->expectTap(1, 1); | 
 | 430 |  | 
 | 431 |     injectTap(201, 201); | 
 | 432 |     surface->expectTap(1, 1); | 
 | 433 | } | 
 | 434 |  | 
 | 435 | TEST_F(InputSurfacesTest, input_respects_layering) { | 
 | 436 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 437 |     std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100); | 
 | 438 |  | 
 | 439 |     surface->showAt(10, 10); | 
 | 440 |     surface2->showAt(10, 10); | 
 | 441 |  | 
 | 442 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 443 |          t.setLayer(sc, LAYER_BASE + 1); | 
 | 444 |     }); | 
 | 445 |  | 
 | 446 |     injectTap(11, 11); | 
 | 447 |     surface->expectTap(1, 1); | 
 | 448 |  | 
 | 449 |     surface2->doTransaction([](auto &t, auto &sc) { | 
 | 450 |          t.setLayer(sc, LAYER_BASE + 1); | 
 | 451 |     }); | 
 | 452 |  | 
 | 453 |     injectTap(11, 11); | 
 | 454 |     surface2->expectTap(1, 1); | 
 | 455 |  | 
 | 456 |     surface2->doTransaction([](auto &t, auto &sc) { | 
 | 457 |          t.hide(sc); | 
 | 458 |     }); | 
 | 459 |  | 
 | 460 |     injectTap(11, 11); | 
 | 461 |     surface->expectTap(1, 1); | 
 | 462 | } | 
 | 463 |  | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 464 | // Surface Insets are set to offset the client content and draw a border around the client surface | 
 | 465 | // (such as shadows in dialogs). Inputs sent to the client are offset such that 0,0 is the start | 
 | 466 | // of the client content. | 
 | 467 | TEST_F(InputSurfacesTest, input_respects_surface_insets) { | 
 | 468 |     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); | 
 | 469 |     std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); | 
 | 470 |     bgSurface->showAt(100, 100); | 
 | 471 |  | 
 | 472 |     fgSurface->mInputInfo.surfaceInset = 5; | 
 | 473 |     fgSurface->showAt(100, 100); | 
 | 474 |  | 
 | 475 |     injectTap(106, 106); | 
 | 476 |     fgSurface->expectTap(1, 1); | 
 | 477 |  | 
 | 478 |     injectTap(101, 101); | 
 | 479 |     bgSurface->expectTap(1, 1); | 
 | 480 | } | 
 | 481 |  | 
 | 482 | // Ensure a surface whose insets are cropped, handles the touch offset correctly. ref:b/120413463 | 
 | 483 | TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { | 
 | 484 |     std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); | 
 | 485 |     std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100); | 
 | 486 |     parentSurface->showAt(100, 100); | 
 | 487 |  | 
 | 488 |     childSurface->mInputInfo.surfaceInset = 10; | 
 | 489 |     childSurface->showAt(100, 100); | 
 | 490 |  | 
 | 491 |     childSurface->doTransaction([&](auto &t, auto &sc) { | 
 | 492 |         t.setPosition(sc, -5, -5); | 
| Pablo Gamito | 11dcc22 | 2020-09-12 15:49:39 +0000 | [diff] [blame] | 493 |         t.reparent(sc, parentSurface->mSurfaceControl); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 494 |     }); | 
 | 495 |  | 
 | 496 |     injectTap(106, 106); | 
 | 497 |     childSurface->expectTap(1, 1); | 
 | 498 |  | 
 | 499 |     injectTap(101, 101); | 
 | 500 |     parentSurface->expectTap(1, 1); | 
 | 501 | } | 
 | 502 |  | 
| Arthur Hung | 118b114 | 2019-05-08 21:25:59 +0800 | [diff] [blame] | 503 | // Ensure a surface whose insets are scaled, handles the touch offset correctly. | 
 | 504 | TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { | 
 | 505 |     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); | 
 | 506 |     std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); | 
 | 507 |     bgSurface->showAt(100, 100); | 
 | 508 |  | 
 | 509 |     fgSurface->mInputInfo.surfaceInset = 5; | 
 | 510 |     fgSurface->showAt(100, 100); | 
 | 511 |  | 
 | 512 |     fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); | 
 | 513 |  | 
 | 514 |     // expect = touch / scale - inset | 
 | 515 |     injectTap(112, 124); | 
 | 516 |     fgSurface->expectTap(1, 1); | 
 | 517 |  | 
 | 518 |     injectTap(101, 101); | 
 | 519 |     bgSurface->expectTap(1, 1); | 
 | 520 | } | 
 | 521 |  | 
| Ady Abraham | 282f1d7 | 2019-07-24 18:05:56 -0700 | [diff] [blame] | 522 | TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { | 
 | 523 |     std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); | 
 | 524 |     // In case we pass the very big inset without any checking. | 
 | 525 |     fgSurface->mInputInfo.surfaceInset = INT32_MAX; | 
 | 526 |     fgSurface->showAt(100, 100); | 
 | 527 |  | 
 | 528 |     fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); | 
 | 529 |  | 
 | 530 |     // expect no crash for overflow, and inset size to be clamped to surface size | 
 | 531 |     injectTap(202, 202); | 
 | 532 |     fgSurface->expectTap(1, 1); | 
 | 533 | } | 
 | 534 |  | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 535 | // Ensure we ignore transparent region when getting screen bounds when positioning input frame. | 
 | 536 | TEST_F(InputSurfacesTest, input_ignores_transparent_region) { | 
 | 537 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 538 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 539 |         Region transparentRegion(Rect(0, 0, 10, 10)); | 
 | 540 |         t.setTransparentRegionHint(sc, transparentRegion); | 
 | 541 |     }); | 
 | 542 |     surface->showAt(100, 100); | 
 | 543 |     injectTap(101, 101); | 
 | 544 |     surface->expectTap(1, 1); | 
 | 545 | } | 
 | 546 |  | 
| Vishnu Nair | f8678ba | 2019-10-11 18:11:26 -0700 | [diff] [blame] | 547 | // TODO(b/139494112) update tests once we define expected behavior | 
 | 548 | // Ensure we still send input to the surface regardless of surface visibility changes due to the | 
 | 549 | // first buffer being submitted or alpha changes. | 
 | 550 | // Original bug ref: b/120839715 | 
 | 551 | TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) { | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 552 |     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 553 |     std::unique_ptr<BlastInputSurface> bufferSurface = | 
 | 554 |             BlastInputSurface::makeBlastInputSurface(mComposerClient, 100, 100); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 555 |  | 
 | 556 |     bgSurface->showAt(10, 10); | 
 | 557 |     bufferSurface->showAt(10, 10); | 
 | 558 |  | 
 | 559 |     injectTap(11, 11); | 
| Vishnu Nair | f8678ba | 2019-10-11 18:11:26 -0700 | [diff] [blame] | 560 |     bufferSurface->expectTap(1, 1); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 561 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 562 |     postBuffer(bufferSurface->mSurfaceControl, 100, 100); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 563 |     injectTap(11, 11); | 
 | 564 |     bufferSurface->expectTap(1, 1); | 
 | 565 | } | 
 | 566 |  | 
| Vishnu Nair | f8678ba | 2019-10-11 18:11:26 -0700 | [diff] [blame] | 567 | TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) { | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 568 |     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 569 |     std::unique_ptr<BlastInputSurface> bufferSurface = | 
 | 570 |             BlastInputSurface::makeBlastInputSurface(mComposerClient, 100, 100); | 
 | 571 |     postBuffer(bufferSurface->mSurfaceControl, 100, 100); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 572 |  | 
 | 573 |     bgSurface->showAt(10, 10); | 
 | 574 |     bufferSurface->showAt(10, 10); | 
 | 575 |  | 
 | 576 |     injectTap(11, 11); | 
 | 577 |     bufferSurface->expectTap(1, 1); | 
 | 578 |  | 
 | 579 |     bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); }); | 
 | 580 |  | 
 | 581 |     injectTap(11, 11); | 
| Vishnu Nair | f8678ba | 2019-10-11 18:11:26 -0700 | [diff] [blame] | 582 |     bufferSurface->expectTap(1, 1); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 583 | } | 
 | 584 |  | 
| Vishnu Nair | f8678ba | 2019-10-11 18:11:26 -0700 | [diff] [blame] | 585 | TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) { | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 586 |     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); | 
 | 587 |     std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); | 
 | 588 |  | 
 | 589 |     bgSurface->showAt(10, 10); | 
 | 590 |     fgSurface->showAt(10, 10); | 
 | 591 |  | 
 | 592 |     injectTap(11, 11); | 
 | 593 |     fgSurface->expectTap(1, 1); | 
 | 594 |  | 
 | 595 |     fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); }); | 
 | 596 |  | 
 | 597 |     injectTap(11, 11); | 
| Vishnu Nair | f8678ba | 2019-10-11 18:11:26 -0700 | [diff] [blame] | 598 |     fgSurface->expectTap(1, 1); | 
| Vishnu Nair | de19f85 | 2018-12-18 16:11:53 -0800 | [diff] [blame] | 599 | } | 
 | 600 |  | 
 | 601 | TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { | 
 | 602 |     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); | 
 | 603 |     std::unique_ptr<InputSurface> containerSurface = | 
 | 604 |             InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); | 
 | 605 |  | 
 | 606 |     bgSurface->showAt(10, 10); | 
 | 607 |     containerSurface->showAt(10, 10); | 
 | 608 |  | 
 | 609 |     injectTap(11, 11); | 
 | 610 |     containerSurface->expectTap(1, 1); | 
 | 611 |  | 
 | 612 |     containerSurface->doTransaction([](auto &t, auto &sc) { t.hide(sc); }); | 
 | 613 |  | 
 | 614 |     injectTap(11, 11); | 
 | 615 |     bgSurface->expectTap(1, 1); | 
 | 616 | } | 
| chaviw | fbe5d9c | 2018-12-26 12:23:37 -0800 | [diff] [blame] | 617 |  | 
| Arthur Hung | d20b270 | 2019-01-14 18:16:16 +0800 | [diff] [blame] | 618 | TEST_F(InputSurfacesTest, input_respects_outscreen) { | 
 | 619 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 620 |     surface->showAt(-1, -1); | 
 | 621 |  | 
 | 622 |     injectTap(0, 0); | 
 | 623 |     surface->expectTap(1, 1); | 
 | 624 | } | 
| arthurhung | b4a0f85 | 2020-06-16 11:02:50 +0800 | [diff] [blame] | 625 |  | 
 | 626 | TEST_F(InputSurfacesTest, input_ignores_cursor_layer) { | 
 | 627 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 628 |     std::unique_ptr<InputSurface> cursorSurface = | 
 | 629 |             InputSurface::makeCursorInputSurface(mComposerClient, 10, 10); | 
 | 630 |  | 
 | 631 |     surface->showAt(10, 10); | 
| arthurhung | b4a0f85 | 2020-06-16 11:02:50 +0800 | [diff] [blame] | 632 |     cursorSurface->showAt(10, 10); | 
 | 633 |  | 
 | 634 |     injectTap(11, 11); | 
 | 635 |     surface->expectTap(1, 1); | 
 | 636 | } | 
| Vishnu Nair | 958da93 | 2020-08-21 17:12:37 -0700 | [diff] [blame] | 637 |  | 
 | 638 | TEST_F(InputSurfacesTest, can_be_focused) { | 
 | 639 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 640 |     surface->showAt(100, 100); | 
 | 641 |     surface->requestFocus(); | 
 | 642 |  | 
 | 643 |     surface->assertFocusChange(true); | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 644 |  | 
 | 645 |     injectKey(AKEYCODE_V); | 
 | 646 |     surface->expectKey(AKEYCODE_V); | 
| Robert Carr | 1c4c559 | 2018-09-24 13:18:43 -0700 | [diff] [blame] | 647 | } | 
| chaviw | 44a6d2b | 2020-09-08 17:14:16 -0700 | [diff] [blame] | 648 |  | 
 | 649 | TEST_F(InputSurfacesTest, rotate_surface) { | 
 | 650 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 651 |     surface->showAt(10, 10); | 
 | 652 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 653 |         t.setMatrix(sc, 0, 1, -1, 0); // 90 degrees | 
 | 654 |     }); | 
 | 655 |     injectTap(8, 11); | 
 | 656 |     surface->expectTap(1, 2); | 
 | 657 |  | 
 | 658 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 659 |         t.setMatrix(sc, -1, 0, 0, -1); // 180 degrees | 
 | 660 |     }); | 
 | 661 |     injectTap(9, 8); | 
 | 662 |     surface->expectTap(1, 2); | 
 | 663 |  | 
 | 664 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 665 |         t.setMatrix(sc, 0, -1, 1, 0); // 270 degrees | 
 | 666 |     }); | 
 | 667 |     injectTap(12, 9); | 
 | 668 |     surface->expectTap(1, 2); | 
 | 669 | } | 
 | 670 |  | 
 | 671 | TEST_F(InputSurfacesTest, rotate_surface_with_scale) { | 
 | 672 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 673 |     surface->showAt(10, 10); | 
 | 674 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 675 |         t.setMatrix(sc, 0, 2, -4, 0); // 90 degrees | 
 | 676 |     }); | 
 | 677 |     injectTap(2, 12); | 
 | 678 |     surface->expectTap(1, 2); | 
 | 679 |  | 
 | 680 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 681 |         t.setMatrix(sc, -2, 0, 0, -4); // 180 degrees | 
 | 682 |     }); | 
 | 683 |     injectTap(8, 2); | 
 | 684 |     surface->expectTap(1, 2); | 
 | 685 |  | 
 | 686 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 687 |         t.setMatrix(sc, 0, -2, 4, 0); // 270 degrees | 
 | 688 |     }); | 
 | 689 |     injectTap(18, 8); | 
 | 690 |     surface->expectTap(1, 2); | 
 | 691 | } | 
 | 692 |  | 
 | 693 | TEST_F(InputSurfacesTest, rotate_surface_with_scale_and_insets) { | 
 | 694 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 695 |     surface->mInputInfo.surfaceInset = 5; | 
 | 696 |     surface->showAt(100, 100); | 
 | 697 |  | 
 | 698 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 699 |         t.setMatrix(sc, 0, 2, -4, 0); // 90 degrees | 
 | 700 |     }); | 
 | 701 |     injectTap(40, 120); | 
 | 702 |     surface->expectTap(5, 10); | 
 | 703 |  | 
 | 704 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 705 |         t.setMatrix(sc, -2, 0, 0, -4); // 180 degrees | 
 | 706 |     }); | 
 | 707 |     injectTap(80, 40); | 
 | 708 |     surface->expectTap(5, 10); | 
 | 709 |  | 
 | 710 |     surface->doTransaction([](auto &t, auto &sc) { | 
 | 711 |         t.setMatrix(sc, 0, -2, 4, 0); // 270 degrees | 
 | 712 |     }); | 
 | 713 |     injectTap(160, 80); | 
 | 714 |     surface->expectTap(5, 10); | 
 | 715 | } | 
 | 716 |  | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 717 | TEST_F(InputSurfacesTest, touch_flag_obscured) { | 
 | 718 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 719 |     surface->showAt(100, 100); | 
 | 720 |  | 
 | 721 |     // Add non touchable window to fully cover touchable window. Window behind gets touch, but | 
 | 722 |     // with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | 
 | 723 |     std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 724 |     nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 725 |     nonTouchableSurface->mInputInfo.ownerUid = 22222; | 
| Bernardo Rufino | 602ef71 | 2020-12-21 11:02:18 +0000 | [diff] [blame] | 726 |     // Overriding occlusion mode otherwise the touch would be discarded at InputDispatcher by | 
 | 727 |     // the default obscured/untrusted touch filter introduced in S. | 
 | 728 |     nonTouchableSurface->mInputInfo.touchOcclusionMode = TouchOcclusionMode::ALLOW; | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 729 |     nonTouchableSurface->showAt(100, 100); | 
 | 730 |  | 
 | 731 |     injectTap(190, 199); | 
 | 732 |     surface->expectTapWithFlag(90, 99, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED); | 
 | 733 | } | 
 | 734 |  | 
 | 735 | TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) { | 
 | 736 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 737 |     surface->showAt(100, 100); | 
 | 738 |  | 
 | 739 |     // Add non touchable window to cover touchable window, but parent is cropped to not cover area | 
 | 740 |     // that will be tapped. Window behind gets touch, but with flag | 
 | 741 |     // AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED | 
 | 742 |     std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); | 
 | 743 |     std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 744 |     nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
 | 745 |     parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 746 |     nonTouchableSurface->mInputInfo.ownerUid = 22222; | 
 | 747 |     parentSurface->mInputInfo.ownerUid = 22222; | 
 | 748 |     nonTouchableSurface->showAt(0, 0); | 
 | 749 |     parentSurface->showAt(100, 100); | 
 | 750 |  | 
 | 751 |     nonTouchableSurface->doTransaction([&](auto &t, auto &sc) { | 
| chaviw | 2571450 | 2021-02-11 10:01:08 -0800 | [diff] [blame] | 752 |         t.setCrop(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50)); | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 753 |         t.reparent(sc, parentSurface->mSurfaceControl); | 
 | 754 |     }); | 
 | 755 |  | 
 | 756 |     injectTap(190, 199); | 
 | 757 |     surface->expectTapWithFlag(90, 99, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); | 
 | 758 | } | 
 | 759 |  | 
 | 760 | TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) { | 
 | 761 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 762 |     surface->showAt(100, 100); | 
 | 763 |  | 
 | 764 |     // Add non touchable window to cover touchable window, but parent is cropped to avoid covering | 
 | 765 |     // the touchable window. Window behind gets touch with no obscured flags. | 
 | 766 |     std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); | 
 | 767 |     std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 768 |     nonTouchableSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
 | 769 |     parentSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 770 |     nonTouchableSurface->mInputInfo.ownerUid = 22222; | 
 | 771 |     parentSurface->mInputInfo.ownerUid = 22222; | 
 | 772 |     nonTouchableSurface->showAt(0, 0); | 
 | 773 |     parentSurface->showAt(50, 50); | 
 | 774 |  | 
 | 775 |     nonTouchableSurface->doTransaction([&](auto &t, auto &sc) { | 
| chaviw | 2571450 | 2021-02-11 10:01:08 -0800 | [diff] [blame] | 776 |         t.setCrop(parentSurface->mSurfaceControl, Rect(0, 0, 50, 50)); | 
| chaviw | 39cfa2e | 2020-11-04 14:19:02 -0800 | [diff] [blame] | 777 |         t.reparent(sc, parentSurface->mSurfaceControl); | 
 | 778 |     }); | 
 | 779 |  | 
 | 780 |     injectTap(101, 110); | 
 | 781 |     surface->expectTap(1, 10); | 
 | 782 | } | 
 | 783 |  | 
| chaviw | 7e72caf | 2020-12-02 16:50:43 -0800 | [diff] [blame] | 784 | TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_bql) { | 
 | 785 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 786 |  | 
 | 787 |     std::unique_ptr<InputSurface> bufferSurface = | 
 | 788 |             InputSurface::makeBufferInputSurface(mComposerClient, 0, 0); | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 789 |     bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
| chaviw | 7e72caf | 2020-12-02 16:50:43 -0800 | [diff] [blame] | 790 |     bufferSurface->mInputInfo.ownerUid = 22222; | 
 | 791 |  | 
 | 792 |     surface->showAt(10, 10); | 
 | 793 |     bufferSurface->showAt(50, 50, Rect::EMPTY_RECT); | 
 | 794 |  | 
 | 795 |     injectTap(11, 11); | 
 | 796 |     surface->expectTap(1, 1); | 
 | 797 | } | 
 | 798 |  | 
 | 799 | TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) { | 
 | 800 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 801 |  | 
| chaviw | 39d0147 | 2021-04-08 14:26:24 -0500 | [diff] [blame] | 802 |     std::unique_ptr<BlastInputSurface> bufferSurface = | 
 | 803 |             BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); | 
| chaviw | 3277faf | 2021-05-19 16:45:23 -0500 | [diff] [blame] | 804 |     bufferSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
| chaviw | 7e72caf | 2020-12-02 16:50:43 -0800 | [diff] [blame] | 805 |     bufferSurface->mInputInfo.ownerUid = 22222; | 
 | 806 |  | 
 | 807 |     surface->showAt(10, 10); | 
 | 808 |     bufferSurface->showAt(50, 50, Rect::EMPTY_RECT); | 
 | 809 |  | 
 | 810 |     injectTap(11, 11); | 
 | 811 |     surface->expectTap(1, 1); | 
 | 812 | } | 
 | 813 |  | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 814 | TEST_F(InputSurfacesTest, strict_unobscured_input_unobscured_window) { | 
 | 815 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 816 |     surface->doTransaction( | 
 | 817 |             [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); | 
 | 818 |     surface->showAt(100, 100); | 
 | 819 |  | 
 | 820 |     injectTap(101, 101); | 
 | 821 |  | 
 | 822 |     EXPECT_NE(surface->consumeEvent(), nullptr); | 
 | 823 |     EXPECT_NE(surface->consumeEvent(), nullptr); | 
 | 824 |  | 
 | 825 |     surface->requestFocus(); | 
 | 826 |     surface->assertFocusChange(true); | 
 | 827 |     injectKey(AKEYCODE_V); | 
 | 828 |     surface->expectKey(AKEYCODE_V); | 
 | 829 | } | 
 | 830 |  | 
 | 831 | TEST_F(InputSurfacesTest, strict_unobscured_input_scaled_without_crop_window) { | 
 | 832 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 833 |     surface->doTransaction([&](auto &t, auto &sc) { | 
 | 834 |         t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); | 
 | 835 |         t.setMatrix(sc, 2.0, 0, 0, 2.0); | 
 | 836 |     }); | 
 | 837 |     surface->showAt(100, 100); | 
 | 838 |  | 
 | 839 |     injectTap(101, 101); | 
 | 840 |  | 
 | 841 |     EXPECT_NE(surface->consumeEvent(), nullptr); | 
 | 842 |     EXPECT_NE(surface->consumeEvent(), nullptr); | 
 | 843 |  | 
 | 844 |     surface->requestFocus(); | 
 | 845 |     surface->assertFocusChange(true); | 
 | 846 |     injectKey(AKEYCODE_V); | 
 | 847 |     surface->expectKey(AKEYCODE_V); | 
 | 848 | } | 
 | 849 |  | 
 | 850 | TEST_F(InputSurfacesTest, strict_unobscured_input_obscured_window) { | 
 | 851 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 852 |     surface->mInputInfo.ownerUid = 11111; | 
 | 853 |     surface->doTransaction( | 
 | 854 |             [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); | 
 | 855 |     surface->showAt(100, 100); | 
 | 856 |     std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); | 
 | 857 |     obscuringSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
 | 858 |     obscuringSurface->mInputInfo.ownerUid = 22222; | 
 | 859 |     obscuringSurface->showAt(100, 100); | 
 | 860 |     injectTap(101, 101); | 
 | 861 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 862 |  | 
 | 863 |     surface->requestFocus(); | 
 | 864 |     surface->assertFocusChange(true); | 
 | 865 |     injectKey(AKEYCODE_V); | 
 | 866 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 867 | } | 
 | 868 |  | 
 | 869 | TEST_F(InputSurfacesTest, strict_unobscured_input_partially_obscured_window) { | 
 | 870 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 871 |     surface->mInputInfo.ownerUid = 11111; | 
 | 872 |     surface->doTransaction( | 
 | 873 |             [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); | 
 | 874 |     surface->showAt(100, 100); | 
 | 875 |     std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); | 
 | 876 |     obscuringSurface->mInputInfo.flags = WindowInfo::Flag::NOT_TOUCHABLE; | 
 | 877 |     obscuringSurface->mInputInfo.ownerUid = 22222; | 
 | 878 |     obscuringSurface->showAt(190, 190); | 
 | 879 |  | 
 | 880 |     injectTap(101, 101); | 
 | 881 |  | 
 | 882 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 883 |  | 
 | 884 |     surface->requestFocus(); | 
 | 885 |     surface->assertFocusChange(true); | 
 | 886 |     injectKey(AKEYCODE_V); | 
 | 887 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 888 | } | 
 | 889 |  | 
 | 890 | TEST_F(InputSurfacesTest, strict_unobscured_input_alpha_window) { | 
 | 891 |     std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300); | 
 | 892 |     parentSurface->showAt(0, 0, Rect(0, 0, 300, 300)); | 
 | 893 |  | 
 | 894 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 895 |     surface->showAt(100, 100); | 
 | 896 |     surface->doTransaction([&](auto &t, auto &sc) { | 
 | 897 |         t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); | 
 | 898 |         t.reparent(sc, parentSurface->mSurfaceControl); | 
 | 899 |         t.setAlpha(parentSurface->mSurfaceControl, 0.9f); | 
 | 900 |     }); | 
 | 901 |  | 
 | 902 |     injectTap(101, 101); | 
 | 903 |  | 
 | 904 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 905 |  | 
 | 906 |     surface->requestFocus(); | 
 | 907 |     surface->assertFocusChange(true); | 
 | 908 |     injectKey(AKEYCODE_V); | 
 | 909 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 910 | } | 
 | 911 |  | 
 | 912 | TEST_F(InputSurfacesTest, strict_unobscured_input_cropped_window) { | 
 | 913 |     std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300); | 
 | 914 |     parentSurface->showAt(0, 0, Rect(0, 0, 300, 300)); | 
 | 915 |  | 
 | 916 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 917 |     surface->doTransaction([&](auto &t, auto &sc) { | 
 | 918 |         t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); | 
 | 919 |         t.reparent(sc, parentSurface->mSurfaceControl); | 
 | 920 |         t.setCrop(parentSurface->mSurfaceControl, Rect(10, 10, 100, 100)); | 
 | 921 |     }); | 
 | 922 |     surface->showAt(100, 100); | 
 | 923 |  | 
 | 924 |     injectTap(111, 111); | 
 | 925 |  | 
 | 926 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 927 |  | 
 | 928 |     surface->requestFocus(); | 
 | 929 |     surface->assertFocusChange(true); | 
 | 930 |     injectKey(AKEYCODE_V); | 
 | 931 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 932 | } | 
 | 933 |  | 
| Arthur Hung | 49d525a | 2021-11-19 15:11:51 +0000 | [diff] [blame] | 934 | TEST_F(InputSurfacesTest, ignore_touch_region_with_zero_sized_blast) { | 
 | 935 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 936 |  | 
 | 937 |     std::unique_ptr<BlastInputSurface> bufferSurface = | 
 | 938 |             BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); | 
 | 939 |  | 
 | 940 |     surface->showAt(100, 100); | 
 | 941 |     bufferSurface->mInputInfo.touchableRegion.orSelf(Rect(0, 0, 200, 200)); | 
 | 942 |     bufferSurface->showAt(100, 100, Rect::EMPTY_RECT); | 
 | 943 |  | 
 | 944 |     injectTap(101, 101); | 
 | 945 |     surface->expectTap(1, 1); | 
 | 946 | } | 
 | 947 |  | 
| Vishnu Nair | fb06059 | 2021-09-13 18:40:17 -0700 | [diff] [blame] | 948 | TEST_F(InputSurfacesTest, drop_input_policy) { | 
 | 949 |     std::unique_ptr<InputSurface> surface = makeSurface(100, 100); | 
 | 950 |     surface->doTransaction( | 
 | 951 |             [&](auto &t, auto &sc) { t.setDropInputMode(sc, gui::DropInputMode::ALL); }); | 
 | 952 |     surface->showAt(100, 100); | 
 | 953 |  | 
 | 954 |     injectTap(101, 101); | 
 | 955 |  | 
 | 956 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 957 |  | 
 | 958 |     surface->requestFocus(); | 
 | 959 |     surface->assertFocusChange(true); | 
 | 960 |     injectKey(AKEYCODE_V); | 
 | 961 |     EXPECT_EQ(surface->consumeEvent(100), nullptr); | 
 | 962 | } | 
| Vishnu Nair | 958da93 | 2020-08-21 17:12:37 -0700 | [diff] [blame] | 963 | } // namespace android::test |