Merge changes I0332cc46,I5f8c7737
* changes:
Fix dump of active config
SF: In dumpsys add head row for "Allocated buffers" table
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index 2618906..b1bc6dc 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -130,7 +130,7 @@
}
IPCThreadState::self()->setTheContextObject(manager);
- ps->becomeContextManager(nullptr, nullptr);
+ ps->becomeContextManager();
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 6efa4f7..5f74682 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -65,6 +65,10 @@
* another process. File descriptors may also be sent to other processes over a Unix domain
* socket with sendmsg and SCM_RIGHTS. See sendmsg(3) and cmsg(3) man pages for more information.
*
+ * If you intend to share this file descriptor with a child process after
+ * calling exec(3), note that you will need to use fcntl(2) with FD_SETFD
+ * to clear the FD_CLOEXEC flag for this to work on all versions of Android.
+ *
* Available since API level 26.
*
* \param name an optional name.
diff --git a/include/attestation/HmacKeyManager.h b/include/attestation/HmacKeyManager.h
new file mode 100644
index 0000000..571a361
--- /dev/null
+++ b/include/attestation/HmacKeyManager.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <array>
+
+namespace android {
+/**
+ * Invalid value of HMAC - SHA256. Any events with this HMAC value will be marked as not verified.
+ */
+constexpr std::array<uint8_t, 32> INVALID_HMAC = {0};
+
+class HmacKeyManager {
+public:
+ HmacKeyManager();
+ std::array<uint8_t, 32> sign(const uint8_t* data, size_t size) const;
+private:
+ const std::array<uint8_t, 128> mHmacKey;
+};
+} // namespace android
\ No newline at end of file
diff --git a/include/input/Input.h b/include/input/Input.h
index d40ba43..7b66d3c 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -312,11 +312,6 @@
*/
constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<float>::quiet_NaN();
-/**
- * Invalid value of HMAC - SHA256. Any events with this HMAC value will be marked as not verified.
- */
-constexpr std::array<uint8_t, 32> INVALID_HMAC = {0};
-
/*
* Pointer coordinate data.
*/
diff --git a/libs/attestation/Android.bp b/libs/attestation/Android.bp
new file mode 100644
index 0000000..b85aecd
--- /dev/null
+++ b/libs/attestation/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2020 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.
+cc_library_static {
+ name: "libattestation",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "HmacKeyManager.cpp"
+ ],
+
+ clang: true,
+
+ shared_libs: [
+ "liblog",
+ "libcrypto",
+ ],
+}
\ No newline at end of file
diff --git a/libs/attestation/HmacKeyManager.cpp b/libs/attestation/HmacKeyManager.cpp
new file mode 100644
index 0000000..b15f143
--- /dev/null
+++ b/libs/attestation/HmacKeyManager.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <attestation/HmacKeyManager.h>
+#include <log/log.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+
+namespace android {
+
+static std::array<uint8_t, 128> getRandomKey() {
+ std::array<uint8_t, 128> key;
+ if (RAND_bytes(key.data(), key.size()) != 1) {
+ LOG_ALWAYS_FATAL("Can't generate HMAC key");
+ }
+ return key;
+}
+
+HmacKeyManager::HmacKeyManager() : mHmacKey(getRandomKey()) {}
+
+std::array<uint8_t, 32> HmacKeyManager::sign(const uint8_t* data, size_t size) const {
+ // SHA256 always generates 32-bytes result
+ std::array<uint8_t, 32> hash;
+ unsigned int hashLen = 0;
+ uint8_t* result =
+ HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data, size, hash.data(), &hashLen);
+ if (result == nullptr) {
+ ALOGE("Could not sign the data using HMAC");
+ return INVALID_HMAC;
+ }
+
+ if (hashLen != hash.size()) {
+ ALOGE("HMAC-SHA256 has unexpected length");
+ return INVALID_HMAC;
+ }
+
+ return hash;
+}
+} // namespace android
\ No newline at end of file
diff --git a/libs/attestation/OWNERS b/libs/attestation/OWNERS
new file mode 100644
index 0000000..4dbb0ea
--- /dev/null
+++ b/libs/attestation/OWNERS
@@ -0,0 +1,2 @@
+chaviw@google.com
+svv@google.com
\ No newline at end of file
diff --git a/libs/attestation/TEST_MAPPING b/libs/attestation/TEST_MAPPING
new file mode 100644
index 0000000..43be638
--- /dev/null
+++ b/libs/attestation/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libattestation_tests"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/libs/attestation/tests/Android.bp b/libs/attestation/tests/Android.bp
new file mode 100644
index 0000000..6ce5ea1
--- /dev/null
+++ b/libs/attestation/tests/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 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.
+
+cc_test {
+ name: "libattestation_tests",
+ test_suites: ["device-tests"],
+ srcs: [
+ "HmacKeyManager_test.cpp",
+ ],
+ static_libs: [
+ "libattestation",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcrypto",
+ ],
+}
diff --git a/libs/attestation/tests/HmacKeyManager_test.cpp b/libs/attestation/tests/HmacKeyManager_test.cpp
new file mode 100644
index 0000000..7f7a408
--- /dev/null
+++ b/libs/attestation/tests/HmacKeyManager_test.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <attestation/HmacKeyManager.h>
+#include <gtest/gtest.h>
+
+namespace android {
+
+class HmacKeyManagerTest : public testing::Test {
+protected:
+ HmacKeyManager mHmacKeyManager;
+};
+
+/**
+ * Ensure that separate calls to sign the same data are generating the same key.
+ * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
+ * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
+ * tests.
+ */
+TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
+ std::array<uint8_t, 10> data = {4, 3, 5, 1, 8, 5, 2, 7, 1, 8};
+
+ std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(data.data(), sizeof(data));
+ std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(data.data(), sizeof(data));
+ ASSERT_EQ(hmac1, hmac2);
+}
+
+/**
+ * Ensure that changes in the hmac verification data produce a different hmac.
+ */
+TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
+ std::array<uint8_t, 10> data = {4, 3, 5, 1, 8, 5, 2, 7, 1, 8};
+ std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(data.data(), sizeof(data));
+
+ data[2] = 2;
+ ASSERT_NE(initialHmac, mHmacKeyManager.sign(data.data(), sizeof(data)));
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 157538e..9aaca65 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -679,7 +679,7 @@
CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
ANDROID_LOG_ERROR);
} else /* FATAL_IF_NOT_ONEWAY */ {
- LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code);
+ LOG_ALWAYS_FATAL("Process may not make non-oneway calls (code: %u).", code);
}
}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index ef93ba1..a530565 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -144,11 +144,9 @@
}
}
-bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
+bool ProcessState::becomeContextManager()
{
AutoMutex _l(mLock);
- mBinderContextCheckFunc = checkFunc;
- mBinderContextUserData = userData;
flat_binder_object obj {
.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
@@ -165,8 +163,6 @@
}
if (result == -1) {
- mBinderContextCheckFunc = nullptr;
- mBinderContextUserData = nullptr;
ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
@@ -397,8 +393,6 @@
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
- , mBinderContextCheckFunc(nullptr)
- , mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 9f5346a..efb95f4 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -50,14 +50,8 @@
sp<IBinder> getContextObject(const sp<IBinder>& caller);
void startThreadPool();
-
- typedef bool (*context_check_func)(const String16& name,
- const sp<IBinder>& caller,
- void* userData);
- bool becomeContextManager(
- context_check_func checkFunc,
- void* userData);
+ bool becomeContextManager();
sp<IBinder> getStrongProxyForHandle(int32_t handle);
void expungeHandle(int32_t handle, IBinder* binder);
@@ -128,9 +122,6 @@
Vector<handle_entry>mHandleToObject;
- context_check_func mBinderContextCheckFunc;
- void* mBinderContextUserData;
-
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index d4feaba..5811760 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -32,7 +32,8 @@
*
* \param binder local server binder to request security contexts on
*/
-void AIBinder_setRequestingSid(AIBinder* binder, bool requestingSid) __INTRODUCED_IN(31);
+__attribute__((weak)) void AIBinder_setRequestingSid(AIBinder* binder, bool requestingSid)
+ __INTRODUCED_IN(31);
/**
* Returns the selinux context of the callee.
@@ -45,7 +46,7 @@
* \return security context or null if unavailable. The lifetime of this context
* is the lifetime of the transaction.
*/
-__attribute__((warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
+__attribute__((weak, warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
__END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 52bcd20..2784aa8 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -29,9 +29,9 @@
* \param binder object to register globally with the service manager.
* \param instance identifier of the service. This will be used to lookup the service.
*
- * \return STATUS_OK on success.
+ * \return EX_NONE on success.
*/
-binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
+binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance);
/**
* Gets a binder object with this specific instance name. Will return nullptr immediately if the
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 6b2184e..c782d47 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -29,14 +29,14 @@
using ::android::status_t;
using ::android::String16;
-binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance) {
+binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) {
if (binder == nullptr || instance == nullptr) {
- return STATUS_UNEXPECTED_NULL;
+ return EX_ILLEGAL_ARGUMENT;
}
sp<IServiceManager> sm = defaultServiceManager();
- status_t status = sm->addService(String16(instance), binder->getBinder());
- return PruneStatusT(status);
+ status_t exception = sm->addService(String16(instance), binder->getBinder());
+ return PruneException(exception);
}
AIBinder* AServiceManager_checkService(const char* instance) {
if (instance == nullptr) {
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index 87e1341..d889593 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -123,8 +123,8 @@
return STATUS_UNKNOWN_ERROR;
default:
- LOG(WARNING) << __func__
- << ": Unknown status_t pruned into STATUS_UNKNOWN_ERROR: " << status;
+ LOG(WARNING) << __func__ << ": Unknown status_t (" << status
+ << ") pruned into STATUS_UNKNOWN_ERROR";
return STATUS_UNKNOWN_ERROR;
}
}
@@ -155,8 +155,8 @@
return EX_TRANSACTION_FAILED;
default:
- LOG(WARNING) << __func__
- << ": Unknown status_t pruned into EX_TRANSACTION_FAILED: " << exception;
+ LOG(WARNING) << __func__ << ": Unknown binder exception (" << exception
+ << ") pruned into EX_TRANSACTION_FAILED";
return EX_TRANSACTION_FAILED;
}
}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 1424b6c..2bd5248 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -84,10 +84,11 @@
AIBinder_setRequestingSid(binder.get(), true);
- binder_status_t status = AServiceManager_addService(binder.get(), kBinderNdkUnitTestService);
+ binder_exception_t exception =
+ AServiceManager_addService(binder.get(), kBinderNdkUnitTestService);
- if (status != STATUS_OK) {
- LOG(FATAL) << "Could not register: " << status << " " << kBinderNdkUnitTestService;
+ if (exception != EX_NONE) {
+ LOG(FATAL) << "Could not register: " << exception << " " << kBinderNdkUnitTestService;
}
ABinderProcess_joinThreadPool();
@@ -111,10 +112,10 @@
void manualService(const char* instance) {
// Strong reference to MyFoo kept by service manager.
- binder_status_t status = (new MyFoo)->addService(instance);
+ binder_exception_t exception = (new MyFoo)->addService(instance);
- if (status != STATUS_OK) {
- LOG(FATAL) << "Could not register: " << status << " " << instance;
+ if (exception != EX_NONE) {
+ LOG(FATAL) << "Could not register: " << exception << " " << instance;
}
}
int manualPollingService(const char* instance) {
@@ -322,11 +323,20 @@
}
};
+TEST(NdkBinder, AddNullService) {
+ EXPECT_EQ(EX_ILLEGAL_ARGUMENT, AServiceManager_addService(nullptr, "any-service-name"));
+}
+
+TEST(NdkBinder, AddInvalidServiceName) {
+ sp<IFoo> foo = new MyTestFoo;
+ EXPECT_EQ(EX_ILLEGAL_ARGUMENT, foo->addService("!@#$%^&"));
+}
+
TEST(NdkBinder, GetServiceInProcess) {
static const char* kInstanceName = "test-get-service-in-process";
sp<IFoo> foo = new MyTestFoo;
- EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName));
+ EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));
sp<IFoo> getFoo = IFoo::getService(kInstanceName);
EXPECT_EQ(foo.get(), getFoo.get());
@@ -373,8 +383,8 @@
static const char* kInstanceName1 = "test-multi-1";
static const char* kInstanceName2 = "test-multi-2";
sp<IFoo> foo = new MyTestFoo;
- EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName1));
- EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2));
+ EXPECT_EQ(EX_NONE, foo->addService(kInstanceName1));
+ EXPECT_EQ(EX_NONE, foo->addService(kInstanceName2));
EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
}
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 51910fe..692c65d 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "Input"
//#define LOG_NDEBUG 0
+#include <attestation/HmacKeyManager.h>
#include <cutils/compiler.h>
#include <limits.h>
#include <string.h>
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index fd35131..7ac8a2e 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -24,9 +24,10 @@
#endif
#include <android/keycodes.h>
+#include <attestation/HmacKeyManager.h>
#include <input/InputEventLabels.h>
-#include <input/Keyboard.h>
#include <input/KeyCharacterMap.h>
+#include <input/Keyboard.h>
#include <utils/Log.h>
#include <utils/Errors.h>
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 069bc0e..601d8da 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -17,6 +17,7 @@
#include <array>
#include <math.h>
+#include <attestation/HmacKeyManager.h>
#include <binder/Parcel.h>
#include <gtest/gtest.h>
#include <input/Input.h>
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index e1f2562..1452745 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -20,11 +20,12 @@
#include <sys/mman.h>
#include <time.h>
+#include <attestation/HmacKeyManager.h>
#include <cutils/ashmem.h>
#include <gtest/gtest.h>
#include <input/InputTransport.h>
-#include <utils/Timers.h>
#include <utils/StopWatch.h>
+#include <utils/Timers.h>
namespace android {
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index e7db4b0..d049d05 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -21,6 +21,7 @@
#include <math.h>
#include <android-base/stringprintf.h>
+#include <attestation/HmacKeyManager.h>
#include <gtest/gtest.h>
#include <input/VelocityTracker.h>
diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp
index 21cfe8c..36f87b8 100644
--- a/libs/input/tests/VerifiedInputEvent_test.cpp
+++ b/libs/input/tests/VerifiedInputEvent_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <attestation/HmacKeyManager.h>
#include <gtest/gtest.h>
#include <input/Input.h>
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index a0de607..96e6207 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -59,6 +59,9 @@
"libutils",
"libui",
],
+ static_libs: [
+ "libattestation",
+ ],
}
cc_library_shared {
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 066a816..9abf8b1 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -18,6 +18,7 @@
"libutils",
],
static_libs: [
+ "libattestation",
"libinputdispatcher",
],
}
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index d29d8df..ff9aac9 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -48,6 +48,9 @@
"libui",
"libutils",
],
+ static_libs: [
+ "libattestation",
+ ],
header_libs: [
"libinputdispatcher_headers",
],
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 9c8481c..b428c4e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -53,8 +53,6 @@
#include <input/InputWindow.h>
#include <log/log.h>
#include <log/log_event_list.h>
-#include <openssl/hmac.h>
-#include <openssl/rand.h>
#include <powermanager/PowerManager.h>
#include <statslog.h>
#include <unistd.h>
@@ -344,53 +342,6 @@
}
}
-static std::array<uint8_t, 128> getRandomKey() {
- std::array<uint8_t, 128> key;
- if (RAND_bytes(key.data(), key.size()) != 1) {
- LOG_ALWAYS_FATAL("Can't generate HMAC key");
- }
- return key;
-}
-
-// --- HmacKeyManager ---
-
-HmacKeyManager::HmacKeyManager() : mHmacKey(getRandomKey()) {}
-
-std::array<uint8_t, 32> HmacKeyManager::sign(const VerifiedInputEvent& event) const {
- size_t size;
- switch (event.type) {
- case VerifiedInputEvent::Type::KEY: {
- size = sizeof(VerifiedKeyEvent);
- break;
- }
- case VerifiedInputEvent::Type::MOTION: {
- size = sizeof(VerifiedMotionEvent);
- break;
- }
- }
- const uint8_t* start = reinterpret_cast<const uint8_t*>(&event);
- return sign(start, size);
-}
-
-std::array<uint8_t, 32> HmacKeyManager::sign(const uint8_t* data, size_t size) const {
- // SHA256 always generates 32-bytes result
- std::array<uint8_t, 32> hash;
- unsigned int hashLen = 0;
- uint8_t* result =
- HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data, size, hash.data(), &hashLen);
- if (result == nullptr) {
- ALOGE("Could not sign the data using HMAC");
- return INVALID_HMAC;
- }
-
- if (hashLen != hash.size()) {
- ALOGE("HMAC-SHA256 has unexpected length");
- return INVALID_HMAC;
- }
-
- return hash;
-}
-
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
@@ -2682,6 +2633,22 @@
}
}
+std::array<uint8_t, 32> InputDispatcher::sign(const VerifiedInputEvent& event) const {
+ size_t size;
+ switch (event.type) {
+ case VerifiedInputEvent::Type::KEY: {
+ size = sizeof(VerifiedKeyEvent);
+ break;
+ }
+ case VerifiedInputEvent::Type::MOTION: {
+ size = sizeof(VerifiedMotionEvent);
+ break;
+ }
+ }
+ const uint8_t* start = reinterpret_cast<const uint8_t*>(&event);
+ return mHmacKeyManager.sign(start, size);
+}
+
const std::array<uint8_t, 32> InputDispatcher::getSignature(
const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const {
int32_t actionMasked = dispatchEntry.resolvedAction & AMOTION_EVENT_ACTION_MASK;
@@ -2691,7 +2658,7 @@
VerifiedMotionEvent verifiedEvent = verifiedMotionEventFromMotionEntry(motionEntry);
verifiedEvent.actionMasked = actionMasked;
verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_MOTION_EVENT_FLAGS;
- return mHmacKeyManager.sign(verifiedEvent);
+ return sign(verifiedEvent);
}
return INVALID_HMAC;
}
@@ -2701,7 +2668,7 @@
VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(keyEntry);
verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
verifiedEvent.action = dispatchEntry.resolvedAction;
- return mHmacKeyManager.sign(verifiedEvent);
+ return sign(verifiedEvent);
}
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
@@ -3549,7 +3516,7 @@
const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
VerifiedKeyEvent verifiedKeyEvent = verifiedKeyEventFromKeyEvent(keyEvent);
result = std::make_unique<VerifiedKeyEvent>(verifiedKeyEvent);
- calculatedHmac = mHmacKeyManager.sign(verifiedKeyEvent);
+ calculatedHmac = sign(verifiedKeyEvent);
break;
}
case AINPUT_EVENT_TYPE_MOTION: {
@@ -3557,7 +3524,7 @@
VerifiedMotionEvent verifiedMotionEvent =
verifiedMotionEventFromMotionEvent(motionEvent);
result = std::make_unique<VerifiedMotionEvent>(verifiedMotionEvent);
- calculatedHmac = mHmacKeyManager.sign(verifiedMotionEvent);
+ calculatedHmac = sign(verifiedMotionEvent);
break;
}
default: {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index c52d256..93d3fde 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -31,6 +31,7 @@
#include "TouchState.h"
#include "TouchedWindow.h"
+#include <attestation/HmacKeyManager.h>
#include <input/Input.h>
#include <input/InputApplication.h>
#include <input/InputTransport.h>
@@ -58,16 +59,6 @@
class Connection;
-class HmacKeyManager {
-public:
- HmacKeyManager();
- std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
-
-private:
- std::array<uint8_t, 32> sign(const uint8_t* data, size_t size) const;
- const std::array<uint8_t, 128> mHmacKey;
-};
-
/* Dispatches events to input targets. Some functions of the input dispatcher, such as
* identifying input targets, are controlled by a separate policy object.
*
@@ -133,6 +124,8 @@
virtual status_t unregisterInputChannel(const InputChannel& inputChannel) override;
virtual status_t pilferPointers(const sp<IBinder>& token) override;
+ std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
+
private:
enum class DropReason {
NOT_DROPPED,
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index da50af5..3e0b5e8 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -294,70 +294,6 @@
}
};
-// --- HmacKeyManagerTest ---
-
-class HmacKeyManagerTest : public testing::Test {
-protected:
- HmacKeyManager mHmacKeyManager;
-};
-
-/**
- * Ensure that separate calls to sign the same data are generating the same key.
- * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
- * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
- * tests.
- */
-TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
- KeyEvent event = getTestKeyEvent();
- VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
-
- std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
- std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
- ASSERT_EQ(hmac1, hmac2);
-}
-
-/**
- * Ensure that changes in VerifiedKeyEvent produce a different hmac.
- */
-TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
- KeyEvent event = getTestKeyEvent();
- VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
- std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
-
- verifiedEvent.deviceId += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.source += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.eventTimeNanos += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.displayId += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.action += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.downTimeNanos += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.flags += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.keyCode += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.scanCode += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.metaState += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-
- verifiedEvent.repeatCount += 1;
- ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
-}
-
// --- InputDispatcherTest ---
class InputDispatcherTest : public testing::Test {
@@ -2027,6 +1963,63 @@
EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
}
+/**
+ * Ensure that separate calls to sign the same data are generating the same key.
+ * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
+ * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
+ * tests.
+ */
+TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
+ KeyEvent event = getTestKeyEvent();
+ VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
+
+ std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
+ std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
+ ASSERT_EQ(hmac1, hmac2);
+}
+
+/**
+ * Ensure that changes in VerifiedKeyEvent produce a different hmac.
+ */
+TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
+ KeyEvent event = getTestKeyEvent();
+ VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
+ std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
+
+ verifiedEvent.deviceId += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.source += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.eventTimeNanos += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.displayId += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.action += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.downTimeNanos += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.flags += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.keyCode += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.scanCode += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.metaState += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+
+ verifiedEvent.repeatCount += 1;
+ ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
+}
+
class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
protected:
static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
diff --git a/services/powermanager/benchmarks/AndroidTest.xml b/services/powermanager/benchmarks/AndroidTest.xml
deleted file mode 100644
index 40f4872..0000000
--- a/services/powermanager/benchmarks/AndroidTest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 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.
- -->
-<configuration description="Config for libpowermanager benchmarks">
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="libpowermanager_benchmarks->/data/benchmarktest/benchmark" />
- </target_preparer>
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-metric-instrumentation" />
- <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
- <option name="native-benchmark-device-path" value="/data/benchmarktest" />
- <option name="benchmark-module-name" value="benchmark" />
- </test>
-</configuration>
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 6ba1942..a2fc692 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -446,9 +446,26 @@
PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
}
- ScreenCaptureResults captureResults;
+ class SyncScreenCaptureListener : public BnScreenCaptureListener {
+ public:
+ status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) override {
+ resultsPromise.set_value(captureResults);
+ return NO_ERROR;
+ }
+
+ ScreenCaptureResults waitForResults() {
+ std::future<ScreenCaptureResults> resultsFuture = resultsPromise.get_future();
+ return resultsFuture.get();
+ }
+
+ private:
+ std::promise<ScreenCaptureResults> resultsPromise;
+ };
+
+ const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- true /* regionSampling */, captureResults);
+ true /* regionSampling */, captureListener);
+ ScreenCaptureResults captureResults = captureListener->waitForResults();
std::vector<Descriptor> activeDescriptors;
for (const auto& descriptor : descriptors) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a3e1a17..6501749 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5531,12 +5531,9 @@
auto traverseLayers = [this, args, layerStack](const LayerVector::Visitor& visitor) {
traverseLayersInLayerStack(layerStack, args.uid, visitor);
};
- ScreenCaptureResults captureResults;
- status_t status = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
- args.pixelFormat, captureResults);
- captureResults.result = status;
- captureListener->onScreenCaptureComplete(captureResults);
- return status;
+
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
+ args.pixelFormat, captureListener);
}
status_t SurfaceFlinger::setSchedFifo(bool enabled) {
@@ -5609,12 +5606,8 @@
traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor);
};
- ScreenCaptureResults captureResults;
- status_t status = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
- ui::PixelFormat::RGBA_8888, captureResults);
- captureResults.result = status;
- captureListener->onScreenCaptureComplete(captureResults);
- return status;
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
+ ui::PixelFormat::RGBA_8888, captureListener);
}
status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
@@ -5705,7 +5698,7 @@
captureSecureLayers);
});
- auto traverseLayers = [parent, args, &excludeLayers](const LayerVector::Visitor& visitor) {
+ auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) {
parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
if (!layer->isVisible()) {
return;
@@ -5727,18 +5720,14 @@
});
};
- ScreenCaptureResults captureResults;
- status_t status = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
- args.pixelFormat, captureResults);
- captureResults.result = status;
- captureListener->onScreenCaptureComplete(captureResults);
- return status;
+ return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
+ args.pixelFormat, captureListener);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
- ScreenCaptureResults& captureResults) {
+ const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
// TODO(b/116112787) Make buffer usage a parameter.
@@ -5748,54 +5737,56 @@
getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
static_cast<android_pixel_format>(reqPixelFormat),
1 /* layerCount */, usage, "screenshot");
-
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- false /* regionSampling */, captureResults);
+ false /* regionSampling */, captureListener);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer, bool regionSampling,
- ScreenCaptureResults& captureResults) {
+ sp<GraphicBuffer>& buffer, bool regionSampling,
+ const sp<IScreenCaptureListener>& captureListener) {
+ ATRACE_CALL();
+
+ if (captureListener == nullptr) {
+ ALOGE("capture screen must provide a capture listener callback");
+ return BAD_VALUE;
+ }
+
const int uid = IPCThreadState::self()->getCallingUid();
const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
- status_t result;
- int syncFd;
+ static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable {
+ if (mRefreshPending) {
+ ALOGW("Skipping screenshot for now");
+ captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
+ captureListener);
+ return;
+ }
+ ScreenCaptureResults captureResults;
+ std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get();
+ if (!renderArea) {
+ ALOGW("Skipping screen capture because of invalid render area.");
+ captureResults.result = NO_MEMORY;
+ captureListener->onScreenCaptureComplete(captureResults);
+ return;
+ }
- do {
- std::tie(result, syncFd) =
- schedule([&]() -> std::pair<status_t, int> {
- if (mRefreshPending) {
- ALOGW("Skipping screenshot for now");
- return {EAGAIN, -1};
- }
- std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get();
- if (!renderArea) {
- ALOGW("Skipping screen capture because of invalid render area.");
- return {NO_MEMORY, -1};
- }
+ status_t result = NO_ERROR;
+ int syncFd = -1;
+ renderArea->render([&] {
+ result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem, &syncFd,
+ regionSampling, captureResults);
+ });
- status_t result = NO_ERROR;
- int fd = -1;
+ if (result == NO_ERROR) {
+ sync_wait(syncFd, -1);
+ close(syncFd);
+ }
+ captureResults.result = result;
+ captureListener->onScreenCaptureComplete(captureResults);
+ }));
- Mutex::Autolock lock(mStateLock);
- renderArea->render([&] {
- result = renderScreenImplLocked(*renderArea, traverseLayers, buffer.get(),
- forSystem, &fd, regionSampling,
- captureResults);
- });
-
- return {result, fd};
- }).get();
- } while (result == EAGAIN);
-
- if (result == NO_ERROR) {
- sync_wait(syncFd, -1);
- close(syncFd);
- }
-
- return result;
+ return NO_ERROR;
}
status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 37cafe9..e0a6073 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -781,14 +781,14 @@
// Boot animation, on/off animations and screen capture
void startBootAnim();
- status_t renderScreenImplLocked(const RenderArea& renderArea,
- TraverseLayersFunction traverseLayers,
- const sp<GraphicBuffer>& buffer, bool forSystem, int* outSyncFd,
- bool regionSampling, ScreenCaptureResults& captureResults);
+ status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
+ const sp<GraphicBuffer>&, bool forSystem, int* outSyncFd,
+ bool regionSampling, ScreenCaptureResults&);
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize,
- ui::PixelFormat, ScreenCaptureResults& captureResults);
- status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, const sp<GraphicBuffer>&,
- bool regionSampling, ScreenCaptureResults& captureResults);
+ ui::PixelFormat, const sp<IScreenCaptureListener>&);
+ status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&,
+ bool regionSampling, const sp<IScreenCaptureListener>&);
+
sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index ce20aeb..9672644 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -501,6 +501,10 @@
}
if (externalControlResult.withDefault(false)) {
capabilities |= Capabilities::EXTERNAL_CONTROL;
+
+ if (amplitudeResult.withDefault(false)) {
+ capabilities |= Capabilities::EXTERNAL_AMPLITUDE_CONTROL;
+ }
}
return HalResult<Capabilities>::fromReturn(externalControlResult, capabilities);
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
new file mode 100644
index 0000000..c1a03a1
--- /dev/null
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -0,0 +1,37 @@
+// Copyright (C) 2020 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.
+
+cc_benchmark {
+ name: "libvibratorservice_benchmarks",
+ srcs: [
+ "VibratorHalControllerBenchmarks.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ "libvibratorservice",
+ "android.hardware.vibrator-cpp",
+ "android.hardware.vibrator@1.0",
+ "android.hardware.vibrator@1.1",
+ "android.hardware.vibrator@1.2",
+ "android.hardware.vibrator@1.3",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
diff --git a/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp b/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp
new file mode 100644
index 0000000..0d4c55e
--- /dev/null
+++ b/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "PowerHalControllerBenchmarks"
+
+#include <benchmark/benchmark.h>
+#include <vibratorservice/VibratorHalController.h>
+
+using ::android::enum_range;
+using ::benchmark::Counter;
+using ::benchmark::Fixture;
+using ::benchmark::kMicrosecond;
+using ::benchmark::State;
+using ::benchmark::internal::Benchmark;
+
+using namespace android;
+using namespace std::chrono_literals;
+
+class VibratorBench : public Fixture {
+public:
+ void SetUp(State& /*state*/) override { mController.init(); }
+
+ void TearDown(State& /*state*/) override { mController.off(); }
+
+ static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
+
+ static void DefaultArgs(Benchmark* /*b*/) {
+ // none
+ }
+
+protected:
+ vibrator::HalController mController;
+
+ auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
+
+ bool hasCapabilities(vibrator::HalResult<vibrator::Capabilities> result,
+ vibrator::Capabilities query) {
+ if (!result.isOk()) {
+ return false;
+ }
+ return (result.value() & query) == query;
+ }
+};
+
+#define BENCHMARK_WRAPPER(fixt, test, code) \
+ BENCHMARK_DEFINE_F(fixt, test) \
+ /* NOLINTNEXTLINE */ \
+ (State& state){code} BENCHMARK_REGISTER_F(fixt, test) \
+ ->Apply(fixt::DefaultConfig) \
+ ->Apply(fixt::DefaultArgs)
+
+BENCHMARK_WRAPPER(VibratorBench, init, {
+ for (auto _ : state) {
+ state.PauseTiming();
+ vibrator::HalController controller;
+ state.ResumeTiming();
+ controller.init();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, initCached, {
+ for (auto _ : state) {
+ mController.init();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, ping, {
+ for (auto _ : state) {
+ mController.ping();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, tryReconnect, {
+ for (auto _ : state) {
+ mController.tryReconnect();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, on, {
+ auto duration = 60s;
+ auto callback = []() {};
+
+ for (auto _ : state) {
+ state.ResumeTiming();
+ mController.on(duration, callback);
+ state.PauseTiming();
+ mController.off();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, off, {
+ auto duration = 60s;
+ auto callback = []() {};
+
+ for (auto _ : state) {
+ state.PauseTiming();
+ mController.on(duration, callback);
+ state.ResumeTiming();
+ mController.off();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::AMPLITUDE_CONTROL)) {
+ return;
+ }
+
+ auto duration = 60s;
+ auto callback = []() {};
+ auto amplitude = UINT8_MAX;
+
+ for (auto _ : state) {
+ state.PauseTiming();
+ vibrator::HalController controller;
+ controller.init();
+ controller.on(duration, callback);
+ state.ResumeTiming();
+ controller.setAmplitude(amplitude);
+ state.PauseTiming();
+ controller.off();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, setAmplitudeCached, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::AMPLITUDE_CONTROL)) {
+ return;
+ }
+
+ auto duration = 6000s;
+ auto callback = []() {};
+ auto amplitude = UINT8_MAX;
+
+ mController.on(duration, callback);
+
+ for (auto _ : state) {
+ mController.setAmplitude(amplitude);
+ }
+
+ mController.off();
+});
+
+BENCHMARK_WRAPPER(VibratorBench, setExternalControl, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::EXTERNAL_CONTROL)) {
+ return;
+ }
+
+ for (auto _ : state) {
+ state.PauseTiming();
+ vibrator::HalController controller;
+ controller.init();
+ state.ResumeTiming();
+ controller.setExternalControl(true);
+ state.PauseTiming();
+ controller.setExternalControl(false);
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, setExternalControlCached, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::EXTERNAL_CONTROL)) {
+ return;
+ }
+
+ for (auto _ : state) {
+ state.ResumeTiming();
+ mController.setExternalControl(true);
+ state.PauseTiming();
+ mController.setExternalControl(false);
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, setExternalAmplitudeCached, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::EXTERNAL_AMPLITUDE_CONTROL)) {
+ return;
+ }
+
+ auto amplitude = UINT8_MAX;
+
+ mController.setExternalControl(true);
+
+ for (auto _ : state) {
+ mController.setAmplitude(amplitude);
+ }
+
+ mController.setExternalControl(false);
+});
+
+BENCHMARK_WRAPPER(VibratorBench, getCapabilities, {
+ for (auto _ : state) {
+ state.PauseTiming();
+ vibrator::HalController controller;
+ controller.init();
+ state.ResumeTiming();
+ controller.getCapabilities();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, getCapabilitiesCached, {
+ // First call to cache values.
+ mController.getCapabilities();
+
+ for (auto _ : state) {
+ mController.getCapabilities();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, getSupportedEffects, {
+ for (auto _ : state) {
+ state.PauseTiming();
+ vibrator::HalController controller;
+ controller.init();
+ state.ResumeTiming();
+ controller.getSupportedEffects();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, getSupportedEffectsCached, {
+ // First call to cache values.
+ mController.getSupportedEffects();
+
+ for (auto _ : state) {
+ mController.getSupportedEffects();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, getSupportedPrimitives, {
+ for (auto _ : state) {
+ state.PauseTiming();
+ vibrator::HalController controller;
+ controller.init();
+ state.ResumeTiming();
+ controller.getSupportedPrimitives();
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorBench, getSupportedPrimitivesCached, {
+ // First call to cache values.
+ mController.getSupportedPrimitives();
+
+ for (auto _ : state) {
+ mController.getSupportedPrimitives();
+ }
+});
+
+class VibratorEffectsBench : public VibratorBench {
+public:
+ static void DefaultArgs(Benchmark* b) {
+ vibrator::HalController controller;
+ auto effectsResult = controller.getSupportedEffects();
+ if (!effectsResult.isOk()) {
+ return;
+ }
+
+ std::vector<hardware::vibrator::Effect> supported = effectsResult.value();
+ b->ArgNames({"Effect", "Strength"});
+ for (const auto& effect : enum_range<hardware::vibrator::Effect>()) {
+ if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
+ continue;
+ }
+ for (const auto& strength : enum_range<hardware::vibrator::EffectStrength>()) {
+ b->Args({static_cast<long>(effect), static_cast<long>(strength)});
+ }
+ }
+ }
+
+protected:
+ auto getEffect(const State& state) const {
+ return static_cast<hardware::vibrator::Effect>(this->getOtherArg(state, 0));
+ }
+
+ auto getStrength(const State& state) const {
+ return static_cast<hardware::vibrator::EffectStrength>(this->getOtherArg(state, 1));
+ }
+};
+
+BENCHMARK_WRAPPER(VibratorEffectsBench, alwaysOnEnable, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::ALWAYS_ON_CONTROL)) {
+ return;
+ }
+
+ int32_t id = 1;
+ auto effect = getEffect(state);
+ auto strength = getStrength(state);
+
+ for (auto _ : state) {
+ state.ResumeTiming();
+ mController.alwaysOnEnable(id, effect, strength);
+ state.PauseTiming();
+ mController.alwaysOnDisable(id);
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorEffectsBench, alwaysOnDisable, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::ALWAYS_ON_CONTROL)) {
+ return;
+ }
+
+ int32_t id = 1;
+ auto effect = getEffect(state);
+ auto strength = getStrength(state);
+
+ for (auto _ : state) {
+ state.PauseTiming();
+ mController.alwaysOnEnable(id, effect, strength);
+ state.ResumeTiming();
+ mController.alwaysOnDisable(id);
+ }
+});
+
+BENCHMARK_WRAPPER(VibratorEffectsBench, performEffect, {
+ auto effect = getEffect(state);
+ auto strength = getStrength(state);
+ auto callback = []() {};
+
+ for (auto _ : state) {
+ state.ResumeTiming();
+ mController.performEffect(effect, strength, callback);
+ state.PauseTiming();
+ mController.off();
+ }
+});
+
+class VibratorPrimitivesBench : public VibratorBench {
+public:
+ static void DefaultArgs(Benchmark* b) {
+ vibrator::HalController controller;
+ auto primitivesResult = controller.getSupportedPrimitives();
+ if (!primitivesResult.isOk()) {
+ return;
+ }
+
+ std::vector<hardware::vibrator::CompositePrimitive> supported = primitivesResult.value();
+ b->ArgNames({"Primitive"});
+ for (const auto& primitive : enum_range<hardware::vibrator::CompositePrimitive>()) {
+ if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
+ continue;
+ }
+ b->Args({static_cast<long>(primitive)});
+ }
+ }
+
+protected:
+ auto getPrimitive(const State& state) const {
+ return static_cast<hardware::vibrator::CompositePrimitive>(this->getOtherArg(state, 0));
+ }
+};
+
+BENCHMARK_WRAPPER(VibratorPrimitivesBench, performComposedEffect, {
+ auto capabilitiesResult = mController.getCapabilities();
+
+ if (!hasCapabilities(capabilitiesResult, vibrator::Capabilities::COMPOSE_EFFECTS)) {
+ return;
+ }
+
+ hardware::vibrator::CompositeEffect effect;
+ effect.primitive = getPrimitive(state);
+ effect.scale = 1.0f;
+ effect.delayMs = 0;
+
+ std::vector<hardware::vibrator::CompositeEffect> effects;
+ effects.push_back(effect);
+ auto callback = []() {};
+
+ for (auto _ : state) {
+ state.ResumeTiming();
+ mController.performComposedEffect(effects, callback);
+ state.PauseTiming();
+ mController.off();
+ }
+});
+
+BENCHMARK_MAIN();
\ No newline at end of file
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp
index 5de6257..08652f4 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp
@@ -118,7 +118,8 @@
auto result = mWrapper->getCapabilities();
ASSERT_TRUE(result.isOk());
- ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL | vibrator::Capabilities::EXTERNAL_CONTROL,
+ ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL | vibrator::Capabilities::EXTERNAL_CONTROL |
+ vibrator::Capabilities::EXTERNAL_AMPLITUDE_CONTROL,
result.value());
}