diff options
Diffstat (limited to 'libs')
53 files changed, 1676 insertions, 260 deletions
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp new file mode 100644 index 0000000000..9cf014380c --- /dev/null +++ b/libs/adbd_auth/Android.bp @@ -0,0 +1,44 @@ +// Copyright (C) 2019 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 { + name: "libadbd_auth", + cflags: [ + "-Wall", + "-Wextra", + "-Wthread-safety", + "-Werror", + ], + srcs: ["adbd_auth.cpp"], + export_include_dirs: ["include"], + + version_script: "libadbd_auth.map.txt", + stubs: { + symbol_file: "libadbd_auth.map.txt", + }, + + host_supported: true, + recovery_available: true, + target: { + darwin: { + enabled: false, + } + }, + + shared_libs: [ + "libbase", + "libcutils", + "liblog", + ], +} diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp new file mode 100644 index 0000000000..64791098ee --- /dev/null +++ b/libs/adbd_auth/adbd_auth.cpp @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2019 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 ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION + +#include "include/adbd_auth.h" + +#include <inttypes.h> +#include <sys/epoll.h> +#include <sys/eventfd.h> +#include <sys/uio.h> + +#include <chrono> +#include <deque> +#include <string> +#include <string_view> +#include <tuple> +#include <unordered_map> +#include <utility> +#include <variant> +#include <vector> + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/macros.h> +#include <android-base/strings.h> +#include <android-base/thread_annotations.h> +#include <android-base/unique_fd.h> +#include <cutils/sockets.h> + +using android::base::unique_fd; + +struct AdbdAuthPacketAuthenticated { + std::string public_key; +}; + +struct AdbdAuthPacketDisconnected { + std::string public_key; +}; + +struct AdbdAuthPacketRequestAuthorization { + std::string public_key; +}; + +using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated, AdbdAuthPacketDisconnected, + AdbdAuthPacketRequestAuthorization>; + +struct AdbdAuthContext { + static constexpr uint64_t kEpollConstSocket = 0; + static constexpr uint64_t kEpollConstEventFd = 1; + static constexpr uint64_t kEpollConstFramework = 2; + +public: + explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) { + epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC)); + if (epoll_fd_ == -1) { + PLOG(FATAL) << "failed to create epoll fd"; + } + + event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); + if (event_fd_ == -1) { + PLOG(FATAL) << "failed to create eventfd"; + } + + sock_fd_.reset(android_get_control_socket("adbd")); + if (sock_fd_ == -1) { + PLOG(ERROR) << "failed to get adbd authentication socket"; + } else { + if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) { + PLOG(FATAL) << "failed to make adbd authentication socket cloexec"; + } + + if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) { + PLOG(FATAL) << "failed to make adbd authentication socket nonblocking"; + } + + if (listen(sock_fd_.get(), 4) != 0) { + PLOG(FATAL) << "failed to listen on adbd authentication socket"; + } + } + } + + AdbdAuthContext(const AdbdAuthContext& copy) = delete; + AdbdAuthContext(AdbdAuthContext&& move) = delete; + AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete; + AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete; + + uint64_t NextId() { return next_id_++; } + + void DispatchPendingPrompt() REQUIRES(mutex_) { + if (dispatched_prompt_) { + LOG(INFO) << "adbd_auth: prompt currently pending, skipping"; + return; + } + + if (pending_prompts_.empty()) { + LOG(INFO) << "adbd_auth: no prompts to send"; + return; + } + + LOG(INFO) << "adbd_auth: prompting user for adb authentication"; + auto [id, public_key, arg] = std::move(pending_prompts_.front()); + pending_prompts_.pop_front(); + + this->output_queue_.emplace_back( + AdbdAuthPacketRequestAuthorization{.public_key = public_key}); + + Interrupt(); + dispatched_prompt_ = std::make_tuple(id, public_key, arg); + } + + void UpdateFrameworkWritable() REQUIRES(mutex_) { + // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified + // at the same time as a framework connection, but that's unlikely and this doesn't need to + // be fast anyway. + if (framework_fd_ != -1) { + struct epoll_event event; + event.events = EPOLLIN; + if (!output_queue_.empty()) { + LOG(INFO) << "marking framework writable"; + event.events |= EPOLLOUT; + } + event.data.u64 = kEpollConstFramework; + CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event)); + } + } + + void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) { + LOG(INFO) << "received new framework fd " << new_fd.get() + << " (current = " << framework_fd_.get() << ")"; + + // If we already had a framework fd, clean up after ourselves. + if (framework_fd_ != -1) { + output_queue_.clear(); + dispatched_prompt_.reset(); + CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr)); + framework_fd_.reset(); + } + + if (new_fd != -1) { + struct epoll_event event; + event.events = EPOLLIN; + if (!output_queue_.empty()) { + LOG(INFO) << "marking framework writable"; + event.events |= EPOLLOUT; + } + event.data.u64 = kEpollConstFramework; + CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event)); + framework_fd_ = std::move(new_fd); + } + } + + void HandlePacket(std::string_view packet) REQUIRES(mutex_) { + LOG(INFO) << "received packet: " << packet; + + if (packet.length() < 2) { + LOG(ERROR) << "received packet of invalid length"; + ReplaceFrameworkFd(unique_fd()); + } + + if (packet[0] == 'O' && packet[1] == 'K') { + CHECK(this->dispatched_prompt_.has_value()); + auto& [id, key, arg] = *this->dispatched_prompt_; + keys_.emplace(id, std::move(key)); + + this->callbacks_.key_authorized(arg, id); + this->dispatched_prompt_ = std::nullopt; + } else if (packet[0] == 'N' && packet[1] == 'O') { + CHECK_EQ(2UL, packet.length()); + // TODO: Do we want a callback if the key is denied? + this->dispatched_prompt_ = std::nullopt; + DispatchPendingPrompt(); + } else { + LOG(ERROR) << "unhandled packet: " << packet; + ReplaceFrameworkFd(unique_fd()); + } + } + + bool SendPacket() REQUIRES(mutex_) { + if (output_queue_.empty()) { + return false; + } + + CHECK_NE(-1, framework_fd_.get()); + + auto& packet = output_queue_.front(); + struct iovec iovs[2]; + if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) { + iovs[0].iov_base = const_cast<char*>("CK"); + iovs[0].iov_len = 2; + iovs[1].iov_base = p->public_key.data(); + iovs[1].iov_len = p->public_key.size(); + } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) { + iovs[0].iov_base = const_cast<char*>("DC"); + iovs[0].iov_len = 2; + iovs[1].iov_base = p->public_key.data(); + iovs[1].iov_len = p->public_key.size(); + } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) { + iovs[0].iov_base = const_cast<char*>("PK"); + iovs[0].iov_len = 2; + iovs[1].iov_base = p->public_key.data(); + iovs[1].iov_len = p->public_key.size(); + } else { + LOG(FATAL) << "unhandled packet type?"; + } + + output_queue_.pop_front(); + + ssize_t rc = writev(framework_fd_.get(), iovs, 2); + if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { + PLOG(ERROR) << "failed to write to framework fd"; + ReplaceFrameworkFd(unique_fd()); + return false; + } + + return true; + } + + void Run() { + if (sock_fd_ == -1) { + LOG(ERROR) << "adbd authentication socket unavailable, disabling user prompts"; + } else { + struct epoll_event event; + event.events = EPOLLIN; + event.data.u64 = kEpollConstSocket; + CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event)); + } + + { + struct epoll_event event; + event.events = EPOLLIN; + event.data.u64 = kEpollConstEventFd; + CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event)); + } + + while (true) { + struct epoll_event events[3]; + int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1)); + if (rc == -1) { + PLOG(FATAL) << "epoll_wait failed"; + } else if (rc == 0) { + LOG(FATAL) << "epoll_wait returned 0"; + } + + bool restart = false; + for (int i = 0; i < rc; ++i) { + if (restart) { + break; + } + + struct epoll_event& event = events[i]; + switch (event.data.u64) { + case kEpollConstSocket: { + unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr, + SOCK_CLOEXEC | SOCK_NONBLOCK)); + if (new_framework_fd == -1) { + PLOG(FATAL) << "failed to accept framework fd"; + } + + LOG(INFO) << "adbd_auth: received a new framework connection"; + std::lock_guard<std::mutex> lock(mutex_); + ReplaceFrameworkFd(std::move(new_framework_fd)); + + // Stop iterating over events: one of the later ones might be the old + // framework fd. + restart = false; + break; + } + + case kEpollConstEventFd: { + // We were woken up to write something. + uint64_t dummy; + int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy))); + if (rc != 8) { + PLOG(FATAL) << "failed to read from eventfd (rc = " << rc << ")"; + } + + std::lock_guard<std::mutex> lock(mutex_); + UpdateFrameworkWritable(); + break; + } + + case kEpollConstFramework: { + char buf[4096]; + if (event.events & EPOLLIN) { + int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf))); + if (rc == -1) { + LOG(FATAL) << "failed to read from framework fd"; + } else if (rc == 0) { + LOG(INFO) << "hit EOF on framework fd"; + std::lock_guard<std::mutex> lock(mutex_); + ReplaceFrameworkFd(unique_fd()); + } else { + std::lock_guard<std::mutex> lock(mutex_); + HandlePacket(std::string_view(buf, rc)); + } + } + + if (event.events & EPOLLOUT) { + std::lock_guard<std::mutex> lock(mutex_); + while (SendPacket()) { + continue; + } + UpdateFrameworkWritable(); + } + + break; + } + } + } + } + } + + static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"}; + void IteratePublicKeys(bool (*callback)(const char*, size_t, void*), void* arg) { + for (const auto& path : key_paths) { + if (access(path, R_OK) == 0) { + LOG(INFO) << "Loading keys from " << path; + std::string content; + if (!android::base::ReadFileToString(path, &content)) { + PLOG(ERROR) << "Couldn't read " << path; + continue; + } + for (const auto& line : android::base::Split(content, "\n")) { + if (!callback(line.data(), line.size(), arg)) { + return; + } + } + } + } + } + + uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) { + uint64_t id = NextId(); + + std::lock_guard<std::mutex> lock(mutex_); + pending_prompts_.emplace_back(id, public_key, arg); + DispatchPendingPrompt(); + return id; + } + + uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) { + uint64_t id = NextId(); + std::lock_guard<std::mutex> lock(mutex_); + keys_.emplace(id, public_key); + output_queue_.emplace_back( + AdbdAuthPacketDisconnected{.public_key = std::string(public_key)}); + return id; + } + + void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) { + std::lock_guard<std::mutex> lock(mutex_); + auto it = keys_.find(id); + if (it == keys_.end()) { + LOG(DEBUG) << "couldn't find public key to notify disconnection, skipping"; + return; + } + output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)}); + keys_.erase(it); + } + + // Interrupt the worker thread to do some work. + void Interrupt() { + uint64_t value = 1; + ssize_t rc = write(event_fd_.get(), &value, sizeof(value)); + if (rc == -1) { + PLOG(FATAL) << "write to eventfd failed"; + } else if (rc != sizeof(value)) { + LOG(FATAL) << "write to eventfd returned short (" << rc << ")"; + } + } + + unique_fd epoll_fd_; + unique_fd event_fd_; + unique_fd sock_fd_; + unique_fd framework_fd_; + + std::atomic<uint64_t> next_id_; + AdbdAuthCallbacksV1 callbacks_; + + std::mutex mutex_; + std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_); + + // We keep two separate queues: one to handle backpressure from the socket (output_queue_) + // and one to make sure we only dispatch one authrequest at a time (pending_prompts_). + std::deque<AdbdAuthPacket> output_queue_; + + std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_); + std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_); +}; + +AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) { + if (callbacks->version != 1) { + LOG(ERROR) << "received unknown AdbdAuthCallbacks version " << callbacks->version; + return nullptr; + } + + return new AdbdAuthContext(&callbacks->callbacks.v1); +} + +void adbd_auth_delete(AdbdAuthContext* ctx) { + delete ctx; +} + +void adbd_auth_run(AdbdAuthContext* ctx) { + return ctx->Run(); +} + +void adbd_auth_get_public_keys(AdbdAuthContext* ctx, + bool (*callback)(const char* public_key, size_t len, void* arg), + void* arg) { + ctx->IteratePublicKeys(callback, arg); +} + +uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) { + return ctx->NotifyAuthenticated(std::string_view(public_key, len)); +} + +void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) { + return ctx->NotifyDisconnected(id); +} + +void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, + void* arg) { + ctx->PromptUser(std::string_view(public_key, len), arg); +} + +bool adbd_auth_supports_feature(AdbdAuthFeature) { + return false; +} diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h new file mode 100644 index 0000000000..b7c1cb88cc --- /dev/null +++ b/libs/adbd_auth/include/adbd_auth.h @@ -0,0 +1,65 @@ +#pragma once + +/* + * Copyright (C) 2019 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 <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +extern "C" { + +struct AdbdAuthCallbacksV1 { + // Callback for a successful user authorization. + void (*key_authorized)(void* arg, uint64_t id); +}; + +struct AdbdAuthCallbacks { + uint32_t version; + union { + AdbdAuthCallbacksV1 v1; + } callbacks; +}; + +struct AdbdAuthContext; + +AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks); +void adbd_auth_delete(AdbdAuthContext* ctx); + +void adbd_auth_run(AdbdAuthContext* ctx); + +// Iterate through the list of authorized public keys. +// Return false from the callback to stop iteration. +void adbd_auth_get_public_keys(AdbdAuthContext* ctx, + bool (*callback)(const char* public_key, size_t len, void* arg), + void* arg); + +// Let system_server know that a key has been successfully used for authentication. +uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len); + +// Let system_server know that a connection has been closed. +void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id); + +// Prompt the user to authorize a public key. +// When this happens, a callback will be run on the auth thread with the result. +void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, void* arg); + +enum AdbdAuthFeature { +}; + +bool adbd_auth_supports_feature(AdbdAuthFeature f); + +} diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt new file mode 100644 index 0000000000..d01233c960 --- /dev/null +++ b/libs/adbd_auth/libadbd_auth.map.txt @@ -0,0 +1,13 @@ +LIBADBD_AUTH { + global: + adbd_auth_new; # apex + adbd_auth_delete; # apex + adbd_auth_run; # apex + adbd_auth_get_public_keys; #apex + adbd_auth_notify_auth; # apex + adbd_auth_notify_disconnect; # apex + adbd_auth_prompt_user; # apex + adbd_auth_supports_feature; # apex + local: + *; +}; diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp index ad8287c203..2518b1427d 100644 --- a/libs/arect/Android.bp +++ b/libs/arect/Android.bp @@ -13,13 +13,18 @@ // limitations under the License. ndk_headers { - name: "libarect_headers", + name: "libarect_headers_for_ndk", from: "include/android", to: "android", srcs: ["include/android/*.h"], license: "NOTICE", } +cc_library_headers { + name: "libarect_headers", + export_include_dirs: ["include"], +} + cc_library_static { name: "libarect", host_supported: true, diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp index 60f047fd90..4f0b7d31a2 100644 --- a/libs/binder/AppOpsManager.cpp +++ b/libs/binder/AppOpsManager.cpp @@ -115,23 +115,19 @@ int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t ui } int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) { - return noteOp(op, uid, callingPackage, String16(), String16()); + return noteOp(op, uid, callingPackage, std::unique_ptr<String16>(), + String16("Legacy AppOpsManager.noteOp call")); } int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage, - const String16& featureId, const String16& message) { + const std::unique_ptr<String16>& featureId, const String16& message) { sp<IAppOpsService> service = getService(); int32_t mode = service != nullptr - ? service->noteOperation(op, uid, callingPackage) + ? service->noteOperation(op, uid, callingPackage, featureId) : APP_OPS_MANAGER_UNAVAILABLE_MODE; if (mode == AppOpsManager::MODE_ALLOWED) { - if (message.size() == 0) { - markAppOpNoted(uid, callingPackage, op, featureId, - String16("noteOp from native code")); - } else { - markAppOpNoted(uid, callingPackage, op, featureId, message); - } + markAppOpNoted(uid, callingPackage, op, featureId, message); } return mode; @@ -139,32 +135,34 @@ int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPa int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage, bool startIfModeDefault) { - return startOpNoThrow(op, uid, callingPackage, startIfModeDefault, String16(), String16()); + return startOpNoThrow(op, uid, callingPackage, startIfModeDefault, std::unique_ptr<String16>(), + String16("Legacy AppOpsManager.startOpNoThrow call")); } int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage, - bool startIfModeDefault, const String16& featureId, const String16& message) { + bool startIfModeDefault, const std::unique_ptr<String16>& featureId, + const String16& message) { sp<IAppOpsService> service = getService(); int32_t mode = service != nullptr ? service->startOperation(getToken(service), op, uid, callingPackage, - startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE; + featureId, startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE; if (mode == AppOpsManager::MODE_ALLOWED) { - if (message.size() == 0) { - markAppOpNoted(uid, callingPackage, op, featureId, - String16("startOp from native code")); - } else { - markAppOpNoted(uid, callingPackage, op, featureId, message); - } + markAppOpNoted(uid, callingPackage, op, featureId, message); } return mode; } void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) { + finishOp(op, uid, callingPackage, std::unique_ptr<String16>()); +} + +void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage, + const std::unique_ptr<String16>& callingFeatureId) { sp<IAppOpsService> service = getService(); if (service != nullptr) { - service->finishOperation(getToken(service), op, uid, callingPackage); + service->finishOperation(getToken(service), op, uid, callingPackage, callingFeatureId); } } @@ -207,7 +205,7 @@ bool AppOpsManager::shouldCollectNotes(int32_t opcode) { } void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode, - const String16& featureId, const String16& message) { + const std::unique_ptr<String16>& featureId, const String16& message) { // check it the appops needs to be collected and cache result if (appOpsToNote[opCode] == 0) { if (shouldCollectNotes(opCode)) { @@ -221,11 +219,11 @@ void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int return; } - noteAsyncOp(String16(), uid, packageName, opCode, featureId, message); + noteAsyncOp(std::unique_ptr<String16>(), uid, packageName, opCode, featureId, message); } -void AppOpsManager::noteAsyncOp(const String16& callingPackageName, int32_t uid, - const String16& packageName, int32_t opCode, const String16& featureId, +void AppOpsManager::noteAsyncOp(const std::unique_ptr<String16>& callingPackageName, int32_t uid, + const String16& packageName, int32_t opCode, const std::unique_ptr<String16>& featureId, const String16& message) { sp<IAppOpsService> service = getService(); if (service != nullptr) { diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp index 9760e135a1..b85a5f298e 100644 --- a/libs/binder/IAppOpsService.cpp +++ b/libs/binder/IAppOpsService.cpp @@ -46,12 +46,14 @@ public: return reply.readInt32(); } - virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) { + virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName, + const std::unique_ptr<String16>& featureId) { Parcel data, reply; data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); data.writeInt32(code); data.writeInt32(uid); data.writeString16(packageName); + data.writeString16(featureId); remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply); // fail on exception if (reply.readExceptionCode() != 0) return MODE_ERRORED; @@ -59,13 +61,15 @@ public: } virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid, - const String16& packageName, bool startIfModeDefault) { + const String16& packageName, const std::unique_ptr<String16>& featureId, + bool startIfModeDefault) { Parcel data, reply; data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); data.writeStrongBinder(token); data.writeInt32(code); data.writeInt32(uid); data.writeString16(packageName); + data.writeString16(featureId); data.writeInt32(startIfModeDefault ? 1 : 0); remote()->transact(START_OPERATION_TRANSACTION, data, &reply); // fail on exception @@ -74,13 +78,14 @@ public: } virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid, - const String16& packageName) { + const String16& packageName, const std::unique_ptr<String16>& featureId) { Parcel data, reply; data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); data.writeStrongBinder(token); data.writeInt32(code); data.writeInt32(uid); data.writeString16(packageName); + data.writeString16(featureId); remote()->transact(FINISH_OPERATION_TRANSACTION, data, &reply); } @@ -144,37 +149,16 @@ public: remote()->transact(SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION, data, &reply); } - virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid, - const String16& packageName, int32_t opCode, const String16& featureId, + virtual void noteAsyncOp(const std::unique_ptr<String16>& callingPackageName, int32_t uid, + const String16& packageName, int32_t opCode, const std::unique_ptr<String16>& featureId, const String16& message) { Parcel data, reply; data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor()); - - // Convert empty callingPackage into null string - if (callingPackageName.size() != 0) { - data.writeString16(callingPackageName); - } else { - data.writeString16(nullptr, 0); - } - + data.writeString16(callingPackageName); data.writeInt32(uid); - - // Convert empty packageName into null string - if (packageName.size() != 0) { - data.writeString16(packageName); - } else { - data.writeString16(nullptr, 0); - } - + data.writeString16(packageName); data.writeInt32(opCode); - - // Convert empty featureId into null string - if (featureId.size() != 0) { - data.writeString16(featureId); - } else { - data.writeString16(nullptr, 0); - } - + data.writeString16(featureId); data.writeString16(message); remote()->transact(NOTE_ASYNC_OP_TRANSACTION, data, &reply); } @@ -217,7 +201,9 @@ status_t BnAppOpsService::onTransact( int32_t code = data.readInt32(); int32_t uid = data.readInt32(); String16 packageName = data.readString16(); - int32_t res = noteOperation(code, uid, packageName); + std::unique_ptr<String16> featureId; + data.readString16(&featureId); + int32_t res = noteOperation(code, uid, packageName, featureId); reply->writeNoException(); reply->writeInt32(res); return NO_ERROR; @@ -228,8 +214,11 @@ status_t BnAppOpsService::onTransact( int32_t code = data.readInt32(); int32_t uid = data.readInt32(); String16 packageName = data.readString16(); + std::unique_ptr<String16> featureId; + data.readString16(&featureId); bool startIfModeDefault = data.readInt32() == 1; - int32_t res = startOperation(token, code, uid, packageName, startIfModeDefault); + int32_t res = startOperation(token, code, uid, packageName, featureId, + startIfModeDefault); reply->writeNoException(); reply->writeInt32(res); return NO_ERROR; @@ -240,7 +229,9 @@ status_t BnAppOpsService::onTransact( int32_t code = data.readInt32(); int32_t uid = data.readInt32(); String16 packageName = data.readString16(); - finishOperation(token, code, uid, packageName); + std::unique_ptr<String16> featureId; + data.readString16(&featureId); + finishOperation(token, code, uid, packageName, featureId); reply->writeNoException(); return NO_ERROR; } break; @@ -296,11 +287,13 @@ status_t BnAppOpsService::onTransact( } break; case NOTE_ASYNC_OP_TRANSACTION: { CHECK_INTERFACE(IAppOpsService, data, reply); - String16 callingPackageName = data.readString16(); + std::unique_ptr<String16> callingPackageName; + data.readString16(&callingPackageName); int32_t uid = data.readInt32(); String16 packageName = data.readString16(); int32_t opCode = data.readInt32(); - String16 featureId = data.readString16(); + std::unique_ptr<String16> featureId; + data.readString16(&featureId); String16 message = data.readString16(); noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId, message); reply->writeNoException(); diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index a30df14bd6..4f47db199e 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -72,6 +72,7 @@ public: bool allowIsolated, int dumpsysPriority) override; Vector<String16> listServices(int dumpsysPriority) override; sp<IBinder> waitForService(const String16& name16) override; + bool isDeclared(const String16& name) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { @@ -321,4 +322,12 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) } } +bool ServiceManagerShim::isDeclared(const String16& name) { + bool declared; + if (!mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared).isOk()) { + return false; + } + return declared; +} + } // namespace android diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp index 038e6bf6ea..b21af960d2 100644 --- a/libs/binder/IUidObserver.cpp +++ b/libs/binder/IUidObserver.cpp @@ -56,13 +56,15 @@ public: remote()->transact(ON_UID_IDLE_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY); } - virtual void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq) + virtual void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq, + int32_t capability) { Parcel data, reply; data.writeInterfaceToken(IUidObserver::getInterfaceDescriptor()); data.writeInt32((int32_t) uid); data.writeInt32(procState); data.writeInt64(procStateSeq); + data.writeInt32(capability); remote()->transact(ON_UID_STATE_CHANGED_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY); } }; @@ -104,7 +106,8 @@ status_t BnUidObserver::onTransact( uid_t uid = data.readInt32(); int32_t procState = data.readInt32(); int64_t procStateSeq = data.readInt64(); - onUidStateChanged(uid, procState, procStateSeq); + int32_t capability = data.readInt32(); + onUidStateChanged(uid, procState, procStateSeq, capability); return NO_ERROR; } break; default: diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 7219b47e1e..a9f8ae63fa 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -1449,41 +1449,38 @@ restart_write: return err; } -status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const { - if (size_t(size) > dataAvail()) { - return BAD_VALUE; - } - return read(data, size); -} - status_t Parcel::readByteVector(std::vector<int8_t>* val) const { - if (status_t status = resizeOutVector(val); status != OK) return status; - return readByteVectorInternal(val->data(), val->size()); + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + return readByteVectorInternal(val, size); } status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { - if (status_t status = resizeOutVector(val); status != OK) return status; - return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size()); + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + return readByteVectorInternal(val, size); } status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { - if (status_t status = resizeOutVector(val); status != OK) return status; + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; if (val->get() == nullptr) { - // resizeOutVector does not create the out vector if size is < 0. + // reserveOutVector does not create the out vector if size is < 0. // This occurs when writing a null byte vector. return OK; } - return readByteVectorInternal((*val)->data(), (*val)->size()); + return readByteVectorInternal(val->get(), size); } status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { - if (status_t status = resizeOutVector(val); status != OK) return status; + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; if (val->get() == nullptr) { - // resizeOutVector does not create the out vector if size is < 0. + // reserveOutVector does not create the out vector if size is < 0. // This occurs when writing a null byte vector. return OK; } - return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size()); + return readByteVectorInternal(val->get(), size); } status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index 471b63fb5e..8c7ebbaf36 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -89,4 +89,11 @@ interface IServiceManager { * Unregisters all requests for notifications for a specific callback. */ void unregisterForNotifications(@utf8InCpp String name, IServiceCallback callback); + + /** + * Returns whether a given interface is declared on the device, even if it + * is not started yet. For instance, this could be a service declared in the VINTF + * manifest. + */ + boolean isDeclared(@utf8InCpp String name); } diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp index a9d2b751a9..521d36fced 100644 --- a/libs/binder/fuzzer/Android.bp +++ b/libs/binder/fuzzer/Android.bp @@ -2,6 +2,11 @@ cc_fuzz { name: "binder_parcel_fuzzer", defaults: ["libbinder_ndk_host_user"], host_supported: true, + + fuzz_config: { + cc: ["smoreland@google.com"], + }, + srcs: [ "binder.cpp", "binder_ndk.cpp", diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h index 2744ce126d..22a017941e 100644 --- a/libs/binder/include/binder/AppOpsManager.h +++ b/libs/binder/include/binder/AppOpsManager.h @@ -134,21 +134,26 @@ public: // const String16&) instead int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage); int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage, - const String16& featureId, const String16& message); + const std::unique_ptr<String16>& featureId, const String16& message); // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&, // const String16&) instead int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage, bool startIfModeDefault); int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage, - bool startIfModeDefault, const String16& featureId, const String16& message); + bool startIfModeDefault, const std::unique_ptr<String16>& featureId, + const String16& message); + // @Deprecated, use finishOp(int32_t, int32_t, const String16&, bool, const String16&) instead void finishOp(int32_t op, int32_t uid, const String16& callingPackage); + void finishOp(int32_t op, int32_t uid, const String16& callingPackage, + const std::unique_ptr<String16>& featureId); void startWatchingMode(int32_t op, const String16& packageName, const sp<IAppOpsCallback>& callback); void stopWatchingMode(const sp<IAppOpsCallback>& callback); int32_t permissionToOpCode(const String16& permission); void setCameraAudioRestriction(int32_t mode); - void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName, - int32_t opCode, const String16& featureId, const String16& message); + void noteAsyncOp(const std::unique_ptr<String16>& callingPackageName, int32_t uid, + const String16& packageName, int32_t opCode, const std::unique_ptr<String16>& featureId, + const String16& message); private: Mutex mLock; @@ -156,7 +161,7 @@ private: sp<IAppOpsService> getService(); void markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode, - const String16& featureId, const String16& message); + const std::unique_ptr<String16>& featureId, const String16& message); bool shouldCollectNotes(int32_t opCode); }; diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h index ad34bc5692..15ba005cec 100644 --- a/libs/binder/include/binder/IAppOpsService.h +++ b/libs/binder/include/binder/IAppOpsService.h @@ -35,11 +35,13 @@ public: DECLARE_META_INTERFACE(AppOpsService) virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0; - virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0; + virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName, + const std::unique_ptr<String16>& featureId) = 0; virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid, - const String16& packageName, bool startIfModeDefault) = 0; + const String16& packageName, const std::unique_ptr<String16>& featureId, + bool startIfModeDefault) = 0; virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid, - const String16& packageName) = 0; + const String16& packageName, const std::unique_ptr<String16>& featureId) = 0; virtual void startWatchingMode(int32_t op, const String16& packageName, const sp<IAppOpsCallback>& callback) = 0; virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0; @@ -48,8 +50,8 @@ public: virtual int32_t checkAudioOperation(int32_t code, int32_t usage,int32_t uid, const String16& packageName) = 0; virtual void setCameraAudioRestriction(int32_t mode) = 0; - virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid, - const String16& packageName, int32_t opCode, const String16& featureId, + virtual void noteAsyncOp(const std::unique_ptr<String16>& callingPackageName, int32_t uid, + const String16& packageName, int32_t opCode, const std::unique_ptr<String16>& featureId, const String16& message) = 0; virtual bool shouldCollectNotes(int32_t opCode) = 0; diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index a675513793..2c4326393e 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -88,6 +88,14 @@ public: * Returns nullptr only for permission problem or fatal error. */ virtual sp<IBinder> waitForService(const String16& name) = 0; + + /** + * Check if a service is declared (e.g. VINTF manifest). + * + * If this returns true, waitForService should always be able to return the + * service. + */ + virtual bool isDeclared(const String16& name) = 0; }; sp<IServiceManager> defaultServiceManager(); @@ -99,6 +107,34 @@ sp<INTERFACE> waitForService(const String16& name) { } template<typename INTERFACE> +sp<INTERFACE> waitForDeclaredService(const String16& name) { + const sp<IServiceManager> sm = defaultServiceManager(); + if (!sm->isDeclared(name)) return nullptr; + return interface_cast<INTERFACE>(sm->waitForService(name)); +} + +template <typename INTERFACE> +sp<INTERFACE> checkDeclaredService(const String16& name) { + const sp<IServiceManager> sm = defaultServiceManager(); + if (!sm->isDeclared(name)) return nullptr; + return interface_cast<INTERFACE>(sm->checkService(name)); +} + +template<typename INTERFACE> +sp<INTERFACE> waitForVintfService( + const String16& instance = String16("default")) { + return waitForDeclaredService<INTERFACE>( + INTERFACE::descriptor + String16("/") + instance); +} + +template<typename INTERFACE> +sp<INTERFACE> checkVintfService( + const String16& instance = String16("default")) { + return checkDeclaredService<INTERFACE>( + INTERFACE::descriptor + String16("/") + instance); +} + +template<typename INTERFACE> status_t getService(const String16& name, sp<INTERFACE>* outService) { const sp<IServiceManager> sm = defaultServiceManager(); diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include/binder/IUidObserver.h index 09e50a9de8..d0703901d7 100644 --- a/libs/binder/include/binder/IUidObserver.h +++ b/libs/binder/include/binder/IUidObserver.h @@ -34,7 +34,8 @@ public: virtual void onUidGone(uid_t uid, bool disabled) = 0; virtual void onUidActive(uid_t uid) = 0; virtual void onUidIdle(uid_t uid, bool disabled) = 0; - virtual void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq) = 0; + virtual void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq, + int32_t capability) = 0; enum { ON_UID_GONE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 0f8ababd6b..d4bb85b102 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -356,6 +356,11 @@ public: status_t resizeOutVector(std::vector<T>* val) const; template<typename T> status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const; + template<typename T> + status_t reserveOutVector(std::vector<T>* val, size_t* size) const; + template<typename T> + status_t reserveOutVector(std::unique_ptr<std::vector<T>>* val, + size_t* size) const; // Like Parcel.java's readExceptionCode(). Reads the first int32 // off of a Parcel's header, returning 0 or the negative error @@ -475,7 +480,8 @@ private: status_t readEnum(T* pArg) const; status_t writeByteVectorInternal(const int8_t* data, size_t size); - status_t readByteVectorInternal(int8_t* data, size_t size) const; + template<typename T> + status_t readByteVectorInternal(std::vector<T>* val, size_t size) const; template<typename T, typename U> status_t unsafeReadTypedVector(std::vector<T>* val, @@ -720,6 +726,42 @@ status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const { } template<typename T> +status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const { + int32_t read_size; + status_t err = readInt32(&read_size); + if (err != NO_ERROR) { + return err; + } + + if (read_size < 0) { + return UNEXPECTED_NULL; + } + *size = static_cast<size_t>(read_size); + val->reserve(*size); + return OK; +} + +template<typename T> +status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val, + size_t* size) const { + int32_t read_size; + status_t err = readInt32(&read_size); + if (err != NO_ERROR) { + return err; + } + + if (read_size >= 0) { + *size = static_cast<size_t>(read_size); + val->reset(new std::vector<T>()); + (*val)->reserve(*size); + } else { + val->reset(); + } + + return OK; +} + +template<typename T> status_t Parcel::readStrongBinder(sp<T>* val) const { sp<IBinder> tmp; status_t ret = readStrongBinder(&tmp); @@ -988,20 +1030,33 @@ status_t Parcel::readEnum(T* pArg) const { return readInt64(reinterpret_cast<int64_t *>(pArg)); } +template<typename T> +inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const { + // readByteVectorInternal expects a vector that has been reserved (but not + // resized) to have the provided size. + const T* data = reinterpret_cast<const T*>(readInplace(size)); + if (!data) return BAD_VALUE; + val->clear(); + val->insert(val->begin(), data, data+size); + return NO_ERROR; +} + template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> status_t Parcel::readEnumVector(std::vector<T>* val) const { - if (status_t status = resizeOutVector(val); status != OK) return status; - return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size()); + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + return readByteVectorInternal(val, size); } template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const { - if (status_t status = resizeOutVector(val); status != OK) return status; + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; if (val->get() == nullptr) { - // resizeOutVector does not create the out vector if size is < 0. + // reserveOutVector does not create the out vector if size is < 0. // This occurs when writing a null Enum vector. return OK; } - return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size()); + return readByteVectorInternal(val->get(), size); } template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> status_t Parcel::readEnumVector(std::vector<T>* val) const { diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h index 662e56e864..4635ad84c6 100644 --- a/libs/binder/include/binder/ParcelFileDescriptor.h +++ b/libs/binder/include/binder/ParcelFileDescriptor.h @@ -42,6 +42,24 @@ public: android::status_t writeToParcel(android::Parcel* parcel) const override; android::status_t readFromParcel(const android::Parcel* parcel) override; + inline bool operator!=(const ParcelFileDescriptor& rhs) const { + return mFd != rhs.mFd; + } + inline bool operator<(const ParcelFileDescriptor& rhs) const { + return mFd < rhs.mFd; + } + inline bool operator<=(const ParcelFileDescriptor& rhs) const { + return mFd <= rhs.mFd; + } + inline bool operator==(const ParcelFileDescriptor& rhs) const { + return mFd == rhs.mFd; + } + inline bool operator>(const ParcelFileDescriptor& rhs) const { + return mFd > rhs.mFd; + } + inline bool operator>=(const ParcelFileDescriptor& rhs) const { + return mFd >= rhs.mFd; + } private: android::base::unique_fd mFd; }; diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp index 22344b6173..fa07d040db 100644 --- a/libs/binder/ndk/Android.bp +++ b/libs/binder/ndk/Android.bp @@ -22,6 +22,8 @@ cc_defaults { cflags: [ "-D__INTRODUCED_IN(n)=", "-D__assert(a,b,c)=", + // We want all the APIs to be available on the host. + "-D__ANDROID_API__=10000", ], }, }, diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h index dc3c8d2e3a..946ccb79a5 100644 --- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h +++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h @@ -21,7 +21,7 @@ /** * @file binder_auto_utils.h - * @brief These objects provide a more C++-like thin interface to the . + * @brief These objects provide a more C++-like thin interface to the binder. */ #pragma once @@ -159,13 +159,17 @@ class ScopedAResource { */ T* getR() { return &mT; } - // copy-constructing, or move/copy assignment is disallowed + // copy-constructing/assignment is disallowed ScopedAResource(const ScopedAResource&) = delete; ScopedAResource& operator=(const ScopedAResource&) = delete; - ScopedAResource& operator=(ScopedAResource&&) = delete; - // move-constructing is okay + // move-constructing/assignment is okay ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; } + ScopedAResource& operator=(ScopedAResource&& other) { + set(other.mT); + other.mT = DEFAULT; + return *this; + } private: T mT; @@ -197,6 +201,7 @@ class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delet explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {} ~ScopedAStatus() {} ScopedAStatus(ScopedAStatus&&) = default; + ScopedAStatus& operator=(ScopedAStatus&&) = default; /** * See AStatus_isOk. @@ -219,9 +224,31 @@ class ScopedAStatus : public impl::ScopedAResource<AStatus*, void, AStatus_delet binder_status_t getStatus() const { return AStatus_getStatus(get()); } /** - * Convenience method for okay status. + * See AStatus_getMessage + */ + const char* getMessage() const { return AStatus_getMessage(get()); } + + /** + * Convenience methods for creating scoped statuses. */ static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); } + static ScopedAStatus fromExceptionCode(binder_exception_t exception) { + return ScopedAStatus(AStatus_fromExceptionCode(exception)); + } + static ScopedAStatus fromExceptionCodeWithMessage(binder_exception_t exception, + const char* message) { + return ScopedAStatus(AStatus_fromExceptionCodeWithMessage(exception, message)); + } + static ScopedAStatus fromServiceSpecificError(int32_t serviceSpecific) { + return ScopedAStatus(AStatus_fromServiceSpecificError(serviceSpecific)); + } + static ScopedAStatus fromServiceSpecificErrorWithMessage(int32_t serviceSpecific, + const char* message) { + return ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(serviceSpecific, message)); + } + static ScopedAStatus fromStatus(binder_status_t status) { + return ScopedAStatus(AStatus_fromStatus(status)); + } }; /** diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index 160739b044..4d5c044232 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h @@ -34,7 +34,7 @@ #include <android/binder_status.h> __BEGIN_DECLS -#if __ANDROID_API__ >= __ANDROID_API_Q__ +#if __ANDROID_API__ >= 29 // Also see TF_* in kernel's binder.h typedef uint32_t binder_flags_t; @@ -165,6 +165,8 @@ typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, transacti * * None of these parameters can be null. * + * Available since API level 29. + * * \param interfaceDescriptor this is a unique identifier for the class. This is used internally for * sanity checks on transactions. * \param onCreate see AIBinder_Class_onCreate. @@ -199,6 +201,8 @@ typedef binder_status_t (*AIBinder_onDump)(AIBinder* binder, int fd, const char* * If this isn't set, nothing will be dumped when dump is called (for instance with * android.os.Binder#dump). Must be called before any instance of the class is created. * + * Available since API level 29. + * * \param dump function to call when an instance of this binder class is being dumped. */ void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29); @@ -220,6 +224,8 @@ void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __I * these two objects are actually equal using the AIBinder pointer alone (which they should be able * to do). Also see the suggested memory ownership model suggested above. * + * Available since API level 29. + * * \param clazz the type of the object to be created. * \param args the args to pass to AIBinder_onCreate for that class. * @@ -231,6 +237,8 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* /** * If this is hosted in a process other than the current one. * + * Available since API level 29. + * * \param binder the binder being queried. * * \return true if the AIBinder represents an object in another process. @@ -244,6 +252,8 @@ bool AIBinder_isRemote(const AIBinder* binder) __INTRODUCED_IN(29); * updated as the result of a transaction made using AIBinder_transact, but it will also be updated * based on the results of bookkeeping or other transactions made internally. * + * Available since API level 29. + * * \param binder the binder being queried. * * \return true if the binder is alive. @@ -255,6 +265,8 @@ bool AIBinder_isAlive(const AIBinder* binder) __INTRODUCED_IN(29); * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a * sanity check. * + * Available since API level 29. + * * \param binder the binder being queried. * * \return STATUS_OK if the ping succeeds. @@ -264,7 +276,9 @@ binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29); /** * Built-in transaction for all binder objects. This dumps information about a given binder. * - * See also AIBinder_Class_setOnDump, AIBinder_onDump + * See also AIBinder_Class_setOnDump, AIBinder_onDump. + * + * Available since API level 29. * * \param binder the binder to dump information about * \param fd where information should be dumped to @@ -287,6 +301,8 @@ binder_status_t AIBinder_dump(AIBinder* binder, int fd, const char** args, uint3 * * If binder is local, this will return STATUS_INVALID_OPERATION. * + * Available since API level 29. + * * \param binder the binder object you want to receive death notifications from. * \param recipient the callback that will receive notifications when/if the binder dies. * \param cookie the value that will be passed to the death recipient on death. @@ -306,6 +322,8 @@ binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* * If the binder dies, it will automatically unlink. If the binder is deleted, it will be * automatically unlinked. * + * Available since API level 29. + * * \param binder the binder object to remove a previously linked death recipient from. * \param recipient the callback to remove. * \param cookie the cookie used to link to death. @@ -322,9 +340,11 @@ binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient * This can be used with higher-level system services to determine the caller's identity and check * permissions. * + * Available since API level 29. + * * \return calling uid or the current process's UID if this thread isn't processing a transaction. */ -uid_t AIBinder_getCallingUid(); +uid_t AIBinder_getCallingUid() __INTRODUCED_IN(29); /** * This returns the calling PID assuming that this thread is called from a thread that is processing @@ -335,14 +355,18 @@ uid_t AIBinder_getCallingUid(); * calling process dies and is replaced with another process with elevated permissions and the same * PID. * + * Available since API level 29. + * * \return calling pid or the current process's PID if this thread isn't processing a transaction. * If the transaction being processed is a oneway transaction, then this method will return 0. */ -pid_t AIBinder_getCallingPid(); +pid_t AIBinder_getCallingPid() __INTRODUCED_IN(29); /** * This can only be called if a strong reference to this object already exists in process. * + * Available since API level 29. + * * \param binder the binder object to add a refcount to. */ void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29); @@ -350,6 +374,8 @@ void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29); /** * This will delete the object and call onDestroy once the refcount reaches zero. * + * Available since API level 29. + * * \param binder the binder object to remove a refcount from. */ void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29); @@ -357,6 +383,8 @@ void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29); /** * For debugging only! * + * Available since API level 29. + * * \param binder the binder object to retrieve the refcount of. * * \return the number of strong-refs on this binder in this process. If binder is null, this will be @@ -373,6 +401,8 @@ int32_t AIBinder_debugGetRefCount(AIBinder* binder) __INTRODUCED_IN(29); * This returns true if the class association succeeds. If it fails, no change is made to the * binder object. * + * Available since API level 29. + * * \param binder the object to attach the class to. * \param clazz the clazz to attach to binder. * @@ -383,6 +413,8 @@ bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) __IN /** * Returns the class that this binder was constructed with or associated with. * + * Available since API level 29. + * * \param binder the object that is being queried. * * \return the class that this binder is associated with. If this binder wasn't created with @@ -394,6 +426,8 @@ const AIBinder_Class* AIBinder_getClass(AIBinder* binder) __INTRODUCED_IN(29); * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns * null), this also returns null. For a remote binder, this will always return null. * + * Available since API level 29. + * * \param binder the object that is being queried. * * \return the userdata returned from AIBinder_onCreate when this object was created. This may be @@ -422,6 +456,8 @@ void* AIBinder_getUserData(AIBinder* binder) __INTRODUCED_IN(29); * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be * deleted with AParcel_delete. * + * Available since API level 29. + * * \param binder the binder object to start a transaction on. * \param in out parameter for input data to the transaction. * @@ -442,6 +478,8 @@ binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) __IN * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller * and must be released with AParcel_delete when finished reading. * + * Available since API level 29. + * * \param binder the binder object to transact on. * \param code the implementation-specific code representing which transaction should be taken. * \param in the implementation-specific input data to this transaction. @@ -459,6 +497,8 @@ binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, APa * This does not take any ownership of the input binder, but it can be used to retrieve it if * something else in some process still holds a reference to it. * + * Available since API level 29. + * * \param binder object to create a weak pointer to. * * \return object representing a weak pointer to binder (or null if binder is null). @@ -469,6 +509,8 @@ __attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* b /** * Deletes the weak reference. This will have no impact on the lifetime of the binder. * + * Available since API level 29. + * * \param weakBinder object created with AIBinder_Weak_new. */ void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29); @@ -477,6 +519,8 @@ void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29); * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns * null. * + * Available since API level 29. + * * \param weakBinder weak pointer to attempt retrieving the original object from. * * \return an AIBinder object with one refcount given to the caller or null. @@ -487,6 +531,8 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Wea /** * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath. * + * Available since API level 29. + * * \param cookie the cookie passed to AIBinder_linkToDeath. */ typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_IN(29); @@ -494,6 +540,8 @@ typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_ /** * Creates a new binder death recipient. This can be attached to multiple different binder objects. * + * Available since API level 29. + * * \param onBinderDied the callback to call when this death recipient is invoked. * * \return the newly constructed object (or null if onBinderDied is null). @@ -505,19 +553,23 @@ __attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecip * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before * calling this as these will all be automatically unlinked. * + * Available since API level 29. + * * \param recipient the binder to delete (previously created with AIBinder_DeathRecipient_new). */ void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29); -#endif //__ANDROID_API__ >= __ANDROID_API_Q__ +#endif //__ANDROID_API__ >= 29 -#if __ANDROID_API__ >= __ANDROID_API_R__ +#if __ANDROID_API__ >= 30 /** * Gets the extension registered with AIBinder_setExtension. * * See AIBinder_setExtension. * + * Available since API level 30. + * * \param binder the object to get the extension of. * \param outExt the returned extension object. Will be null if there is no extension set or * non-null with one strong ref count. @@ -570,6 +622,8 @@ binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INT * // if bar is null, then there is no extension or a different * // type of extension * + * Available since API level 30. + * * \param binder the object to get the extension on. Must be local. * \param ext the extension to set (binder will hold a strong reference to this) * @@ -578,7 +632,7 @@ binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INT */ binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30); -#endif //__ANDROID_API__ >= __ANDROID_API_R__ +#endif //__ANDROID_API__ >= 30 __END_DECLS diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h index 124f36c55b..be3029c3ff 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h @@ -31,7 +31,7 @@ #include <jni.h> __BEGIN_DECLS -#if __ANDROID_API__ >= __ANDROID_API_Q__ +#if __ANDROID_API__ >= 29 /** * Converts an android.os.IBinder object into an AIBinder* object. @@ -40,6 +40,8 @@ __BEGIN_DECLS * AIBinder object, the original object is returned. The returned object has one refcount * associated with it, and so this should be accompanied with an AIBinder_decStrong call. * + * Available since API level 29. + * * \param env Java environment. * \param binder android.os.IBinder java object. * @@ -55,6 +57,8 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* en * If either env or the binder is null, null is returned. If this binder object was originally an * IBinder object, the original java object will be returned. * + * Available since API level 29. + * * \param env Java environment. * \param binder the object to convert. * @@ -63,7 +67,7 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* en __attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) __INTRODUCED_IN(29); -#endif //__ANDROID_API__ >= __ANDROID_API_Q__ +#endif //__ANDROID_API__ >= 29 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h index 8c4170754a..86b75b8c61 100644 --- a/libs/binder/ndk/include_ndk/android/binder_parcel.h +++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h @@ -35,7 +35,7 @@ struct AIBinder; typedef struct AIBinder AIBinder; __BEGIN_DECLS -#if __ANDROID_API__ >= __ANDROID_API_Q__ +#if __ANDROID_API__ >= 29 /** * This object represents a package of data that can be sent between processes. When transacting, an @@ -49,6 +49,8 @@ typedef struct AParcel AParcel; /** * Cleans up a parcel. * + * Available since API level 29. + * * \param parcel A parcel returned by AIBinder_prepareTransaction or AIBinder_transact when a * transaction is being aborted. */ @@ -57,6 +59,8 @@ void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29); /** * Sets the position within the parcel. * + * Available since API level 29. + * * \param parcel The parcel of which to set the position. * \param position Position of the parcel to set. This must be a value returned by * AParcel_getDataPosition. Positions are constant for a given parcel between processes. @@ -69,6 +73,8 @@ binder_status_t AParcel_setDataPosition(const AParcel* parcel, int32_t position) /** * Gets the current position within the parcel. * + * Available since API level 29. + * * \param parcel The parcel of which to get the position. * * \return The size of the parcel. This will always be greater than 0. The values returned by this @@ -389,6 +395,8 @@ typedef bool (*AParcel_byteArrayAllocator)(void* arrayData, int32_t length, int8 * Writes an AIBinder to the next location in a non-null parcel. Can be null. This does not take any * refcounts of ownership of the binder from the client. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param binder the value to write to the parcel. * @@ -400,6 +408,8 @@ binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) __I * Reads an AIBinder from the next location in a non-null parcel. One strong ref-count of ownership * is passed to the caller of this function. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param binder the out parameter for what is read from the parcel. This may be null. * @@ -414,12 +424,14 @@ binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binde * * This corresponds to the SDK's android.os.ParcelFileDescriptor. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor). * * \return STATUS_OK on successful write. */ -binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd); +binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) __INTRODUCED_IN(29); /** * Reads an int from the next location in a non-null parcel. @@ -428,13 +440,16 @@ binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd); * * This corresponds to the SDK's android.os.ParcelFileDescriptor. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param fd the out parameter for what is read from the parcel (or -1 to represent a null * ParcelFileDescriptor) * * \return STATUS_OK on successful write. */ -binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd); +binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) + __INTRODUCED_IN(29); /** * Writes an AStatus object to the next location in a non-null parcel. @@ -445,6 +460,8 @@ binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) * this happens or if writing the status object itself fails, the return value from this function * should be propagated to the client, and AParcel_readStatusHeader shouldn't be called. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param status the value to write to the parcel. * @@ -457,6 +474,8 @@ binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status * Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller * of this function. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param status the out parameter for what is read from the parcel. * @@ -470,6 +489,8 @@ binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status * * If length is -1, and string is nullptr, this will write a 'null' string to the parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param string the null-terminated string to write to the parcel, at least of size 'length'. * \param length the length of the string to be written. @@ -487,6 +508,8 @@ binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t * the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator * will be called with length -1. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param stringData some external representation of a string. * \param allocator allocator that will be called once the size of the string is known. @@ -504,6 +527,8 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData, * returned from this function will be used to fill out the data from the parcel. If length is -1, * this will write a 'null' string array to the binder buffer. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData some external representation of an array. * \param length the length of the array to be written. @@ -526,6 +551,8 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, * the contents of the string that is read. If the string array being read is 'null', this will * instead just pass -1 to AParcel_stringArrayAllocator. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called with arrayData once the size of the output @@ -543,6 +570,8 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, /** * Writes an array of parcelables (user-defined types) to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -562,6 +591,8 @@ binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayD * length is greater than zero, elementReader will be called for every index to read the * corresponding parcelable. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -578,6 +609,8 @@ binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayDa /** * Writes int32_t value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -588,6 +621,8 @@ binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) __INTRODUCED_ /** * Writes uint32_t value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -598,6 +633,8 @@ binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) __INTRODUCE /** * Writes int64_t value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -608,6 +645,8 @@ binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) __INTRODUCED_ /** * Writes uint64_t value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -618,6 +657,8 @@ binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) __INTRODUCE /** * Writes float value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -628,6 +669,8 @@ binder_status_t AParcel_writeFloat(AParcel* parcel, float value) __INTRODUCED_IN /** * Writes double value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -638,6 +681,8 @@ binder_status_t AParcel_writeDouble(AParcel* parcel, double value) __INTRODUCED_ /** * Writes bool value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -648,6 +693,8 @@ binder_status_t AParcel_writeBool(AParcel* parcel, bool value) __INTRODUCED_IN(2 /** * Writes char16_t value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -658,6 +705,8 @@ binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) __INTRODUCED_ /** * Writes int8_t value to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param value the value to write to the parcel. * @@ -668,6 +717,8 @@ binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) __INTRODUCED_IN /** * Reads into int32_t value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -678,6 +729,8 @@ binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) __INTRO /** * Reads into uint32_t value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -688,6 +741,8 @@ binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) __INT /** * Reads into int64_t value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -698,6 +753,8 @@ binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) __INTRO /** * Reads into uint64_t value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -708,6 +765,8 @@ binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) __INT /** * Reads into float value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -718,6 +777,8 @@ binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) __INTRODU /** * Reads into double value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -728,6 +789,8 @@ binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) __INTRO /** * Reads into bool value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -738,6 +801,8 @@ binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) __INTRODUCE /** * Reads into char16_t value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -748,6 +813,8 @@ binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) __INTRO /** * Reads into int8_t value from the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param value the value to read from the parcel. * @@ -758,6 +825,8 @@ binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) __INTRODU /** * Writes an array of int32_t to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -770,6 +839,8 @@ binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayDat /** * Writes an array of uint32_t to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -782,6 +853,8 @@ binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayD /** * Writes an array of int64_t to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -794,6 +867,8 @@ binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayDat /** * Writes an array of uint64_t to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -806,6 +881,8 @@ binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayD /** * Writes an array of float to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -818,6 +895,8 @@ binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, /** * Writes an array of double to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -833,6 +912,8 @@ binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayDat * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying * values to write to the parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData some external representation of an array. * \param length the length of arrayData (or -1 if this represents a null array). @@ -846,6 +927,8 @@ binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, i /** * Writes an array of char16_t to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -858,6 +941,8 @@ binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayDat /** * Writes an array of int8_t to the next location in a non-null parcel. * + * Available since API level 29. + * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. @@ -874,6 +959,8 @@ binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -890,6 +977,8 @@ binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -906,6 +995,8 @@ binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -922,6 +1013,8 @@ binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -938,6 +1031,8 @@ binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -954,6 +1049,8 @@ binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -969,6 +1066,8 @@ binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData, * First, allocator will be called with the length of the array. Then, for every i in [0, length), * setter(arrayData, i, x) will be called where x is the value at the associated index. * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -988,6 +1087,8 @@ binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -1004,6 +1105,8 @@ binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData, * length is greater than zero, the buffer returned by the allocator will be filled with the * corresponding data * + * Available since API level 29. + * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. @@ -1015,7 +1118,7 @@ binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData, // @END-PRIMITIVE-READ-WRITE -#endif //__ANDROID_API__ >= __ANDROID_API_Q__ +#endif //__ANDROID_API__ >= 29 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h index 2671b9b6fc..78d70f87ba 100644 --- a/libs/binder/ndk/include_ndk/android/binder_status.h +++ b/libs/binder/ndk/include_ndk/android/binder_status.h @@ -30,7 +30,7 @@ #include <sys/cdefs.h> __BEGIN_DECLS -#if __ANDROID_API__ >= __ANDROID_API_Q__ +#if __ANDROID_API__ >= 29 enum { STATUS_OK = 0, @@ -105,6 +105,8 @@ typedef struct AStatus AStatus; /** * New status which is considered a success. * + * Available since API level 29. + * * \return a newly constructed status object that the caller owns. */ __attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29); @@ -112,6 +114,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29) /** * New status with exception code. * + * Available since API level 29. + * * \param exception the code that this status should represent. If this is EX_NONE, then this * constructs an non-error status object. * @@ -123,6 +127,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCode(binder_ex /** * New status with exception code and message. * + * Available since API level 29. + * * \param exception the code that this status should represent. If this is EX_NONE, then this * constructs an non-error status object. * \param message the error message to associate with this status object. @@ -137,6 +143,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCodeWithMessag * * This is considered to be EX_TRANSACTION_FAILED with extra information. * + * Available since API level 29. + * * \param serviceSpecific an implementation defined error code. * * \return a newly constructed status object that the caller owns. @@ -149,6 +157,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificError( * * This is considered to be EX_TRANSACTION_FAILED with extra information. * + * Available since API level 29. + * * \param serviceSpecific an implementation defined error code. * \param message the error message to associate with this status object. * @@ -162,6 +172,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWit * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning * an AStatus instance. * + * Available since API level 29. + * * \param a low-level error to associate with this status object. * * \return a newly constructed status object that the caller owns. @@ -173,6 +185,8 @@ __attribute__((warn_unused_result)) AStatus* AStatus_fromStatus(binder_status_t * Whether this object represents a successful transaction. If this function returns true, then * AStatus_getExceptionCode will return EX_NONE. * + * Available since API level 29. + * * \param status the status being queried. * * \return whether the status represents a successful transaction. For more details, see below. @@ -182,6 +196,8 @@ bool AStatus_isOk(const AStatus* status) __INTRODUCED_IN(29); /** * The exception that this status object represents. * + * Available since API level 29. + * * \param status the status being queried. * * \return the exception code that this object represents. @@ -194,6 +210,8 @@ binder_exception_t AStatus_getExceptionCode(const AStatus* status) __INTRODUCED_ * 0, the status object may still represent a different exception or status. To find out if this * transaction as a whole is okay, use AStatus_isOk instead. * + * Available since API level 29. + * * \param status the status being queried. * * \return the service-specific error code if the exception code is EX_SERVICE_SPECIFIC or 0. @@ -206,6 +224,8 @@ int32_t AStatus_getServiceSpecificError(const AStatus* status) __INTRODUCED_IN(2 * object may represent a different exception or a service specific error. To find out if this * transaction as a whole is okay, use AStatus_isOk instead. * + * Available since API level 29. + * * \param status the status being queried. * * \return the status code if the exception code is EX_TRANSACTION_FAILED or 0. @@ -218,6 +238,8 @@ binder_status_t AStatus_getStatus(const AStatus* status) __INTRODUCED_IN(29); * * The returned string has the lifetime of the status object passed into this function. * + * Available since API level 29. + * * \param status the status being queried. * * \return the message associated with this error. @@ -227,11 +249,13 @@ const char* AStatus_getMessage(const AStatus* status) __INTRODUCED_IN(29); /** * Deletes memory associated with the status instance. * + * Available since API level 29. + * * \param status the status to delete, returned from AStatus_newOk or one of the AStatus_from* APIs. */ void AStatus_delete(AStatus* status) __INTRODUCED_IN(29); -#endif //__ANDROID_API__ >= __ANDROID_API_Q__ +#endif //__ANDROID_API__ >= 29 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp index ae2276e794..f18e118bc9 100644 --- a/libs/binder/ndk/parcel.cpp +++ b/libs/binder/ndk/parcel.cpp @@ -50,7 +50,7 @@ binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int if (length < -1) return STATUS_BAD_VALUE; if (!isNullArray && length < 0) { - LOG(ERROR) << __func__ << ": null array must be used with length == -1."; + LOG(ERROR) << __func__ << ": non-null array but length is " << length; return STATUS_BAD_VALUE; } if (isNullArray && length > 0) { diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh deleted file mode 100755 index 698d291cb1..0000000000 --- a/libs/binder/ndk/scripts/format.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2018 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. - -set -e - -echo "Formatting code" - -bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp") -clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\)) diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh deleted file mode 100755 index 1eba892021..0000000000 --- a/libs/binder/ndk/update.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (C) 2018 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. - - -set -ex - -# This script makes sure that the source code is in sync with the various scripts -./scripts/gen_parcel_helper.py -./scripts/format.sh diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp index 0bee56c943..1f2779abf0 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -134,18 +134,15 @@ TEST(BinderStability, OnlyVintfStabilityBinderNeedsVintfDeclaration) { TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) { sp<IBinder> vintfServer = BadStableBinder::vintf(); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("."), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("/"), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("/."), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("a.d.IFoo"), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("foo"), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("a.d.IFoo/foo"), vintfServer)); + for (const char* instance8 : { + ".", "/", "/.", "a.d.IFoo", "foo", "a.d.IFoo/foo" + }) { + String16 instance (instance8); + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8; + EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8; + } } TEST(BinderStability, CantCallVendorBinderInSystemContext) { diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index e6d442d225..b360a268db 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -17,8 +17,16 @@ cc_library_headers { export_include_dirs: ["include"], // we must build this module to get the required header as that is generated - export_shared_lib_headers: [ "android.hidl.token@1.0-utils" ], - shared_libs: [ "android.hidl.token@1.0-utils" ], + export_shared_lib_headers: [ + "android.hidl.token@1.0-utils", + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", + ], + shared_libs: [ + "android.hidl.token@1.0-utils", + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", + ], } cc_library_shared { diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 9a5017577d..3c31d7439f 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -33,6 +33,7 @@ BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, mBufferItemConsumer->setBufferFreedListener(this); mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight); mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888); + mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint()); } void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) { @@ -41,6 +42,7 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int mWidth = width; mHeight = height; mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight); + mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint()); } static void transactionCallbackThunk(void* context, nsecs_t latchTime, @@ -63,6 +65,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence ? stats[0].previousReleaseFence : Fence::NO_FENCE); mNextCallbackBufferItem = BufferItem(); + mBufferItemConsumer->setTransformHint(stats[0].transformHint); } mDequeueWaitCV.notify_all(); decStrong((void*)transactionCallbackThunk); diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 09c74deee4..a307d04a16 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -512,6 +512,12 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou mCore->mSharedBufferSlot = found; mSlots[found].mBufferState.mShared = true; } + + if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) { + if (mCore->mConsumerListener != nullptr) { + mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId()); + } + } } // Autolock scope if (returnFlags & BUFFER_NEEDS_REALLOCATION) { @@ -528,6 +534,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou if (error == NO_ERROR && !mCore->mIsAbandoned) { graphicBuffer->setGenerationNumber(mCore->mGenerationNumber); mSlots[*outSlot].mGraphicBuffer = graphicBuffer; + if (mCore->mConsumerListener != nullptr) { + mCore->mConsumerListener->onFrameDequeued( + mSlots[*outSlot].mGraphicBuffer->getId()); + } } mCore->mIsAllocating = false; @@ -580,11 +590,6 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou } addAndGetFrameTimestamps(nullptr, outTimestamps); - { // Autolock scope - std::lock_guard<std::mutex> lock(mCore->mMutex); - mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId()); - } - return returnFlags; } diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index b98e48b52a..621cf5950b 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -49,25 +49,28 @@ public: status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, const sp<IBinder>& parent, LayerMetadata metadata, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) override { + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, + uint32_t* outTransformHint) override { return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE, name, width, height, format, flags, parent, std::move(metadata), - handle, gbp); + handle, gbp, + outTransformHint); } status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, const sp<IGraphicBufferProducer>& parent, LayerMetadata metadata, sp<IBinder>* handle, - sp<IGraphicBufferProducer>* gbp) override { + sp<IGraphicBufferProducer>* gbp, + uint32_t* outTransformHint) override { return callRemote<decltype( &ISurfaceComposerClient::createWithSurfaceParent)>(Tag::CREATE_WITH_SURFACE_PARENT, name, width, height, format, flags, parent, - std::move(metadata), handle, - gbp); + std::move(metadata), handle, gbp, + outTransformHint); } status_t clearLayerFrameStats(const sp<IBinder>& handle) const override { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e9079efd29..7023311eb9 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -224,6 +224,8 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceStats.acquireTime, surfaceStats.previousReleaseFence, surfaceStats.transformHint); + surfaceControls[surfaceStats.surfaceControl]->setTransformHint( + surfaceStats.transformHint); } callbackFunction(transactionStats.latchTime, transactionStats.presentFence, @@ -1451,16 +1453,19 @@ void SurfaceComposerClient::dispose() { sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, SurfaceControl* parent, - LayerMetadata metadata) { + LayerMetadata metadata, + uint32_t* outTransformHint) { sp<SurfaceControl> s; - createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata)); + createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata), + outTransformHint); return s; } sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, Surface* parent, - LayerMetadata metadata) { + LayerMetadata metadata, + uint32_t* outTransformHint) { sp<SurfaceControl> sur; status_t err = mStatus; @@ -1469,11 +1474,15 @@ sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& sp<IGraphicBufferProducer> parentGbp = parent->getIGraphicBufferProducer(); sp<IGraphicBufferProducer> gbp; + uint32_t transformHint = 0; err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, - std::move(metadata), &handle, &gbp); + std::move(metadata), &handle, &gbp, &transformHint); + if (outTransformHint) { + *outTransformHint = transformHint; + } ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err)); if (err == NO_ERROR) { - return new SurfaceControl(this, handle, gbp, true /* owned */); + return new SurfaceControl(this, handle, gbp, true /* owned */, transformHint); } } return nullptr; @@ -1482,8 +1491,8 @@ sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h, PixelFormat format, sp<SurfaceControl>* outSurface, uint32_t flags, - SurfaceControl* parent, - LayerMetadata metadata) { + SurfaceControl* parent, LayerMetadata metadata, + uint32_t* outTransformHint) { sp<SurfaceControl> sur; status_t err = mStatus; @@ -1496,11 +1505,15 @@ status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32 parentHandle = parent->getHandle(); } + uint32_t transformHint = 0; err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), - &handle, &gbp); + &handle, &gbp, &transformHint); + if (outTransformHint) { + *outTransformHint = transformHint; + } ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { - *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */); + *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */, transformHint); } } return err; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 071314f082..6292388ac3 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -45,20 +45,21 @@ namespace android { // SurfaceControl // ============================================================================ -SurfaceControl::SurfaceControl( - const sp<SurfaceComposerClient>& client, - const sp<IBinder>& handle, - const sp<IGraphicBufferProducer>& gbp, - bool owned) - : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned) -{ -} +SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle, + const sp<IGraphicBufferProducer>& gbp, bool owned, + uint32_t transform) + : mClient(client), + mHandle(handle), + mGraphicBufferProducer(gbp), + mOwned(owned), + mTransformHint(transform) {} SurfaceControl::SurfaceControl(const sp<SurfaceControl>& other) { mClient = other->mClient; mHandle = other->mHandle; mGraphicBufferProducer = other->mGraphicBufferProducer; mOwned = false; + mTransformHint = other->mTransformHint; } SurfaceControl::~SurfaceControl() @@ -171,11 +172,22 @@ sp<SurfaceComposerClient> SurfaceControl::getClient() const return mClient; } +uint32_t SurfaceControl::getTransformHint() const { + Mutex::Autolock _l(mLock); + return mTransformHint; +} + +void SurfaceControl::setTransformHint(uint32_t hint) { + Mutex::Autolock _l(mLock); + mTransformHint = hint; +} + void SurfaceControl::writeToParcel(Parcel* parcel) { parcel->writeStrongBinder(ISurfaceComposerClient::asBinder(mClient->getClient())); parcel->writeStrongBinder(mHandle); parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer)); + parcel->writeUint32(mTransformHint); } sp<SurfaceControl> SurfaceControl::readFromParcel(const Parcel* parcel) { @@ -189,10 +201,12 @@ sp<SurfaceControl> SurfaceControl::readFromParcel(const Parcel* parcel) { sp<IBinder> gbp; parcel->readNullableStrongBinder(&gbp); + uint32_t transformHint = parcel->readUint32(); // We aren't the original owner of the surface. return new SurfaceControl(new SurfaceComposerClient( - interface_cast<ISurfaceComposerClient>(client)), - handle.get(), interface_cast<IGraphicBufferProducer>(gbp), false /* owned */); + interface_cast<ISurfaceComposerClient>(client)), + handle.get(), interface_cast<IGraphicBufferProducer>(gbp), + false /* owned */, transformHint); } // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 06be1b36b2..f2bae98be2 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -30,6 +30,7 @@ #include <ui/FrameStats.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicTypes.h> +#include <ui/PhysicalDisplayId.h> #include <ui/PixelFormat.h> #include <utils/Errors.h> diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 5fe7ca5344..2b65d2f42d 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -56,7 +56,7 @@ public: virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp<IBinder>& parent, LayerMetadata metadata, sp<IBinder>* handle, - sp<IGraphicBufferProducer>* gbp) = 0; + sp<IGraphicBufferProducer>* gbp, uint32_t* outTransformHint) = 0; /* * Requires ACCESS_SURFACE_FLINGER permission @@ -65,7 +65,8 @@ public: PixelFormat format, uint32_t flags, const sp<IGraphicBufferProducer>& parent, LayerMetadata metadata, sp<IBinder>* handle, - sp<IGraphicBufferProducer>* gbp) = 0; + sp<IGraphicBufferProducer>* gbp, + uint32_t* outTransformHint) = 0; /* * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 08f4e9e9d3..7a9598cddd 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -226,18 +226,18 @@ public: PixelFormat format, // pixel-format desired uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent - LayerMetadata metadata = LayerMetadata() // metadata - ); + LayerMetadata metadata = LayerMetadata(), // metadata + uint32_t* outTransformHint = nullptr); status_t createSurfaceChecked(const String8& name, // name of the surface uint32_t w, // width in pixel uint32_t h, // height in pixel PixelFormat format, // pixel-format desired sp<SurfaceControl>* outSurface, - uint32_t flags = 0, // usage flags - SurfaceControl* parent = nullptr, // parent - LayerMetadata metadata = LayerMetadata() // metadata - ); + uint32_t flags = 0, // usage flags + SurfaceControl* parent = nullptr, // parent + LayerMetadata metadata = LayerMetadata(), // metadata + uint32_t* outTransformHint = nullptr); //! Create a surface sp<SurfaceControl> createWithSurfaceParent(const String8& name, // name of the surface @@ -246,8 +246,8 @@ public: PixelFormat format, // pixel-format desired uint32_t flags = 0, // usage flags Surface* parent = nullptr, // parent - LayerMetadata metadata = LayerMetadata() // metadata - ); + LayerMetadata metadata = LayerMetadata(), // metadata + uint32_t* outTransformHint = nullptr); // Creates a mirrored hierarchy for the mirrorFromSurface. This returns a SurfaceControl // which is a parent of the root of the mirrored hierarchy. diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index ae4a14690f..7bc7c686c9 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -82,10 +82,14 @@ public: sp<SurfaceComposerClient> getClient() const; + uint32_t getTransformHint() const; + + void setTransformHint(uint32_t hint); + explicit SurfaceControl(const sp<SurfaceControl>& other); SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle, - const sp<IGraphicBufferProducer>& gbp, bool owned); + const sp<IGraphicBufferProducer>& gbp, bool owned, uint32_t transformHint = 0); private: // can't be copied @@ -106,6 +110,7 @@ private: mutable Mutex mLock; mutable sp<Surface> mSurfaceData; bool mOwned; + uint32_t mTransformHint; }; }; // namespace android diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index db1ac249b5..ff22913226 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -26,6 +26,7 @@ #include <ui/DisplayInfo.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicTypes.h> +#include <ui/Transform.h> #include <gtest/gtest.h> @@ -201,6 +202,7 @@ TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) { igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &qbOutput)); ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(3)); + ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); int slot; sp<Fence> fence; @@ -222,6 +224,7 @@ TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) { NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); + ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallback(); diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 03b9cd75db..8d36ba7b70 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -69,7 +69,6 @@ public: mSurfaceControl = sc; InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); - mServerChannel->setToken(new BBinder()); mInputFlinger = getInputFlinger(); mInputFlinger->registerInputChannel(mServerChannel); @@ -165,7 +164,7 @@ private: } void populateInputInfo(int width, int height) { - mInputInfo.token = mServerChannel->getToken(); + mInputInfo.token = mServerChannel->getConnectionToken(); mInputInfo.name = "Test info"; mInputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; mInputInfo.layoutParamsType = InputWindowInfo::TYPE_BASE_APPLICATION; diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index c4f7fe0bf2..a5dd3c0544 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -11,7 +11,7 @@ #define DEBUG_CHANNEL_MESSAGES 0 // Log debug messages whenever InputChannel objects are created/destroyed -#define DEBUG_CHANNEL_LIFECYCLE 0 +static constexpr bool DEBUG_CHANNEL_LIFECYCLE = false; // Log debug messages about transport actions #define DEBUG_TRANSPORT_ACTIONS 0 @@ -225,28 +225,28 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { // --- InputChannel --- -sp<InputChannel> InputChannel::create(const std::string& name, android::base::unique_fd fd) { +sp<InputChannel> InputChannel::create(const std::string& name, android::base::unique_fd fd, + sp<IBinder> token) { const int result = fcntl(fd, F_SETFL, O_NONBLOCK); if (result != 0) { LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(), strerror(errno)); return nullptr; } - return new InputChannel(name, std::move(fd)); + return new InputChannel(name, std::move(fd), token); } -InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd) - : mName(name), mFd(std::move(fd)) { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel constructed: name='%s', fd=%d", - mName.c_str(), fd); -#endif +InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token) + : mName(name), mFd(std::move(fd)), mToken(token) { + if (DEBUG_CHANNEL_LIFECYCLE) { + ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get()); + } } InputChannel::~InputChannel() { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); -#endif + if (DEBUG_CHANNEL_LIFECYCLE) { + ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); + } } status_t InputChannel::openInputChannelPair(const std::string& name, @@ -267,13 +267,15 @@ status_t InputChannel::openInputChannelPair(const std::string& name, setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); + sp<IBinder> token = new BBinder(); + std::string serverChannelName = name + " (server)"; android::base::unique_fd serverFd(sockets[0]); - outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd)); + outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token); std::string clientChannelName = name + " (client)"; android::base::unique_fd clientFd(sockets[1]); - outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd)); + outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token); return OK; } @@ -369,7 +371,7 @@ sp<InputChannel> InputChannel::dup() const { getName().c_str()); return nullptr; } - return InputChannel::create(mName, std::move(newFd)); + return InputChannel::create(mName, std::move(newFd), mToken); } status_t InputChannel::write(Parcel& out) const { @@ -396,24 +398,13 @@ sp<InputChannel> InputChannel::read(const Parcel& from) { return nullptr; } - sp<InputChannel> channel = InputChannel::create(name, std::move(rawFd)); - if (channel != nullptr) { - channel->setToken(token); - } - return channel; + return InputChannel::create(name, std::move(rawFd), token); } -sp<IBinder> InputChannel::getToken() const { +sp<IBinder> InputChannel::getConnectionToken() const { return mToken; } -void InputChannel::setToken(const sp<IBinder>& token) { - if (mToken != nullptr) { - ALOGE("Assigning InputChannel (%s) a second handle?", mName.c_str()); - } - mToken = token; -} - // --- InputPublisher --- InputPublisher::InputPublisher(const sp<InputChannel>& channel) : diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index 7c331e132d..ada275d014 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -46,7 +46,8 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor android::base::unique_fd sendFd(pipe.sendFd); - sp<InputChannel> inputChannel = InputChannel::create("channel name", std::move(sendFd)); + sp<InputChannel> inputChannel = + InputChannel::create("channel name", std::move(sendFd), new BBinder()); EXPECT_NE(inputChannel, nullptr) << "channel should be successfully created"; EXPECT_STREQ("channel name", inputChannel->getName().c_str()) @@ -59,13 +60,11 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor TEST_F(InputChannelTest, SetAndGetToken) { Pipe pipe; + sp<IBinder> token = new BBinder(); sp<InputChannel> channel = - InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd)); - EXPECT_EQ(channel->getToken(), nullptr); + InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd), token); - sp<IBinder> token = new BBinder(); - channel->setToken(token); - EXPECT_EQ(token, channel->getToken()); + EXPECT_EQ(token, channel->getConnectionToken()); } TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp new file mode 100644 index 0000000000..666563520e --- /dev/null +++ b/libs/nativedisplay/ADisplay.cpp @@ -0,0 +1,262 @@ +/* + * Copyright 2019 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 <apex/display.h> +#include <gui/SurfaceComposerClient.h> +#include <ui/DisplayInfo.h> +#include <ui/GraphicTypes.h> + +#include <algorithm> +#include <optional> +#include <type_traits> +#include <vector> + +namespace android::display::impl { + +/** + * Implementation of ADisplayConfig + */ +struct DisplayConfigImpl { + /** + * The width in pixels of the display configuration. + */ + int32_t width{0}; + + /** + * The height in pixels of the display configuration. + */ + + int32_t height{0}; + + /** + * The display density. + */ + float density{0}; + + /** + * The refresh rate of the display configuration, in frames per second. + */ + float fps{0.0}; + + /** + * The vsync offset at which surfaceflinger runs, in nanoseconds. + */ + int64_t sfOffset{0}; + + /** + * The vsync offset at which applications run, in nanoseconds. + */ + int64_t appOffset{0}; +}; + +// DisplayConfigImpl allocation is not managed through C++ memory apis, so +// preventing calling the destructor here. +static_assert(std::is_trivially_destructible<DisplayConfigImpl>::value); + +/** + * Implementation of ADisplay + */ +struct DisplayImpl { + /** + * A physical display ID, unique to this display. + */ + PhysicalDisplayId id; + + /** + * The type of the display, i.e. whether it is an internal or external + * display. + */ + ADisplayType type; + + /** + * Number of supported configs + */ + size_t numConfigs; + + /** + * Set of supported configs by this display. + */ + DisplayConfigImpl* configs; +}; + +// DisplayImpl allocation is not managed through C++ memory apis, so +// preventing calling the destructor here. +static_assert(std::is_trivially_destructible<DisplayImpl>::value); + +} // namespace android::display::impl + +using namespace android; +using namespace android::display::impl; + +#define CHECK_NOT_NULL(name) \ + LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument"); + +namespace { +sp<IBinder> getToken(ADisplay* display) { + DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display); + return SurfaceComposerClient::getPhysicalDisplayToken(impl->id); +} + +int64_t computeSfOffset(const DisplayInfo& info) { + // This should probably be part of the config instead of extrapolated from + // the presentation deadline and fudged here, but the way the math works out + // here we do get the right offset. + return static_cast<int64_t>((1000000000 / info.fps) - info.presentationDeadline + 1000000); +} +} // namespace + +int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { + const std::vector<PhysicalDisplayId> ids = SurfaceComposerClient::getPhysicalDisplayIds(); + const size_t size = ids.size(); + if (size == 0) { + return NO_INIT; + } + + std::vector<DisplayConfigImpl> configsPerDisplay[size]; + int numConfigs = 0; + for (int i = 0; i < size; ++i) { + const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]); + Vector<DisplayInfo> configs; + const status_t status = SurfaceComposerClient::getDisplayConfigs(token, &configs); + if (status != OK) { + return status; + } + if (configs.empty()) { + return NO_INIT; + } + + numConfigs += configs.size(); + configsPerDisplay[i].reserve(configs.size()); + for (int j = 0; j < configs.size(); ++j) { + const DisplayInfo config = configs[j]; + configsPerDisplay[i].emplace_back( + DisplayConfigImpl{static_cast<int32_t>(config.w), + static_cast<int32_t>(config.h), config.density, config.fps, + computeSfOffset(config), config.appVsyncOffset}); + } + } + + const std::optional<PhysicalDisplayId> internalId = + SurfaceComposerClient::getInternalDisplayId(); + + // Here we allocate all our required memory in one block. The layout is as + // follows: + // ------------------------------------------------------------ + // | DisplayImpl pointers | DisplayImpls | DisplayConfigImpls | + // ------------------------------------------------------------ + // + // The caller will be given a DisplayImpl** which points to the beginning of + // the block of DisplayImpl pointers. + // Each DisplayImpl* points to a DisplayImpl in the second block. + // Each DisplayImpl contains a DisplayConfigImpl*, which points to a + // contiguous block of DisplayConfigImpls specific to that display. + DisplayImpl** const impls = reinterpret_cast<DisplayImpl**>( + malloc((sizeof(DisplayImpl) + sizeof(DisplayImpl*)) * size + + sizeof(DisplayConfigImpl) * numConfigs)); + DisplayImpl* const displayData = reinterpret_cast<DisplayImpl*>(impls + size); + DisplayConfigImpl* configData = reinterpret_cast<DisplayConfigImpl*>(displayData + size); + + for (size_t i = 0; i < size; ++i) { + const PhysicalDisplayId id = ids[i]; + const ADisplayType type = (internalId == id) ? ADisplayType::DISPLAY_TYPE_INTERNAL + : ADisplayType::DISPLAY_TYPE_EXTERNAL; + const std::vector<DisplayConfigImpl>& configs = configsPerDisplay[i]; + memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size()); + + displayData[i] = DisplayImpl{id, type, configs.size(), configData}; + impls[i] = displayData + i; + // Advance the configData pointer so that future configs are written to + // the correct display. + configData += configs.size(); + } + + *outDisplays = reinterpret_cast<ADisplay**>(impls); + return size; +} + +void ADisplay_release(ADisplay** displays) { + if (displays == nullptr) { + return; + } + free(displays); +} + +float ADisplay_getMaxSupportedFps(ADisplay* display) { + CHECK_NOT_NULL(display); + DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display); + float maxFps = 0.0; + for (int i = 0; i < impl->numConfigs; ++i) { + maxFps = std::max(maxFps, impl->configs[i].fps); + } + return maxFps; +} + +ADisplayType ADisplay_getDisplayType(ADisplay* display) { + CHECK_NOT_NULL(display); + + return reinterpret_cast<DisplayImpl*>(display)->type; +} + +int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) { + CHECK_NOT_NULL(display); + + sp<IBinder> token = getToken(display); + const int index = SurfaceComposerClient::getActiveConfig(token); + if (index < 0) { + return index; + } + + DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display); + + *outConfig = reinterpret_cast<ADisplayConfig*>(impl->configs + index); + return OK; +} + +float ADisplayConfig_getDensity(ADisplayConfig* config) { + CHECK_NOT_NULL(config); + + return reinterpret_cast<DisplayConfigImpl*>(config)->density; +} + +int32_t ADisplayConfig_getWidth(ADisplayConfig* config) { + CHECK_NOT_NULL(config); + + return reinterpret_cast<DisplayConfigImpl*>(config)->width; +} + +int32_t ADisplayConfig_getHeight(ADisplayConfig* config) { + CHECK_NOT_NULL(config); + + return reinterpret_cast<DisplayConfigImpl*>(config)->height; +} + +float ADisplayConfig_getFps(ADisplayConfig* config) { + CHECK_NOT_NULL(config); + + return reinterpret_cast<DisplayConfigImpl*>(config)->fps; +} + +int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config) { + CHECK_NOT_NULL(config); + + return reinterpret_cast<DisplayConfigImpl*>(config)->sfOffset; +} + +int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config) { + CHECK_NOT_NULL(config); + + return reinterpret_cast<DisplayConfigImpl*>(config)->appOffset; +} diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp new file mode 100644 index 0000000000..66ebdfd6f8 --- /dev/null +++ b/libs/nativedisplay/Android.bp @@ -0,0 +1,50 @@ +// Copyright 2019 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_headers { + name: "libnativedisplay_headers", + export_include_dirs: ["include"], +} + +cc_library { + name: "libnativedisplay", + export_include_dirs: [ + "include", + ], + + clang: true, + + cflags: [ + "-Wall", + "-Werror", + "-Wno-enum-compare", + "-Wno-unused-function", + ], + + srcs: [ + "ADisplay.cpp", + ], + + shared_libs: [ + "libgui", + "liblog", + "libui", + "libutils", + ], + + header_libs: [ + "libnativedisplay_headers", + ], + +} diff --git a/libs/nativedisplay/include/apex/display.h b/libs/nativedisplay/include/apex/display.h new file mode 100644 index 0000000000..7af452a782 --- /dev/null +++ b/libs/nativedisplay/include/apex/display.h @@ -0,0 +1,125 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include <inttypes.h> + +__BEGIN_DECLS + +/** + * Opaque handle for a native display + */ +typedef struct ADisplay ADisplay; + +/** + * Enum describing the possible types of a display + */ +enum ADisplayType { + /** + * A display that is the internal, or "primary" display for a device. + */ + DISPLAY_TYPE_INTERNAL = 0, + + /** + * A display that is externally connected for a device. + */ + DISPLAY_TYPE_EXTERNAL = 1, +}; + +/** + * Opaque handle for display metadata + */ +typedef struct ADisplayConfig ADisplayConfig; + +/** + * Acquires a list of display handles. Memory is allocated for the list and is + * owned by the caller. The caller is responsible for freeing this memory by + * calling ADisplayList_release. + * + * Returns the size of the returned list on success. + * Returns -errno on error. + */ +int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays); + +/** + * Releases a list of display handles created by + * ADisplayList_acquirePhysicalDisplays. + */ +void ADisplay_release(ADisplay** displays); + +/** + * Queries the maximum supported fps for the given display. + */ +float ADisplay_getMaxSupportedFps(ADisplay* display); + +/** + * Queries the display's type. + */ +ADisplayType ADisplay_getDisplayType(ADisplay* display); + +/** + * Gets the current display configuration for the given display. + * + * Memory is *not* allocated for the caller. As such, the returned output + * configuration's lifetime will not be longer than the ADisplay* passed to this + * function - if ADisplay_release is called destroying the ADisplay object then + * it is invalid to access the ADisplayConfig returned here. + * + * Note that the current display configuration can change. Listening to updates + * to the current display configuration should be done via Choreographer. If + * such an update is observed, then this method should be recalled to get the + * new current configuration. + * + * Returns OK on success, -errno on failure. + */ +int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig); + +/** + * Queries the density for a given display configuration. + */ +float ADisplayConfig_getDensity(ADisplayConfig* config); + +/** + * Queries the width in pixels for a given display configuration. + */ +int32_t ADisplayConfig_getWidth(ADisplayConfig* config); + +/** + * Queries the height in pixels for a given display configuration. + */ +int32_t ADisplayConfig_getHeight(ADisplayConfig* config); + +/** + * Queries the display refresh rate for a given display configuration. + */ +float ADisplayConfig_getFps(ADisplayConfig* config); + +/** + * Queries the vsync offset from which the system compositor is scheduled to + * run. If a vsync occurs at time T, and the compositor runs at time T + S, then + * this returns S in nanoseconds. + */ +int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config); + +/** + * Queries the vsync offset from which applications are scheduled to run. If a + * vsync occurs at time T, and applications run at time T + S, then this returns + * S in nanoseconds. + */ +int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config); + +__END_DECLS diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h index da959e36d2..ae5e47ba97 100644 --- a/libs/nativewindow/include/android/hardware_buffer.h +++ b/libs/nativewindow/include/android/hardware_buffer.h @@ -342,6 +342,8 @@ typedef struct AHardwareBuffer AHardwareBuffer; * not compatible with its usage flags, the results are undefined and * may include program termination. * + * Available since API level 26. + * * \return 0 on success, or an error number of the allocation fails for * any reason. The returned buffer has a reference count of 1. */ @@ -352,18 +354,24 @@ int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc, * * This prevents the object from being deleted until the last reference * is removed. + * + * Available since API level 26. */ void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26); /** * Remove a reference that was previously acquired with * AHardwareBuffer_acquire() or AHardwareBuffer_allocate(). + * + * Available since API level 26. */ void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26); /** * Return a description of the AHardwareBuffer in the passed * AHardwareBuffer_Desc struct. + * + * Available since API level 26. */ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26); @@ -413,6 +421,8 @@ void AHardwareBuffer_describe(const AHardwareBuffer* buffer, * simultaneously, and the contents of the buffer behave like shared * memory. * + * Available since API level 26. + * * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer * has more than one layer. Error number if the lock fails for any other @@ -441,6 +451,8 @@ int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage, * * See the AHardwareBuffer_lock documentation for all other locking semantics. * + * Available since API level 29. + * * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer * has more than one layer. Error number if the lock fails for any other @@ -462,6 +474,8 @@ int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage, * completed before the function returned and no further operations are * necessary. * + * Available since API level 26. + * * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if * the unlock fails for any reason. */ @@ -470,6 +484,8 @@ int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED /** * Send the AHardwareBuffer to an AF_UNIX socket. * + * Available since API level 26. + * * \return 0 on success, -EINVAL if \a buffer is NULL, or an error * number if the operation fails for any reason. */ @@ -478,6 +494,8 @@ int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int so /** * Receive an AHardwareBuffer from an AF_UNIX socket. * + * Available since API level 26. + * * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error * number if the operation fails for any reason. */ @@ -501,6 +519,8 @@ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** out * some implementations have implementation-defined limits on texture * size and layer count. * + * Available since API level 29. + * * \return 1 if the format and usage flag combination is allocatable, * 0 otherwise. */ @@ -514,6 +534,8 @@ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_I * of the locked buffer. If the bytes per pixel or bytes per stride are unknown * or variable, or if the underlying mapper implementation does not support returning * additional information, then this call will fail with INVALID_OPERATION + * + * Available since API level 29. */ int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress, diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h index 6730596ec7..3e436e3b07 100644 --- a/libs/nativewindow/include/android/native_window.h +++ b/libs/nativewindow/include/android/native_window.h @@ -189,6 +189,8 @@ int32_t ANativeWindow_unlockAndPost(ANativeWindow* window); /** * Set a transform that will be applied to future buffers posted to the window. * + * Available since API level 26. + * * \param transform combination of {@link ANativeWindowTransform} flags * \return 0 for success, or -EINVAL if \p transform is invalid */ @@ -208,6 +210,8 @@ int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transfo * measurement data instead of color images. The default dataSpace is 0, * ADATASPACE_UNKNOWN, unless it has been overridden by the producer. * + * Available since API level 28. + * * \param dataSpace data space of all buffers queued after this call. * \return 0 for success, -EINVAL if window is invalid or the dataspace is not * supported. @@ -216,6 +220,9 @@ int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpa /** * Get the dataspace of the buffers in window. + * + * Available since API level 28. + * * \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if * dataspace is unknown, or -EINVAL if window is invalid. */ diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 9c600a89fd..fcc2547f0a 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -144,7 +144,8 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, // if stride has no meaning or is too large, // approximate size with the input width instead - if (std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) { + if ((*stride) != 0 && + std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) { bufSize = static_cast<size_t>(width) * height * bpp; } else { bufSize = static_cast<size_t>((*stride)) * height * bpp; diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h index 5dc56c8181..d7411ea36a 100644 --- a/libs/ui/include/ui/GraphicTypes.h +++ b/libs/ui/include/ui/GraphicTypes.h @@ -16,19 +16,12 @@ #pragma once -#include <cinttypes> -#include <cstdint> - #include <android/hardware/graphics/common/1.1/types.h> #include <android/hardware/graphics/common/1.2/types.h> #include <system/graphics.h> -#define ANDROID_PHYSICAL_DISPLAY_ID_FORMAT PRIu64 - namespace android { -using PhysicalDisplayId = uint64_t; - // android::ui::* in this header file will alias different types as // the HIDL interface is updated. namespace ui { diff --git a/libs/ui/include/ui/PhysicalDisplayId.h b/libs/ui/include/ui/PhysicalDisplayId.h new file mode 100644 index 0000000000..1a345acc86 --- /dev/null +++ b/libs/ui/include/ui/PhysicalDisplayId.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include <cinttypes> +#include <cstdint> + +#define ANDROID_PHYSICAL_DISPLAY_ID_FORMAT PRIu64 + +namespace android { + +using PhysicalDisplayId = uint64_t; + +constexpr uint8_t getPhysicalDisplayPort(PhysicalDisplayId displayId) { + return static_cast<uint8_t>(displayId); +} + +} // namespace android diff --git a/libs/ui/include_vndk/ui/PhysicalDisplayId.h b/libs/ui/include_vndk/ui/PhysicalDisplayId.h new file mode 120000 index 0000000000..6e3fb1e62e --- /dev/null +++ b/libs/ui/include_vndk/ui/PhysicalDisplayId.h @@ -0,0 +1 @@ +../../include/ui/PhysicalDisplayId.h
\ No newline at end of file diff --git a/libs/ui/tests/GraphicBufferAllocator_test.cpp b/libs/ui/tests/GraphicBufferAllocator_test.cpp index 4bbc54993c..efca083e6e 100644 --- a/libs/ui/tests/GraphicBufferAllocator_test.cpp +++ b/libs/ui/tests/GraphicBufferAllocator_test.cpp @@ -76,7 +76,21 @@ TEST_F(GraphicBufferAllocatorTest, AllocateNoError) { ASSERT_EQ(kTestWidth, stride); } -TEST_F(GraphicBufferAllocatorTest, AllocateBadStride) { +TEST_F(GraphicBufferAllocatorTest, AllocateZeroStride) { + android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; + uint32_t expectedStride = 0; + + mAllocator.setUpAllocateExpectations(NO_ERROR, expectedStride); + uint32_t stride = 0; + buffer_handle_t handle; + // a divide by zero would cause a crash + status_t err = mAllocator.allocate(kTestWidth, kTestHeight, format, kTestLayerCount, kTestUsage, + &handle, &stride, 0, "GraphicBufferAllocatorTest"); + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(expectedStride, stride); +} + +TEST_F(GraphicBufferAllocatorTest, AllocateLargeStride) { uint32_t height = std::numeric_limits<uint32_t>::max(); uint32_t bpp = 4; android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp index 6d202aec05..2fcee7bee6 100644 --- a/libs/vr/libbufferhub/Android.bp +++ b/libs/vr/libbufferhub/Android.bp @@ -29,11 +29,9 @@ sourceFiles = [ sharedLibraries = [ "libbase", "libcutils", - "libhardware", "liblog", "libui", "libutils", - "libnativewindow", "libpdx_default_transport", ] |