From e8ef7b0bccd7e49bec7dc77fcf1f37d82c4e32df Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Mon, 17 Jun 2019 17:22:19 -0700 Subject: Add a separate flag in the installer for keeping ART profiles Currently this is only use in the PackageManagerService. In follow up we should use this to integrate profile clearing in the same methods as AppDataClearing. Test: manual Bug: 135299330 Change-Id: I3bafdef769d7838d8048b7df4d7a779464104641 --- cmds/installd/binder/android/os/IInstalld.aidl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'cmds') diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 26e9984f11..d99bcc8d13 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -127,4 +127,6 @@ interface IInstalld { const int FLAG_USE_QUOTA = 0x1000; const int FLAG_FORCE = 0x2000; + + const int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES = 0x20000; } -- cgit v1.2.3-59-g8ed1b From 3e092daa14c63831d76d3ad6e56b2919a0523536 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Fri, 21 Jun 2019 12:35:59 -0700 Subject: servicemanager: use libbinder Bug: 135768100 Test: boot Test: servicemanager_test Change-Id: I9d657b6c0d0be0f763b6d54e0e6c6bc1c1e3fc7a --- cmds/servicemanager/Access.cpp | 140 +++++ cmds/servicemanager/Access.h | 59 ++ cmds/servicemanager/Android.bp | 54 +- cmds/servicemanager/ServiceManager.cpp | 144 +++++ cmds/servicemanager/ServiceManager.h | 47 ++ cmds/servicemanager/TEST_MAPPING | 7 + cmds/servicemanager/bctest.c | 107 ---- cmds/servicemanager/binder.c | 682 ----------------------- cmds/servicemanager/binder.h | 94 ---- cmds/servicemanager/main.cpp | 54 ++ cmds/servicemanager/service_manager.c | 442 --------------- cmds/servicemanager/test_sm.cpp | 261 +++++++++ libs/binder/Android.bp | 4 +- libs/binder/IPCThreadState.cpp | 2 +- libs/binder/IServiceManager.cpp | 58 +- libs/binder/aidl/android/os/IServiceManager.aidl | 80 +++ libs/binder/include/binder/IPCThreadState.h | 2 + 17 files changed, 851 insertions(+), 1386 deletions(-) create mode 100644 cmds/servicemanager/Access.cpp create mode 100644 cmds/servicemanager/Access.h create mode 100644 cmds/servicemanager/ServiceManager.cpp create mode 100644 cmds/servicemanager/ServiceManager.h create mode 100644 cmds/servicemanager/TEST_MAPPING delete mode 100644 cmds/servicemanager/bctest.c delete mode 100644 cmds/servicemanager/binder.c delete mode 100644 cmds/servicemanager/binder.h create mode 100644 cmds/servicemanager/main.cpp delete mode 100644 cmds/servicemanager/service_manager.c create mode 100644 cmds/servicemanager/test_sm.cpp create mode 100644 libs/binder/aidl/android/os/IServiceManager.aidl (limited to 'cmds') diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp new file mode 100644 index 0000000000..f4005c4dee --- /dev/null +++ b/cmds/servicemanager/Access.cpp @@ -0,0 +1,140 @@ +/* + * 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 "Access.h" + +#include +#include +#include +#include +#include + +namespace android { + +#ifdef VENDORSERVICEMANAGER +constexpr bool kIsVendor = true; +#else +constexpr bool kIsVendor = false; +#endif + +static std::string getPidcon(pid_t pid) { + android_errorWriteLog(0x534e4554, "121035042"); + + char* lookup = nullptr; + if (getpidcon(pid, &lookup) < 0) { + LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context"; + return ""; + } + std::string result = lookup; + freecon(lookup); + return result; +} + +static struct selabel_handle* getSehandle() { + static struct selabel_handle* gSehandle = nullptr; + + if (gSehandle != nullptr && selinux_status_updated()) { + selabel_close(gSehandle); + gSehandle = nullptr; + } + + if (gSehandle == nullptr) { + gSehandle = kIsVendor + ? selinux_android_vendor_service_context_handle() + : selinux_android_service_context_handle(); + } + + CHECK(gSehandle != nullptr); + return gSehandle; +} + +static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) { + const Access::CallingContext* ad = reinterpret_cast(data); + + if (!ad) { + LOG(ERROR) << "No service manager audit data"; + return 0; + } + + snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name.c_str(), ad->debugPid, ad->uid); + return 0; +} + +Access::Access() { + union selinux_callback cb; + + cb.func_audit = auditCallback; + selinux_set_callback(SELINUX_CB_AUDIT, cb); + + cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback; + selinux_set_callback(SELINUX_CB_LOG, cb); + + CHECK(selinux_status_open(true /*fallback*/) >= 0); + + CHECK(getcon(&mThisProcessContext) == 0); +} + +Access::~Access() { + freecon(mThisProcessContext); +} + +Access::CallingContext Access::getCallingContext(const std::string& name) { + IPCThreadState* ipc = IPCThreadState::self(); + + const char* callingSid = ipc->getCallingSid(); + pid_t callingPid = ipc->getCallingPid(); + + return CallingContext { + .debugPid = callingPid, + .uid = ipc->getCallingUid(), + .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid), + .name = name, + }; +} + +bool Access::canFind(const CallingContext& ctx) { + return actionAllowedFromLookup(ctx, "find"); +} + +bool Access::canAdd(const CallingContext& ctx) { + return actionAllowedFromLookup(ctx, "add"); +} + +bool Access::canList(const CallingContext& ctx) { + CHECK(ctx.name == ""); + + return actionAllowed(ctx, mThisProcessContext, "list"); +} + +bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm) { + const char* tclass = "service_manager"; + + return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm, reinterpret_cast(const_cast((&sctx)))); +} + +bool Access::actionAllowedFromLookup(const CallingContext& sctx, const char *perm) { + char *tctx = nullptr; + if (selabel_lookup(getSehandle(), &tctx, sctx.name.c_str(), 0) != 0) { + LOG(ERROR) << "SELinux: No match for " << sctx.name << " in service_contexts.\n"; + return false; + } + + bool allowed = actionAllowed(sctx, tctx, perm); + freecon(tctx); + return allowed; +} + +} // android diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h new file mode 100644 index 0000000000..b2c78cc34d --- /dev/null +++ b/cmds/servicemanager/Access.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#pragma once + +#include +#include + +namespace android { + +// singleton +class Access { +public: + Access(); + virtual ~Access(); + + Access(const Access&) = delete; + Access& operator=(const Access&) = delete; + Access(Access&&) = delete; + Access& operator=(Access&&) = delete; + + struct CallingContext { + pid_t debugPid; + uid_t uid; + std::string sid; + + // name of the service + // + // empty if call is unrelated to service (e.g. list) + std::string name; + }; + + virtual CallingContext getCallingContext(const std::string& name); + + virtual bool canFind(const CallingContext& ctx); + virtual bool canAdd(const CallingContext& ctx); + virtual bool canList(const CallingContext& ctx); + +private: + bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm); + bool actionAllowedFromLookup(const CallingContext& sctx, const char *perm); + + char* mThisProcessContext = nullptr; +}; + +}; diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp index 428561bc8a..9cf3c5c134 100644 --- a/cmds/servicemanager/Android.bp +++ b/cmds/servicemanager/Android.bp @@ -1,51 +1,51 @@ cc_defaults { - name: "servicemanager_flags", + name: "servicemanager_defaults", cflags: [ "-Wall", "-Wextra", "-Werror", ], - product_variables: { - binder32bit: { - cflags: ["-DBINDER_IPC_32BIT=1"], - }, - }, - shared_libs: ["liblog"], -} - -cc_binary { - name: "bctest", - defaults: ["servicemanager_flags"], srcs: [ - "bctest.c", - "binder.c", + "Access.cpp", + "ServiceManager.cpp", + ], + + shared_libs: [ + "libbase", + "libbinder", // also contains servicemanager_interface + "libcutils", + "liblog", + "libutils", + "libselinux", ], } cc_binary { name: "servicemanager", - defaults: ["servicemanager_flags"], - srcs: [ - "service_manager.c", - "binder.c", - ], - shared_libs: ["libcutils", "libselinux"], + defaults: ["servicemanager_defaults"], init_rc: ["servicemanager.rc"], + srcs: ["main.cpp"], } cc_binary { name: "vndservicemanager", - defaults: ["servicemanager_flags"], + defaults: ["servicemanager_defaults"], + init_rc: ["vndservicemanager.rc"], vendor: true, - srcs: [ - "service_manager.c", - "binder.c", - ], cflags: [ "-DVENDORSERVICEMANAGER=1", ], - shared_libs: ["libcutils", "libselinux"], - init_rc: ["vndservicemanager.rc"], + srcs: ["main.cpp"], +} + +cc_test { + name: "servicemanager_test", + test_suites: ["device-tests"], + defaults: ["servicemanager_defaults"], + srcs: [ + "test_sm.cpp", + ], + static_libs: ["libgmock"], } diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp new file mode 100644 index 0000000000..b88b67d138 --- /dev/null +++ b/cmds/servicemanager/ServiceManager.cpp @@ -0,0 +1,144 @@ +/* + * 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 "ServiceManager.h" + +#include +#include +#include + +using ::android::binder::Status; + +namespace android { + +ServiceManager::ServiceManager(std::unique_ptr&& access) : mAccess(std::move(access)) {} + +Status ServiceManager::getService(const std::string& name, sp* outBinder) { + // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons. + return checkService(name, outBinder); +} + +Status ServiceManager::checkService(const std::string& name, sp* outBinder) { + auto ctx = mAccess->getCallingContext(name); + + auto it = mNameToService.find(name); + if (it == mNameToService.end()) { + *outBinder = nullptr; + return Status::ok(); + } + + const Service& service = it->second; + + if (!service.allowIsolated) { + uid_t appid = multiuser_get_app_id(ctx.uid); + bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; + + if (isIsolated) { + *outBinder = nullptr; + return Status::ok(); + } + } + + // TODO(b/136023468): move this check to be first + if (!mAccess->canFind(ctx)) { + // returns ok and null for legacy reasons + *outBinder = nullptr; + return Status::ok(); + } + + *outBinder = service.binder; + return Status::ok(); +} + +Status ServiceManager::addService(const std::string& name, const sp& binder, bool allowIsolated, int32_t dumpPriority) { + auto ctx = mAccess->getCallingContext(name); + + // apps cannot add services + if (multiuser_get_app_id(ctx.uid) >= AID_APP) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + if (!mAccess->canAdd(ctx)) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + if (binder == nullptr) { + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + } + + // match legacy rules + if (name.size() == 0 || name.size() > 127) { + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + } + + if (OK != binder->linkToDeath(this)) { + LOG(ERROR) << "Could not linkToDeath when adding " << name; + return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); + } + + auto it = mNameToService.find(name); + if (it != mNameToService.end()) { + if (OK != it->second.binder->unlinkToDeath(this)) { + LOG(WARNING) << "Could not unlinkToDeath when adding " << name; + } + } + + mNameToService[name] = Service { + .binder = binder, + .allowIsolated = allowIsolated, + .dumpPriority = dumpPriority, + }; + + return Status::ok(); +} + +Status ServiceManager::listServices(int32_t dumpPriority, std::vector* outList) { + if (!mAccess->canList(mAccess->getCallingContext(""))) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + size_t toReserve = 0; + for (auto const& [name, service] : mNameToService) { + (void) name; + + if (service.dumpPriority & dumpPriority) ++toReserve; + } + + CHECK(outList->empty()); + + outList->reserve(toReserve); + for (auto const& [name, service] : mNameToService) { + (void) service; + + if (service.dumpPriority & dumpPriority) { + outList->push_back(name); + } + } + + return Status::ok(); +} + +void ServiceManager::binderDied(const wp& who) { + for (auto it = mNameToService.begin(); it != mNameToService.end();) { + if (who == it->second.binder) { + it = mNameToService.erase(it); + } else { + ++it; + } + } +} + +} // namespace android diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h new file mode 100644 index 0000000000..78e48052b8 --- /dev/null +++ b/cmds/servicemanager/ServiceManager.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#pragma once + +#include + +#include "Access.h" + +namespace android { + +class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient { +public: + ServiceManager(std::unique_ptr&& access); + + binder::Status getService(const std::string& name, sp* outBinder) override; + binder::Status checkService(const std::string& name, sp* outBinder) override; + binder::Status addService(const std::string& name, const sp& binder, bool allowIsolated, int32_t dumpPriority) override; + binder::Status listServices(int32_t dumpPriority, std::vector* outList) override; + + void binderDied(const wp& who) override; + +private: + struct Service { + sp binder; + bool allowIsolated; + int32_t dumpPriority; + }; + + std::map mNameToService; + std::unique_ptr mAccess; +}; + +} // namespace android diff --git a/cmds/servicemanager/TEST_MAPPING b/cmds/servicemanager/TEST_MAPPING new file mode 100644 index 0000000000..3e47269fe0 --- /dev/null +++ b/cmds/servicemanager/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "servicemanager_test" + } + ] +} diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c deleted file mode 100644 index 354df670e5..0000000000 --- a/cmds/servicemanager/bctest.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#include -#include -#include -#include - -#include "binder.h" - -uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name) -{ - uint32_t handle; - unsigned iodata[512/4]; - struct binder_io msg, reply; - - bio_init(&msg, iodata, sizeof(iodata), 4); - bio_put_uint32(&msg, 0); // strict mode header - bio_put_string16_x(&msg, SVC_MGR_NAME); - bio_put_string16_x(&msg, name); - - if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE)) - return 0; - - handle = bio_get_ref(&reply); - - if (handle) - binder_acquire(bs, handle); - - binder_done(bs, &msg, &reply); - - return handle; -} - -int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr) -{ - int status; - unsigned iodata[512/4]; - struct binder_io msg, reply; - - bio_init(&msg, iodata, sizeof(iodata), 4); - bio_put_uint32(&msg, 0); // strict mode header - bio_put_string16_x(&msg, SVC_MGR_NAME); - bio_put_string16_x(&msg, name); - bio_put_obj(&msg, ptr); - - if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE)) - return -1; - - status = bio_get_uint32(&reply); - - binder_done(bs, &msg, &reply); - - return status; -} - -unsigned token; - -int main(int argc, char **argv) -{ - struct binder_state *bs; - uint32_t svcmgr = BINDER_SERVICE_MANAGER; - uint32_t handle; - - bs = binder_open("/dev/binder", 128*1024); - if (!bs) { - fprintf(stderr, "failed to open binder driver\n"); - return -1; - } - - argc--; - argv++; - while (argc > 0) { - if (!strcmp(argv[0],"alt")) { - handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr"); - if (!handle) { - fprintf(stderr,"cannot find alt_svc_mgr\n"); - return -1; - } - svcmgr = handle; - fprintf(stderr,"svcmgr is via %x\n", handle); - } else if (!strcmp(argv[0],"lookup")) { - if (argc < 2) { - fprintf(stderr,"argument required\n"); - return -1; - } - handle = svcmgr_lookup(bs, svcmgr, argv[1]); - fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle); - argc--; - argv++; - } else if (!strcmp(argv[0],"publish")) { - if (argc < 2) { - fprintf(stderr,"argument required\n"); - return -1; - } - svcmgr_publish(bs, svcmgr, argv[1], &token); - argc--; - argv++; - } else { - fprintf(stderr,"unknown command %s\n", argv[0]); - return -1; - } - argc--; - argv++; - } - return 0; -} diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c deleted file mode 100644 index cf3b1728b6..0000000000 --- a/cmds/servicemanager/binder.c +++ /dev/null @@ -1,682 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#define LOG_TAG "Binder" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "binder.h" - -#define MAX_BIO_SIZE (1 << 30) - -#define TRACE 0 - -void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn); - -#if TRACE -void hexdump(void *_data, size_t len) -{ - unsigned char *data = _data; - size_t count; - - for (count = 0; count < len; count++) { - if ((count & 15) == 0) - fprintf(stderr,"%04zu:", count); - fprintf(stderr," %02x %c", *data, - (*data < 32) || (*data > 126) ? '.' : *data); - data++; - if ((count & 15) == 15) - fprintf(stderr,"\n"); - } - if ((count & 15) != 0) - fprintf(stderr,"\n"); -} - -void binder_dump_txn(struct binder_transaction_data *txn) -{ - struct flat_binder_object *obj; - binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets; - size_t count = txn->offsets_size / sizeof(binder_size_t); - - fprintf(stderr," target %016"PRIx64" cookie %016"PRIx64" code %08x flags %08x\n", - (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags); - fprintf(stderr," pid %8d uid %8d data %"PRIu64" offs %"PRIu64"\n", - txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size); - hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size); - while (count--) { - obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++); - fprintf(stderr," - type %08x flags %08x ptr %016"PRIx64" cookie %016"PRIx64"\n", - obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie); - } -} - -#define NAME(n) case n: return #n -const char *cmd_name(uint32_t cmd) -{ - switch(cmd) { - NAME(BR_NOOP); - NAME(BR_TRANSACTION_COMPLETE); - NAME(BR_INCREFS); - NAME(BR_ACQUIRE); - NAME(BR_RELEASE); - NAME(BR_DECREFS); - NAME(BR_TRANSACTION); - NAME(BR_REPLY); - NAME(BR_FAILED_REPLY); - NAME(BR_DEAD_REPLY); - NAME(BR_DEAD_BINDER); - default: return "???"; - } -} -#else -#define hexdump(a,b) do{} while (0) -#define binder_dump_txn(txn) do{} while (0) -#endif - -#define BIO_F_SHARED 0x01 /* needs to be buffer freed */ -#define BIO_F_OVERFLOW 0x02 /* ran out of space */ -#define BIO_F_IOERROR 0x04 -#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */ - -struct binder_state -{ - int fd; - void *mapped; - size_t mapsize; -}; - -struct binder_state *binder_open(const char* driver, size_t mapsize) -{ - struct binder_state *bs; - struct binder_version vers; - - bs = malloc(sizeof(*bs)); - if (!bs) { - errno = ENOMEM; - return NULL; - } - - bs->fd = open(driver, O_RDWR | O_CLOEXEC); - if (bs->fd < 0) { - fprintf(stderr,"binder: cannot open %s (%s)\n", - driver, strerror(errno)); - goto fail_open; - } - - if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || - (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { - fprintf(stderr, - "binder: kernel driver version (%d) differs from user space version (%d)\n", - vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); - goto fail_open; - } - - bs->mapsize = mapsize; - bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); - if (bs->mapped == MAP_FAILED) { - fprintf(stderr,"binder: cannot map device (%s)\n", - strerror(errno)); - goto fail_map; - } - - return bs; - -fail_map: - close(bs->fd); -fail_open: - free(bs); - return NULL; -} - -void binder_close(struct binder_state *bs) -{ - munmap(bs->mapped, bs->mapsize); - close(bs->fd); - free(bs); -} - -int binder_become_context_manager(struct binder_state *bs) -{ - struct flat_binder_object obj; - memset(&obj, 0, sizeof(obj)); - obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX; - - int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj); - - // fallback to original method - if (result != 0) { - android_errorWriteLog(0x534e4554, "121035042"); - - result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); - } - return result; -} - -int binder_write(struct binder_state *bs, void *data, size_t len) -{ - struct binder_write_read bwr; - int res; - - bwr.write_size = len; - bwr.write_consumed = 0; - bwr.write_buffer = (uintptr_t) data; - bwr.read_size = 0; - bwr.read_consumed = 0; - bwr.read_buffer = 0; - res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); - if (res < 0) { - fprintf(stderr,"binder_write: ioctl failed (%s)\n", - strerror(errno)); - } - return res; -} - -void binder_free_buffer(struct binder_state *bs, - binder_uintptr_t buffer_to_free) -{ - struct { - uint32_t cmd_free; - binder_uintptr_t buffer; - } __attribute__((packed)) data; - data.cmd_free = BC_FREE_BUFFER; - data.buffer = buffer_to_free; - binder_write(bs, &data, sizeof(data)); -} - -void binder_send_reply(struct binder_state *bs, - struct binder_io *reply, - binder_uintptr_t buffer_to_free, - int status) -{ - struct { - uint32_t cmd_free; - binder_uintptr_t buffer; - uint32_t cmd_reply; - struct binder_transaction_data txn; - } __attribute__((packed)) data; - - data.cmd_free = BC_FREE_BUFFER; - data.buffer = buffer_to_free; - data.cmd_reply = BC_REPLY; - data.txn.target.ptr = 0; - data.txn.cookie = 0; - data.txn.code = 0; - if (status) { - data.txn.flags = TF_STATUS_CODE; - data.txn.data_size = sizeof(int); - data.txn.offsets_size = 0; - data.txn.data.ptr.buffer = (uintptr_t)&status; - data.txn.data.ptr.offsets = 0; - } else { - data.txn.flags = 0; - data.txn.data_size = reply->data - reply->data0; - data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0); - data.txn.data.ptr.buffer = (uintptr_t)reply->data0; - data.txn.data.ptr.offsets = (uintptr_t)reply->offs0; - } - binder_write(bs, &data, sizeof(data)); -} - -int binder_parse(struct binder_state *bs, struct binder_io *bio, - uintptr_t ptr, size_t size, binder_handler func) -{ - int r = 1; - uintptr_t end = ptr + (uintptr_t) size; - - while (ptr < end) { - uint32_t cmd = *(uint32_t *) ptr; - ptr += sizeof(uint32_t); -#if TRACE - fprintf(stderr,"%s:\n", cmd_name(cmd)); -#endif - switch(cmd) { - case BR_NOOP: - break; - case BR_TRANSACTION_COMPLETE: - break; - case BR_INCREFS: - case BR_ACQUIRE: - case BR_RELEASE: - case BR_DECREFS: -#if TRACE - fprintf(stderr," %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *))); -#endif - ptr += sizeof(struct binder_ptr_cookie); - break; - case BR_TRANSACTION_SEC_CTX: - case BR_TRANSACTION: { - struct binder_transaction_data_secctx txn; - if (cmd == BR_TRANSACTION_SEC_CTX) { - if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) { - ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n"); - return -1; - } - memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx)); - ptr += sizeof(struct binder_transaction_data_secctx); - } else /* BR_TRANSACTION */ { - if ((end - ptr) < sizeof(struct binder_transaction_data)) { - ALOGE("parse: txn too small (binder_transaction_data)!\n"); - return -1; - } - memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data)); - ptr += sizeof(struct binder_transaction_data); - - txn.secctx = 0; - } - - binder_dump_txn(&txn.transaction_data); - if (func) { - unsigned rdata[256/4]; - struct binder_io msg; - struct binder_io reply; - int res; - - bio_init(&reply, rdata, sizeof(rdata), 4); - bio_init_from_txn(&msg, &txn.transaction_data); - res = func(bs, &txn, &msg, &reply); - if (txn.transaction_data.flags & TF_ONE_WAY) { - binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer); - } else { - binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res); - } - } - break; - } - case BR_REPLY: { - struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; - if ((end - ptr) < sizeof(*txn)) { - ALOGE("parse: reply too small!\n"); - return -1; - } - binder_dump_txn(txn); - if (bio) { - bio_init_from_txn(bio, txn); - bio = 0; - } else { - /* todo FREE BUFFER */ - } - ptr += sizeof(*txn); - r = 0; - break; - } - case BR_DEAD_BINDER: { - struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr; - ptr += sizeof(binder_uintptr_t); - death->func(bs, death->ptr); - break; - } - case BR_FAILED_REPLY: - r = -1; - break; - case BR_DEAD_REPLY: - r = -1; - break; - default: - ALOGE("parse: OOPS %d\n", cmd); - return -1; - } - } - - return r; -} - -void binder_acquire(struct binder_state *bs, uint32_t target) -{ - uint32_t cmd[2]; - cmd[0] = BC_ACQUIRE; - cmd[1] = target; - binder_write(bs, cmd, sizeof(cmd)); -} - -void binder_release(struct binder_state *bs, uint32_t target) -{ - uint32_t cmd[2]; - cmd[0] = BC_RELEASE; - cmd[1] = target; - binder_write(bs, cmd, sizeof(cmd)); -} - -void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death) -{ - struct { - uint32_t cmd; - struct binder_handle_cookie payload; - } __attribute__((packed)) data; - - data.cmd = BC_REQUEST_DEATH_NOTIFICATION; - data.payload.handle = target; - data.payload.cookie = (uintptr_t) death; - binder_write(bs, &data, sizeof(data)); -} - -int binder_call(struct binder_state *bs, - struct binder_io *msg, struct binder_io *reply, - uint32_t target, uint32_t code) -{ - int res; - struct binder_write_read bwr; - struct { - uint32_t cmd; - struct binder_transaction_data txn; - } __attribute__((packed)) writebuf; - unsigned readbuf[32]; - - if (msg->flags & BIO_F_OVERFLOW) { - fprintf(stderr,"binder: txn buffer overflow\n"); - goto fail; - } - - writebuf.cmd = BC_TRANSACTION; - writebuf.txn.target.handle = target; - writebuf.txn.code = code; - writebuf.txn.flags = 0; - writebuf.txn.data_size = msg->data - msg->data0; - writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0); - writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0; - writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0; - - bwr.write_size = sizeof(writebuf); - bwr.write_consumed = 0; - bwr.write_buffer = (uintptr_t) &writebuf; - - hexdump(msg->data0, msg->data - msg->data0); - for (;;) { - bwr.read_size = sizeof(readbuf); - bwr.read_consumed = 0; - bwr.read_buffer = (uintptr_t) readbuf; - - res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); - - if (res < 0) { - fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno)); - goto fail; - } - - res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0); - if (res == 0) return 0; - if (res < 0) goto fail; - } - -fail: - memset(reply, 0, sizeof(*reply)); - reply->flags |= BIO_F_IOERROR; - return -1; -} - -void binder_loop(struct binder_state *bs, binder_handler func) -{ - int res; - struct binder_write_read bwr; - uint32_t readbuf[32]; - - bwr.write_size = 0; - bwr.write_consumed = 0; - bwr.write_buffer = 0; - - readbuf[0] = BC_ENTER_LOOPER; - binder_write(bs, readbuf, sizeof(uint32_t)); - - for (;;) { - bwr.read_size = sizeof(readbuf); - bwr.read_consumed = 0; - bwr.read_buffer = (uintptr_t) readbuf; - - res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); - - if (res < 0) { - ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); - break; - } - - res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); - if (res == 0) { - ALOGE("binder_loop: unexpected reply?!\n"); - break; - } - if (res < 0) { - ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); - break; - } - } -} - -void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn) -{ - bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer; - bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets; - bio->data_avail = txn->data_size; - bio->offs_avail = txn->offsets_size / sizeof(size_t); - bio->flags = BIO_F_SHARED; -} - -void bio_init(struct binder_io *bio, void *data, - size_t maxdata, size_t maxoffs) -{ - size_t n = maxoffs * sizeof(size_t); - - if (n > maxdata) { - bio->flags = BIO_F_OVERFLOW; - bio->data_avail = 0; - bio->offs_avail = 0; - return; - } - - bio->data = bio->data0 = (char *) data + n; - bio->offs = bio->offs0 = data; - bio->data_avail = maxdata - n; - bio->offs_avail = maxoffs; - bio->flags = 0; -} - -static void *bio_alloc(struct binder_io *bio, size_t size) -{ - size = (size + 3) & (~3); - if (size > bio->data_avail) { - bio->flags |= BIO_F_OVERFLOW; - return NULL; - } else { - void *ptr = bio->data; - bio->data += size; - bio->data_avail -= size; - return ptr; - } -} - -void binder_done(struct binder_state *bs, - __unused struct binder_io *msg, - struct binder_io *reply) -{ - struct { - uint32_t cmd; - uintptr_t buffer; - } __attribute__((packed)) data; - - if (reply->flags & BIO_F_SHARED) { - data.cmd = BC_FREE_BUFFER; - data.buffer = (uintptr_t) reply->data0; - binder_write(bs, &data, sizeof(data)); - reply->flags = 0; - } -} - -static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio) -{ - struct flat_binder_object *obj; - - obj = bio_alloc(bio, sizeof(*obj)); - - if (obj && bio->offs_avail) { - bio->offs_avail--; - *bio->offs++ = ((char*) obj) - ((char*) bio->data0); - return obj; - } - - bio->flags |= BIO_F_OVERFLOW; - return NULL; -} - -void bio_put_uint32(struct binder_io *bio, uint32_t n) -{ - uint32_t *ptr = bio_alloc(bio, sizeof(n)); - if (ptr) - *ptr = n; -} - -void bio_put_obj(struct binder_io *bio, void *ptr) -{ - struct flat_binder_object *obj; - - obj = bio_alloc_obj(bio); - if (!obj) - return; - - obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj->hdr.type = BINDER_TYPE_BINDER; - obj->binder = (uintptr_t)ptr; - obj->cookie = 0; -} - -void bio_put_ref(struct binder_io *bio, uint32_t handle) -{ - struct flat_binder_object *obj; - - if (handle) - obj = bio_alloc_obj(bio); - else - obj = bio_alloc(bio, sizeof(*obj)); - - if (!obj) - return; - - obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj->hdr.type = BINDER_TYPE_HANDLE; - obj->handle = handle; - obj->cookie = 0; -} - -void bio_put_string16(struct binder_io *bio, const uint16_t *str) -{ - size_t len; - uint16_t *ptr; - - if (!str) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - len = 0; - while (str[len]) len++; - - if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - /* Note: The payload will carry 32bit size instead of size_t */ - bio_put_uint32(bio, (uint32_t) len); - len = (len + 1) * sizeof(uint16_t); - ptr = bio_alloc(bio, len); - if (ptr) - memcpy(ptr, str, len); -} - -void bio_put_string16_x(struct binder_io *bio, const char *_str) -{ - unsigned char *str = (unsigned char*) _str; - size_t len; - uint16_t *ptr; - - if (!str) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - len = strlen(_str); - - if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { - bio_put_uint32(bio, 0xffffffff); - return; - } - - /* Note: The payload will carry 32bit size instead of size_t */ - bio_put_uint32(bio, len); - ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t)); - if (!ptr) - return; - - while (*str) - *ptr++ = *str++; - *ptr++ = 0; -} - -static void *bio_get(struct binder_io *bio, size_t size) -{ - size = (size + 3) & (~3); - - if (bio->data_avail < size){ - bio->data_avail = 0; - bio->flags |= BIO_F_OVERFLOW; - return NULL; - } else { - void *ptr = bio->data; - bio->data += size; - bio->data_avail -= size; - return ptr; - } -} - -uint32_t bio_get_uint32(struct binder_io *bio) -{ - uint32_t *ptr = bio_get(bio, sizeof(*ptr)); - return ptr ? *ptr : 0; -} - -uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz) -{ - size_t len; - - /* Note: The payload will carry 32bit size instead of size_t */ - len = (size_t) bio_get_uint32(bio); - if (sz) - *sz = len; - return bio_get(bio, (len + 1) * sizeof(uint16_t)); -} - -static struct flat_binder_object *_bio_get_obj(struct binder_io *bio) -{ - size_t n; - size_t off = bio->data - bio->data0; - - /* TODO: be smarter about this? */ - for (n = 0; n < bio->offs_avail; n++) { - if (bio->offs[n] == off) - return bio_get(bio, sizeof(struct flat_binder_object)); - } - - bio->data_avail = 0; - bio->flags |= BIO_F_OVERFLOW; - return NULL; -} - -uint32_t bio_get_ref(struct binder_io *bio) -{ - struct flat_binder_object *obj; - - obj = _bio_get_obj(bio); - if (!obj) - return 0; - - if (obj->hdr.type == BINDER_TYPE_HANDLE) - return obj->handle; - - return 0; -} diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h deleted file mode 100644 index a9ccc74130..0000000000 --- a/cmds/servicemanager/binder.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#ifndef _BINDER_H_ -#define _BINDER_H_ - -#include -#include - -struct binder_state; - -struct binder_io -{ - char *data; /* pointer to read/write from */ - binder_size_t *offs; /* array of offsets */ - size_t data_avail; /* bytes available in data buffer */ - size_t offs_avail; /* entries available in offsets array */ - - char *data0; /* start of data buffer */ - binder_size_t *offs0; /* start of offsets buffer */ - uint32_t flags; - uint32_t unused; -}; - -struct binder_death { - void (*func)(struct binder_state *bs, void *ptr); - void *ptr; -}; - -/* the one magic handle */ -#define BINDER_SERVICE_MANAGER 0U - -#define SVC_MGR_NAME "android.os.IServiceManager" - -enum { - /* Must match definitions in IBinder.h and IServiceManager.h */ - PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'), - SVC_MGR_GET_SERVICE = 1, - SVC_MGR_CHECK_SERVICE, - SVC_MGR_ADD_SERVICE, - SVC_MGR_LIST_SERVICES, -}; - -typedef int (*binder_handler)(struct binder_state *bs, - struct binder_transaction_data_secctx *txn, - struct binder_io *msg, - struct binder_io *reply); - -struct binder_state *binder_open(const char* driver, size_t mapsize); -void binder_close(struct binder_state *bs); - -/* initiate a blocking binder call - * - returns zero on success - */ -int binder_call(struct binder_state *bs, - struct binder_io *msg, struct binder_io *reply, - uint32_t target, uint32_t code); - -/* release any state associate with the binder_io - * - call once any necessary data has been extracted from the - * binder_io after binder_call() returns - * - can safely be called even if binder_call() fails - */ -void binder_done(struct binder_state *bs, - struct binder_io *msg, struct binder_io *reply); - -/* manipulate strong references */ -void binder_acquire(struct binder_state *bs, uint32_t target); -void binder_release(struct binder_state *bs, uint32_t target); - -void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death); - -void binder_loop(struct binder_state *bs, binder_handler func); - -int binder_become_context_manager(struct binder_state *bs); - -/* allocate a binder_io, providing a stack-allocated working - * buffer, size of the working buffer, and how many object - * offset entries to reserve from the buffer - */ -void bio_init(struct binder_io *bio, void *data, - size_t maxdata, size_t maxobjects); - -void bio_put_obj(struct binder_io *bio, void *ptr); -void bio_put_ref(struct binder_io *bio, uint32_t handle); -void bio_put_uint32(struct binder_io *bio, uint32_t n); -void bio_put_string16(struct binder_io *bio, const uint16_t *str); -void bio_put_string16_x(struct binder_io *bio, const char *_str); - -uint32_t bio_get_uint32(struct binder_io *bio); -uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz); -uint32_t bio_get_ref(struct binder_io *bio); - -#endif diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp new file mode 100644 index 0000000000..c8ceb42ac8 --- /dev/null +++ b/cmds/servicemanager/main.cpp @@ -0,0 +1,54 @@ +/* + * 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 +#include +#include +#include +#include + +#include "Access.h" +#include "ServiceManager.h" + +using ::android::sp; +using ::android::ProcessState; +using ::android::IPCThreadState; +using ::android::ServiceManager; +using ::android::Access; + +int main(int argc, char** argv) { + if (argc > 2) { + LOG(FATAL) << "usage: " << argv[0] << " [binder driver]"; + } + + const char* driver = argc == 2 ? argv[1] : "/dev/binder"; + + android::base::InitLogging(nullptr, &android::base::KernelLogger); + + ProcessState::self()->initWithDriver(driver); + ProcessState::self()->setThreadPoolMaxThreadCount(0); + ProcessState::self()->setCallRestriction( + ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); + + sp manager = new ServiceManager(std::make_unique()); + IPCThreadState::self()->setTheContextObject(manager); + ProcessState::self()->becomeContextManager(nullptr, nullptr); + + IPCThreadState::self()->joinThreadPool(); + + // should not be reached + return EXIT_FAILURE; +} diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c deleted file mode 100644 index ec3fac538d..0000000000 --- a/cmds/servicemanager/service_manager.c +++ /dev/null @@ -1,442 +0,0 @@ -/* Copyright 2008 The Android Open Source Project - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "binder.h" - -#ifdef VENDORSERVICEMANAGER -#define LOG_TAG "VendorServiceManager" -#else -#define LOG_TAG "ServiceManager" -#endif -#include - -struct audit_data { - pid_t pid; - uid_t uid; - const char *name; -}; - -const char *str8(const uint16_t *x, size_t x_len) -{ - static char buf[128]; - size_t max = 127; - char *p = buf; - - if (x_len < max) { - max = x_len; - } - - if (x) { - while ((max > 0) && (*x != '\0')) { - *p++ = *x++; - max--; - } - } - *p++ = 0; - return buf; -} - -int str16eq(const uint16_t *a, const char *b) -{ - while (*a && *b) - if (*a++ != *b++) return 0; - if (*a || *b) - return 0; - return 1; -} - -static char *service_manager_context; -static struct selabel_handle* sehandle; - -static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name) -{ - char *lookup_sid = NULL; - const char *class = "service_manager"; - bool allowed; - struct audit_data ad; - - if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) { - ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); - return false; - } - - ad.pid = spid; - ad.uid = uid; - ad.name = name; - - if (sid == NULL) { - android_errorWriteLog(0x534e4554, "121035042"); - } - - int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad); - allowed = (result == 0); - - freecon(lookup_sid); - return allowed; -} - -static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm) -{ - return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL); -} - -static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name) -{ - bool allowed; - char *tctx = NULL; - - if (!sehandle) { - ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n"); - abort(); - } - - if (selabel_lookup(sehandle, &tctx, name, 0) != 0) { - ALOGE("SELinux: No match for %s in service_contexts.\n", name); - return false; - } - - allowed = check_mac_perms(spid, sid, uid, tctx, perm, name); - freecon(tctx); - return allowed; -} - -static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid) -{ - const char *perm = "add"; - - if (multiuser_get_app_id(uid) >= AID_APP) { - return 0; /* Don't allow apps to register services */ - } - - return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0; -} - -static int svc_can_list(pid_t spid, const char* sid, uid_t uid) -{ - const char *perm = "list"; - return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0; -} - -static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid) -{ - const char *perm = "find"; - return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0; -} - -struct svcinfo -{ - struct svcinfo *next; - uint32_t handle; - struct binder_death death; - int allow_isolated; - uint32_t dumpsys_priority; - size_t len; - uint16_t name[0]; -}; - -struct svcinfo *svclist = NULL; - -struct svcinfo *find_svc(const uint16_t *s16, size_t len) -{ - struct svcinfo *si; - - for (si = svclist; si; si = si->next) { - if ((len == si->len) && - !memcmp(s16, si->name, len * sizeof(uint16_t))) { - return si; - } - } - return NULL; -} - -void svcinfo_death(struct binder_state *bs, void *ptr) -{ - struct svcinfo *si = (struct svcinfo* ) ptr; - - ALOGI("service '%s' died\n", str8(si->name, si->len)); - if (si->handle) { - binder_release(bs, si->handle); - si->handle = 0; - } -} - -uint16_t svcmgr_id[] = { - 'a','n','d','r','o','i','d','.','o','s','.', - 'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r' -}; - - -uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid) -{ - struct svcinfo *si = find_svc(s, len); - - if (!si || !si->handle) { - return 0; - } - - if (!si->allow_isolated) { - // If this service doesn't allow access from isolated processes, - // then check the uid to see if it is isolated. - uid_t appid = uid % AID_USER; - if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { - return 0; - } - } - - if (!svc_can_find(s, len, spid, sid, uid)) { - return 0; - } - - return si->handle; -} - -int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, - uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) { - struct svcinfo *si; - - //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle, - // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); - - if (!handle || (len == 0) || (len > 127)) - return -1; - - if (!svc_can_register(s, len, spid, sid, uid)) { - ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", - str8(s, len), handle, uid); - return -1; - } - - si = find_svc(s, len); - if (si) { - if (si->handle) { - ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n", - str8(s, len), handle, uid); - svcinfo_death(bs, si); - } - si->handle = handle; - } else { - si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); - if (!si) { - ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n", - str8(s, len), handle, uid); - return -1; - } - si->handle = handle; - si->len = len; - memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); - si->name[len] = '\0'; - si->death.func = (void*) svcinfo_death; - si->death.ptr = si; - si->allow_isolated = allow_isolated; - si->dumpsys_priority = dumpsys_priority; - si->next = svclist; - svclist = si; - } - - binder_acquire(bs, handle); - binder_link_to_death(bs, handle, &si->death); - return 0; -} - -int svcmgr_handler(struct binder_state *bs, - struct binder_transaction_data_secctx *txn_secctx, - struct binder_io *msg, - struct binder_io *reply) -{ - struct svcinfo *si; - uint16_t *s; - size_t len; - uint32_t handle; - uint32_t strict_policy; - int allow_isolated; - uint32_t dumpsys_priority; - - struct binder_transaction_data *txn = &txn_secctx->transaction_data; - - //ALOGI("target=%p code=%d pid=%d uid=%d\n", - // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); - - if (txn->target.ptr != BINDER_SERVICE_MANAGER) - return -1; - - if (txn->code == PING_TRANSACTION) - return 0; - - // Equivalent to Parcel::enforceInterface(), reading the RPC - // header with the strict mode policy mask and the interface name. - // Note that we ignore the strict_policy and don't propagate it - // further (since we do no outbound RPCs anyway). - strict_policy = bio_get_uint32(msg); - bio_get_uint32(msg); // Ignore worksource header. - s = bio_get_string16(msg, &len); - if (s == NULL) { - return -1; - } - - if ((len != (sizeof(svcmgr_id) / 2)) || - memcmp(svcmgr_id, s, sizeof(svcmgr_id))) { - fprintf(stderr,"invalid id %s\n", str8(s, len)); - return -1; - } - - if (sehandle && selinux_status_updated() > 0) { -#ifdef VENDORSERVICEMANAGER - struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle(); -#else - struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle(); -#endif - if (tmp_sehandle) { - selabel_close(sehandle); - sehandle = tmp_sehandle; - } - } - - switch(txn->code) { - case SVC_MGR_GET_SERVICE: - case SVC_MGR_CHECK_SERVICE: - s = bio_get_string16(msg, &len); - if (s == NULL) { - return -1; - } - handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid, - (const char*) txn_secctx->secctx); - if (!handle) - break; - bio_put_ref(reply, handle); - return 0; - - case SVC_MGR_ADD_SERVICE: - s = bio_get_string16(msg, &len); - if (s == NULL) { - return -1; - } - handle = bio_get_ref(msg); - allow_isolated = bio_get_uint32(msg) ? 1 : 0; - dumpsys_priority = bio_get_uint32(msg); - if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority, - txn->sender_pid, (const char*) txn_secctx->secctx)) - return -1; - break; - - case SVC_MGR_LIST_SERVICES: { - uint32_t n = bio_get_uint32(msg); - uint32_t req_dumpsys_priority = bio_get_uint32(msg); - - if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) { - ALOGE("list_service() uid=%d - PERMISSION DENIED\n", - txn->sender_euid); - return -1; - } - si = svclist; - // walk through the list of services n times skipping services that - // do not support the requested priority - while (si) { - if (si->dumpsys_priority & req_dumpsys_priority) { - if (n == 0) break; - n--; - } - si = si->next; - } - if (si) { - bio_put_string16(reply, si->name); - return 0; - } - return -1; - } - default: - ALOGE("unknown code %d\n", txn->code); - return -1; - } - - bio_put_uint32(reply, 0); - return 0; -} - - -static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len) -{ - struct audit_data *ad = (struct audit_data *)data; - - if (!ad || !ad->name) { - ALOGE("No service manager audit data"); - return 0; - } - - snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid); - return 0; -} - -int main(int argc, char** argv) -{ - struct binder_state *bs; - union selinux_callback cb; - char *driver; - - if (argc > 1) { - driver = argv[1]; - } else { - driver = "/dev/binder"; - } - - bs = binder_open(driver, 128*1024); - if (!bs) { -#ifdef VENDORSERVICEMANAGER - ALOGW("failed to open binder driver %s\n", driver); - while (true) { - sleep(UINT_MAX); - } -#else - ALOGE("failed to open binder driver %s\n", driver); -#endif - return -1; - } - - if (binder_become_context_manager(bs)) { - ALOGE("cannot become context manager (%s)\n", strerror(errno)); - return -1; - } - - cb.func_audit = audit_callback; - selinux_set_callback(SELINUX_CB_AUDIT, cb); -#ifdef VENDORSERVICEMANAGER - cb.func_log = selinux_vendor_log_callback; -#else - cb.func_log = selinux_log_callback; -#endif - selinux_set_callback(SELINUX_CB_LOG, cb); - -#ifdef VENDORSERVICEMANAGER - sehandle = selinux_android_vendor_service_context_handle(); -#else - sehandle = selinux_android_service_context_handle(); -#endif - selinux_status_open(true); - - if (sehandle == NULL) { - ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n"); - abort(); - } - - if (getcon(&service_manager_context) != 0) { - ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); - abort(); - } - - - binder_loop(bs, svcmgr_handler); - - return 0; -} diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp new file mode 100644 index 0000000000..812d5cacd5 --- /dev/null +++ b/cmds/servicemanager/test_sm.cpp @@ -0,0 +1,261 @@ +/* + * 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 +#include +#include +#include + +#include "Access.h" +#include "ServiceManager.h" + +using android::sp; +using android::Access; +using android::IBinder; +using android::ServiceManager; +using android::os::IServiceManager; +using testing::_; +using testing::ElementsAre; +using testing::NiceMock; +using testing::Return; + +static sp getBinder() { + // It doesn't matter what remote binder it is, we just need one so that linkToDeath will work. + // The context manager (servicemanager) is easy to get and is in another process. + return android::ProcessState::self()->getContextObject(nullptr); +} + +class MockAccess : public Access { +public: + MOCK_METHOD1(getCallingContext, CallingContext(const std::string& name)); + MOCK_METHOD1(canAdd, bool(const CallingContext&)); + MOCK_METHOD1(canFind, bool(const CallingContext&)); + MOCK_METHOD1(canList, bool(const CallingContext&)); +}; + +static sp getPermissiveServiceManager() { + std::unique_ptr access = std::make_unique>(); + + ON_CALL(*access, getCallingContext(_)).WillByDefault(Return(Access::CallingContext{})); + ON_CALL(*access, canAdd(_)).WillByDefault(Return(true)); + ON_CALL(*access, canFind(_)).WillByDefault(Return(true)); + ON_CALL(*access, canList(_)).WillByDefault(Return(true)); + + sp sm = new ServiceManager(std::move(access)); + return sm; +} + +TEST(AddService, HappyHappy) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, EmptyNameDisallowed) { + auto sm = getPermissiveServiceManager(); + EXPECT_FALSE(sm->addService("", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, JustShortEnoughServiceNameHappy) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService(std::string(127, 'a'), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, TooLongNameDisallowed) { + auto sm = getPermissiveServiceManager(); + EXPECT_FALSE(sm->addService(std::string(128, 'a'), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, AddNullServiceDisallowed) { + auto sm = getPermissiveServiceManager(); + EXPECT_FALSE(sm->addService("foo", nullptr, false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, AddDisallowedFromApp) { + for (uid_t uid : { AID_APP_START, AID_APP_START + 1, AID_APP_END }) { + std::unique_ptr access = std::make_unique>(); + EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{ + .debugPid = 1337, + .uid = uid, + })); + EXPECT_CALL(*access, canAdd(_)).Times(0); + sp sm = new ServiceManager(std::move(access)); + + EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + } + +} + +TEST(AddService, HappyOverExistingService) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(AddService, NoPermissions) { + std::unique_ptr access = std::make_unique>(); + + EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{})); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(false)); + + sp sm = new ServiceManager(std::move(access)); + + EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); +} + +TEST(GetService, HappyHappy) { + auto sm = getPermissiveServiceManager(); + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp out; + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(getBinder(), out); +} + +TEST(GetService, NonExistant) { + auto sm = getPermissiveServiceManager(); + + sp out; + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(nullptr, out.get()); +} + +TEST(GetService, NoPermissionsForGettingService) { + std::unique_ptr access = std::make_unique>(); + + EXPECT_CALL(*access, getCallingContext(_)).WillRepeatedly(Return(Access::CallingContext{})); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true)); + EXPECT_CALL(*access, canFind(_)).WillOnce(Return(false)); + + sp sm = new ServiceManager(std::move(access)); + + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp out; + // returns nullptr but has OK status for legacy compatibility + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(nullptr, out.get()); +} + +TEST(GetService, AllowedFromIsolated) { + std::unique_ptr access = std::make_unique>(); + + EXPECT_CALL(*access, getCallingContext(_)) + // something adds it + .WillOnce(Return(Access::CallingContext{})) + // next call is from isolated app + .WillOnce(Return(Access::CallingContext{ + .uid = AID_ISOLATED_START, + })); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true)); + EXPECT_CALL(*access, canFind(_)).WillOnce(Return(true)); + + sp sm = new ServiceManager(std::move(access)); + + EXPECT_TRUE(sm->addService("foo", getBinder(), true /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp out; + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(getBinder(), out.get()); +} + +TEST(GetService, NotAllowedFromIsolated) { + std::unique_ptr access = std::make_unique>(); + + EXPECT_CALL(*access, getCallingContext(_)) + // something adds it + .WillOnce(Return(Access::CallingContext{})) + // next call is from isolated app + .WillOnce(Return(Access::CallingContext{ + .uid = AID_ISOLATED_START, + })); + EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true)); + + // TODO(b/136023468): when security check is first, this should be called first + // EXPECT_CALL(*access, canFind(_)).WillOnce(Return(true)); + + sp sm = new ServiceManager(std::move(access)); + + EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + + sp out; + // returns nullptr but has OK status for legacy compatibility + EXPECT_TRUE(sm->getService("foo", &out).isOk()); + EXPECT_EQ(nullptr, out.get()); +} + +TEST(ListServices, NoPermissions) { + std::unique_ptr access = std::make_unique>(); + + EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{})); + EXPECT_CALL(*access, canList(_)).WillOnce(Return(false)); + + sp sm = new ServiceManager(std::move(access)); + + std::vector out; + EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk()); + EXPECT_TRUE(out.empty()); +} + +TEST(ListServices, AllServices) { + auto sm = getPermissiveServiceManager(); + + EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk()); + EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk()); + EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk()); + + std::vector out; + EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk()); + + // all there and in the right order + EXPECT_THAT(out, ElementsAre("sa", "sb", "sc", "sd")); +} + +TEST(ListServices, CriticalServices) { + auto sm = getPermissiveServiceManager(); + + EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); + EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk()); + EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk()); + EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk()); + + std::vector out; + EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, &out).isOk()); + + // all there and in the right order + EXPECT_THAT(out, ElementsAre("sa")); +} diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 905b25f397..760d55b751 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -94,7 +94,6 @@ cc_library_shared { "PermissionController.cpp", "ProcessInfoService.cpp", "IpPrefix.cpp", - ":libbinder_aidl", ], }, }, @@ -142,8 +141,7 @@ filegroup { name: "libbinder_aidl", srcs: [ "aidl/android/content/pm/IPackageManagerNative.aidl", + "aidl/android/os/IServiceManager.aidl", ], path: "aidl", } - -subdirs = ["tests"] diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index a2d10ab0ab..3424c28883 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -1062,7 +1062,7 @@ status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, sp the_context_object; -void setTheContextObject(sp obj) +void IPCThreadState::setTheContextObject(sp obj) { the_context_object = obj; } diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 0203d41992..07550fb571 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -18,6 +18,7 @@ #include +#include #include #include #ifndef __ANDROID_VNDK__ @@ -34,6 +35,9 @@ namespace android { +using AidlServiceManager = android::os::IServiceManager; +using android::binder::Status; + sp defaultServiceManager() { static Mutex gDefaultServiceManagerLock; @@ -142,11 +146,12 @@ class BpServiceManager : public BpInterface { public: explicit BpServiceManager(const sp& impl) - : BpInterface(impl) + : BpInterface(impl), + mTheRealServiceManager(interface_cast(impl)) { } - virtual sp getService(const String16& name) const + sp getService(const String16& name) const override { static bool gSystemBootCompleted = false; @@ -179,43 +184,36 @@ public: return nullptr; } - virtual sp checkService( const String16& name) const - { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); - return reply.readStrongBinder(); + sp checkService(const String16& name) const override { + sp ret; + if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { + return nullptr; + } + return ret; } - virtual status_t addService(const String16& name, const sp& service, - bool allowIsolated, int dumpsysPriority) { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeString16(name); - data.writeStrongBinder(service); - data.writeInt32(allowIsolated ? 1 : 0); - data.writeInt32(dumpsysPriority); - status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); - return err == NO_ERROR ? reply.readExceptionCode() : err; + status_t addService(const String16& name, const sp& service, + bool allowIsolated, int dumpsysPriority) override { + Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority); + return status.exceptionCode(); } virtual Vector listServices(int dumpsysPriority) { - Vector res; - int n = 0; + std::vector ret; + if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { + return {}; + } - for (;;) { - Parcel data, reply; - data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); - data.writeInt32(n++); - data.writeInt32(dumpsysPriority); - status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply); - if (err != NO_ERROR) - break; - res.add(reply.readString16()); + Vector res; + res.setCapacity(ret.size()); + for (const std::string& name : ret) { + res.push(String16(name.c_str())); } return res; } + +private: + sp mTheRealServiceManager; }; IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl new file mode 100644 index 0000000000..50a72aa9e4 --- /dev/null +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** + * Basic interface for finding and publishing system services. + * + * You likely want to use android.os.ServiceManager in Java or + * android::IServiceManager in C++ in order to use this interface. + * + * @hide + */ +interface IServiceManager { + /* + * Must update values in IServiceManager.h + */ + /* Allows services to dump sections according to priorities. */ + const int DUMP_FLAG_PRIORITY_CRITICAL = 1; // 1 << 0 + const int DUMP_FLAG_PRIORITY_HIGH = 2; // 1 << 1 + const int DUMP_FLAG_PRIORITY_NORMAL = 4; // 1 << 2 + /** + * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the + * same priority as NORMAL priority but the services are not called with dump priority + * arguments. + */ + const int DUMP_FLAG_PRIORITY_DEFAULT = 8; // 1 << 3 + + const int DUMP_FLAG_PRIORITY_ALL = 15; + // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH + // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT; + + /* Allows services to dump sections in protobuf format. */ + const int DUMP_FLAG_PROTO = 16; // 1 << 4 + + /** + * Retrieve an existing service called @a name from the + * service manager. + * + * This is the same as checkService (returns immediately) but + * exists for legacy purposes. + * + * Returns null if the service does not exist. + */ + @UnsupportedAppUsage + IBinder getService(@utf8InCpp String name); + + /** + * Retrieve an existing service called @a name from the service + * manager. Non-blocking. Returns null if the service does not + * exist. + */ + @UnsupportedAppUsage + IBinder checkService(@utf8InCpp String name); + + /** + * Place a new @a service called @a name into the service + * manager. + */ + void addService(@utf8InCpp String name, IBinder service, + boolean allowIsolated, int dumpPriority); + + /** + * Return a list of all currently running services. + */ + @utf8InCpp String[] listServices(int dumpPriority); +} diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h index 614b0b33dd..b810f7e8ee 100644 --- a/libs/binder/include/binder/IPCThreadState.h +++ b/libs/binder/include/binder/IPCThreadState.h @@ -110,6 +110,8 @@ public: // the maximum number of binder threads threads allowed for this process. void blockUntilThreadAvailable(); + // Service manager registration + void setTheContextObject(sp obj); // Is this thread currently serving a binder call. This method // returns true if while traversing backwards from the function call -- cgit v1.2.3-59-g8ed1b From c3e2f8dd52946b1736bb96db4da76425af34196f Mon Sep 17 00:00:00 2001 From: Sahana Rao Date: Fri, 28 Jun 2019 13:18:57 +0100 Subject: dumpstate: Update readme Add command to enable bugreport from new Bugreport API workflow Test: N/A Change-Id: I5299102634ef6421842be90022cbffbb5cdcc812 --- cmds/dumpstate/README.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'cmds') diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md index c818c05117..26dabbbcef 100644 --- a/cmds/dumpstate/README.md +++ b/cmds/dumpstate/README.md @@ -92,6 +92,12 @@ Then to restore the default version: adb shell setprop dumpstate.version default ``` +## To set Bugreport API workflow for bugreport + +``` +adb shell setprop settings_call_bugreport_api true +``` + ## Code style and formatting Use the style defined at the -- cgit v1.2.3-59-g8ed1b From fd712afb49fd1a44d3270e090876b8b9faf8388f Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Tue, 16 Jul 2019 08:44:16 -0700 Subject: Fix whitespace errors Change-Id: I2ac1f097aa84a2a5241fb7521c869b7416265ca0 --- cmds/service/service.cpp | 128 +++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 64 deletions(-) (limited to 'cmds') diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp index d5dc6b741d..543357c564 100644 --- a/cmds/service/service.cpp +++ b/cmds/service/service.cpp @@ -70,7 +70,7 @@ int main(int argc, char* const argv[]) { bool wantsUsage = false; int result = 0; - + while (1) { int ic = getopt(argc, argv, "h?"); if (ic < 0) @@ -97,7 +97,7 @@ int main(int argc, char* const argv[]) aerr << "service: Unable to get default service manager!" << endl; return 20; } - + if (optind >= argc) { wantsUsage = true; } else if (!wantsUsage) { @@ -119,8 +119,8 @@ int main(int argc, char* const argv[]) for (unsigned i = 0; i < services.size(); i++) { String16 name = services[i]; sp service = sm->checkService(name); - aout << i - << "\t" << good_old_string(name) + aout << i + << "\t" << good_old_string(name) << ": [" << good_old_string(get_interface_name(service)) << "]" << endl; } @@ -188,68 +188,68 @@ int main(int argc, char* const argv[]) optind++; data.writeStrongBinder(nullptr); } else if (strcmp(argv[optind], "intent") == 0) { - - char* action = nullptr; - char* dataArg = nullptr; - char* type = nullptr; - int launchFlags = 0; - char* component = nullptr; - int categoryCount = 0; - char* categories[16]; - - char* context1 = nullptr; - + + char* action = nullptr; + char* dataArg = nullptr; + char* type = nullptr; + int launchFlags = 0; + char* component = nullptr; + int categoryCount = 0; + char* categories[16]; + + char* context1 = nullptr; + optind++; - - while (optind < argc) - { - char* key = strtok_r(argv[optind], "=", &context1); - char* value = strtok_r(nullptr, "=", &context1); - + + while (optind < argc) + { + char* key = strtok_r(argv[optind], "=", &context1); + char* value = strtok_r(nullptr, "=", &context1); + // we have reached the end of the XXX=XXX args. if (key == nullptr) break; - - if (strcmp(key, "action") == 0) - { - action = value; - } - else if (strcmp(key, "data") == 0) - { - dataArg = value; - } - else if (strcmp(key, "type") == 0) - { - type = value; - } - else if (strcmp(key, "launchFlags") == 0) - { - launchFlags = atoi(value); - } - else if (strcmp(key, "component") == 0) - { - component = value; - } - else if (strcmp(key, "categories") == 0) - { - char* context2 = nullptr; - categories[categoryCount] = strtok_r(value, ",", &context2); - - while (categories[categoryCount] != nullptr) - { - categoryCount++; - categories[categoryCount] = strtok_r(nullptr, ",", &context2); - } - } - + + if (strcmp(key, "action") == 0) + { + action = value; + } + else if (strcmp(key, "data") == 0) + { + dataArg = value; + } + else if (strcmp(key, "type") == 0) + { + type = value; + } + else if (strcmp(key, "launchFlags") == 0) + { + launchFlags = atoi(value); + } + else if (strcmp(key, "component") == 0) + { + component = value; + } + else if (strcmp(key, "categories") == 0) + { + char* context2 = nullptr; + categories[categoryCount] = strtok_r(value, ",", &context2); + + while (categories[categoryCount] != nullptr) + { + categoryCount++; + categories[categoryCount] = strtok_r(nullptr, ",", &context2); + } + } + optind++; - } - + } + writeString16(data, action); writeString16(data, dataArg); writeString16(data, type); - data.writeInt32(launchFlags); + data.writeInt32(launchFlags); writeString16(data, component); - + if (categoryCount > 0) { data.writeInt32(categoryCount); @@ -261,10 +261,10 @@ int main(int argc, char* const argv[]) else { data.writeInt32(0); - } - + } + // for now just set the extra field to be null. - data.writeInt32(-1); + data.writeInt32(-1); } else { aerr << "service: unknown option " << argv[optind] << endl; wantsUsage = true; @@ -272,7 +272,7 @@ int main(int argc, char* const argv[]) break; } } - + service->transact(code, data, &reply); aout << "Result: " << reply << endl; } else { @@ -295,7 +295,7 @@ int main(int argc, char* const argv[]) result = 10; } } - + if (wantsUsage) { aout << "Usage: service [-h|-?]\n" " service list\n" @@ -311,7 +311,7 @@ int main(int argc, char* const argv[]) // " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n"; return result; } - + return result; } -- cgit v1.2.3-59-g8ed1b From 456bbb2a5ecfadbdc639e0a2b671802401d3c663 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 18 Jul 2019 16:02:00 -0700 Subject: Add more layer state changes to SurfaceInterceptor Track flag set and clear state changes. Track reparenting, detach children and relative z changes. Test: run surface interceptor and view results Test: atest SurfaceFlinger_test:SurfaceInterceptorTest#* Change-Id: I0c55e6d45034e180a3c8970c60af21bf8f2bb01c --- cmds/surfacereplayer/proto/src/trace.proto | 21 ++++ cmds/surfacereplayer/replayer/Replayer.cpp | 44 +++++++ cmds/surfacereplayer/replayer/Replayer.h | 8 ++ services/surfaceflinger/SurfaceInterceptor.cpp | 93 +++++++++++--- services/surfaceflinger/SurfaceInterceptor.h | 15 ++- .../tests/SurfaceInterceptor_test.cpp | 137 +++++++++++++++++++-- 6 files changed, 291 insertions(+), 27 deletions(-) (limited to 'cmds') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index c70bc3e5c1..a738527fbb 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -46,6 +46,10 @@ message SurfaceChange { SecureFlagChange secure_flag = 14; DeferredTransactionChange deferred_transaction = 15; CornerRadiusChange corner_radius = 16; + ReparentChange reparent = 17; + RelativeParentChange relative_parent = 18; + DetachChildrenChange detach_children = 19; + ReparentChildrenChange reparent_children = 20; } } @@ -177,3 +181,20 @@ message PowerModeUpdate { required int32 id = 1; required int32 mode = 2; } + +message ReparentChange { + required int32 parent_id = 1; +} + +message ReparentChildrenChange { + required int32 parent_id = 1; +} + +message RelativeParentChange { + required int32 relative_parent_id = 1; + required int32 z = 2; +} + +message DetachChildrenChange { + required bool detach_children = 1; +} diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 34886a99e9..a4a9b6a6f4 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -412,6 +412,18 @@ status_t Replayer::doSurfaceTransaction( setDeferredTransaction(transaction, change.id(), change.deferred_transaction()); break; + case SurfaceChange::SurfaceChangeCase::kReparent: + setReparentChange(transaction, change.id(), change.reparent()); + break; + case SurfaceChange::SurfaceChangeCase::kReparentChildren: + setReparentChildrenChange(transaction, change.id(), change.reparent_children()); + break; + case SurfaceChange::SurfaceChangeCase::kRelativeParent: + setRelativeParentChange(transaction, change.id(), change.relative_parent()); + break; + case SurfaceChange::SurfaceChangeCase::kDetachChildren: + setDetachChildrenChange(transaction, change.id(), change.detach_children()); + break; default: status = 1; break; @@ -680,3 +692,35 @@ status_t Replayer::loadSurfaceComposerClient() { mComposerClient = new SurfaceComposerClient; return mComposerClient->initCheck(); } + +void Replayer::setReparentChange(SurfaceComposerClient::Transaction& t, + layer_id id, const ReparentChange& c) { + sp newParentHandle = nullptr; + if (mLayers.count(c.parent_id()) != 0 && mLayers[c.parent_id()] != nullptr) { + newParentHandle = mLayers[c.parent_id()]->getHandle(); + } + t.reparent(mLayers[id], newParentHandle); +} + +void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t, + layer_id id, const RelativeParentChange& c) { + if (mLayers.count(c.relative_parent_id()) == 0 || mLayers[c.relative_parent_id()] == nullptr) { + ALOGE("Layer %d not found in set relative parent transaction", c.relative_parent_id()); + return; + } + t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()]->getHandle(), c.z()); +} + +void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t, + layer_id id, const DetachChildrenChange& c) { + t.detachChildren(mLayers[id]); +} + +void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t, + layer_id id, const ReparentChildrenChange& c) { + if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) { + ALOGE("Layer %d not found in reparent children transaction", c.parent_id()); + return; + } + t.reparentChildren(mLayers[id], mLayers[c.parent_id()]->getHandle()); +} diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index ad807ee950..d7709cc211 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -108,6 +108,14 @@ class Replayer { layer_id id, const SecureFlagChange& sfc); void setDeferredTransaction(SurfaceComposerClient::Transaction& t, layer_id id, const DeferredTransactionChange& dtc); + void setReparentChange(SurfaceComposerClient::Transaction& t, + layer_id id, const ReparentChange& c); + void setRelativeParentChange(SurfaceComposerClient::Transaction& t, + layer_id id, const RelativeParentChange& c); + void setDetachChildrenChange(SurfaceComposerClient::Transaction& t, + layer_id id, const DetachChildrenChange& c); + void setReparentChildrenChange(SurfaceComposerClient::Transaction& t, + layer_id id, const ReparentChildrenChange& c); void setDisplaySurface(SurfaceComposerClient::Transaction& t, display_id id, const DispSurfaceChange& dsc); diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 7bfe0338f7..a02d14cc4d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -116,7 +116,14 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, layer->mCurrentState.frameNumber_legacy); } addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); - addFlagsLocked(transaction, layerId, layer->mCurrentState.flags); + addFlagsLocked(transaction, layerId, layer->mCurrentState.flags, + layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque | + layer_state_t::eLayerSecure); + addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent)); + addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached()); + addRelativeParentLocked(transaction, layerId, + getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf), + layer->mCurrentState.z); } void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, @@ -150,7 +157,7 @@ status_t SurfaceInterceptor::writeProtoFileLocked() { return NO_ERROR; } -const sp SurfaceInterceptor::getLayer(const wp& weakHandle) { +const sp SurfaceInterceptor::getLayer(const wp& weakHandle) const { const sp& handle(weakHandle.promote()); const auto layerHandle(static_cast(handle.get())); const sp layer(layerHandle->owner.promote()); @@ -158,14 +165,31 @@ const sp SurfaceInterceptor::getLayer(const wp& weak return layer; } -const std::string SurfaceInterceptor::getLayerName(const sp& layer) { +const std::string SurfaceInterceptor::getLayerName(const sp& layer) const { return layer->getName().string(); } -int32_t SurfaceInterceptor::getLayerId(const sp& layer) { +int32_t SurfaceInterceptor::getLayerId(const sp& layer) const { return layer->sequence; } +int32_t SurfaceInterceptor::getLayerIdFromWeakRef(const wp& layer) const { + if (layer == nullptr) { + return -1; + } + auto strongLayer = layer.promote(); + return strongLayer == nullptr ? -1 : getLayerId(strongLayer); +} + +int32_t SurfaceInterceptor::getLayerIdFromHandle(const sp& handle) const { + if (handle == nullptr) { + return -1; + } + const auto layerHandle(static_cast(handle.get())); + const sp layer(layerHandle->owner.promote()); + return layer == nullptr ? -1 : getLayerId(layer); +} + Increment* SurfaceInterceptor::createTraceIncrementLocked() { Increment* increment(mTrace.add_increment()); increment->set_time_stamp(systemTime()); @@ -252,24 +276,23 @@ void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction, } } -void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, - uint8_t flags) -{ +void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags, + uint8_t mask) { // There can be multiple flags changed - if (flags & layer_state_t::eLayerHidden) { + if (mask & layer_state_t::eLayerHidden) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); HiddenFlagChange* flagChange(change->mutable_hidden_flag()); - flagChange->set_hidden_flag(true); + flagChange->set_hidden_flag(flags & layer_state_t::eLayerHidden); } - if (flags & layer_state_t::eLayerOpaque) { + if (mask & layer_state_t::eLayerOpaque) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); OpaqueFlagChange* flagChange(change->mutable_opaque_flag()); - flagChange->set_opaque_flag(true); + flagChange->set_opaque_flag(flags & layer_state_t::eLayerOpaque); } - if (flags & layer_state_t::eLayerSecure) { + if (mask & layer_state_t::eLayerSecure) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); SecureFlagChange* flagChange(change->mutable_secure_flag()); - flagChange->set_secure_flag(true); + flagChange->set_secure_flag(flags & layer_state_t::eLayerSecure); } } @@ -320,6 +343,35 @@ void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction, overrideChange->set_override_scaling_mode(overrideScalingMode); } +void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t layerId, + int32_t parentId) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + ReparentChange* overrideChange(change->mutable_reparent()); + overrideChange->set_parent_id(parentId); +} + +void SurfaceInterceptor::addReparentChildrenLocked(Transaction* transaction, int32_t layerId, + int32_t parentId) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + ReparentChildrenChange* overrideChange(change->mutable_reparent_children()); + overrideChange->set_parent_id(parentId); +} + +void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId, + bool detached) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + DetachChildrenChange* overrideChange(change->mutable_detach_children()); + overrideChange->set_detach_children(detached); +} + +void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId, + int32_t parentId, int z) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + RelativeParentChange* overrideChange(change->mutable_relative_parent()); + overrideChange->set_relative_parent_id(parentId); + overrideChange->set_z(z); +} + void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state) { @@ -351,7 +403,7 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, addTransparentRegionLocked(transaction, layerId, state.transparentRegion); } if (state.what & layer_state_t::eFlagsChanged) { - addFlagsLocked(transaction, layerId, state.flags); + addFlagsLocked(transaction, layerId, state.flags, state.mask); } if (state.what & layer_state_t::eLayerStackChanged) { addLayerStackLocked(transaction, layerId, state.layerStack); @@ -380,6 +432,19 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); } + if (state.what & layer_state_t::eReparent) { + addReparentLocked(transaction, layerId, getLayerIdFromHandle(state.parentHandleForChild)); + } + if (state.what & layer_state_t::eReparentChildren) { + addReparentChildrenLocked(transaction, layerId, getLayerIdFromHandle(state.reparentHandle)); + } + if (state.what & layer_state_t::eDetachChildren) { + addDetachChildrenLocked(transaction, layerId, true); + } + if (state.what & layer_state_t::eRelativeLayerChanged) { + addRelativeParentLocked(transaction, layerId, + getLayerIdFromHandle(state.relativeLayerHandle), state.z); + } } void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 563a44c088..7f86c1423a 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -116,9 +116,11 @@ private: void addInitialDisplayStateLocked(Increment* increment, const DisplayDeviceState& display); status_t writeProtoFileLocked(); - const sp getLayer(const wp& weakHandle); - const std::string getLayerName(const sp& layer); - int32_t getLayerId(const sp& layer); + const sp getLayer(const wp& weakHandle) const; + const std::string getLayerName(const sp& layer) const; + int32_t getLayerId(const sp& layer) const; + int32_t getLayerIdFromWeakRef(const wp& layer) const; + int32_t getLayerIdFromHandle(const sp& weakHandle) const; Increment* createTraceIncrementLocked(); void addSurfaceCreationLocked(Increment* increment, const sp& layer); @@ -141,7 +143,7 @@ private: const layer_state_t::matrix22_t& matrix); void addTransparentRegionLocked(Transaction* transaction, int32_t layerId, const Region& transRegion); - void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags); + void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags, uint8_t mask); void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack); void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius); @@ -153,6 +155,11 @@ private: void addTransactionLocked(Increment* increment, const Vector& stateUpdates, const DefaultKeyedVector< wp, DisplayDeviceState>& displays, const Vector& changedDisplays, uint32_t transactionFlags); + void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId); + void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId); + void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached); + void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, + int z); // Add display transactions to the trace DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 5cc946aa79..26c6da95dd 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -43,14 +43,17 @@ constexpr uint32_t LAYER_UPDATE = INT_MAX - 2; constexpr uint32_t SIZE_UPDATE = 134; constexpr uint32_t STACK_UPDATE = 1; constexpr uint64_t DEFERRED_UPDATE = 0; +constexpr int32_t RELATIVE_Z = 42; constexpr float ALPHA_UPDATE = 0.29f; constexpr float CORNER_RADIUS_UPDATE = 0.2f; constexpr float POSITION_UPDATE = 121; const Rect CROP_UPDATE(16, 16, 32, 32); const String8 DISPLAY_NAME("SurfaceInterceptor Display Test"); -constexpr auto TEST_SURFACE_NAME = "BG Interceptor Test Surface"; -constexpr auto UNIQUE_TEST_SURFACE_NAME = "BG Interceptor Test Surface#0"; +constexpr auto TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface"; +constexpr auto TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface"; +constexpr auto UNIQUE_TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface#0"; +constexpr auto UNIQUE_TEST_FG_SURFACE_NAME = "FG Interceptor Test Surface#0"; constexpr auto LAYER_NAME = "Layer Create and Delete Test"; constexpr auto UNIQUE_LAYER_NAME = "Layer Create and Delete Test#0"; @@ -136,12 +139,15 @@ protected: void TearDown() override { mComposerClient->dispose(); mBGSurfaceControl.clear(); + mFGSurfaceControl.clear(); mComposerClient.clear(); } sp mComposerClient; sp mBGSurfaceControl; + sp mFGSurfaceControl; int32_t mBGLayerId; + int32_t mFGLayerId; public: using TestTransactionAction = void (SurfaceInterceptorTest::*)(Transaction&); @@ -177,6 +183,10 @@ public: bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag); bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag); bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred); + bool reparentUpdateFound(const SurfaceChange& change, bool found); + bool relativeParentUpdateFound(const SurfaceChange& change, bool found); + bool detachChildrenUpdateFound(const SurfaceChange& change, bool found); + bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found); bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); // Find all of the updates in the single trace @@ -209,6 +219,10 @@ public: void opaqueFlagUpdate(Transaction&); void secureFlagUpdate(Transaction&); void deferredTransactionUpdate(Transaction&); + void reparentUpdate(Transaction&); + void relativeParentUpdate(Transaction&); + void detachChildrenUpdate(Transaction&); + void reparentChildrenUpdate(Transaction&); void surfaceCreation(Transaction&); void displayCreation(Transaction&); void displayDeletion(Transaction&); @@ -250,21 +264,30 @@ void SurfaceInterceptorTest::setupBackgroundSurface() { ssize_t displayHeight = info.h; // Background surface - mBGSurfaceControl = mComposerClient->createSurface( - String8(TEST_SURFACE_NAME), displayWidth, displayHeight, - PIXEL_FORMAT_RGBA_8888, 0); + mBGSurfaceControl = mComposerClient->createSurface(String8(TEST_BG_SURFACE_NAME), displayWidth, + displayHeight, PIXEL_FORMAT_RGBA_8888, 0); ASSERT_TRUE(mBGSurfaceControl != nullptr); ASSERT_TRUE(mBGSurfaceControl->isValid()); + // Foreground surface + mFGSurfaceControl = mComposerClient->createSurface(String8(TEST_FG_SURFACE_NAME), displayWidth, + displayHeight, PIXEL_FORMAT_RGBA_8888, 0); + ASSERT_TRUE(mFGSurfaceControl != nullptr); + ASSERT_TRUE(mFGSurfaceControl->isValid()); + Transaction t; t.setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3) - .show(mBGSurfaceControl) - .apply()); + ASSERT_EQ(NO_ERROR, + t.setLayer(mBGSurfaceControl, INT_MAX - 3) + .show(mBGSurfaceControl) + .setLayer(mFGSurfaceControl, INT_MAX - 3) + .show(mFGSurfaceControl) + .apply()); } void SurfaceInterceptorTest::preProcessTrace(const Trace& trace) { - mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_SURFACE_NAME); + mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_BG_SURFACE_NAME); + mFGLayerId = getSurfaceId(trace, UNIQUE_TEST_FG_SURFACE_NAME); } void SurfaceInterceptorTest::captureTest(TestTransactionAction action, @@ -364,6 +387,22 @@ void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { DEFERRED_UPDATE); } +void SurfaceInterceptorTest::reparentUpdate(Transaction& t) { + t.reparent(mBGSurfaceControl, mFGSurfaceControl->getHandle()); +} + +void SurfaceInterceptorTest::relativeParentUpdate(Transaction& t) { + t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl->getHandle(), RELATIVE_Z); +} + +void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) { + t.detachChildren(mBGSurfaceControl); +} + +void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) { + t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl->getHandle()); +} + void SurfaceInterceptorTest::displayCreation(Transaction&) { sp testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true); SurfaceComposerClient::destroyDisplay(testDisplay); @@ -389,6 +428,10 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::opaqueFlagUpdate); runInTransaction(&SurfaceInterceptorTest::secureFlagUpdate); runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate); + runInTransaction(&SurfaceInterceptorTest::reparentUpdate); + runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate); + runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate); + runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate); } void SurfaceInterceptorTest::surfaceCreation(Transaction&) { @@ -569,6 +612,46 @@ bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& return foundDeferred; } +bool SurfaceInterceptorTest::reparentUpdateFound(const SurfaceChange& change, bool found) { + bool hasId(change.reparent().parent_id() == mFGLayerId); + if (hasId && !found) { + found = true; + } else if (hasId && found) { + []() { FAIL(); }(); + } + return found; +} + +bool SurfaceInterceptorTest::relativeParentUpdateFound(const SurfaceChange& change, bool found) { + bool hasId(change.relative_parent().relative_parent_id() == mFGLayerId); + if (hasId && !found) { + found = true; + } else if (hasId && found) { + []() { FAIL(); }(); + } + return found; +} + +bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) { + bool detachChildren(change.detach_children().detach_children()); + if (detachChildren && !found) { + found = true; + } else if (detachChildren && found) { + []() { FAIL(); }(); + } + return found; +} + +bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) { + bool hasId(change.reparent_children().parent_id() == mFGLayerId); + if (hasId && !found) { + found = true; + } else if (hasId && found) { + []() { FAIL(); }(); + } + return found; +} + bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase) { bool foundUpdate = false; @@ -620,6 +703,18 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kDeferredTransaction: foundUpdate = deferredTransactionUpdateFound(change, foundUpdate); break; + case SurfaceChange::SurfaceChangeCase::kReparent: + foundUpdate = reparentUpdateFound(change, foundUpdate); + break; + case SurfaceChange::SurfaceChangeCase::kReparentChildren: + foundUpdate = reparentChildrenUpdateFound(change, foundUpdate); + break; + case SurfaceChange::SurfaceChangeCase::kRelativeParent: + foundUpdate = relativeParentUpdateFound(change, foundUpdate); + break; + case SurfaceChange::SurfaceChangeCase::kDetachChildren: + foundUpdate = detachChildrenUpdateFound(change, foundUpdate); + break; case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET: break; } @@ -644,6 +739,10 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction)); + ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent)); + ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren)); + ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent)); + ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren)); } bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) { @@ -798,6 +897,26 @@ TEST_F(SurfaceInterceptorTest, InterceptDeferredTransactionUpdateWorks) { SurfaceChange::SurfaceChangeCase::kDeferredTransaction); } +TEST_F(SurfaceInterceptorTest, InterceptReparentUpdateWorks) { + captureTest(&SurfaceInterceptorTest::reparentUpdate, + SurfaceChange::SurfaceChangeCase::kReparent); +} + +TEST_F(SurfaceInterceptorTest, InterceptReparentChildrenUpdateWorks) { + captureTest(&SurfaceInterceptorTest::reparentChildrenUpdate, + SurfaceChange::SurfaceChangeCase::kReparentChildren); +} + +TEST_F(SurfaceInterceptorTest, InterceptRelativeParentUpdateWorks) { + captureTest(&SurfaceInterceptorTest::relativeParentUpdate, + SurfaceChange::SurfaceChangeCase::kRelativeParent); +} + +TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) { + captureTest(&SurfaceInterceptorTest::detachChildrenUpdate, + SurfaceChange::SurfaceChangeCase::kDetachChildren); +} + TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) { captureTest(&SurfaceInterceptorTest::runAllUpdates, &SurfaceInterceptorTest::assertAllUpdatesFound); -- cgit v1.2.3-59-g8ed1b From 359b1ff6b4eb4b26fb5acfd25a21c71f0da7929d Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Fri, 26 Jul 2019 16:01:36 +0100 Subject: Make dumpstate bugreport names as tmp if called by API Since we are migrating away from dumpstate being directly triggered, only API will be calling dumpstate. API would pass final bugreport file fds to dumpstate, that implies dumpstate bugreport files are getting copied over. Marking these files with a suffix of -tmp as: * These (bugreport .zip and screenshot .png) files are eventually getting deleted. * These (bugreport .zip and screenshot .png) file names can be used by API callers (as the final bugreport names) for consistency. Since the files are in the same dir, need to add suffix to differentiate. Bug: 126862297 Test: * Build and flash to the device * Turn on Settings feature flag to use the bugreport API * Take interactive and full bugreports * run `adb shell ls /bugreports` while bugreports are being generated and after the bugreport is captured * Can see tmp files when the bugreport is in progress * Output file names same as before Change-Id: Ia88e373a373d573d9c1e089924290b9526a3d2e1 --- cmds/dumpstate/dumpstate.cpp | 14 +++++++++----- cmds/dumpstate/dumpstate.h | 5 +++++ 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 2bcb17deee..76580c5e73 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1986,12 +1986,12 @@ static void PrepareToWriteToFile() { } if (ds.options_->do_fb) { - ds.screenshot_path_ = ds.GetPath(".png"); + ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png"); } ds.tmp_path_ = ds.GetPath(".tmp"); ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt"); - std::string destination = ds.options_->bugreport_fd.get() != -1 + std::string destination = ds.CalledByApi() ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get()) : ds.bugreport_internal_dir_.c_str(); MYLOGD( @@ -2005,7 +2005,7 @@ static void PrepareToWriteToFile() { ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); if (ds.options_->do_zip_file) { - ds.path_ = ds.GetPath(".zip"); + ds.path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.zip" : ".zip"); MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str()); create_parent_dirs(ds.path_.c_str()); ds.zip_file.reset(fopen(ds.path_.c_str(), "wb")); @@ -2040,7 +2040,7 @@ static void FinalizeFile() { MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str()); ds.name_ = name; if (!ds.screenshot_path_.empty()) { - std::string new_screenshot_path = ds.GetPath(".png"); + std::string new_screenshot_path = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png"); if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(), new_screenshot_path.c_str(), strerror(errno)); @@ -2058,7 +2058,7 @@ static void FinalizeFile() { } else { do_text_file = false; // If the user has changed the suffix, we need to change the zip file name. - std::string new_path = ds.GetPath(".zip"); + std::string new_path = ds.GetPath(ds.CalledByApi() ? "-tmp.zip" : ".zip"); if (ds.path_ != new_path) { MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str()); if (rename(ds.path_.c_str(), new_path.c_str())) { @@ -2706,6 +2706,10 @@ bool Dumpstate::IsUserConsentDenied() const { ds.consent_callback_->getResult() == UserConsentResult::DENIED; } +bool Dumpstate::CalledByApi() const { + return ds.options_->bugreport_fd.get() != -1 ? true : false; +} + void Dumpstate::CleanupFiles() { android::os::UnlinkAndLogOnError(tmp_path_); android::os::UnlinkAndLogOnError(screenshot_path_); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index ae6a72171a..fe330df30a 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -340,6 +340,11 @@ class Dumpstate { */ bool IsUserConsentDenied() const; + /* + * Returns true if dumpstate is called by bugreporting API + */ + bool CalledByApi() const; + /* * Structure to hold options that determine the behavior of dumpstate. */ -- cgit v1.2.3-59-g8ed1b From cb12994d1e27aca47df6db63f4790055dc8239b6 Mon Sep 17 00:00:00 2001 From: Robert Delgado Date: Tue, 23 Jul 2019 16:28:20 -0700 Subject: Included android surfaceflinger package to the proto. Test: run yarn dev on transaction. Change-Id: Ie4daa5fb037ead2f1339d36032df1ca702fff3b0 --- cmds/surfacereplayer/proto/src/trace.proto | 1 + cmds/surfacereplayer/replayer/Event.cpp | 1 + cmds/surfacereplayer/replayer/Event.h | 2 ++ cmds/surfacereplayer/replayer/Replayer.h | 2 ++ services/surfaceflinger/SurfaceInterceptor.h | 7 +++++++ services/surfaceflinger/tests/SurfaceInterceptor_test.cpp | 4 +++- 6 files changed, 16 insertions(+), 1 deletion(-) (limited to 'cmds') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index a738527fbb..792ff91dfa 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -1,5 +1,6 @@ syntax = "proto2"; option optimize_for = LITE_RUNTIME; +package android.surfaceflinger; message Trace { repeated Increment increment = 1; diff --git a/cmds/surfacereplayer/replayer/Event.cpp b/cmds/surfacereplayer/replayer/Event.cpp index 390d3982ca..64db5f07b1 100644 --- a/cmds/surfacereplayer/replayer/Event.cpp +++ b/cmds/surfacereplayer/replayer/Event.cpp @@ -17,6 +17,7 @@ #include "Event.h" using namespace android; +using Increment = surfaceflinger::Increment; Event::Event(Increment::IncrementCase type) : mIncrementType(type) {} diff --git a/cmds/surfacereplayer/replayer/Event.h b/cmds/surfacereplayer/replayer/Event.h index 44b60f566a..09a7c248d5 100644 --- a/cmds/surfacereplayer/replayer/Event.h +++ b/cmds/surfacereplayer/replayer/Event.h @@ -24,6 +24,8 @@ namespace android { +using Increment = surfaceflinger::Increment; + class Event { public: Event(Increment::IncrementCase); diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index d7709cc211..3b94618acb 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -38,6 +38,8 @@ #include #include +using namespace android::surfaceflinger; + namespace android { const auto DEFAULT_PATH = "/data/local/tmp/SurfaceTrace.dat"; diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 7f86c1423a..fdc6c580ed 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -39,6 +39,12 @@ struct ComposerState; struct DisplayDeviceState; struct DisplayState; struct layer_state_t; +using Transaction = surfaceflinger::Transaction; +using Trace = surfaceflinger::Trace; +using Rectangle = surfaceflinger::Rectangle; +using SurfaceChange = surfaceflinger::SurfaceChange; +using Increment = surfaceflinger::Increment; +using DisplayChange = surfaceflinger::DisplayChange; constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat"; @@ -183,6 +189,7 @@ private: }; } // namespace impl + } // namespace android #endif // ANDROID_SURFACEINTERCEPTOR_H diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 26c6da95dd..bc5f1aab42 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -36,6 +36,9 @@ namespace android { using Transaction = SurfaceComposerClient::Transaction; +using SurfaceChange = surfaceflinger::SurfaceChange; +using Trace = surfaceflinger::Trace; +using Increment = surfaceflinger::Increment; constexpr int32_t SCALING_UPDATE = 1; constexpr uint32_t BUFFER_UPDATES = 18; @@ -980,5 +983,4 @@ TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) { ASSERT_TRUE(bufferUpdatesFound(capturedTrace)); ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceCreation)); } - } -- cgit v1.2.3-59-g8ed1b From 402a839ef5e2fdecfd9a0fc75e6250d374bfc83e Mon Sep 17 00:00:00 2001 From: Nandana Dutt Date: Fri, 14 Jun 2019 14:25:13 +0100 Subject: Remove old dumpstate aidl methods In Q we added new aidl methods for dumpstate to communicate with SystemServer. The old methods can be removed now. This change is functionally equivalent to before except for how progress is reported. Dumpstate loads previous run stats and calculates expected run time. If the current run exceeds that time, it used to let the client know via onMaxProgressUpdated(). Given the API world, this CL simplifies this model so that dumpstate conveys just one piece of information, i.e. final progress precentage, rather than current, previous_max, and new_max. Test: atest dumpstate_test Test: bugreport from power button works as expected BUG: 128980174 Change-Id: Id9103649b0f7c8e6ea0b79583ea04825cb5b455f --- cmds/dumpstate/Android.bp | 1 - cmds/dumpstate/DumpstateSectionReporter.cpp | 42 ------------- cmds/dumpstate/DumpstateSectionReporter.h | 65 ------------------- cmds/dumpstate/DumpstateService.cpp | 3 +- .../binder/android/os/IDumpstateListener.aidl | 17 ----- cmds/dumpstate/dumpstate.cpp | 25 ++------ cmds/dumpstate/dumpstate.h | 8 +-- cmds/dumpstate/tests/dumpstate_smoke_test.cpp | 21 ------- cmds/dumpstate/tests/dumpstate_test.cpp | 72 +++++----------------- 9 files changed, 22 insertions(+), 232 deletions(-) delete mode 100644 cmds/dumpstate/DumpstateSectionReporter.cpp delete mode 100644 cmds/dumpstate/DumpstateSectionReporter.h (limited to 'cmds') diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index 8d383f501a..93bbe902c0 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -93,7 +93,6 @@ cc_defaults { "libutils", ], srcs: [ - "DumpstateSectionReporter.cpp", "DumpstateService.cpp", ], static_libs: [ diff --git a/cmds/dumpstate/DumpstateSectionReporter.cpp b/cmds/dumpstate/DumpstateSectionReporter.cpp deleted file mode 100644 index f814bde26d..0000000000 --- a/cmds/dumpstate/DumpstateSectionReporter.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "dumpstate" - -#include "DumpstateSectionReporter.h" - -namespace android { -namespace os { -namespace dumpstate { - -DumpstateSectionReporter::DumpstateSectionReporter(const std::string& title, - sp listener, - bool sendReport) - : title_(title), listener_(listener), sendReport_(sendReport), status_(OK), size_(-1) { - started_ = std::chrono::steady_clock::now(); -} - -DumpstateSectionReporter::~DumpstateSectionReporter() { - if ((listener_ != nullptr) && (sendReport_)) { - auto elapsed = std::chrono::duration_cast( - std::chrono::steady_clock::now() - started_); - listener_->onSectionComplete(title_, status_, size_, (int32_t)elapsed.count()); - } -} - -} // namespace dumpstate -} // namespace os -} // namespace android diff --git a/cmds/dumpstate/DumpstateSectionReporter.h b/cmds/dumpstate/DumpstateSectionReporter.h deleted file mode 100644 index e971de84c5..0000000000 --- a/cmds/dumpstate/DumpstateSectionReporter.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -#ifndef ANDROID_OS_DUMPSTATESECTIONREPORTER_H_ -#define ANDROID_OS_DUMPSTATESECTIONREPORTER_H_ - -#include -#include - -namespace android { -namespace os { -namespace dumpstate { - - -/* - * Helper class used to report per section details to a listener. - * - * Typical usage: - * - * DumpstateSectionReporter sectionReporter(title, listener, sendReport); - * sectionReporter.setSize(5000); - * - */ -class DumpstateSectionReporter { - public: - DumpstateSectionReporter(const std::string& title, sp listener, - bool sendReport); - - ~DumpstateSectionReporter(); - - void setStatus(status_t status) { - status_ = status; - } - - void setSize(int size) { - size_ = size; - } - - private: - std::string title_; - android::sp listener_; - bool sendReport_; - status_t status_; - int size_; - std::chrono::time_point started_; -}; - -} // namespace dumpstate -} // namespace os -} // namespace android - -#endif // ANDROID_OS_DUMPSTATESECTIONREPORTER_H_ diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index 37ba4f906e..f98df99534 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -200,8 +200,7 @@ status_t DumpstateService::dump(int fd, const Vector&) { dprintf(fd, "id: %d\n", ds_->id_); dprintf(fd, "pid: %d\n", ds_->pid_); dprintf(fd, "update_progress: %s\n", ds_->options_->do_progress_updates ? "true" : "false"); - dprintf(fd, "update_progress_threshold: %d\n", ds_->update_progress_threshold_); - dprintf(fd, "last_updated_progress: %d\n", ds_->last_updated_progress_); + dprintf(fd, "last_percent_progress: %d\n", ds_->last_reported_percent_progress_); dprintf(fd, "progress:\n"); ds_->progress_->Dump(fd, " "); dprintf(fd, "args: %s\n", ds_->options_->args.c_str()); diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl index ea1e467dca..e486460753 100644 --- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl +++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl @@ -61,21 +61,4 @@ interface IDumpstateListener { * Called when taking bugreport finishes successfully. */ void onFinished(); - - // TODO(b/111441001): Remove old methods when not used anymore. - void onProgressUpdated(int progress); - void onMaxProgressUpdated(int maxProgress); - - /** - * Called after every section is complete. - * - * @param name section name - * @param status values from status_t - * {@code OK} section completed successfully - * {@code TIMEOUT} dump timed out - * {@code != OK} error - * @param size size in bytes, may be invalid if status != OK - * @param durationMs duration in ms - */ - void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs); } diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index fe55fe7d4b..6b2e3b70cd 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -80,7 +80,6 @@ #include #include #include "DumpstateInternal.h" -#include "DumpstateSectionReporter.h" #include "DumpstateService.h" #include "dumpstate.h" @@ -105,7 +104,6 @@ using android::base::StringPrintf; using android::os::IDumpstateListener; using android::os::dumpstate::CommandOptions; using android::os::dumpstate::DumpFileToFd; -using android::os::dumpstate::DumpstateSectionReporter; using android::os::dumpstate::PropertiesHelper; // Keep in sync with @@ -1047,7 +1045,6 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i RETURN_IF_USER_DENIED_CONSENT(); std::string path(title); path.append(" - ").append(String8(service).c_str()); - DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_); size_t bytes_written = 0; status_t status = dumpsys.startDumpThread(service, args); if (status == OK) { @@ -1055,12 +1052,10 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i std::chrono::duration elapsed_seconds; status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout, /* as_proto = */ false, elapsed_seconds, bytes_written); - section_reporter.setSize(bytes_written); dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds); bool dump_complete = (status == OK); dumpsys.stopDumpThread(dump_complete); } - section_reporter.setStatus(status); auto elapsed_duration = std::chrono::duration_cast( std::chrono::steady_clock::now() - start); @@ -1123,7 +1118,6 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori path.append("_HIGH"); } path.append(kProtoExt); - DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_); status_t status = dumpsys.startDumpThread(service, args); if (status == OK) { status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); @@ -1132,8 +1126,6 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori } ZipWriter::FileEntry file_entry; ds.zip_writer_->GetLastEntry(&file_entry); - section_reporter.setSize(file_entry.compressed_size); - section_reporter.setStatus(status); auto elapsed_duration = std::chrono::duration_cast( std::chrono::steady_clock::now() - start); @@ -2813,6 +2805,7 @@ int run_main(int argc, char* argv[]) { Dumpstate::Dumpstate(const std::string& version) : pid_(getpid()), options_(new Dumpstate::DumpOptions()), + last_reported_percent_progress_(0), version_(version), now_(time(nullptr)) { } @@ -3575,31 +3568,25 @@ void Dumpstate::UpdateProgress(int32_t delta_sec) { } // Always update progess so stats can be tuned... - bool max_changed = progress_->Inc(delta_sec); + progress_->Inc(delta_sec); // ...but only notifiy listeners when necessary. if (!options_->do_progress_updates) return; int progress = progress_->Get(); int max = progress_->GetMax(); + int percent = 100 * progress / max; - // adjusts max on the fly - if (max_changed && listener_ != nullptr) { - listener_->onMaxProgressUpdated(max); - } - - int32_t last_update_delta = progress - last_updated_progress_; - if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) { + if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) { return; } - last_updated_progress_ = progress; + last_reported_percent_progress_ = percent; if (control_socket_fd_ >= 0) { dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max); fsync(control_socket_fd_); } - int percent = 100 * progress / max; if (listener_ != nullptr) { if (percent % 5 == 0) { // We don't want to spam logcat, so only log multiples of 5. @@ -3611,8 +3598,6 @@ void Dumpstate::UpdateProgress(int32_t delta_sec) { fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max, percent); } - // TODO(b/111441001): Remove in favor of onProgress - listener_->onProgressUpdated(progress); listener_->onProgress(percent); } diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index fe330df30a..77b5e8a9f9 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -405,12 +405,8 @@ class Dumpstate { // Runtime options. std::unique_ptr options_; - // How frequently the progess should be updated;the listener will only be notificated when the - // delta from the previous update is more than the threshold. - int32_t update_progress_threshold_ = 100; - - // Last progress that triggered a listener updated - int32_t last_updated_progress_; + // Last progress that was sent to the listener [0-100]. + int last_reported_percent_progress_ = 0; // Whether it should take an screenshot earlier in the process. bool do_early_screenshot_ = false; diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index f7acaf1b9b..181046a7a7 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -167,26 +167,6 @@ class DumpstateListener : public BnDumpstateListener { return binder::Status::ok(); } - binder::Status onProgressUpdated(int32_t progress) override { - dprintf(out_fd_, "\rIn progress %d/%d", progress, max_progress_); - return binder::Status::ok(); - } - - binder::Status onMaxProgressUpdated(int32_t max_progress) override { - std::lock_guard lock(lock_); - max_progress_ = max_progress; - return binder::Status::ok(); - } - - binder::Status onSectionComplete(const ::std::string& name, int32_t, int32_t size_bytes, - int32_t) override { - std::lock_guard lock(lock_); - if (sections_.get() != nullptr) { - sections_->push_back({name, size_bytes}); - } - return binder::Status::ok(); - } - bool getIsFinished() { std::lock_guard lock(lock_); return is_finished_; @@ -199,7 +179,6 @@ class DumpstateListener : public BnDumpstateListener { private: int out_fd_; - int max_progress_ = 5000; int error_code_ = -1; bool is_finished_ = false; std::shared_ptr> sections_; diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index 4e6b084ff6..cff1d439d9 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -62,10 +62,6 @@ class DumpstateListenerMock : public IDumpstateListener { MOCK_METHOD1(onProgress, binder::Status(int32_t progress)); MOCK_METHOD1(onError, binder::Status(int32_t error_code)); MOCK_METHOD0(onFinished, binder::Status()); - MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress)); - MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress)); - MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status, - int32_t size, int32_t durationMs)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); @@ -590,7 +586,6 @@ class DumpstateTest : public DumpstateBaseTest { SetDryRun(false); SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)")); ds.progress_.reset(new Progress()); - ds.update_progress_threshold_ = 0; ds.options_.reset(new Dumpstate::DumpOptions()); } @@ -615,10 +610,9 @@ class DumpstateTest : public DumpstateBaseTest { return status; } - void SetProgress(long progress, long initial_max, long threshold = 0) { + void SetProgress(long progress, long initial_max) { + ds.last_reported_percent_progress_ = 0; ds.options_->do_progress_updates = true; - ds.update_progress_threshold_ = threshold; - ds.last_updated_progress_ = 0; ds.progress_.reset(new Progress(initial_max, progress, 1.2)); } @@ -796,73 +790,36 @@ TEST_F(DumpstateTest, RunCommandProgress) { ds.listener_name_ = "FoxMulder"; SetProgress(0, 30); - EXPECT_CALL(*listener, onProgressUpdated(20)); EXPECT_CALL(*listener, onProgress(66)); // 20/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build())); std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); - EXPECT_CALL(*listener, onProgressUpdated(30)); - EXPECT_CALL(*listener, onProgress(100)); // 35/35 % - EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 30, 30); - EXPECT_THAT(out, StrEq("stdout\n")); - EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); - - // Run a command that will increase maximum timeout. - EXPECT_CALL(*listener, onProgressUpdated(31)); - EXPECT_CALL(*listener, onMaxProgressUpdated(37)); - EXPECT_CALL(*listener, onProgress(83)); // 31/37 % - EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase + EXPECT_CALL(*listener, onProgress(80)); // 24/30 % + EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); + progress_message = GetProgressMessage(ds.listener_name_, 24, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); // Make sure command ran while in dry_run is counted. SetDryRun(true); - EXPECT_CALL(*listener, onProgressUpdated(35)); - EXPECT_CALL(*listener, onProgress(94)); // 35/37 % - EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 35, 37); + EXPECT_CALL(*listener, onProgress(90)); // 27/30 % + EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build())); + progress_message = GetProgressMessage(ds.listener_name_, 27, 30); EXPECT_THAT(out, IsEmpty()); EXPECT_THAT(err, StrEq(progress_message)); - ds.listener_.clear(); -} - -TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) { - sp listener(new DumpstateListenerMock()); - ds.listener_ = listener; - ds.listener_name_ = "FoxMulder"; - SetProgress(0, 8, 5); // 8 max, 5 threshold - - // First update should always be sent. - EXPECT_CALL(*listener, onProgressUpdated(1)); - EXPECT_CALL(*listener, onProgress(12)); // 1/12 % - EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); - std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8); + SetDryRun(false); + EXPECT_CALL(*listener, onProgress(96)); // 29/30 % + EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build())); + progress_message = GetProgressMessage(ds.listener_name_, 29, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); - // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5). - EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); - EXPECT_THAT(out, StrEq("stdout\n")); - EXPECT_THAT(err, StrEq("stderr\n")); - - // Third update should be sent because it reaches threshold (6 - 1 = 5). - EXPECT_CALL(*listener, onProgressUpdated(6)); - EXPECT_CALL(*listener, onProgress(75)); // 6/8 % + EXPECT_CALL(*listener, onProgress(100)); // 30/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 6, 8); - EXPECT_THAT(out, StrEq("stdout\n")); - EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); - - // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5). - // But max update should be sent. - EXPECT_CALL(*listener, onMaxProgressUpdated(10)); // 9 * 120% = 10.8 = 10 - EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false); + progress_message = GetProgressMessage(ds.listener_name_, 30, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); @@ -1090,7 +1047,6 @@ TEST_F(DumpstateTest, DumpFileUpdateProgress) { ds.listener_name_ = "FoxMulder"; SetProgress(0, 30); - EXPECT_CALL(*listener, onProgressUpdated(5)); EXPECT_CALL(*listener, onProgress(16)); // 5/30 % EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); -- cgit v1.2.3-59-g8ed1b From ef582cd2423f969fdbda7cdce68dbce602c5c331 Mon Sep 17 00:00:00 2001 From: Martin Stjernholm Date: Wed, 17 Jul 2019 22:14:14 +0100 Subject: Update identifiers and paths to the new ART APEX. Test: atest -p frameworks/native/cmds/installd Test: ATP asit/dexoptota/self_full on Forrest: https://android-build.googleplex.com/builds/forrest/run/L53500000356596506 Bug: 135753770 Change-Id: I11000a8cc95085bb0144f858b4f3968e5aceac36 --- cmds/installd/dexopt.h | 16 ++++++++-------- cmds/installd/otapreopt_chroot.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'cmds') diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h index a8c48c564e..ef739bafd4 100644 --- a/cmds/installd/dexopt.h +++ b/cmds/installd/dexopt.h @@ -32,15 +32,15 @@ static constexpr int DEX2OAT_FROM_SCRATCH = 1; static constexpr int DEX2OAT_FOR_BOOT_IMAGE = 2; static constexpr int DEX2OAT_FOR_FILTER = 3; -#define ANDROID_RUNTIME_APEX_BIN "/apex/com.android.runtime/bin" +#define ANDROID_ART_APEX_BIN "/apex/com.android.art/bin" // Location of binaries in the Android Runtime APEX. -static constexpr const char* kDex2oatPath = ANDROID_RUNTIME_APEX_BIN "/dex2oat"; -static constexpr const char* kDex2oatDebugPath = ANDROID_RUNTIME_APEX_BIN "/dex2oatd"; -static constexpr const char* kProfmanPath = ANDROID_RUNTIME_APEX_BIN "/profman"; -static constexpr const char* kProfmanDebugPath = ANDROID_RUNTIME_APEX_BIN "/profmand"; -static constexpr const char* kDexoptanalyzerPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzer"; -static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_RUNTIME_APEX_BIN "/dexoptanalyzerd"; -#undef ANDROID_RUNTIME_APEX_BIN +static constexpr const char* kDex2oatPath = ANDROID_ART_APEX_BIN "/dex2oat"; +static constexpr const char* kDex2oatDebugPath = ANDROID_ART_APEX_BIN "/dex2oatd"; +static constexpr const char* kProfmanPath = ANDROID_ART_APEX_BIN "/profman"; +static constexpr const char* kProfmanDebugPath = ANDROID_ART_APEX_BIN "/profmand"; +static constexpr const char* kDexoptanalyzerPath = ANDROID_ART_APEX_BIN "/dexoptanalyzer"; +static constexpr const char* kDexoptanalyzerDebugPath = ANDROID_ART_APEX_BIN "/dexoptanalyzerd"; +#undef ANDROID_ART_APEX_BIN // Clear the reference profile identified by the given profile name. bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name); diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp index b4bcd53120..3ff9d11806 100644 --- a/cmds/installd/otapreopt_chroot.cpp +++ b/cmds/installd/otapreopt_chroot.cpp @@ -233,17 +233,17 @@ static int otapreopt_chroot(const int argc, char **arg) { } // Try to mount APEX packages in "/apex" in the chroot dir. We need at least - // the Android Runtime APEX, as it is required by otapreopt to run dex2oat. + // the ART APEX, as it is required by otapreopt to run dex2oat. std::vector active_packages = ActivateApexPackages(); - // Check that an Android Runtime APEX has been activated; clean up and exit + // Check that an ART APEX has been activated; clean up and exit // early otherwise. if (std::none_of(active_packages.begin(), active_packages.end(), [](const apex::ApexFile& package){ - return package.GetManifest().name() == "com.android.runtime"; + return package.GetManifest().name() == "com.android.art"; })) { - LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.runtime APEX package."; + LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package."; DeactivateApexPackages(active_packages); exit(217); } -- cgit v1.2.3-59-g8ed1b From 07d587b98905d04c8a5fb05c7f6820c1acfc7a67 Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Thu, 29 Aug 2019 14:11:57 +0100 Subject: Remove outfile flag as it's unused and all callers migrated Bug: 111441001 Bug: 135186519 Test: builds Test: atest dumpstate_test Change-Id: I9fbaa6765f7384d99239161a38a9962d476e1394 --- cmds/dumpstate/dumpstate.cpp | 3 --- cmds/dumpstate/dumpstate.rc | 3 +-- cmds/dumpstate/tests/dumpstate_smoke_test.cpp | 4 +--- 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index a8e6738228..b781da308c 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2328,9 +2328,6 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) // clang-format off case 'd': do_add_date = true; break; case 'z': do_zip_file = true; break; - // o=use_outfile not supported anymore. - // TODO(b/111441001): Remove when all callers have migrated. - case 'o': break; case 's': use_socket = true; break; case 'S': use_control_socket = true; break; case 'v': show_header_only = true; break; diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc index 14937b80b9..e491a4b614 100644 --- a/cmds/dumpstate/dumpstate.rc +++ b/cmds/dumpstate/dumpstate.rc @@ -11,8 +11,7 @@ service dumpstate /system/bin/dumpstate -s # dumpstatez generates a zipped bugreport but also uses a socket to print the file location once # it is finished. -service dumpstatez /system/bin/dumpstate -S -d -z \ - -o /data/user_de/0/com.android.shell/files/bugreports/bugreport +service dumpstatez /system/bin/dumpstate -S -d -z socket dumpstate stream 0660 shell log class main disabled diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index 181046a7a7..dbbcdff63e 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -201,9 +201,7 @@ class ZippedBugreportGenerationTest : public Test { (char*)"dumpstate", (char*)"-d", (char*)"-z", - (char*)"-B", - (char*)"-o", - (char*)dirname(android::base::GetExecutablePath().c_str()) + (char*)"-B" }; // clang-format on sp listener(new DumpstateListener(dup(fileno(stdout)), sections)); -- cgit v1.2.3-59-g8ed1b From 69b479a4de8911eb2a3ea76a185953fa756acf53 Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Tue, 3 Sep 2019 13:40:27 +0100 Subject: Do not send finished broadcasts when called by API Bug: 137825297 Test: builds and takes bugreports Change-Id: I7a393ac928098f147362dd6e728e740cfe2d4ca3 --- cmds/dumpstate/dumpstate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 3f2469cde4..ca3a9b345b 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2708,7 +2708,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, } /* tell activity manager we're done */ - if (options_->do_broadcast) { + if (options_->do_broadcast && !CalledByApi()) { SendBugreportFinishedBroadcast(); // Note that listener_ is notified in Run(); } -- cgit v1.2.3-59-g8ed1b From 3172b538334b22eafae042048d2bd95c25667ee6 Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Tue, 15 Oct 2019 15:07:03 +0100 Subject: Allow Shell to trigger bugreports without user consent dialog Bug: 141442785 Test: Takes interactive/full bugreports as expected. Test: atest dumpstate_test Change-Id: Iee09c749bc7f70c94568cd447ea3eece9a59223b --- cmds/dumpstate/dumpstate.cpp | 20 +++++++++++++++----- cmds/dumpstate/dumpstate.h | 5 +++-- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index e1181a6dc8..dae5c17ce5 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2526,6 +2526,8 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, return RunStatus::OK; } + MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n", + calling_uid, calling_package.c_str()); if (options_->bugreport_fd.get() != -1) { // If the output needs to be copied over to the caller's fd, get user consent. android::String16 package(calling_package.c_str()); @@ -2703,10 +2705,10 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, FinalizeFile(); } - // Share the final file with the caller if the user has consented. + // Share the final file with the caller if the user has consented or Shell is the caller. Dumpstate::RunStatus status = Dumpstate::RunStatus::OK; if (options_->bugreport_fd.get() != -1) { - status = CopyBugreportIfUserConsented(); + status = CopyBugreportIfUserConsented(calling_uid); if (status != Dumpstate::RunStatus::OK && status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) { // Do an early return if there were errors. We make an exception for consent @@ -2776,6 +2778,9 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, } void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) { + if (calling_uid == AID_SHELL) { + return; + } consent_callback_ = new ConsentCallback(); const String16 incidentcompanion("incidentcompanion"); sp ics(defaultServiceManager()->getService(incidentcompanion)); @@ -2810,10 +2815,15 @@ Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() { return USER_CONSENT_DENIED; } -Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() { +Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) { // If the caller has asked to copy the bugreport over to their directory, we need explicit - // user consent. - UserConsentResult consent_result = consent_callback_->getResult(); + // user consent (unless the caller is Shell). + UserConsentResult consent_result; + if (calling_uid == AID_SHELL) { + consent_result = UserConsentResult::APPROVED; + } else { + consent_result = consent_callback_->getResult(); + } if (consent_result == UserConsentResult::UNAVAILABLE) { // User has not responded yet. uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs(); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 5ba84cad84..430936ebfd 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -498,8 +498,9 @@ class Dumpstate { RunStatus HandleUserConsentDenied(); - // Copies bugreport artifacts over to the caller's directories provided there is user consent. - RunStatus CopyBugreportIfUserConsented(); + // Copies bugreport artifacts over to the caller's directories provided there is user consent or + // called by Shell. + RunStatus CopyBugreportIfUserConsented(int32_t calling_uid); // Used by GetInstance() only. explicit Dumpstate(const std::string& version = VERSION_CURRENT); -- cgit v1.2.3-59-g8ed1b From e370d68932f5c81c4cfdaa4412e65d1fe055ca29 Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Tue, 1 Oct 2019 16:49:30 +0100 Subject: Sunset legacy bugreport methods Bugreport is now triggered using API and not via broadcasts from dumpstate. As migration to API flow is stable, we can remove methods and broadcasts that were used in non-API bugreport flow. * Finished broadcasts are handled by Shell when onfinished() is called from dumpstate. This is because dumpstate does not have any information about the final files (other than their fds). * Remove system properties title/description as they are handled by Shell. * File rename is not handled by dumpstate as it does not own the final files. File rename is handled by the caller of the API (Shell for instance). * Remove system property to read mode and set properties from it. Modify tests accordingly. Rename extra_options to bugreport_mode. * Deprecate do_broadcast flag, as finished notification is no longer handled by dumpstate. Bug: 136066578 Test: Takes interactive/full bugreport as expected Test: atest dumpstate_test Test: adb bugreport (works as expected) Test: adb bugreport br.zip (works as expected) Change-Id: Ib39798944c4308ae0c87a22a9164567f249adfff --- cmds/dumpstate/DumpstateService.cpp | 3 +- cmds/dumpstate/dumpstate.cpp | 260 +++----------------------- cmds/dumpstate/dumpstate.h | 8 +- cmds/dumpstate/tests/dumpstate_smoke_test.cpp | 1 - cmds/dumpstate/tests/dumpstate_test.cpp | 127 +------------ 5 files changed, 35 insertions(+), 364 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index f98df99534..99dfee63e9 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -204,14 +204,13 @@ status_t DumpstateService::dump(int fd, const Vector&) { dprintf(fd, "progress:\n"); ds_->progress_->Dump(fd, " "); dprintf(fd, "args: %s\n", ds_->options_->args.c_str()); - dprintf(fd, "extra_options: %s\n", ds_->options_->extra_options.c_str()); + dprintf(fd, "bugreport_mode: %s\n", ds_->options_->bugreport_mode.c_str()); dprintf(fd, "version: %s\n", ds_->version_.c_str()); dprintf(fd, "bugreport_dir: %s\n", destination.c_str()); dprintf(fd, "screenshot_path: %s\n", ds_->screenshot_path_.c_str()); dprintf(fd, "log_path: %s\n", ds_->log_path_.c_str()); dprintf(fd, "tmp_path: %s\n", ds_->tmp_path_.c_str()); dprintf(fd, "path: %s\n", ds_->path_.c_str()); - dprintf(fd, "extra_options: %s\n", ds_->options_->extra_options.c_str()); dprintf(fd, "base_name: %s\n", ds_->base_name_.c_str()); dprintf(fd, "name: %s\n", ds_->name_.c_str()); dprintf(fd, "now: %ld\n", ds_->now_); diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index b87582eab7..4688cedc96 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -231,14 +231,6 @@ static bool UnlinkAndLogOnError(const std::string& file) { return true; } -static bool IsFileEmpty(const std::string& file_path) { - std::ifstream file(file_path, std::ios::binary | std::ios::ate); - if(file.bad()) { - MYLOGE("Cannot open file: %s\n", file_path.c_str()); - return true; - } - return file.tellg() <= 0; -} int64_t GetModuleMetadataVersion() { auto binder = defaultServiceManager()->getService(android::String16("package_native")); @@ -288,11 +280,8 @@ static const std::string kDumpstateBoardFiles[] = { }; static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles); -static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; static constexpr char PROPERTY_VERSION[] = "dumpstate.version"; -static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title"; -static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description"; static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build(); @@ -696,8 +685,8 @@ void Dumpstate::PrintHeader() const { RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"}, CommandOptions::WithTimeout(1).Always().Build()); printf("Bugreport format version: %s\n", version_.c_str()); - printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_, - PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str()); + printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s bugreport_mode=%s\n", id_, pid_, + PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->bugreport_mode.c_str()); printf("\n"); } @@ -1905,7 +1894,7 @@ void Dumpstate::DumpstateBoard() { static void ShowUsage() { fprintf(stderr, "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] " - "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n" + "[-z]] [-s] [-S] [-q] [-P] [-R] [-V version]\n" " -h: display this help message\n" " -b: play sound file instead of vibrate, at beginning of job\n" " -e: play sound file instead of vibrate, at end of job\n" @@ -1915,11 +1904,8 @@ static void ShowUsage() { " -s: write output to control socket (for init)\n" " -S: write file location to control socket (for init; requires -z)\n" " -q: disable vibrate\n" - " -B: send broadcast when finished\n" - " -P: send broadcast when started and update system properties on " - "progress (requires -B)\n" - " -R: take bugreport in remote mode (requires -z, -d and -B, " - "shouldn't be used with -P)\n" + " -P: send broadcast when started and do progress updates\n" + " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n" " -w: start binder service and make it wait for a call to startBugreport\n" " -v: prints the dumpstate header and exit\n"); } @@ -1976,41 +1962,6 @@ bool Dumpstate::FinishZipFile() { return true; } -static std::string SHA256_file_hash(const std::string& filepath) { - android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK - | O_CLOEXEC | O_NOFOLLOW))); - if (fd == -1) { - MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno)); - return nullptr; - } - - SHA256_CTX ctx; - SHA256_Init(&ctx); - - std::vector buffer(65536); - while (1) { - ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size())); - if (bytes_read == 0) { - break; - } else if (bytes_read == -1) { - MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno)); - return nullptr; - } - - SHA256_Update(&ctx, buffer.data(), bytes_read); - } - - uint8_t hash[SHA256_DIGEST_LENGTH]; - SHA256_Final(hash, &ctx); - - char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1]; - for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) { - sprintf(hash_buffer + (i * 2), "%02x", hash[i]); - } - hash_buffer[sizeof(hash_buffer) - 1] = 0; - return std::string(hash_buffer); -} - static void SendBroadcast(const std::string& action, const std::vector& args) { // clang-format off std::vector am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0", @@ -2103,37 +2054,10 @@ static void PrepareToWriteToFile() { } /* - * Finalizes writing to the file by renaming or zipping the tmp file to the final location, + * Finalizes writing to the file by zipping the tmp file to the final location, * printing zipped file status, etc. */ static void FinalizeFile() { - /* check if user changed the suffix using system properties */ - std::string name = - android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), ""); - bool change_suffix = false; - if (!name.empty()) { - /* must whitelist which characters are allowed, otherwise it could cross directories */ - std::regex valid_regex("^[-_a-zA-Z0-9]+$"); - if (std::regex_match(name.c_str(), valid_regex)) { - change_suffix = true; - } else { - MYLOGE("invalid suffix provided by user: %s\n", name.c_str()); - } - } - if (change_suffix) { - MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str()); - ds.name_ = name; - if (!ds.screenshot_path_.empty()) { - std::string new_screenshot_path = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png"); - if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) { - MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(), - new_screenshot_path.c_str(), strerror(errno)); - } else { - ds.screenshot_path_ = new_screenshot_path; - } - } - } - bool do_text_file = true; if (ds.options_->do_zip_file) { if (!ds.FinishZipFile()) { @@ -2141,25 +2065,6 @@ static void FinalizeFile() { do_text_file = true; } else { do_text_file = false; - // If the user has changed the suffix, we need to change the zip file name. - std::string new_path = ds.GetPath(ds.CalledByApi() ? "-tmp.zip" : ".zip"); - if (ds.path_ != new_path) { - MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str()); - if (rename(ds.path_.c_str(), new_path.c_str())) { - MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(), - strerror(errno)); - } else { - ds.path_ = new_path; - } - } - } - } - if (do_text_file) { - ds.path_ = ds.GetPath(".txt"); - MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str()); - if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) { - MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno)); - ds.path_.clear(); } } if (ds.options_->use_control_socket) { @@ -2174,49 +2079,6 @@ static void FinalizeFile() { } } -/* Broadcasts that we are done with the bugreport */ -static void SendBugreportFinishedBroadcast() { - // TODO(b/111441001): use callback instead of broadcast. - if (!ds.path_.empty()) { - MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); - // clang-format off - - std::vector am_args = { - "--receiver-permission", "android.permission.DUMP", - "--ei", "android.intent.extra.ID", std::to_string(ds.id_), - "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), - "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), - "--es", "android.intent.extra.BUGREPORT", ds.path_, - "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ - }; - // clang-format on - if (ds.options_->do_fb && !android::os::IsFileEmpty(ds.screenshot_path_)) { - am_args.push_back("--es"); - am_args.push_back("android.intent.extra.SCREENSHOT"); - am_args.push_back(ds.screenshot_path_); - } - if (!ds.options_->notification_title.empty()) { - am_args.push_back("--es"); - am_args.push_back("android.intent.extra.TITLE"); - am_args.push_back(ds.options_->notification_title); - if (!ds.options_->notification_description.empty()) { - am_args.push_back("--es"); - am_args.push_back("android.intent.extra.DESCRIPTION"); - am_args.push_back(ds.options_->notification_description); - } - } - if (ds.options_->is_remote_mode) { - am_args.push_back("--es"); - am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); - am_args.push_back(SHA256_file_hash(ds.path_)); - SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); - } else { - SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); - } - } else { - MYLOGE("Skipping finished broadcast because bugreport could not be generated\n"); - } -} static inline const char* ModeToString(Dumpstate::BugreportMode mode) { switch (mode) { @@ -2238,10 +2100,9 @@ static inline const char* ModeToString(Dumpstate::BugreportMode mode) { } static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) { - options->extra_options = ModeToString(mode); + options->bugreport_mode = ModeToString(mode); switch (mode) { case Dumpstate::BugreportMode::BUGREPORT_FULL: - options->do_broadcast = true; options->do_fb = true; break; case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE: @@ -2249,88 +2110,32 @@ static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOpt options->do_start_service = true; options->do_progress_updates = true; options->do_fb = false; - options->do_broadcast = true; break; case Dumpstate::BugreportMode::BUGREPORT_REMOTE: options->do_vibrate = false; options->is_remote_mode = true; options->do_fb = false; - options->do_broadcast = true; break; case Dumpstate::BugreportMode::BUGREPORT_WEAR: options->do_start_service = true; options->do_progress_updates = true; options->do_zip_file = true; options->do_fb = true; - options->do_broadcast = true; break; case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY: options->telephony_only = true; options->do_fb = false; - options->do_broadcast = true; break; case Dumpstate::BugreportMode::BUGREPORT_WIFI: options->wifi_only = true; options->do_zip_file = true; options->do_fb = false; - options->do_broadcast = true; break; case Dumpstate::BugreportMode::BUGREPORT_DEFAULT: break; } } -static Dumpstate::BugreportMode getBugreportModeFromProperty() { - // If the system property is not set, it's assumed to be a default bugreport. - Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT; - - std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); - if (!extra_options.empty()) { - // Framework uses a system property to override some command-line args. - // Currently, it contains the type of the requested bugreport. - if (extra_options == "bugreportplus") { - mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE; - } else if (extra_options == "bugreportfull") { - mode = Dumpstate::BugreportMode::BUGREPORT_FULL; - } else if (extra_options == "bugreportremote") { - mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE; - } else if (extra_options == "bugreportwear") { - mode = Dumpstate::BugreportMode::BUGREPORT_WEAR; - } else if (extra_options == "bugreporttelephony") { - mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY; - } else if (extra_options == "bugreportwifi") { - mode = Dumpstate::BugreportMode::BUGREPORT_WIFI; - } else { - MYLOGE("Unknown extra option: %s\n", extra_options.c_str()); - } - // Reset the property - android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, ""); - } - return mode; -} - -// TODO: Move away from system properties when we have options passed via binder calls. -/* Sets runtime options from the system properties and then clears those properties. */ -static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) { - Dumpstate::BugreportMode mode = getBugreportModeFromProperty(); - SetOptionsFromMode(mode, options); - - options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, ""); - if (!options->notification_title.empty()) { - // Reset the property - android::base::SetProperty(PROPERTY_EXTRA_TITLE, ""); - - options->notification_description = - android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, ""); - if (!options->notification_description.empty()) { - // Reset the property - android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, ""); - } - MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(), - options->notification_description.c_str()); - } -} - static void LogDumpOptions(const Dumpstate::DumpOptions& options) { MYLOGI("do_zip_file: %d\n", options.do_zip_file); MYLOGI("do_add_date: %d\n", options.do_add_date); @@ -2338,7 +2143,6 @@ static void LogDumpOptions(const Dumpstate::DumpOptions& options) { MYLOGI("use_socket: %d\n", options.use_socket); MYLOGI("use_control_socket: %d\n", options.use_control_socket); MYLOGI("do_fb: %d\n", options.do_fb); - MYLOGI("do_broadcast: %d\n", options.do_broadcast); MYLOGI("is_remote_mode: %d\n", options.is_remote_mode); MYLOGI("show_header_only: %d\n", options.show_header_only); MYLOGI("do_start_service: %d\n", options.do_start_service); @@ -2346,10 +2150,8 @@ static void LogDumpOptions(const Dumpstate::DumpOptions& options) { MYLOGI("wifi_only: %d\n", options.wifi_only); MYLOGI("do_progress_updates: %d\n", options.do_progress_updates); MYLOGI("fd: %d\n", options.bugreport_fd.get()); - MYLOGI("extra_options: %s\n", options.extra_options.c_str()); + MYLOGI("bugreport_mode: %s\n", options.bugreport_mode.c_str()); MYLOGI("args: %s\n", options.args.c_str()); - MYLOGI("notification_title: %s\n", options.notification_title.c_str()); - MYLOGI("notification_description: %s\n", options.notification_description.c_str()); } void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode, @@ -2364,7 +2166,6 @@ void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode, bugreport_fd.reset(dup(bugreport_fd_in.get())); screenshot_fd.reset(dup(screenshot_fd_in.get())); - extra_options = ModeToString(bugreport_mode); SetOptionsFromMode(bugreport_mode, this); } @@ -2383,7 +2184,6 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) case 'p': do_fb = true; break; case 'P': do_progress_updates = true; break; case 'R': is_remote_mode = true; break; - case 'B': do_broadcast = true; break; case 'V': break; // compatibility no-op case 'w': // This was already processed @@ -2409,7 +2209,6 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) // Reset next index used by getopt so this can be called multiple times, for eg, in tests. optind = 1; - SetOptionsFromProperties(this); return status; } @@ -2418,7 +2217,7 @@ bool Dumpstate::DumpOptions::ValidateOptions() const { return false; } - if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) { + if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) { return false; } @@ -2426,11 +2225,7 @@ bool Dumpstate::DumpOptions::ValidateOptions() const { return false; } - if (do_progress_updates && !do_broadcast) { - return false; - } - - if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) { + if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) { return false; } return true; @@ -2528,7 +2323,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n", calling_uid, calling_package.c_str()); - if (options_->bugreport_fd.get() != -1) { + if (CalledByApi()) { // If the output needs to be copied over to the caller's fd, get user consent. android::String16 package(calling_package.c_str()); CheckUserConsent(calling_uid, package); @@ -2573,8 +2368,8 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } - MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(), - options_->extra_options.c_str()); + MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s)\n", id_, options_->args.c_str(), + options_->bugreport_mode.c_str()); MYLOGI("bugreport format version: %s\n", version_.c_str()); @@ -2601,18 +2396,13 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, PrepareToWriteToFile(); if (options_->do_progress_updates) { - if (options_->do_broadcast) { - // clang-format off - std::vector am_args = { - "--receiver-permission", "android.permission.DUMP", - "--es", "android.intent.extra.NAME", name_, - "--ei", "android.intent.extra.ID", std::to_string(id_), - "--ei", "android.intent.extra.PID", std::to_string(pid_), - "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()), - }; - // clang-format on - SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args); - } + // clang-format off + std::vector am_args = { + "--receiver-permission", "android.permission.DUMP", + }; + // clang-format on + // Send STARTED broadcast for apps that listen to bugreport generation events + SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args); if (options_->use_control_socket) { dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str()); } @@ -2700,14 +2490,14 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout))); } - // Rename, and/or zip the (now complete) .tmp file within the internal directory. + // Zip the (now complete) .tmp file within the internal directory. if (options_->OutputToFile()) { FinalizeFile(); } // Share the final file with the caller if the user has consented or Shell is the caller. Dumpstate::RunStatus status = Dumpstate::RunStatus::OK; - if (options_->bugreport_fd.get() != -1) { + if (CalledByApi()) { status = CopyBugreportIfUserConsented(calling_uid); if (status != Dumpstate::RunStatus::OK && status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) { @@ -2748,12 +2538,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, } } - /* tell activity manager we're done */ - if (options_->do_broadcast && !CalledByApi()) { - SendBugreportFinishedBroadcast(); - // Note that listener_ is notified in Run(); - } - MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(), progress_->GetInitialMax()); progress_->Save(); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 430936ebfd..4b13adc68b 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -359,7 +359,6 @@ class Dumpstate { bool use_socket = false; bool use_control_socket = false; bool do_fb = false; - bool do_broadcast = false; bool is_remote_mode = false; bool show_header_only = false; bool do_start_service = false; @@ -371,16 +370,15 @@ class Dumpstate { android::base::unique_fd bugreport_fd; // File descriptor to screenshot file. android::base::unique_fd screenshot_fd; - // TODO: rename to MODE. - // Extra options passed as system property. - std::string extra_options; + // Bugreport mode of the bugreport. + std::string bugreport_mode; // Command-line arguments as string std::string args; // Notification title and description std::string notification_title; std::string notification_description; - /* Initializes options from commandline arguments and system properties. */ + /* Initializes options from commandline arguments. */ RunStatus Initialize(int argc, char* argv[]); /* Initializes options from the requested mode. */ diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index fbb01f5e99..b9c7568ace 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -195,7 +195,6 @@ class ZippedBugreportGenerationTest : public Test { static Dumpstate& ds; static std::chrono::milliseconds duration; static void SetUpTestCase() { - property_set("dumpstate.options", "bugreportplus"); // clang-format off char* argv[] = { (char*)"dumpstate", diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index cff1d439d9..84eeab39ca 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace android { namespace os { @@ -148,10 +149,9 @@ class DumpOptionsTest : public Test { options_ = Dumpstate::DumpOptions(); } void TearDown() { - // Reset the property - property_set("dumpstate.options", ""); } Dumpstate::DumpOptions options_; + android::base::unique_fd fd; }; TEST_F(DumpOptionsTest, InitializeNone) { @@ -174,7 +174,6 @@ TEST_F(DumpOptionsTest, InitializeNone) { EXPECT_FALSE(options_.do_fb); EXPECT_FALSE(options_.do_progress_updates); EXPECT_FALSE(options_.is_remote_mode); - EXPECT_FALSE(options_.do_broadcast); } TEST_F(DumpOptionsTest, InitializeAdbBugreport) { @@ -200,7 +199,6 @@ TEST_F(DumpOptionsTest, InitializeAdbBugreport) { EXPECT_FALSE(options_.do_fb); EXPECT_FALSE(options_.do_progress_updates); EXPECT_FALSE(options_.is_remote_mode); - EXPECT_FALSE(options_.do_broadcast); EXPECT_FALSE(options_.use_socket); } @@ -226,28 +224,13 @@ TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) { EXPECT_FALSE(options_.do_fb); EXPECT_FALSE(options_.do_progress_updates); EXPECT_FALSE(options_.is_remote_mode); - EXPECT_FALSE(options_.do_broadcast); } TEST_F(DumpOptionsTest, InitializeFullBugReport) { - // clang-format off - char* argv[] = { - const_cast("bugreport"), - const_cast("-d"), - const_cast("-p"), - const_cast("-B"), - const_cast("-z"), - }; - // clang-format on - property_set("dumpstate.options", "bugreportfull"); - - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); - - EXPECT_EQ(status, Dumpstate::RunStatus::OK); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd); EXPECT_TRUE(options_.do_add_date); EXPECT_TRUE(options_.do_fb); EXPECT_TRUE(options_.do_zip_file); - EXPECT_TRUE(options_.do_broadcast); // Other options retain default values EXPECT_TRUE(options_.do_vibrate); @@ -260,23 +243,8 @@ TEST_F(DumpOptionsTest, InitializeFullBugReport) { } TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) { - // clang-format off - char* argv[] = { - const_cast("bugreport"), - const_cast("-d"), - const_cast("-p"), - const_cast("-B"), - const_cast("-z"), - }; - // clang-format on - - property_set("dumpstate.options", "bugreportplus"); - - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); - - EXPECT_EQ(status, Dumpstate::RunStatus::OK); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd); EXPECT_TRUE(options_.do_add_date); - EXPECT_TRUE(options_.do_broadcast); EXPECT_TRUE(options_.do_zip_file); EXPECT_TRUE(options_.do_progress_updates); EXPECT_TRUE(options_.do_start_service); @@ -291,23 +259,8 @@ TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) { } TEST_F(DumpOptionsTest, InitializeRemoteBugReport) { - // clang-format off - char* argv[] = { - const_cast("bugreport"), - const_cast("-d"), - const_cast("-p"), - const_cast("-B"), - const_cast("-z"), - }; - // clang-format on - - property_set("dumpstate.options", "bugreportremote"); - - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); - - EXPECT_EQ(status, Dumpstate::RunStatus::OK); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd); EXPECT_TRUE(options_.do_add_date); - EXPECT_TRUE(options_.do_broadcast); EXPECT_TRUE(options_.do_zip_file); EXPECT_TRUE(options_.is_remote_mode); EXPECT_FALSE(options_.do_vibrate); @@ -321,24 +274,9 @@ TEST_F(DumpOptionsTest, InitializeRemoteBugReport) { } TEST_F(DumpOptionsTest, InitializeWearBugReport) { - // clang-format off - char* argv[] = { - const_cast("bugreport"), - const_cast("-d"), - const_cast("-p"), - const_cast("-B"), - const_cast("-z"), - }; - // clang-format on - - property_set("dumpstate.options", "bugreportwear"); - - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); - - EXPECT_EQ(status, Dumpstate::RunStatus::OK); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd); EXPECT_TRUE(options_.do_add_date); EXPECT_TRUE(options_.do_fb); - EXPECT_TRUE(options_.do_broadcast); EXPECT_TRUE(options_.do_zip_file); EXPECT_TRUE(options_.do_progress_updates); EXPECT_TRUE(options_.do_start_service); @@ -352,24 +290,9 @@ TEST_F(DumpOptionsTest, InitializeWearBugReport) { } TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) { - // clang-format off - char* argv[] = { - const_cast("bugreport"), - const_cast("-d"), - const_cast("-p"), - const_cast("-B"), - const_cast("-z"), - }; - // clang-format on - - property_set("dumpstate.options", "bugreporttelephony"); - - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); - - EXPECT_EQ(status, Dumpstate::RunStatus::OK); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd); EXPECT_TRUE(options_.do_add_date); EXPECT_FALSE(options_.do_fb); - EXPECT_TRUE(options_.do_broadcast); EXPECT_TRUE(options_.do_zip_file); EXPECT_TRUE(options_.telephony_only); @@ -383,24 +306,9 @@ TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) { } TEST_F(DumpOptionsTest, InitializeWifiBugReport) { - // clang-format off - char* argv[] = { - const_cast("bugreport"), - const_cast("-d"), - const_cast("-p"), - const_cast("-B"), - const_cast("-z"), - }; - // clang-format on - - property_set("dumpstate.options", "bugreportwifi"); - - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); - - EXPECT_EQ(status, Dumpstate::RunStatus::OK); + options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd); EXPECT_TRUE(options_.do_add_date); EXPECT_FALSE(options_.do_fb); - EXPECT_TRUE(options_.do_broadcast); EXPECT_TRUE(options_.do_zip_file); EXPECT_TRUE(options_.wifi_only); @@ -420,20 +328,15 @@ TEST_F(DumpOptionsTest, InitializeDefaultBugReport) { const_cast("bugreport"), const_cast("-d"), const_cast("-p"), - const_cast("-B"), const_cast("-z"), }; // clang-format on - - property_set("dumpstate.options", ""); - Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv); EXPECT_EQ(status, Dumpstate::RunStatus::OK); EXPECT_TRUE(options_.do_add_date); EXPECT_TRUE(options_.do_fb); EXPECT_TRUE(options_.do_zip_file); - EXPECT_TRUE(options_.do_broadcast); // Other options retain default values EXPECT_TRUE(options_.do_vibrate); @@ -472,7 +375,6 @@ TEST_F(DumpOptionsTest, InitializePartial1) { EXPECT_FALSE(options_.do_fb); EXPECT_FALSE(options_.do_progress_updates); EXPECT_FALSE(options_.is_remote_mode); - EXPECT_FALSE(options_.do_broadcast); } TEST_F(DumpOptionsTest, InitializePartial2) { @@ -484,7 +386,6 @@ TEST_F(DumpOptionsTest, InitializePartial2) { const_cast("-p"), const_cast("-P"), const_cast("-R"), - const_cast("-B"), }; // clang-format on @@ -496,7 +397,6 @@ TEST_F(DumpOptionsTest, InitializePartial2) { EXPECT_TRUE(options_.do_fb); EXPECT_TRUE(options_.do_progress_updates); EXPECT_TRUE(options_.is_remote_mode); - EXPECT_TRUE(options_.do_broadcast); // Other options retain default values EXPECT_FALSE(options_.do_add_date); @@ -544,7 +444,7 @@ TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) { } TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) { - options_.do_broadcast = true; + options_.do_progress_updates = true; // Writing to socket = !writing to file. options_.use_socket = true; EXPECT_FALSE(options_.ValidateOptions()); @@ -561,19 +461,10 @@ TEST_F(DumpOptionsTest, ValidateOptionsNeedZipfile) { EXPECT_TRUE(options_.ValidateOptions()); } -TEST_F(DumpOptionsTest, ValidateOptionsUpdateProgressNeedsBroadcast) { - options_.do_progress_updates = true; - EXPECT_FALSE(options_.ValidateOptions()); - - options_.do_broadcast = true; - EXPECT_TRUE(options_.ValidateOptions()); -} - TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) { options_.is_remote_mode = true; EXPECT_FALSE(options_.ValidateOptions()); - options_.do_broadcast = true; options_.do_zip_file = true; options_.do_add_date = true; EXPECT_TRUE(options_.ValidateOptions()); -- cgit v1.2.3-59-g8ed1b From ed5d6a6fb26534c8564e51ca2e958b59c9d2fec5 Mon Sep 17 00:00:00 2001 From: Abhijeet Kaur Date: Mon, 7 Oct 2019 15:02:05 +0100 Subject: Remove no-op setListener method from dumpstate listener Bugreports using Bugreport API flow is stable, remove unused legacy flow method: setListener. * Remove DumpstateToken as it was only used by setListener. * Remove listener_name_ and report_section_ Bug: 136066578 Test: Build and flash. Takes bugreport as expected. Test: atest dumpstate_test Test: `adb bugreport` works as expected. Change-Id: I31d1795fa91275091950320c71f4cf085895e4e0 --- cmds/dumpstate/Android.bp | 1 - cmds/dumpstate/DumpstateService.cpp | 38 +------------ cmds/dumpstate/DumpstateService.h | 4 -- cmds/dumpstate/binder/android/os/IDumpstate.aidl | 12 ---- .../binder/android/os/IDumpstateToken.aidl | 24 -------- cmds/dumpstate/dumpstate.cpp | 6 +- cmds/dumpstate/dumpstate.h | 2 - cmds/dumpstate/tests/dumpstate_smoke_test.cpp | 2 - cmds/dumpstate/tests/dumpstate_test.cpp | 66 ++++------------------ 9 files changed, 13 insertions(+), 142 deletions(-) delete mode 100644 cmds/dumpstate/binder/android/os/IDumpstateToken.aidl (limited to 'cmds') diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index 09aee89e1b..be7e3e1a73 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -66,7 +66,6 @@ filegroup { name: "dumpstate_aidl", srcs: [ "binder/android/os/IDumpstateListener.aidl", - "binder/android/os/IDumpstateToken.aidl", "binder/android/os/IDumpstate.aidl", ], path: "binder", diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index f98df99534..2c845e6e56 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -58,8 +58,6 @@ static binder::Status exception(uint32_t code, const std::string& msg) { exit(0); } -class DumpstateToken : public BnDumpstateToken {}; - } // namespace DumpstateService::DumpstateService() : ds_(nullptr) { @@ -81,38 +79,6 @@ status_t DumpstateService::Start() { return android::OK; } -// Note: this method is part of the old flow and is not expected to be used in combination -// with startBugreport. -binder::Status DumpstateService::setListener(const std::string& name, - const sp& listener, - bool getSectionDetails, - sp* returned_token) { - *returned_token = nullptr; - if (name.empty()) { - MYLOGE("setListener(): name not set\n"); - return binder::Status::ok(); - } - if (listener == nullptr) { - MYLOGE("setListener(): listener not set\n"); - return binder::Status::ok(); - } - std::lock_guard lock(lock_); - if (ds_ == nullptr) { - ds_ = &(Dumpstate::GetInstance()); - } - if (ds_->listener_ != nullptr) { - MYLOGE("setListener(%s): already set (%s)\n", name.c_str(), ds_->listener_name_.c_str()); - return binder::Status::ok(); - } - - ds_->listener_name_ = name; - ds_->listener_ = listener; - ds_->report_section_ = getSectionDetails; - *returned_token = new DumpstateToken(); - - return binder::Status::ok(); -} - binder::Status DumpstateService::startBugreport(int32_t calling_uid, const std::string& calling_package, const android::base::unique_fd& bugreport_fd, @@ -121,8 +87,7 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, const sp& listener) { MYLOGI("startBugreport() with mode: %d\n", bugreport_mode); - // This is the bugreporting API flow, so ensure there is only one bugreport in progress at a - // time. + // Ensure there is only one bugreport in progress at a time. std::lock_guard lock(lock_); if (ds_ != nullptr) { MYLOGE("Error! There is already a bugreport in progress. Returning."); @@ -216,7 +181,6 @@ status_t DumpstateService::dump(int fd, const Vector&) { dprintf(fd, "name: %s\n", ds_->name_.c_str()); dprintf(fd, "now: %ld\n", ds_->now_); dprintf(fd, "is_zipping: %s\n", ds_->IsZipping() ? "true" : "false"); - dprintf(fd, "listener: %s\n", ds_->listener_name_.c_str()); dprintf(fd, "notification title: %s\n", ds_->options_->notification_title.c_str()); dprintf(fd, "notification description: %s\n", ds_->options_->notification_description.c_str()); diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h index 68eda4763a..27954adbae 100644 --- a/cmds/dumpstate/DumpstateService.h +++ b/cmds/dumpstate/DumpstateService.h @@ -24,7 +24,6 @@ #include #include "android/os/BnDumpstate.h" -#include "android/os/BnDumpstateToken.h" #include "dumpstate.h" namespace android { @@ -38,9 +37,6 @@ class DumpstateService : public BinderService, public BnDumpst static char const* getServiceName(); status_t dump(int fd, const Vector& args) override; - binder::Status setListener(const std::string& name, const sp& listener, - bool getSectionDetails, - sp* returned_token) override; binder::Status startBugreport(int32_t calling_uid, const std::string& calling_package, const android::base::unique_fd& bugreport_fd, diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl index cb2d8b8d2c..3f359c86c5 100644 --- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl +++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl @@ -17,24 +17,12 @@ package android.os; import android.os.IDumpstateListener; -import android.os.IDumpstateToken; /** * Binder interface for the currently running dumpstate process. * {@hide} */ interface IDumpstate { - // TODO: remove method once startBugReport is used by Shell. - /* - * Sets the listener for this dumpstate progress. - * - * Returns a token used to monitor dumpstate death, or `nullptr` if the listener was already - * set (the listener behaves like a Highlander: There Can be Only One). - * Set {@code getSectionDetails} to true in order to receive callbacks with per section - * progress details - */ - IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener, - boolean getSectionDetails); // NOTE: If you add to or change these modes, please also change the corresponding enums // in system server, in BugreportParams.java. diff --git a/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl b/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl deleted file mode 100644 index 7f74ceb539..0000000000 --- a/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2016, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -/** - * Token used by the IDumpstateListener to watch for dumpstate death. - * {@hide} - */ -interface IDumpstateToken { -} diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index b87582eab7..7c03ccfd9c 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -3686,13 +3686,11 @@ void Dumpstate::UpdateProgress(int32_t delta_sec) { if (listener_ != nullptr) { if (percent % 5 == 0) { // We don't want to spam logcat, so only log multiples of 5. - MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max, - percent); + MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent); } else { // stderr is ignored on normal invocations, but useful when calling // /system/bin/dumpstate directly for debuggging. - fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), - progress, max, percent); + fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent); } listener_->onProgress(percent); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 430936ebfd..3139b77168 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -456,8 +456,6 @@ class Dumpstate { // Binder object listening to progress. android::sp listener_; - std::string listener_name_; - bool report_section_; // List of open tombstone dump files. std::vector tombstone_data_; diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index fbb01f5e99..c0ac9e4611 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -206,8 +206,6 @@ class ZippedBugreportGenerationTest : public Test { // clang-format on sp listener(new DumpstateListener(dup(fileno(stdout)), sections)); ds.listener_ = listener; - ds.listener_name_ = "Smokey"; - ds.report_section_ = true; auto start = std::chrono::steady_clock::now(); ds.ParseCommandlineAndRun(ARRAY_SIZE(argv), argv); auto end = std::chrono::steady_clock::now(); diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index cff1d439d9..7010301f9a 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -616,8 +616,8 @@ class DumpstateTest : public DumpstateBaseTest { ds.progress_.reset(new Progress(initial_max, progress, 1.2)); } - std::string GetProgressMessage(const std::string& listener_name, int progress, int max, - int old_max = 0, bool update_progress = true) { + std::string GetProgressMessage(int progress, int max, + int old_max = 0, bool update_progress = true) { EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress"; EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max"; @@ -630,9 +630,8 @@ class DumpstateTest : public DumpstateBaseTest { } if (update_progress) { - message += android::base::StringPrintf("Setting progress (%s): %d/%d (%d%%)\n", - listener_name.c_str(), progress, max, - (100 * progress / max)); + message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n", + progress, max, (100 * progress / max)); } return message; @@ -787,18 +786,17 @@ TEST_F(DumpstateTest, RunCommandIsKilled) { TEST_F(DumpstateTest, RunCommandProgress) { sp listener(new DumpstateListenerMock()); ds.listener_ = listener; - ds.listener_name_ = "FoxMulder"; SetProgress(0, 30); EXPECT_CALL(*listener, onProgress(66)); // 20/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build())); - std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30); + std::string progress_message = GetProgressMessage(20, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); EXPECT_CALL(*listener, onProgress(80)); // 24/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 24, 30); + progress_message = GetProgressMessage(24, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); @@ -806,20 +804,20 @@ TEST_F(DumpstateTest, RunCommandProgress) { SetDryRun(true); EXPECT_CALL(*listener, onProgress(90)); // 27/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 27, 30); + progress_message = GetProgressMessage(27, 30); EXPECT_THAT(out, IsEmpty()); EXPECT_THAT(err, StrEq(progress_message)); SetDryRun(false); EXPECT_CALL(*listener, onProgress(96)); // 29/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 29, 30); + progress_message = GetProgressMessage(29, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); EXPECT_CALL(*listener, onProgress(100)); // 30/30 % EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); - progress_message = GetProgressMessage(ds.listener_name_, 30, 30); + progress_message = GetProgressMessage(30, 30); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); @@ -1044,14 +1042,12 @@ TEST_F(DumpstateTest, DumpFileOnDryRun) { TEST_F(DumpstateTest, DumpFileUpdateProgress) { sp listener(new DumpstateListenerMock()); ds.listener_ = listener; - ds.listener_name_ = "FoxMulder"; SetProgress(0, 30); EXPECT_CALL(*listener, onProgress(16)); // 5/30 % EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); - std::string progress_message = - GetProgressMessage(ds.listener_name_, 5, 30); // TODO: unhardcode WEIGHT_FILE (5)? + std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)? EXPECT_THAT(err, StrEq(progress_message)); EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline @@ -1063,48 +1059,6 @@ class DumpstateServiceTest : public DumpstateBaseTest { DumpstateService dss; }; -TEST_F(DumpstateServiceTest, SetListenerNoName) { - sp listener(new DumpstateListenerMock()); - sp token; - EXPECT_TRUE(dss.setListener("", listener, /* getSectionDetails = */ false, &token).isOk()); - ASSERT_THAT(token, IsNull()); -} - -TEST_F(DumpstateServiceTest, SetListenerNoPointer) { - sp token; - EXPECT_TRUE( - dss.setListener("whatever", nullptr, /* getSectionDetails = */ false, &token).isOk()); - ASSERT_THAT(token, IsNull()); -} - -TEST_F(DumpstateServiceTest, SetListenerTwice) { - sp listener(new DumpstateListenerMock()); - sp token; - EXPECT_TRUE( - dss.setListener("whatever", listener, /* getSectionDetails = */ false, &token).isOk()); - ASSERT_THAT(token, NotNull()); - EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); - EXPECT_FALSE(Dumpstate::GetInstance().report_section_); - - token.clear(); - EXPECT_TRUE( - dss.setListener("whatsoever", listener, /* getSectionDetails = */ false, &token).isOk()); - ASSERT_THAT(token, IsNull()); - EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); - EXPECT_FALSE(Dumpstate::GetInstance().report_section_); -} - -TEST_F(DumpstateServiceTest, SetListenerWithSectionDetails) { - sp listener(new DumpstateListenerMock()); - sp token; - Dumpstate::GetInstance().listener_ = nullptr; - EXPECT_TRUE( - dss.setListener("whatever", listener, /* getSectionDetails = */ true, &token).isOk()); - ASSERT_THAT(token, NotNull()); - EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); - EXPECT_TRUE(Dumpstate::GetInstance().report_section_); -} - class ProgressTest : public DumpstateBaseTest { public: Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") { -- cgit v1.2.3-59-g8ed1b From 4cfac15ede76ded84ac4ad79d70cf3ff232c1c4b Mon Sep 17 00:00:00 2001 From: MÃ¥rten Kongstad Date: Thu, 6 Dec 2018 13:15:16 +0100 Subject: Remove legacy idmap binary The idmap tool has been replaced by idmap2. Remove now obsolete code related to the old binary. Bug: 118711077 Test: atest OverlayDeviceTests OverlayHostTests Change-Id: Ie1b8fe6f53ce5308b3a1ee6b9f4719cd830a2ecf --- cmds/installd/InstalldNativeService.cpp | 204 ------------------------- cmds/installd/InstalldNativeService.h | 3 - cmds/installd/binder/android/os/IInstalld.aidl | 2 - 3 files changed, 209 deletions(-) (limited to 'cmds') diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 4026f29208..e6e232ce2f 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -92,10 +92,6 @@ static constexpr const char* PKG_LIB_POSTFIX = "/lib"; static constexpr const char* CACHE_DIR_POSTFIX = "/cache"; static constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache"; -static constexpr const char *kIdMapPath = "/system/bin/idmap"; -static constexpr const char* IDMAP_PREFIX = "/data/resource-cache/"; -static constexpr const char* IDMAP_SUFFIX = "@idmap"; - // fsverity assumes the page size is always 4096. If not, the feature can not be // enabled. static constexpr int kVerityPageSize = 4096; @@ -2253,206 +2249,6 @@ out: return res; } -static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) -{ - execl(kIdMapPath, kIdMapPath, "--fd", target_apk, overlay_apk, - StringPrintf("%d", idmap_fd).c_str(), (char*)nullptr); - PLOG(ERROR) << "execl (" << kIdMapPath << ") failed"; -} - -static void run_verify_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) -{ - execl(kIdMapPath, kIdMapPath, "--verify", target_apk, overlay_apk, - StringPrintf("%d", idmap_fd).c_str(), (char*)nullptr); - PLOG(ERROR) << "execl (" << kIdMapPath << ") failed"; -} - -static bool delete_stale_idmap(const char* target_apk, const char* overlay_apk, - const char* idmap_path, int32_t uid) { - int idmap_fd = open(idmap_path, O_RDWR); - if (idmap_fd < 0) { - PLOG(ERROR) << "idmap open failed: " << idmap_path; - unlink(idmap_path); - return true; - } - - pid_t pid; - pid = fork(); - if (pid == 0) { - /* child -- drop privileges before continuing */ - if (setgid(uid) != 0) { - LOG(ERROR) << "setgid(" << uid << ") failed during idmap"; - exit(1); - } - if (setuid(uid) != 0) { - LOG(ERROR) << "setuid(" << uid << ") failed during idmap"; - exit(1); - } - if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { - PLOG(ERROR) << "flock(" << idmap_path << ") failed during idmap"; - exit(1); - } - - run_verify_idmap(target_apk, overlay_apk, idmap_fd); - exit(1); /* only if exec call to deleting stale idmap failed */ - } else { - int status = wait_child(pid); - close(idmap_fd); - - if (status != 0) { - // Failed on verifying if idmap is made from target_apk and overlay_apk. - LOG(DEBUG) << "delete stale idmap: " << idmap_path; - unlink(idmap_path); - return true; - } - } - return false; -} - -// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix) -// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap -static int flatten_path(const char *prefix, const char *suffix, - const char *overlay_path, char *idmap_path, size_t N) -{ - if (overlay_path == nullptr || idmap_path == nullptr) { - return -1; - } - const size_t len_overlay_path = strlen(overlay_path); - // will access overlay_path + 1 further below; requires absolute path - if (len_overlay_path < 2 || *overlay_path != '/') { - return -1; - } - const size_t len_idmap_root = strlen(prefix); - const size_t len_suffix = strlen(suffix); - if (SIZE_MAX - len_idmap_root < len_overlay_path || - SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { - // additions below would cause overflow - return -1; - } - if (N < len_idmap_root + len_overlay_path + len_suffix) { - return -1; - } - memset(idmap_path, 0, N); - snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); - char *ch = idmap_path + len_idmap_root; - while (*ch != '\0') { - if (*ch == '/') { - *ch = '@'; - } - ++ch; - } - return 0; -} - -binder::Status InstalldNativeService::idmap(const std::string& targetApkPath, - const std::string& overlayApkPath, int32_t uid) { - ENFORCE_UID(AID_SYSTEM); - CHECK_ARGUMENT_PATH(targetApkPath); - CHECK_ARGUMENT_PATH(overlayApkPath); - std::lock_guard lock(mLock); - - const char* target_apk = targetApkPath.c_str(); - const char* overlay_apk = overlayApkPath.c_str(); - ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); - - int idmap_fd = -1; - char idmap_path[PATH_MAX]; - struct stat idmap_stat; - bool outdated = false; - - if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, - idmap_path, sizeof(idmap_path)) == -1) { - ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); - goto fail; - } - - if (stat(idmap_path, &idmap_stat) < 0) { - outdated = true; - } else { - outdated = delete_stale_idmap(target_apk, overlay_apk, idmap_path, uid); - } - - if (outdated) { - idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644); - } else { - idmap_fd = open(idmap_path, O_RDWR); - } - - if (idmap_fd < 0) { - ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno)); - goto fail; - } - if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) { - ALOGE("idmap cannot chown '%s'\n", idmap_path); - goto fail; - } - if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { - ALOGE("idmap cannot chmod '%s'\n", idmap_path); - goto fail; - } - - if (!outdated) { - close(idmap_fd); - return ok(); - } - - pid_t pid; - pid = fork(); - if (pid == 0) { - /* child -- drop privileges before continuing */ - if (setgid(uid) != 0) { - ALOGE("setgid(%d) failed during idmap\n", uid); - exit(1); - } - if (setuid(uid) != 0) { - ALOGE("setuid(%d) failed during idmap\n", uid); - exit(1); - } - if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { - ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno)); - exit(1); - } - - run_idmap(target_apk, overlay_apk, idmap_fd); - exit(1); /* only if exec call to idmap failed */ - } else { - int status = wait_child(pid); - if (status != 0) { - ALOGE("idmap failed, status=0x%04x\n", status); - goto fail; - } - } - - close(idmap_fd); - return ok(); -fail: - if (idmap_fd >= 0) { - close(idmap_fd); - unlink(idmap_path); - } - return error(); -} - -binder::Status InstalldNativeService::removeIdmap(const std::string& overlayApkPath) { - ENFORCE_UID(AID_SYSTEM); - CHECK_ARGUMENT_PATH(overlayApkPath); - std::lock_guard lock(mLock); - - const char* overlay_apk = overlayApkPath.c_str(); - char idmap_path[PATH_MAX]; - - if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, - idmap_path, sizeof(idmap_path)) == -1) { - ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); - return error(); - } - if (unlink(idmap_path) < 0) { - ALOGE("couldn't unlink idmap file %s\n", idmap_path); - return error(); - } - return ok(); -} - binder::Status InstalldNativeService::restoreconAppData(const std::unique_ptr& uuid, const std::string& packageName, int32_t userId, int32_t flags, int32_t appId, const std::string& seInfo) { diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index 2b7bf33cbc..ef91bf84be 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -119,9 +119,6 @@ public: binder::Status destroyProfileSnapshot(const std::string& packageName, const std::string& profileName); - binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath, - int32_t uid); - binder::Status removeIdmap(const std::string& overlayApkPath); binder::Status rmPackageDir(const std::string& packageDir); binder::Status markBootComplete(const std::string& instructionSet); binder::Status freeCache(const std::unique_ptr& uuid, int64_t targetFreeBytes, diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index d99bcc8d13..6cc4bde2f1 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -72,8 +72,6 @@ interface IInstalld { @utf8InCpp String profileName, @utf8InCpp String classpath); void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String profileName); - void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid); - void removeIdmap(@utf8InCpp String overlayApkPath); void rmPackageDir(@utf8InCpp String packageDir); void markBootComplete(@utf8InCpp String instructionSet); void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes, -- cgit v1.2.3-59-g8ed1b From 3594978ab43eb1f4a41a7235beab97dd3e7202bd Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 19 Nov 2019 15:54:36 -0800 Subject: Adding visible windows dump in bugreport Bug: 64101886 Test: Verified that bug report contain the view dump Change-Id: I802a0517cd10d4a7520b0848c2ddff77abd57871 --- cmds/dumpstate/dumpstate.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 61e22a4912..8400cdc69b 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -933,6 +933,31 @@ static void DumpIncidentReport() { unlink(path.c_str()); } +static void DumpVisibleWindowViews() { + if (!ds.IsZipping()) { + MYLOGD("Not dumping visible views because it's not a zipped bugreport\n"); + return; + } + DurationReporter duration_reporter("VISIBLE WINDOW VIEWS"); + const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views"; + auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), + O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); + if (fd < 0) { + MYLOGE("Could not open %s to dump visible views.\n", path.c_str()); + return; + } + RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"}, + CommandOptions::WithTimeout(120).Build()); + bool empty = 0 == lseek(fd, 0, SEEK_END); + if (!empty) { + ds.AddZipEntry("visible_windows.zip", path); + } else { + MYLOGW("Failed to dump visible windows\n"); + } + unlink(path.c_str()); +} + static void DumpIpTablesAsRoot() { RunCommand("IPTABLES", {"iptables", "-L", "-nvx"}); RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"}); @@ -1317,6 +1342,8 @@ static Dumpstate::RunStatus dumpstate() { RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20); + RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews); + DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat"); DumpFile("VMALLOC INFO", "/proc/vmallocinfo"); DumpFile("SLAB INFO", "/proc/slabinfo"); -- cgit v1.2.3-59-g8ed1b From e89d9c183ac1d7a2e86120b4b5d2610411c5a62d Mon Sep 17 00:00:00 2001 From: Jichao Li Date: Thu, 21 Nov 2019 19:02:51 -0800 Subject: For full & interactive bugreports, collect consent only after critical dumpsys has completed. This way each type of dumpstate can control the timing of the consent more precisely. Right now this is necessary because otherwise consent is going to interfere with sysui states all the time. Also some minor name changes for clarify on the way. Bug: 142921485 Test: build & flash, br captured with API does not have consent screen in critical dumpsys. i.e. Grepping ConfirmationActivity from permission controller within critical dumpsys yields no result. Change-Id: I30c1bd9559af82ebdb6dc56e91ca81d0f2745270 --- cmds/dumpstate/dumpstate.cpp | 33 +++++++++++++++++++-------------- cmds/dumpstate/dumpstate.h | 4 +++- 2 files changed, 22 insertions(+), 15 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 8400cdc69b..aa31d3256f 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1545,11 +1545,7 @@ static Dumpstate::RunStatus dumpstate() { * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport * with the caller. */ -static Dumpstate::RunStatus DumpstateDefault() { - // Invoking the following dumpsys calls before DumpTraces() to try and - // keep the system stats as close to its initial state as possible. - RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical); - +Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() { // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the // buffer. DoLogcat(); @@ -1634,6 +1630,7 @@ static void DumpstateRadioCommon() { // This method collects dumpsys for telephony debugging only static void DumpstateTelephonyOnly() { DurationReporter duration_reporter("DUMPSTATE"); + const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build(); DumpstateRadioCommon(); @@ -2353,11 +2350,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n", calling_uid, calling_package.c_str()); - if (CalledByApi()) { - // If the output needs to be copied over to the caller's fd, get user consent. - android::String16 package(calling_package.c_str()); - CheckUserConsent(calling_uid, package); - } // Redirect output if needed bool is_redirecting = options_->OutputToFile(); @@ -2500,13 +2492,23 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, PrintHeader(); if (options_->telephony_only) { + MaybeCheckUserConsent(calling_uid, calling_package); DumpstateTelephonyOnly(); DumpstateBoard(); } else if (options_->wifi_only) { + MaybeCheckUserConsent(calling_uid, calling_package); DumpstateWifiOnly(); } else { + // Invoking the critical dumpsys calls before DumpTraces() to try and + // keep the system stats as close to its initial state as possible. + RunDumpsysCritical(); + + // Run consent check only after critical dumpsys has finished -- so the consent + // isn't going to pollute the system state / logs. + MaybeCheckUserConsent(calling_uid, calling_package); + // Dump state for the default case. This also drops root. - RunStatus s = DumpstateDefault(); + RunStatus s = DumpstateDefaultAfterCritical(); if (s != RunStatus::OK) { if (s == RunStatus::USER_CONSENT_DENIED) { HandleUserConsentDenied(); @@ -2591,17 +2593,20 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, : RunStatus::OK; } -void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) { - if (calling_uid == AID_SHELL) { +void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) { + if (calling_uid == AID_SHELL || !CalledByApi()) { + // No need to get consent for shell triggered dumpstates, or not through + // bugreporting API (i.e. no fd to copy back). return; } consent_callback_ = new ConsentCallback(); const String16 incidentcompanion("incidentcompanion"); sp ics(defaultServiceManager()->getService(incidentcompanion)); + android::String16 package(calling_package.c_str()); if (ics != nullptr) { MYLOGD("Checking user consent via incidentcompanion service\n"); android::interface_cast(ics)->authorizeReport( - calling_uid, calling_package, String16(), String16(), + calling_uid, package, String16(), String16(), 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get()); } else { MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n"); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 831574d9aa..7d9b113f1e 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -486,7 +486,9 @@ class Dumpstate { private: RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package); - void CheckUserConsent(int32_t calling_uid, const android::String16& calling_package); + RunStatus DumpstateDefaultAfterCritical(); + + void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package); // Removes the in progress files output files (tmp file, zip/txt file, screenshot), // but leaves the log file alone. -- cgit v1.2.3-59-g8ed1b From 235c6679b8949db848004aa69e816413cd6808b6 Mon Sep 17 00:00:00 2001 From: Nandana Dutt Date: Thu, 14 Nov 2019 15:22:32 +0000 Subject: Make dumpstate logs less verbose * Combine some log lines * Log progress half as frequently BUG: 138254116 Change-Id: Ic372cc04ec3ccd582e3dfe272c6e979974837e60 --- cmds/dumpstate/dumpstate.cpp | 47 +++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 8400cdc69b..8371e3cf6f 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2060,12 +2060,12 @@ static void PrepareToWriteToFile() { ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get()) : ds.bugreport_internal_dir_.c_str(); MYLOGD( - "Bugreport dir: %s\n" - "Base name: %s\n" - "Suffix: %s\n" - "Log path: %s\n" - "Temporary path: %s\n" - "Screenshot path: %s\n", + "Bugreport dir: [%s] " + "Base name: [%s] " + "Suffix: [%s] " + "Log path: [%s] " + "Temporary path: [%s] " + "Screenshot path: [%s]\n", destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); @@ -2167,21 +2167,14 @@ static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOpt } static void LogDumpOptions(const Dumpstate::DumpOptions& options) { - MYLOGI("do_zip_file: %d\n", options.do_zip_file); - MYLOGI("do_add_date: %d\n", options.do_add_date); - MYLOGI("do_vibrate: %d\n", options.do_vibrate); - MYLOGI("use_socket: %d\n", options.use_socket); - MYLOGI("use_control_socket: %d\n", options.use_control_socket); - MYLOGI("do_fb: %d\n", options.do_fb); - MYLOGI("is_remote_mode: %d\n", options.is_remote_mode); - MYLOGI("show_header_only: %d\n", options.show_header_only); - MYLOGI("do_start_service: %d\n", options.do_start_service); - MYLOGI("telephony_only: %d\n", options.telephony_only); - MYLOGI("wifi_only: %d\n", options.wifi_only); - MYLOGI("do_progress_updates: %d\n", options.do_progress_updates); - MYLOGI("fd: %d\n", options.bugreport_fd.get()); - MYLOGI("bugreport_mode: %s\n", options.bugreport_mode.c_str()); - MYLOGI("args: %s\n", options.args.c_str()); + MYLOGI( + "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_fb: %d " + "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d " + "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s args: %s\n", + options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket, + options.do_fb, options.is_remote_mode, options.show_header_only, options.do_start_service, + options.telephony_only, options.wifi_only, options.do_progress_updates, + options.bugreport_fd.get(), options.bugreport_mode.c_str(), options.args.c_str()); } void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode, @@ -2374,8 +2367,6 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, id_ = ++last_id; android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id)); - MYLOGI("begin\n"); - if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) { MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno)); } else { @@ -2398,10 +2389,8 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } - MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s)\n", id_, options_->args.c_str(), - options_->bugreport_mode.c_str()); - - MYLOGI("bugreport format version: %s\n", version_.c_str()); + MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n", + id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str()); do_early_screenshot_ = options_->do_progress_updates; @@ -3498,8 +3487,8 @@ void Dumpstate::UpdateProgress(int32_t delta_sec) { } if (listener_ != nullptr) { - if (percent % 5 == 0) { - // We don't want to spam logcat, so only log multiples of 5. + if (percent % 10 == 0) { + // We don't want to spam logcat, so only log multiples of 10. MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent); } else { // stderr is ignored on normal invocations, but useful when calling -- cgit v1.2.3-59-g8ed1b From 95a1ed40c58a7631abd7a94468e523065cfb33f8 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 6 Dec 2019 12:25:11 -0800 Subject: Add shadow radius and corner radius crop to sf and transaction trace Bug: 136561771 Test: capture sf and transaction trace and check in winscope Test: atest SurfaceFlinger_test Change-Id: Ie2dce153ad8614657b6a2db43cbf7dd4912d8ddf --- cmds/surfacereplayer/proto/src/trace.proto | 5 ++++ cmds/surfacereplayer/replayer/Replayer.cpp | 8 +++++++ cmds/surfacereplayer/replayer/Replayer.h | 2 ++ services/surfaceflinger/Layer.cpp | 3 +++ services/surfaceflinger/SurfaceInterceptor.cpp | 11 +++++++++ services/surfaceflinger/SurfaceInterceptor.h | 1 + .../surfaceflinger/layerproto/LayerProtoParser.cpp | 8 ++++--- .../include/layerproto/LayerProtoParser.h | 2 ++ services/surfaceflinger/layerproto/layers.proto | 7 ++++++ .../tests/SurfaceInterceptor_test.cpp | 27 ++++++++++++++++++++++ 10 files changed, 71 insertions(+), 3 deletions(-) (limited to 'cmds') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 792ff91dfa..7f2f94912e 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -51,6 +51,7 @@ message SurfaceChange { RelativeParentChange relative_parent = 18; DetachChildrenChange detach_children = 19; ReparentChildrenChange reparent_children = 20; + ShadowRadiusChange shadow_radius = 22; } } @@ -199,3 +200,7 @@ message RelativeParentChange { message DetachChildrenChange { required bool detach_children = 1; } + +message ShadowRadiusChange { + required float radius = 1; +} \ No newline at end of file diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index a4a9b6a6f4..0d6c31ee2f 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -424,6 +424,9 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kDetachChildren: setDetachChildrenChange(transaction, change.id(), change.detach_children()); break; + case SurfaceChange::SurfaceChangeCase::kShadowRadius: + setShadowRadiusChange(transaction, change.id(), change.shadow_radius()); + break; default: status = 1; break; @@ -724,3 +727,8 @@ void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t, } t.reparentChildren(mLayers[id], mLayers[c.parent_id()]->getHandle()); } + +void Replayer::setShadowRadiusChange(SurfaceComposerClient::Transaction& t, + layer_id id, const ShadowRadiusChange& c) { + t.setShadowRadius(mLayers[id], c.radius()); +} diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 3b94618acb..b5478344cb 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -118,6 +118,8 @@ class Replayer { layer_id id, const DetachChildrenChange& c); void setReparentChildrenChange(SurfaceComposerClient::Transaction& t, layer_id id, const ReparentChildrenChange& c); + void setShadowRadiusChange(SurfaceComposerClient::Transaction& t, + layer_id id, const ShadowRadiusChange& c); void setDisplaySurface(SurfaceComposerClient::Transaction& t, display_id id, const DispSurfaceChange& dsc); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 35fc4be056..bb618ac0a3 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1935,6 +1935,9 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) [&]() { return layerInfo->mutable_source_bounds(); }); LayerProtoHelper::writeToProto(mScreenBounds, [&]() { return layerInfo->mutable_screen_bounds(); }); + LayerProtoHelper::writeToProto(getRoundedCornerState().cropRect, + [&]() { return layerInfo->mutable_corner_radius_crop(); }); + layerInfo->set_shadow_radius(mEffectiveShadowRadius); } } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 7e6c472d7f..5e8910a3c5 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -124,6 +124,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addRelativeParentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf), layer->mCurrentState.z); + addShadowRadiusLocked(transaction, layerId, layer->mCurrentState.shadowRadius); } void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, @@ -368,6 +369,13 @@ void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32 overrideChange->set_z(z); } +void SurfaceInterceptor::addShadowRadiusLocked(Transaction* transaction, int32_t layerId, + float shadowRadius) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + ShadowRadiusChange* overrideChange(change->mutable_shadow_radius()); + overrideChange->set_radius(shadowRadius); +} + void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state) { @@ -441,6 +449,9 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, addRelativeParentLocked(transaction, layerId, getLayerIdFromHandle(state.relativeLayerHandle), state.z); } + if (state.what & layer_state_t::eShadowRadiusChanged) { + addShadowRadiusLocked(transaction, layerId, state.shadowRadius); + } } void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 72b734b8fd..c6f9e8a9a1 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -165,6 +165,7 @@ private: void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached); void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z); + void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius); // Add display transactions to the trace DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index ef488bd881..ef27847e55 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -112,7 +112,8 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP outData.resize(dataStr.size()); memcpy(outData.data(), dataStr.data(), dataStr.size()); } - + layer.cornerRadiusCrop = generateFloatRect(layerProto.corner_radius_crop()); + layer.shadowRadius = layerProto.shadow_radius(); return layer; } @@ -307,8 +308,9 @@ std::string LayerProtoParser::Layer::to_string() const { first = false; result.append(metadata.itemToString(entry.first, ":")); } - result.append("}"); - + result.append("},"); + StringAppendF(&result, " cornerRadiusCrop=%s, ", cornerRadiusCrop.to_string().c_str()); + StringAppendF(&result, " shadowRadius=%.3f, ", shadowRadius); return result; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 54e02cadee..774b0e15f0 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -111,6 +111,8 @@ public: bool isProtected; float cornerRadius; LayerMetadata metadata; + LayerProtoParser::FloatRect cornerRadiusCrop; + float shadowRadius; std::string to_string() const; }; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index c7fbff37da..9ad9b91a9a 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -94,6 +94,13 @@ message LayerProto { FloatRectProto screen_bounds = 46; InputWindowInfoProto input_window_info = 47; + + // Crop used to draw the rounded corner. + FloatRectProto corner_radius_crop = 48; + + // length of the shadow to draw around the layer, it may be set on the + // layer or set by a parent layer. + float shadow_radius = 49; } message PositionProto { diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 59e9c00ae7..1fa426d14e 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -51,6 +51,7 @@ constexpr float ALPHA_UPDATE = 0.29f; constexpr float CORNER_RADIUS_UPDATE = 0.2f; constexpr float POSITION_UPDATE = 121; const Rect CROP_UPDATE(16, 16, 32, 32); +const float SHADOW_RADIUS_UPDATE = 35.0f; const String8 DISPLAY_NAME("SurfaceInterceptor Display Test"); constexpr auto TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface"; @@ -190,6 +191,7 @@ public: bool relativeParentUpdateFound(const SurfaceChange& change, bool found); bool detachChildrenUpdateFound(const SurfaceChange& change, bool found); bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found); + bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found); bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); // Find all of the updates in the single trace @@ -226,6 +228,7 @@ public: void relativeParentUpdate(Transaction&); void detachChildrenUpdate(Transaction&); void reparentChildrenUpdate(Transaction&); + void shadowRadiusUpdate(Transaction&); void surfaceCreation(Transaction&); void displayCreation(Transaction&); void displayDeletion(Transaction&); @@ -406,6 +409,10 @@ void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) { t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl->getHandle()); } +void SurfaceInterceptorTest::shadowRadiusUpdate(Transaction& t) { + t.setShadowRadius(mBGSurfaceControl, SHADOW_RADIUS_UPDATE); +} + void SurfaceInterceptorTest::displayCreation(Transaction&) { sp testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true); SurfaceComposerClient::destroyDisplay(testDisplay); @@ -435,6 +442,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate); runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate); runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate); + runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate); } void SurfaceInterceptorTest::surfaceCreation(Transaction&) { @@ -655,6 +663,17 @@ bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& ch return found; } +bool SurfaceInterceptorTest::shadowRadiusUpdateFound(const SurfaceChange& change, + bool foundShadowRadius) { + bool hasShadowRadius(change.shadow_radius().radius() == SHADOW_RADIUS_UPDATE); + if (hasShadowRadius && !foundShadowRadius) { + foundShadowRadius = true; + } else if (hasShadowRadius && foundShadowRadius) { + []() { FAIL(); }(); + } + return foundShadowRadius; +} + bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase) { bool foundUpdate = false; @@ -718,6 +737,9 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kDetachChildren: foundUpdate = detachChildrenUpdateFound(change, foundUpdate); break; + case SurfaceChange::SurfaceChangeCase::kShadowRadius: + foundUpdate = shadowRadiusUpdateFound(change, foundUpdate); + break; case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET: break; } @@ -920,6 +942,11 @@ TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) { SurfaceChange::SurfaceChangeCase::kDetachChildren); } +TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) { + captureTest(&SurfaceInterceptorTest::shadowRadiusUpdate, + SurfaceChange::SurfaceChangeCase::kShadowRadius); +} + TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) { captureTest(&SurfaceInterceptorTest::runAllUpdates, &SurfaceInterceptorTest::assertAllUpdatesFound); -- cgit v1.2.3-59-g8ed1b From 3b25ae153fb5aaa1d2f70600b45604e3665f0da2 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 25 Nov 2019 11:06:16 +0900 Subject: unique_fd is passed by value in AIDL interfaces FileDescriptor type in AIDL was translated into const unique_fd& in C++. Now, it is unique_fd, i.e. passed by value, to make it easier to keep it beyond the scope of the call. Bug: 144943748 Test: m Change-Id: Id0fead2717b1f6a3b9a1867efa8b588b59d3fbd2 --- cmds/dumpstate/DumpstateService.cpp | 4 ++-- cmds/dumpstate/DumpstateService.h | 4 ++-- cmds/dumpstate/tests/dumpstate_smoke_test.cpp | 12 ++++++++---- cmds/installd/InstalldNativeService.cpp | 2 +- cmds/installd/InstalldNativeService.h | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) (limited to 'cmds') diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index ccd74dbc74..87ea520f84 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -81,8 +81,8 @@ status_t DumpstateService::Start() { binder::Status DumpstateService::startBugreport(int32_t calling_uid, const std::string& calling_package, - const android::base::unique_fd& bugreport_fd, - const android::base::unique_fd& screenshot_fd, + android::base::unique_fd bugreport_fd, + android::base::unique_fd screenshot_fd, int bugreport_mode, const sp& listener) { MYLOGI("startBugreport() with mode: %d\n", bugreport_mode); diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h index 27954adbae..6dc0225f02 100644 --- a/cmds/dumpstate/DumpstateService.h +++ b/cmds/dumpstate/DumpstateService.h @@ -39,8 +39,8 @@ class DumpstateService : public BinderService, public BnDumpst status_t dump(int fd, const Vector& args) override; binder::Status startBugreport(int32_t calling_uid, const std::string& calling_package, - const android::base::unique_fd& bugreport_fd, - const android::base::unique_fd& screenshot_fd, int bugreport_mode, + android::base::unique_fd bugreport_fd, + android::base::unique_fd screenshot_fd, int bugreport_mode, const sp& listener) override; // No-op diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index f1884f8f5c..dac90d91b0 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -444,7 +444,7 @@ TEST_F(DumpstateBinderTest, Baseline) { sp listener(new DumpstateListener(dup(fileno(stdout)))); android::binder::Status status = - ds_binder->startBugreport(123, "com.dummy.package", bugreport_fd, screenshot_fd, + ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd), std::move(screenshot_fd), Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener); // startBugreport is an async call. Verify binder call succeeded first, then wait till listener // gets expected callbacks. @@ -480,7 +480,7 @@ TEST_F(DumpstateBinderTest, ServiceDies_OnInvalidInput) { // Call startBugreport with bad arguments. sp listener(new DumpstateListener(dup(fileno(stdout)))); android::binder::Status status = - ds_binder->startBugreport(123, "com.dummy.package", bugreport_fd, screenshot_fd, + ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd), std::move(screenshot_fd), 2000, // invalid bugreport mode listener); EXPECT_EQ(listener->getErrorCode(), IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT); @@ -501,20 +501,24 @@ TEST_F(DumpstateBinderTest, SimultaneousBugreportsNotAllowed) { // Prepare arguments unique_fd bugreport_fd(OpenForWrite("/data/local/tmp/tmp.zip")); + unique_fd bugreport_fd2(dup(bugreport_fd.get())); unique_fd screenshot_fd(OpenForWrite("/data/local/tmp/tmp.png")); + unique_fd screenshot_fd2(dup(screenshot_fd.get())); EXPECT_NE(bugreport_fd.get(), -1); + EXPECT_NE(bugreport_fd2.get(), -1); EXPECT_NE(screenshot_fd.get(), -1); + EXPECT_NE(screenshot_fd2.get(), -1); sp listener1(new DumpstateListener(dup(fileno(stdout)))); android::binder::Status status = - ds_binder->startBugreport(123, "com.dummy.package", bugreport_fd, screenshot_fd, + ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd), std::move(screenshot_fd), Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener1); EXPECT_TRUE(status.isOk()); // try to make another call to startBugreport. This should fail. sp listener2(new DumpstateListener(dup(fileno(stdout)))); - status = ds_binder->startBugreport(123, "com.dummy.package", bugreport_fd, screenshot_fd, + status = ds_binder->startBugreport(123, "com.dummy.package", std::move(bugreport_fd2), std::move(screenshot_fd2), Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, listener2); EXPECT_FALSE(status.isOk()); WaitTillExecutionComplete(listener2.get()); diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index e6e232ce2f..e3b3424c62 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -2401,7 +2401,7 @@ struct fsverity_measurement { #endif binder::Status InstalldNativeService::installApkVerity(const std::string& filePath, - const ::android::base::unique_fd& verityInputAshmem, int32_t contentSize) { + android::base::unique_fd verityInputAshmem, int32_t contentSize) { ENFORCE_UID(AID_SYSTEM); CHECK_ARGUMENT_PATH(filePath); std::lock_guard lock(mLock); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index ef91bf84be..fb0273098a 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -133,7 +133,7 @@ public: binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::unique_ptr& outputPath); binder::Status installApkVerity(const std::string& filePath, - const ::android::base::unique_fd& verityInput, int32_t contentSize); + android::base::unique_fd verityInput, int32_t contentSize); binder::Status assertFsverityRootHashMatches(const std::string& filePath, const std::vector& expectedHash); binder::Status reconcileSecondaryDexFile(const std::string& dexPath, -- cgit v1.2.3-59-g8ed1b From ff9d3ea0424f8be64ff78f52b5d352fa3aeb52c7 Mon Sep 17 00:00:00 2001 From: Ricky Wai Date: Mon, 18 Nov 2019 18:18:24 +0000 Subject: Create, mount and unmount app data mirror directory - When volume is ready, system/installd will create app data mirror, and bind mount it the actual CE storage for that app. - When a new private volume is mounted, DE mirror will be created and mounted. - When a private volume is unmounted, all users CE mirror will be unmounted and DE mirror will be unmounted also. - Fix inode createAppData() return a wrong inode number in 32bit system. Bug: 143937733 Bug: 145989852 Test: After reboot, all apps mirror CE directories are created and mounted Test: After adding a new private volume, new CE DE mirror for that volume are created and mounted. Test: After unmounting a private volume, that vol CE DE mirror are unmounted. Change-Id: I8a06ae8917e5f2c7f1f905b73ec934de7f1ee802 --- cmds/installd/InstalldNativeService.cpp | 105 ++++++++++++++++++++++++- cmds/installd/InstalldNativeService.h | 2 + cmds/installd/QuotaUtils.cpp | 4 + cmds/installd/binder/android/os/IInstalld.aidl | 2 + 4 files changed, 110 insertions(+), 3 deletions(-) (limited to 'cmds') diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index f5a53f19aa..2d99715fcf 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,9 @@ static constexpr const mode_t kRollbackFolderMode = 0700; static constexpr const char* kCpPath = "/system/bin/cp"; static constexpr const char* kXattrDefault = "user.default"; +static constexpr const char* kDataMirrorCePath = "/data_mirror/data_ce"; +static constexpr const char* kDataMirrorDePath = "/data_mirror/data_de"; + static constexpr const int MIN_RESTRICTED_HOME_SDK_VERSION = 24; // > M static constexpr const char* PKG_LIB_POSTFIX = "/lib"; @@ -99,6 +103,13 @@ static constexpr size_t kSha256Size = 32; static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode"; static constexpr const char* kFuseProp = "persist.sys.fuse"; +/** + * Property to control if app data isolation is enabled. + */ +static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation"; + +static std::atomic sAppDataIsolationEnabled(false); + namespace { constexpr const char* kDump = "android.permission.DUMP"; @@ -258,6 +269,8 @@ status_t InstalldNativeService::start() { sp ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); + sAppDataIsolationEnabled = android::base::GetBoolProperty( + kAppDataIsolationEnabledProperty, false); return android::OK; } @@ -450,9 +463,12 @@ binder::Status InstalldNativeService::createAppData(const std::unique_ptr(_aidl_return)) != 0) { - return error("Failed to get_path_inode for " + path); + if (_aidl_return != nullptr) { + ino_t result; + if (get_path_inode(path, &result) != 0) { + return error("Failed to get_path_inode for " + path); + } + *_aidl_return = static_cast(result); } } if (flags & FLAG_STORAGE_DE) { @@ -2613,6 +2629,89 @@ binder::Status InstalldNativeService::invalidateMounts() { return ok(); } +// Mount volume's CE and DE storage to mirror +binder::Status InstalldNativeService::onPrivateVolumeMounted( + const std::unique_ptr& uuid) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(uuid); + if (!sAppDataIsolationEnabled) { + return ok(); + } + if (!uuid) { + return error("Should not happen, mounting uuid == null"); + } + + const char* uuid_ = uuid->c_str(); + // Mount CE mirror + std::string mirrorVolCePath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_)); + std::lock_guard lock(mLock); + if (fs_prepare_dir(mirrorVolCePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { + return error("Failed to create CE mirror"); + } + auto cePath = StringPrintf("%s/user_ce", create_data_path(uuid_).c_str()); + if (TEMP_FAILURE_RETRY(mount(cePath.c_str(), mirrorVolCePath.c_str(), NULL, + MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) { + return error("Failed to mount " + mirrorVolCePath); + } + + // Mount DE mirror + std::string mirrorVolDePath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_)); + if (fs_prepare_dir(mirrorVolDePath.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) { + return error("Failed to create DE mirror"); + } + auto dePath = StringPrintf("%s/user_de", create_data_path(uuid_).c_str()); + if (TEMP_FAILURE_RETRY(mount(dePath.c_str(), mirrorVolDePath.c_str(), NULL, + MS_NOSUID | MS_NODEV | MS_NOATIME | MS_BIND | MS_NOEXEC, nullptr)) == -1) { + return error("Failed to mount " + mirrorVolDePath); + } + return ok(); +} + +// Unmount volume's CE and DE storage from mirror +binder::Status InstalldNativeService::onPrivateVolumeRemoved( + const std::unique_ptr& uuid) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(uuid); + if (!sAppDataIsolationEnabled) { + return ok(); + } + if (!uuid) { + // It happens when private volume failed to mount. + LOG(INFO) << "Ignore unmount uuid=null"; + return ok(); + } + const char* uuid_ = uuid->c_str(); + + binder::Status res = ok(); + + std::string mirrorCeVolPath(StringPrintf("%s/%s", kDataMirrorCePath, uuid_)); + std::string mirrorDeVolPath(StringPrintf("%s/%s", kDataMirrorDePath, uuid_)); + + // Unmount CE storage + std::lock_guard lock(mLock); + if (TEMP_FAILURE_RETRY(umount(mirrorCeVolPath.c_str())) != 0) { + if (errno != ENOENT) { + res = error(StringPrintf("Failed to umount %s %s", mirrorCeVolPath.c_str(), + strerror(errno))); + } + } + if (delete_dir_contents_and_dir(mirrorCeVolPath, true) != 0) { + res = error("Failed to delete " + mirrorCeVolPath); + } + + // Unmount DE storage + if (TEMP_FAILURE_RETRY(umount(mirrorDeVolPath.c_str())) != 0) { + if (errno != ENOENT) { + res = error(StringPrintf("Failed to umount %s %s", mirrorDeVolPath.c_str(), + strerror(errno))); + } + } + if (delete_dir_contents_and_dir(mirrorDeVolPath, true) != 0) { + res = error("Failed to delete " + mirrorDeVolPath); + } + return res; +} + std::string InstalldNativeService::findDataMediaPath( const std::unique_ptr& uuid, userid_t userid) { std::lock_guard lock(mMountsLock); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index ef91bf84be..432c2867ec 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -146,6 +146,8 @@ public: binder::Status invalidateMounts(); binder::Status isQuotaSupported(const std::unique_ptr& volumeUuid, bool* _aidl_return); + binder::Status onPrivateVolumeMounted(const std::unique_ptr& volumeUuid); + binder::Status onPrivateVolumeRemoved(const std::unique_ptr& volumeUuid); binder::Status prepareAppProfile(const std::string& packageName, int32_t userId, int32_t appId, const std::string& profileName, diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp index b238dd36e3..a71e01c943 100644 --- a/cmds/installd/QuotaUtils.cpp +++ b/cmds/installd/QuotaUtils.cpp @@ -61,6 +61,10 @@ bool InvalidateQuotaMounts() { std::getline(in, target, ' '); std::getline(in, ignored); + if (target.compare(0, 13, "/data_mirror/") == 0) { + continue; + } + if (source.compare(0, 11, "/dev/block/") == 0) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0, diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 6cc4bde2f1..fda6559bcb 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -109,6 +109,8 @@ interface IInstalld { int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags); void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, int userId, long ceSnapshotInode, int snapshotId, int storageFlags); + void onPrivateVolumeMounted(@nullable @utf8InCpp String volumeUuid); + void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid); void migrateLegacyObbData(); -- cgit v1.2.3-59-g8ed1b From 2a0a246603f9fe167d6f868667538d86092d8856 Mon Sep 17 00:00:00 2001 From: Felka Chang Date: Wed, 20 Nov 2019 14:20:40 +0800 Subject: add function to traversal the crates The system_server needs to traversal Context.getCratesDir() to get all of crates. But, system_server doesn't have the permission. system_server needs installd to traverse Context.getCratesDir(). The depth of traversal in Context.getCratesDir is 1. installd returns the list CrateMetadata. CrateMetadata contains the following information. * crateName: it is the folder name To add .gitigTo add .gitignore to collect the ignore file list. Test: atest \ CtsOsTestCases:android.os.storage.cts.CrateInfoTest \ CtsOsTestCases:android.os.storage.cts.StorageManagerCratesTest \ CtsOsTestCases:android.os.storage.cts.StorageStatsManagerTest Bug: 141660526 Change-Id: Iea5eee4606e4ff437edef617a1f8db93e37f51c4 --- cmds/installd/.gitignore | 2 + cmds/installd/Android.bp | 2 + cmds/installd/CrateManager.cpp | 129 +++++++++++++++++++++ cmds/installd/CrateManager.h | 82 +++++++++++++ cmds/installd/InstalldNativeService.cpp | 77 ++++++++++++ cmds/installd/InstalldNativeService.h | 10 ++ cmds/installd/binder/android/os/IInstalld.aidl | 8 ++ .../binder/android/os/storage/CrateMetadata.aidl | 41 +++++++ cmds/installd/utils.cpp | 9 ++ cmds/installd/utils.h | 4 + 10 files changed, 364 insertions(+) create mode 100644 cmds/installd/.gitignore create mode 100644 cmds/installd/CrateManager.cpp create mode 100644 cmds/installd/CrateManager.h create mode 100644 cmds/installd/binder/android/os/storage/CrateMetadata.aidl (limited to 'cmds') diff --git a/cmds/installd/.gitignore b/cmds/installd/.gitignore new file mode 100644 index 0000000000..abc921ce64 --- /dev/null +++ b/cmds/installd/.gitignore @@ -0,0 +1,2 @@ +# ignore the files generated by intellij +.idea diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp index 75dec371bc..8ff4dd862d 100644 --- a/cmds/installd/Android.bp +++ b/cmds/installd/Android.bp @@ -13,6 +13,7 @@ cc_defaults { srcs: [ "CacheItem.cpp", "CacheTracker.cpp", + "CrateManager.cpp", "InstalldNativeService.cpp", "QuotaUtils.cpp", "dexopt.cpp", @@ -163,6 +164,7 @@ filegroup { name: "installd_aidl", srcs: [ "binder/android/os/IInstalld.aidl", + "binder/android/os/storage/CrateMetadata.aidl", ], path: "binder", } diff --git a/cmds/installd/CrateManager.cpp b/cmds/installd/CrateManager.cpp new file mode 100644 index 0000000000..344aefbcbe --- /dev/null +++ b/cmds/installd/CrateManager.cpp @@ -0,0 +1,129 @@ +/* + * 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 "CrateManager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "utils.h" + +using android::base::StringPrintf; + +namespace android { +namespace installd { + +CrateManager::CrateManager(const char* uuid, userid_t userId, const std::string& packageName) { + mPackageName = packageName; + mRoot = create_data_user_ce_package_path(uuid, userId, (const char*)packageName.c_str()); + mCratedFoldersRoot = StringPrintf("%s/crates", mRoot.c_str()); +} + +CrateManager::~CrateManager() {} + +static std::string getValidatedCratedPath(std::string path) { + size_t pos = path.rfind("/"); + if (pos == std::string::npos) { + return path; + } + + return path.substr(pos + 1, path.length()); +} + +void CrateManager::traverseChildDir(const std::string& targetDir, + std::function& onVisitChildDir) { + char* argv[] = {(char*)targetDir.c_str(), nullptr}; + FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr); + if (fts == nullptr) { + PLOG(WARNING) << "Failed to fts_open " << targetDir; + return; + } + + FTSENT* p; + while ((p = fts_read(fts)) != nullptr) { + switch (p->fts_info) { + case FTS_D: + if (p->fts_level == 1) { + onVisitChildDir(p); + } + break; + default: + break; + } + + if (p->fts_level == 1) { + fts_set(fts, p, FTS_SKIP); + } + } + fts_close(fts); +} + +void CrateManager::traverseAllPackagesForUser( + const std::unique_ptr& uuid, userid_t userId, + std::function& onHandlingPackage) { + const char* uuid_ = uuid ? uuid->c_str() : nullptr; + + auto ce_path = create_data_user_ce_path(uuid_, userId); + traverseChildDir(ce_path, onHandlingPackage); +} + +void CrateManager::createCrate( + CratedFolder cratedFolder, + std::function&)>& onCreateCrate) { + const char* path = cratedFolder->fts_path; + if (path == nullptr || *path == '\0') { + return; + } + + std::unique_ptr crateMetadata = std::make_unique(); + crateMetadata->uid = cratedFolder->fts_statp->st_uid; + crateMetadata->packageName = mPackageName; + crateMetadata->id = getValidatedCratedPath(path); + + onCreateCrate(cratedFolder, crateMetadata); +} + +void CrateManager::traverseAllCrates(std::function&)>& onCreateCrate) { + std::function onVisitCrateDir = [&](FTSENT* cratedFolder) -> void { + createCrate(cratedFolder, onCreateCrate); + }; + traverseChildDir(mCratedFoldersRoot, onVisitCrateDir); +} + +#if CRATE_DEBUG +void CrateManager::dump(std::unique_ptr& CrateMetadata) { + LOG(DEBUG) << "CrateMetadata = {" + << "uid : \"" << CrateMetadata->uid + << "\", packageName : \"" << CrateMetadata->packageName + << "\", id : \"" << CrateMetadata->id + << "\"}"; +} +#endif + +} // namespace installd +} // namespace android diff --git a/cmds/installd/CrateManager.h b/cmds/installd/CrateManager.h new file mode 100644 index 0000000000..1776622d6a --- /dev/null +++ b/cmds/installd/CrateManager.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#ifndef ANDROID_INSTALLD_CRATE_INFO_MANAGER_H +#define ANDROID_INSTALLD_CRATE_INFO_MANAGER_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef CRATE_DEBUG +#define CRATE_DEBUG 1 +#endif + +namespace android { +namespace installd { + +using android::os::storage::CrateMetadata; + +/** + * The crated folder actually is a folder that is the first level child director. In order to + * distingish between the crated folder and the other FTSENT*, to define the type "CratedFolder" + * make the code easy to identify the difference. + */ +typedef FTSENT* CratedFolder; + +/** + * In order to give the users more fine-grained files controlling, the crate information can help + * applications' developers to show the more detail information to the users. The crate information + * include the Label, Expiration etc.. + */ +class CrateManager { +public: + CrateManager(const char* uuid, userid_t userId, const std::string& packageName); + ~CrateManager(); + + void traverseAllCrates(std::function&)>& onCreateCrate); + + static void traverseChildDir(const std::string& targetDir, + std::function& onVisitChildDir); + + static void traverseAllPackagesForUser( + const std::unique_ptr& uuid, + userid_t userId, + std::function& onHandlingPackage); + +#if CRATE_DEBUG + static void dump(std::unique_ptr& CrateMetadata); +#endif +private: + std::string mRoot; + std::string mCratedFoldersRoot; + std::string mPackageName; + + void createCrate( + CratedFolder cratedFolder, + std::function&)>& onCreateCrate); +}; + +} // namespace installd +} // namespace android + +#endif // ANDROID_INSTALLD_CRATE_INFO_MANAGER_H diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 8c8d94dafe..9e3520dd60 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -65,6 +65,7 @@ #include "view_compiler.h" #include "CacheTracker.h" +#include "CrateManager.h" #include "MatchExtensionGen.h" #include "QuotaUtils.h" @@ -2029,6 +2030,82 @@ binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr& uuid, + const std::vector& packageNames, int32_t userId, + std::unique_ptr>>* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(uuid); + for (const auto& packageName : packageNames) { + CHECK_ARGUMENT_PACKAGE_NAME(packageName); + } + std::lock_guard lock(mLock); + + auto retVector = std::make_unique>>(); + const char* uuid_ = uuid ? uuid->c_str() : nullptr; + + std::function &)> onCreateCrate = + [&](CratedFolder cratedFolder, std::unique_ptr &crateMetadata) -> void { + if (cratedFolder == nullptr) { + return; + } + retVector->push_back(std::move(crateMetadata)); + }; + + for (const auto& packageName : packageNames) { +#if CRATE_DEBUG + LOG(DEBUG) << "packageName = " << packageName; +#endif + auto crateManager = std::make_unique(uuid_, userId, packageName); + crateManager->traverseAllCrates(onCreateCrate); + } + +#if CRATE_DEBUG + LOG(WARNING) << "retVector->size() =" << retVector->size(); + for (auto iter = retVector->begin(); iter != retVector->end(); ++iter) { + CrateManager::dump(*iter); + } +#endif + + *_aidl_return = std::move(retVector); + return ok(); +} + +binder::Status InstalldNativeService::getUserCrates( + const std::unique_ptr& uuid, int32_t userId, + std::unique_ptr>>* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(uuid); + std::lock_guard lock(mLock); + + const char* uuid_ = uuid ? uuid->c_str() : nullptr; + auto retVector = std::make_unique>>(); + + std::function &)> onCreateCrate = + [&](CratedFolder cratedFolder, std::unique_ptr &crateMetadata) -> void { + if (cratedFolder == nullptr) { + return; + } + retVector->push_back(std::move(crateMetadata)); + }; + + std::function onHandingPackage = [&](FTSENT* packageDir) -> void { + auto crateManager = std::make_unique(uuid_, userId, packageDir->fts_name); + crateManager->traverseAllCrates(onCreateCrate); + }; + CrateManager::traverseAllPackagesForUser(uuid, userId, onHandingPackage); + +#if CRATE_DEBUG + LOG(DEBUG) << "retVector->size() =" << retVector->size(); + for (auto iter = retVector->begin(); iter != retVector->end(); ++iter) { + CrateManager::dump(*iter); + } +#endif + + *_aidl_return = std::move(retVector); + return ok(); +} + binder::Status InstalldNativeService::setAppQuota(const std::unique_ptr& uuid, int32_t userId, int32_t appId, int64_t cacheQuota) { ENFORCE_UID(AID_SYSTEM); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index fb0273098a..aff3733692 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -81,6 +81,16 @@ public: int32_t userId, int32_t flags, const std::vector& appIds, std::vector* _aidl_return); + binder::Status getAppCrates(const std::unique_ptr& uuid, + const std::vector& packageNames, + int32_t userId, + std::unique_ptr>>* + _aidl_return); + binder::Status getUserCrates( + const std::unique_ptr& uuid, int32_t userId, + std::unique_ptr>>* + _aidl_return); + binder::Status setAppQuota(const std::unique_ptr& uuid, int32_t userId, int32_t appId, int64_t cacheQuota); diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 6cc4bde2f1..f6a4530a9b 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -40,6 +40,14 @@ interface IInstalld { long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds); long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds); + @nullable + android.os.storage.CrateMetadata[] getAppCrates( + @nullable @utf8InCpp String uuid, in @utf8InCpp String[] packageNames, + int userId); + @nullable + android.os.storage.CrateMetadata[] getUserCrates( + @nullable @utf8InCpp String uuid, int userId); + void setAppQuota(@nullable @utf8InCpp String uuid, int userId, int appId, long cacheQuota); void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid, diff --git a/cmds/installd/binder/android/os/storage/CrateMetadata.aidl b/cmds/installd/binder/android/os/storage/CrateMetadata.aidl new file mode 100644 index 0000000000..bd6d12d9ce --- /dev/null +++ b/cmds/installd/binder/android/os/storage/CrateMetadata.aidl @@ -0,0 +1,41 @@ +/* + * 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. + */ +package android.os.storage; + +/** {@hide} */ +parcelable CrateMetadata { + /** + * To tell which uid the crate belong to. + *

Because installd query all of crates in specified userId, the install may return the list + * whose elements have the same crate id but different uid and package name. + * It needs to tell the caller the difference between these elements. + */ + int uid; + + /** + * To tell which the package the crate belong to. + *

Because installd query all of crates in specified uid, the install may return the list + * whose elements have the same uid and crate id but different package name. + * It needs to tell the caller the difference between these elements. + */ + @utf8InCpp String packageName; + + /** + * To tell the crate id that is the child directory/folder name in crates + * root. + */ + @utf8InCpp String id; +} diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 4eb1df0b2e..6012822f69 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -278,6 +278,15 @@ std::string create_data_dalvik_cache_path() { return "/data/dalvik-cache"; } +std::string create_system_user_ce_path(userid_t userId) { + return StringPrintf("%s/system_ce/%u", create_data_path(nullptr).c_str(), userId); +} + +std::string create_system_user_ce_package_path(userid_t userId, const char* package_name) { + check_package_name(package_name); + return StringPrintf("%s/%s", create_system_user_ce_path(userId).c_str(), package_name); +} + // Keep profile paths in sync with ActivityThread and LoadedApk. const std::string PROFILE_EXT = ".prof"; const std::string CURRENT_PROFILE_EXT = ".cur"; diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h index 6a420261a1..6a39adc41f 100644 --- a/cmds/installd/utils.h +++ b/cmds/installd/utils.h @@ -82,6 +82,10 @@ std::string create_data_misc_legacy_path(userid_t userid); std::string create_data_dalvik_cache_path(); +std::string create_system_user_ce_path(userid_t userId); + +std::string create_system_user_ce_package_path(userid_t userId, const char* package_name); + std::string create_primary_cur_profile_dir_path(userid_t userid); std::string create_primary_current_profile_package_dir_path( userid_t user, const std::string& package_name); -- cgit v1.2.3-59-g8ed1b From 97e818b99105e12bd75f100b41d5abf0cfd52e45 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 6 Jan 2020 13:40:51 -0800 Subject: vibrator: use package as name In order to provide a more descriptive name, and to be consistent with HIDL, the stable AIDL package names are switching from vintf-vibrator format to the package format (android.hardware.vibrator). Bug: N/A Test: all build time Change-Id: I60b85ed6c69190bcd287403408e31ea6643cee3e --- cmds/idlcli/Android.bp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmds') diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp index 08a31c1636..402767a426 100644 --- a/cmds/idlcli/Android.bp +++ b/cmds/idlcli/Android.bp @@ -15,6 +15,7 @@ cc_defaults { name: "idlcli-defaults", shared_libs: [ + "android.hardware.vibrator-ndk_platform", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", @@ -24,7 +25,6 @@ cc_defaults { "libhidlbase", "liblog", "libutils", - "vintf-vibrator-ndk_platform", ], cflags: [ "-DLOG_TAG=\"idlcli\"", -- cgit v1.2.3-59-g8ed1b From 718f9601c611f657fd872f84f27d5cc9aec533b4 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Sat, 9 Nov 2019 20:01:35 -0800 Subject: ui: Deduplicate rotation types Introduce ui::Rotation, replacing ISurfaceComposer::Rotation as well as DISPLAY_ORIENTATION_* and DisplayState::eOrientation* constants. libinput has widespread use of int32_t for orientation, so move DISPLAY_ORIENTATION_* to input/DisplayViewport.h for now. Bug: 144601064 Test: go/wm-smoke Test: screencap Change-Id: Ic4b8494e37c9d79c00d5b4be5eb88585f09efebf --- cmds/surfacereplayer/replayer/Replayer.cpp | 2 +- include/input/DisplayViewport.h | 13 +- include/input/TouchVideoFrame.h | 1 - libs/gui/ISurfaceComposer.cpp | 9 +- libs/gui/LayerState.cpp | 5 +- libs/gui/SurfaceComposerClient.cpp | 39 +++-- libs/gui/include/gui/ISurfaceComposer.h | 22 +-- libs/gui/include/gui/LayerState.h | 12 +- libs/gui/include/gui/SurfaceComposerClient.h | 33 ++-- libs/gui/tests/BLASTBufferQueue_test.cpp | 10 +- libs/gui/tests/Surface_test.cpp | 9 +- libs/input/TouchVideoFrame.cpp | 1 + libs/input/tests/TouchVideoFrame_test.cpp | 1 + libs/ui/include/ui/DisplayInfo.h | 11 +- libs/ui/include/ui/Rotation.h | 57 +++++++ libs/ui/include/ui/Transform.h | 39 +++-- libs/ui/include_vndk/ui/Rotation.h | 1 + opengl/tests/lib/WindowSurface.cpp | 3 +- services/surfaceflinger/BufferLayer.cpp | 6 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 75 +++------ services/surfaceflinger/DisplayDevice.h | 169 +++++++++------------ services/surfaceflinger/LayerRejecter.cpp | 2 +- services/surfaceflinger/RegionSamplingThread.cpp | 14 +- services/surfaceflinger/RenderArea.h | 16 +- services/surfaceflinger/SurfaceFlinger.cpp | 101 ++++++------ services/surfaceflinger/SurfaceFlinger.h | 10 +- services/surfaceflinger/SurfaceInterceptor.cpp | 8 +- services/surfaceflinger/tests/Credentials_test.cpp | 3 +- .../tests/LayerRenderTypeTransaction_test.cpp | 4 +- .../surfaceflinger/tests/LayerTransaction_test.cpp | 2 +- .../tests/unittests/DisplayTransactionTest.cpp | 12 +- .../tests/unittests/TestableSurfaceFlinger.h | 1 - 33 files changed, 329 insertions(+), 364 deletions(-) create mode 100644 libs/ui/include/ui/Rotation.h create mode 120000 libs/ui/include_vndk/ui/Rotation.h (limited to 'cmds') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 0d6c31ee2f..675aad6f81 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -606,7 +606,7 @@ void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t, pc.viewport().bottom()); Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom()); - t.setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame); + t.setDisplayProjection(mDisplays[id], ui::toRotation(pc.orientation()), viewport, frame); } status_t Replayer::createSurfaceControl( diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index fa456bb213..610062697c 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -17,16 +17,23 @@ #ifndef _LIBINPUT_DISPLAY_VIEWPORT_H #define _LIBINPUT_DISPLAY_VIEWPORT_H +#include +#include + #include -#include #include -#include -#include using android::base::StringPrintf; namespace android { +enum { + DISPLAY_ORIENTATION_0 = 0, + DISPLAY_ORIENTATION_90 = 1, + DISPLAY_ORIENTATION_180 = 2, + DISPLAY_ORIENTATION_270 = 3 +}; + /** * Describes the different type of viewports supported by input flinger. * Keep in sync with values in InputManagerService.java. diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h index b49c623204..4fa2f86dc1 100644 --- a/include/input/TouchVideoFrame.h +++ b/include/input/TouchVideoFrame.h @@ -19,7 +19,6 @@ #include #include -#include #include namespace android { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ab4d51e3cb..d34fe3b0ba 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -110,10 +110,10 @@ public: } virtual status_t captureScreen(const sp& display, sp* outBuffer, - bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - ISurfaceComposer::Rotation rotation, bool captureSecureLayers) { + ui::Rotation rotation, bool captureSecureLayers) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -1214,8 +1214,7 @@ status_t BnSurfaceComposer::onTransact( bool capturedSecureLayers = false; status_t res = captureScreen(display, &outBuffer, capturedSecureLayers, reqDataspace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, - useIdentityTransform, - static_cast(rotation), + useIdentityTransform, ui::toRotation(rotation), captureSecureLayers); reply->writeInt32(res); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e033f93286..a7c4f4670a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -203,7 +203,6 @@ status_t ComposerState::read(const Parcel& input) { DisplayState::DisplayState() : what(0), layerStack(0), - orientation(eOrientationDefault), viewport(Rect::EMPTY_RECT), frame(Rect::EMPTY_RECT), width(0), @@ -215,7 +214,7 @@ status_t DisplayState::write(Parcel& output) const { output.writeStrongBinder(IInterface::asBinder(surface)); output.writeUint32(what); output.writeUint32(layerStack); - output.writeUint32(orientation); + output.writeUint32(toRotationInt(orientation)); output.write(viewport); output.write(frame); output.writeUint32(width); @@ -228,7 +227,7 @@ status_t DisplayState::read(const Parcel& input) { surface = interface_cast(input.readStrongBinder()); what = input.readUint32(); layerStack = input.readUint32(); - orientation = input.readUint32(); + orientation = ui::toRotation(input.readUint32()); input.read(viewport); input.read(frame); width = input.readUint32(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index f378fc5ef6..1dac70a950 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1399,9 +1399,9 @@ void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp& } void SurfaceComposerClient::Transaction::setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect) { + ui::Rotation orientation, + const Rect& layerStackRect, + const Rect& displayRect) { DisplayState& s(getDisplayState(token)); s.orientation = orientation; s.viewport = layerStackRect; @@ -1773,28 +1773,26 @@ status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColo // ---------------------------------------------------------------------------- -status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, +status_t ScreenshotClient::capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, bool captureSecureLayers, + ui::Rotation rotation, bool captureSecureLayers, sp* outBuffer, bool& outCapturedSecureLayers) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; - status_t ret = - s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace, - reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, - static_cast(rotation), - captureSecureLayers); + status_t ret = s->captureScreen(display, outBuffer, outCapturedSecureLayers, reqDataSpace, + reqPixelFormat, sourceCrop, reqWidth, reqHeight, + useIdentityTransform, rotation, captureSecureLayers); if (ret != NO_ERROR) { return ret; } return ret; } -status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, +status_t ScreenshotClient::capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, sp* outBuffer) { + ui::Rotation rotation, sp* outBuffer) { bool ignored; return capture(display, reqDataSpace, reqPixelFormat, sourceCrop, reqWidth, reqHeight, useIdentityTransform, rotation, false, outBuffer, ignored); @@ -1807,9 +1805,8 @@ status_t ScreenshotClient::capture(uint64_t displayOrLayerStack, ui::Dataspace* return s->captureScreen(displayOrLayerStack, outDataspace, outBuffer); } -status_t ScreenshotClient::captureLayers(const sp& layerHandle, - const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, +status_t ScreenshotClient::captureLayers(const sp& layerHandle, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); if (s == nullptr) return NO_INIT; @@ -1819,8 +1816,8 @@ status_t ScreenshotClient::captureLayers(const sp& layerHandle, } status_t ScreenshotClient::captureChildLayers( - const sp& layerHandle, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + const sp& layerHandle, ui::Dataspace reqDataSpace, ui::PixelFormat reqPixelFormat, + const Rect& sourceCrop, const std::unordered_set, ISurfaceComposer::SpHash>& excludeHandles, float frameScale, sp* outBuffer) { sp s(ComposerService::getComposerService()); @@ -1830,5 +1827,5 @@ status_t ScreenshotClient::captureChildLayers( excludeHandles, frameScale, true /* childrenOnly */); return ret; } -// ---------------------------------------------------------------------------- -}; // namespace android + +} // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 998973c4dc..9804c92d0c 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -81,13 +82,6 @@ public: eEarlyWakeup = 0x04 }; - enum Rotation { - eRotateNone = 0, - eRotate90 = 1, - eRotate180 = 2, - eRotate270 = 3 - }; - enum VsyncSource { eVsyncSourceApp = 0, eVsyncSourceSurfaceFlinger = 1 @@ -249,10 +243,10 @@ public: * it) around its center. */ virtual status_t captureScreen(const sp& display, sp* outBuffer, - bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - Rotation rotation = eRotateNone, + ui::Rotation rotation = ui::ROTATION_0, bool captureSecureLayers = false) = 0; /** * Capture the specified screen. This requires READ_FRAME_BUFFER @@ -276,8 +270,9 @@ public: * it) around its center. */ virtual status_t captureScreen(const sp& display, sp* outBuffer, - Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, Rotation rotation = eRotateNone) { + const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, + bool useIdentityTransform, + ui::Rotation rotation = ui::ROTATION_0) { bool outIgnored; return captureScreen(display, outBuffer, outIgnored, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, sourceCrop, reqWidth, reqHeight, @@ -301,8 +296,7 @@ public: */ virtual status_t captureLayers( const sp& layerHandleBinder, sp* outBuffer, - const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat, - const Rect& sourceCrop, + ui::Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, const std::unordered_set, SpHash>& excludeHandles, float frameScale = 1.0, bool childrenOnly = false) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index c2b5119242..fb186396a6 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace android { @@ -217,15 +218,6 @@ struct ComposerState { }; struct DisplayState { - enum { - eOrientationDefault = 0, - eOrientation90 = 1, - eOrientation180 = 2, - eOrientation270 = 3, - eOrientationUnchanged = 4, - eOrientationSwapMask = 0x01 - }; - enum { eSurfaceChanged = 0x01, eLayerStackChanged = 0x02, @@ -252,7 +244,7 @@ struct DisplayState { // 0, layers will be scaled by a factor of 2 and translated by (20, 10). // When orientation is 1, layers will be additionally rotated by 90 // degrees around the origin clockwise and translated by (W, 0). - uint32_t orientation; + ui::Rotation orientation = ui::ROTATION_0; Rect viewport; Rect frame; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 86468a49f3..44f29eaa6f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -531,10 +532,8 @@ public: * mapped to. displayRect is specified post-orientation, that is * it uses the orientation seen by the end-user. */ - void setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect); + void setDisplayProjection(const sp& token, ui::Rotation orientation, + const Rect& layerStackRect, const Rect& displayRect); void setDisplaySize(const sp& token, uint32_t width, uint32_t height); void setAnimationTransaction(); void setEarlyWakeup(); @@ -548,10 +547,8 @@ public: static status_t getHdrCapabilities(const sp& display, HdrCapabilities* outCapabilities); - static void setDisplayProjection(const sp& token, - uint32_t orientation, - const Rect& layerStackRect, - const Rect& displayRect); + static void setDisplayProjection(const sp& token, ui::Rotation orientation, + const Rect& layerStackRect, const Rect& displayRect); inline sp getClient() { return mClient; } @@ -583,23 +580,23 @@ class ScreenshotClient { public: // if cropping isn't required, callers may pass in a default Rect, e.g.: // capture(display, producer, Rect(), reqWidth, ...); - static status_t capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + static status_t capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, bool captureSecureLayers, + ui::Rotation rotation, bool captureSecureLayers, sp* outBuffer, bool& outCapturedSecureLayers); - static status_t capture(const sp& display, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + static status_t capture(const sp& display, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, - uint32_t rotation, sp* outBuffer); + ui::Rotation rotation, sp* outBuffer); static status_t capture(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp* outBuffer); - static status_t captureLayers(const sp& layerHandle, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + static status_t captureLayers(const sp& layerHandle, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, float frameScale, sp* outBuffer); static status_t captureChildLayers( - const sp& layerHandle, const ui::Dataspace reqDataSpace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, + const sp& layerHandle, ui::Dataspace reqDataSpace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, const std::unordered_set, ISurfaceComposer::SpHash>& excludeHandles, float frameScale, sp* outBuffer); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 0f618f181c..85cf62f44f 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -127,7 +127,7 @@ protected: ASSERT_EQ(NO_ERROR, igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &qbOutput)); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); producer = igbProducer; } @@ -266,7 +266,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); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); @@ -349,7 +349,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); // capture screen and verify that it is red @@ -410,7 +410,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { NATIVE_WINDOW_SCALING_MODE_SCALE_CROP, 0, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); // capture screen and verify that it is red @@ -456,7 +456,7 @@ public: NATIVE_WINDOW_SCALING_MODE_FREEZE, tr, Fence::NO_FENCE); igbProducer->queueBuffer(slot, input, &qbOutput); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, qbOutput.transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint); adapter.waitForCallbacks(); bool capturedSecureLayers; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 0445755ade..f9540b2a41 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -742,11 +742,10 @@ public: status_t setActiveColorMode(const sp& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureScreen(const sp& /*display*/, sp* /*outBuffer*/, - bool& /* outCapturedSecureLayers */, - const ui::Dataspace /*reqDataspace*/, - const ui::PixelFormat /*reqPixelFormat*/, Rect /*sourceCrop*/, + bool& /*outCapturedSecureLayers*/, ui::Dataspace /*reqDataspace*/, + ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, - bool /*useIdentityTransform*/, Rotation /*rotation*/, + bool /*useIdentityTransform*/, ui::Rotation, bool /*captureSecureLayers*/) override { return NO_ERROR; } @@ -766,7 +765,7 @@ public: } virtual status_t captureLayers( const sp& /*parentHandle*/, sp* /*outBuffer*/, - const ui::Dataspace /*reqDataspace*/, const ui::PixelFormat /*reqPixelFormat*/, + ui::Dataspace /*reqDataspace*/, ui::PixelFormat /*reqPixelFormat*/, const Rect& /*sourceCrop*/, const std::unordered_set, ISurfaceComposer::SpHash>& /*excludeHandles*/, diff --git a/libs/input/TouchVideoFrame.cpp b/libs/input/TouchVideoFrame.cpp index 8a4298a36f..145b4ae03b 100644 --- a/libs/input/TouchVideoFrame.cpp +++ b/libs/input/TouchVideoFrame.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include namespace android { diff --git a/libs/input/tests/TouchVideoFrame_test.cpp b/libs/input/tests/TouchVideoFrame_test.cpp index 815424ee31..1ec935859d 100644 --- a/libs/input/tests/TouchVideoFrame_test.cpp +++ b/libs/input/tests/TouchVideoFrame_test.cpp @@ -16,6 +16,7 @@ #include +#include #include namespace android { diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h index 07722104de..38f8d6be02 100644 --- a/libs/ui/include/ui/DisplayInfo.h +++ b/libs/ui/include/ui/DisplayInfo.h @@ -20,6 +20,7 @@ #include #include +#include #include namespace android { @@ -33,7 +34,7 @@ struct DisplayInfo { float ydpi{0}; float fps{0}; float density{0}; - uint8_t orientation{0}; + ui::Rotation orientation{ui::ROTATION_0}; bool secure{false}; nsecs_t appVsyncOffset{0}; nsecs_t presentationDeadline{0}; @@ -42,14 +43,6 @@ struct DisplayInfo { uint32_t layerStack{NO_LAYER_STACK}; }; -/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */ -enum { - DISPLAY_ORIENTATION_0 = 0, - DISPLAY_ORIENTATION_90 = 1, - DISPLAY_ORIENTATION_180 = 2, - DISPLAY_ORIENTATION_270 = 3 -}; - } // namespace android #endif // ANDROID_COMPOSER_DISPLAY_INFO_H diff --git a/libs/ui/include/ui/Rotation.h b/libs/ui/include/ui/Rotation.h new file mode 100644 index 0000000000..89008f6694 --- /dev/null +++ b/libs/ui/include/ui/Rotation.h @@ -0,0 +1,57 @@ +/* + * 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 + +namespace android::ui { + +enum class Rotation { Rotation0 = 0, Rotation90 = 1, Rotation180 = 2, Rotation270 = 3 }; + +// Equivalent to Surface.java constants. +constexpr auto ROTATION_0 = Rotation::Rotation0; +constexpr auto ROTATION_90 = Rotation::Rotation90; +constexpr auto ROTATION_180 = Rotation::Rotation180; +constexpr auto ROTATION_270 = Rotation::Rotation270; + +constexpr auto toRotation(std::underlying_type_t rotation) { + return static_cast(rotation); +} + +constexpr auto toRotationInt(Rotation rotation) { + return static_cast>(rotation); +} + +constexpr Rotation operator+(Rotation lhs, Rotation rhs) { + constexpr auto N = toRotationInt(ROTATION_270) + 1; + return toRotation((toRotationInt(lhs) + toRotationInt(rhs)) % N); +} + +constexpr const char* toCString(Rotation rotation) { + switch (rotation) { + case ROTATION_0: + return "ROTATION_0"; + case ROTATION_90: + return "ROTATION_90"; + case ROTATION_180: + return "ROTATION_180"; + case ROTATION_270: + return "ROTATION_270"; + } +} + +} // namespace android::ui diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h index de07684d79..c6bb598d7f 100644 --- a/libs/ui/include/ui/Transform.h +++ b/libs/ui/include/ui/Transform.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef ANDROID_TRANSFORM_H -#define ANDROID_TRANSFORM_H +#pragma once #include #include @@ -28,6 +27,7 @@ #include #include #include +#include namespace android { @@ -42,13 +42,13 @@ public: explicit Transform(uint32_t orientation, int w = 0, int h = 0); ~Transform(); - enum orientation_flags { - ROT_0 = 0x00000000, - FLIP_H = HAL_TRANSFORM_FLIP_H, - FLIP_V = HAL_TRANSFORM_FLIP_V, - ROT_90 = HAL_TRANSFORM_ROT_90, - ROT_180 = FLIP_H|FLIP_V, - ROT_270 = ROT_180|ROT_90, + enum RotationFlags : uint32_t { + ROT_0 = 0, + FLIP_H = HAL_TRANSFORM_FLIP_H, + FLIP_V = HAL_TRANSFORM_FLIP_V, + ROT_90 = HAL_TRANSFORM_ROT_90, + ROT_180 = FLIP_H | FLIP_V, + ROT_270 = ROT_180 | ROT_90, ROT_INVALID = 0x80 }; @@ -100,6 +100,8 @@ public: void dump(std::string& result, const char* name) const; void dump(const char* name) const; + static RotationFlags toRotationFlags(Rotation); + private: struct mat33 { vec3 v[3]; @@ -117,13 +119,26 @@ private: mutable uint32_t mType; }; -static inline void PrintTo(const Transform& t, ::std::ostream* os) { +inline void PrintTo(const Transform& t, ::std::ostream* os) { std::string out; t.dump(out, "ui::Transform"); *os << out; } +inline Transform::RotationFlags Transform::toRotationFlags(Rotation rotation) { + switch (rotation) { + case ROTATION_0: + return ROT_0; + case ROTATION_90: + return ROT_90; + case ROTATION_180: + return ROT_180; + case ROTATION_270: + return ROT_270; + default: + return ROT_INVALID; + } +} + } // namespace ui } // namespace android - -#endif /* ANDROID_TRANSFORM_H */ diff --git a/libs/ui/include_vndk/ui/Rotation.h b/libs/ui/include_vndk/ui/Rotation.h new file mode 120000 index 0000000000..d84fb4b46b --- /dev/null +++ b/libs/ui/include_vndk/ui/Rotation.h @@ -0,0 +1 @@ +../../include/ui/Rotation.h \ No newline at end of file diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp index a0bd4e2409..4dcc1ca4db 100644 --- a/opengl/tests/lib/WindowSurface.cpp +++ b/opengl/tests/lib/WindowSurface.cpp @@ -48,8 +48,7 @@ WindowSurface::WindowSurface() { } uint32_t width, height; - if (mainDpyInfo.orientation != DISPLAY_ORIENTATION_0 && - mainDpyInfo.orientation != DISPLAY_ORIENTATION_180) { + if (mainDpyInfo.orientation != ui::ROTATION_0 && mainDpyInfo.orientation != ui::ROTATION_180) { // rotated width = mainDpyInfo.h; height = mainDpyInfo.w; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index bdecdb78d0..3b1b796076 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -207,7 +207,7 @@ std::optional BufferLayer::prepareClientComposition * the code below applies the primary display's inverse transform to * the texture transform */ - uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags(); mat4 tr = inverseOrientation(transform); /** @@ -622,7 +622,7 @@ Rect BufferLayer::getBufferSize(const State& s) const { } if (getTransformToDisplayInverse()) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -658,7 +658,7 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const } if (getTransformToDisplayInverse()) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 1e471e53ff..170956ca80 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -468,7 +468,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } if (s.transformToDisplayInverse) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 84ec597d2f..e0dc3e7751 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -41,12 +41,7 @@ namespace android { using android::base::StringAppendF; -/* - * Initialize the display to the specified values. - * - */ - -uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0; +ui::Transform::RotationFlags DisplayDevice::sPrimaryDisplayRotationFlags = ui::Transform::ROT_0; DisplayDeviceCreationArgs::DisplayDeviceCreationArgs(const sp& flinger, const wp& displayToken, @@ -57,13 +52,11 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) : mFlinger(args.flinger), mDisplayToken(args.displayToken), mSequenceId(args.sequenceId), - mDisplayInstallOrientation(args.displayInstallOrientation), + mIsVirtual(args.isVirtual), mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay( compositionengine::DisplayCreationArgs{args.isVirtual, args.displayId, args.powerAdvisor})}, - mIsVirtual(args.isVirtual), - mOrientation(), - mActiveConfig(0), + mPhysicalOrientation(args.physicalOrientation), mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; mCompositionDisplay->createRenderSurface( @@ -88,7 +81,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) setPowerMode(args.initialPowerMode); // initialize the display orientation transform. - setProjection(DisplayState::eOrientationDefault, Rect::INVALID_RECT, Rect::INVALID_RECT); + setProjection(ui::ROTATION_0, Rect::INVALID_RECT, Rect::INVALID_RECT); } DisplayDevice::~DisplayDevice() = default; @@ -131,7 +124,6 @@ bool DisplayDevice::isPoweredOn() const { return mPowerMode != HWC_POWER_MODE_OFF; } -// ---------------------------------------------------------------------------- void DisplayDevice::setActiveConfig(HwcConfigIndexType mode) { mActiveConfig = mode; } @@ -140,53 +132,19 @@ HwcConfigIndexType DisplayDevice::getActiveConfig() const { return mActiveConfig; } -// ---------------------------------------------------------------------------- - ui::Dataspace DisplayDevice::getCompositionDataSpace() const { return mCompositionDisplay->getState().dataspace; } -// ---------------------------------------------------------------------------- - void DisplayDevice::setLayerStack(uint32_t stack) { mCompositionDisplay->setLayerStackFilter(stack, isPrimary()); } -// ---------------------------------------------------------------------------- - -uint32_t DisplayDevice::displayStateOrientationToTransformOrientation(int orientation) { - switch (orientation) { - case DisplayState::eOrientationDefault: - return ui::Transform::ROT_0; - case DisplayState::eOrientation90: - return ui::Transform::ROT_90; - case DisplayState::eOrientation180: - return ui::Transform::ROT_180; - case DisplayState::eOrientation270: - return ui::Transform::ROT_270; - default: - return ui::Transform::ROT_INVALID; - } -} - -status_t DisplayDevice::orientationToTransfrom(int orientation, int w, int h, ui::Transform* tr) { - uint32_t flags = displayStateOrientationToTransformOrientation(orientation); - if (flags == ui::Transform::ROT_INVALID) { - return BAD_VALUE; - } - tr->set(flags, w, h); - return NO_ERROR; -} - void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) { mCompositionDisplay->setBounds(ui::Size(newWidth, newHeight)); } -void DisplayDevice::setProjection(int orientation, - const Rect& newViewport, const Rect& newFrame) { - Rect viewport(newViewport); - Rect frame(newFrame); - +void DisplayDevice::setProjection(ui::Rotation orientation, Rect viewport, Rect frame) { mOrientation = orientation; const Rect& displayBounds = getCompositionDisplay()->getState().bounds; @@ -194,7 +152,10 @@ void DisplayDevice::setProjection(int orientation, const int h = displayBounds.height(); ui::Transform R; - DisplayDevice::orientationToTransfrom(orientation, w, h, &R); + if (const auto flags = ui::Transform::toRotationFlags(orientation); + flags != ui::Transform::ROT_INVALID) { + R.set(flags, w, h); + } if (!frame.isValid()) { // the destination frame can be invalid if it has never been set, @@ -236,9 +197,10 @@ void DisplayDevice::setProjection(int orientation, // need to take care of primary display rotation for globalTransform // for case if the panel is not installed aligned with device orientation if (isPrimary()) { - DisplayDevice::orientationToTransfrom( - (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1), - w, h, &R); + if (const auto flags = ui::Transform::toRotationFlags(orientation + mPhysicalOrientation); + flags != ui::Transform::ROT_INVALID) { + R.set(flags, w, h); + } } // The viewport and frame are both in the logical orientation. @@ -258,19 +220,18 @@ void DisplayDevice::setProjection(int orientation, uint32_t transformOrientation; if (isPrimary()) { - sPrimaryDisplayOrientation = displayStateOrientationToTransformOrientation(orientation); - transformOrientation = displayStateOrientationToTransformOrientation( - (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1)); + sPrimaryDisplayRotationFlags = ui::Transform::toRotationFlags(orientation); + transformOrientation = ui::Transform::toRotationFlags(orientation + mPhysicalOrientation); } else { - transformOrientation = displayStateOrientationToTransformOrientation(orientation); + transformOrientation = ui::Transform::toRotationFlags(orientation); } getCompositionDisplay()->setProjection(globalTransform, transformOrientation, frame, viewport, scissor, needsFiltering); } -uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() { - return sPrimaryDisplayOrientation; +ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() { + return sPrimaryDisplayRotationFlags; } std::string DisplayDevice::getDebugName() const { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 79a118571e..605e7c8ab4 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef ANDROID_DISPLAY_DEVICE_H -#define ANDROID_DISPLAY_DEVICE_H +#pragma once #include @@ -83,14 +82,17 @@ public: int getWidth() const; int getHeight() const; - int getInstallOrientation() const { return mDisplayInstallOrientation; } void setLayerStack(uint32_t stack); void setDisplaySize(const int newWidth, const int newHeight); - void setProjection(int orientation, const Rect& viewport, const Rect& frame); - int getOrientation() const { return mOrientation; } - static uint32_t getPrimaryDisplayOrientationTransform(); + void setProjection(ui::Rotation orientation, Rect viewport, Rect frame); + + ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; } + ui::Rotation getOrientation() const { return mOrientation; } + + static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags(); + const ui::Transform& getTransform() const; const Rect& getViewport() const; const Rect& getFrame() const; @@ -156,37 +158,21 @@ public: void dump(std::string& result) const; private: - /* - * Constants, set during initialization - */ const sp mFlinger; const wp mDisplayToken; const int32_t mSequenceId; + const bool mIsVirtual; - const int mDisplayInstallOrientation; const std::shared_ptr mCompositionDisplay; std::string mDisplayName; - const bool mIsVirtual; - /* - * Can only accessed from the main thread, these members - * don't need synchronization. - */ - - /* - * Transaction state - */ - static uint32_t displayStateOrientationToTransformOrientation(int orientation); - static status_t orientationToTransfrom(int orientation, - int w, int h, ui::Transform* tr); + const ui::Rotation mPhysicalOrientation; + ui::Rotation mOrientation = ui::ROTATION_0; - int mOrientation; - static uint32_t sPrimaryDisplayOrientation; + static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags; - // Current power mode - int mPowerMode; - // Current active config + int mPowerMode = HWC_POWER_MODE_OFF; HwcConfigIndexType mActiveConfig; // TODO(b/74619554): Remove special cases for primary display. @@ -202,7 +188,7 @@ struct DisplayDeviceState { uint32_t layerStack = NO_LAYER_STACK; Rect viewport; Rect frame; - uint8_t orientation = 0; + ui::Rotation orientation = ui::ROTATION_0; uint32_t width = 0; uint32_t height = 0; std::string displayName; @@ -227,7 +213,7 @@ struct DisplayDeviceCreationArgs { bool isSecure{false}; sp nativeWindow; sp displaySurface; - int displayInstallOrientation{DisplayState::eOrientationDefault}; + ui::Rotation physicalOrientation{ui::ROTATION_0}; bool hasWideColorGamut{false}; HdrCapabilities hdrCapabilities; int32_t supportedPerFrameMetadata{0}; @@ -239,31 +225,33 @@ struct DisplayDeviceCreationArgs { class DisplayRenderArea : public RenderArea { public: - DisplayRenderArea(const sp device, - ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) - : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(), - device->getCompositionDataSpace(), rotation) {} - DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqWidth, - uint32_t reqHeight, ui::Dataspace reqDataSpace, - ui::Transform::orientation_flags rotation, bool allowSecureLayers = true) + DisplayRenderArea(const sp& display, + RotationFlags rotation = ui::Transform::ROT_0) + : DisplayRenderArea(display, display->getBounds(), display->getWidth(), + display->getHeight(), display->getCompositionDataSpace(), rotation) {} + + DisplayRenderArea(sp display, const Rect& sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, + bool allowSecureLayers = true) : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, - device->getViewport(), - getDisplayRotation(rotation, device->getInstallOrientation())), - mDevice(device), + display->getViewport(), + applyInversePhysicalOrientation(rotation, + display->getPhysicalOrientation())), + mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} - const ui::Transform& getTransform() const override { return mDevice->getTransform(); } - Rect getBounds() const override { return mDevice->getBounds(); } - int getHeight() const override { return mDevice->getHeight(); } - int getWidth() const override { return mDevice->getWidth(); } - bool isSecure() const override { return mAllowSecureLayers && mDevice->isSecure(); } - const sp getDisplayDevice() const override { return mDevice; } + const ui::Transform& getTransform() const override { return mDisplay->getTransform(); } + Rect getBounds() const override { return mDisplay->getBounds(); } + int getHeight() const override { return mDisplay->getHeight(); } + int getWidth() const override { return mDisplay->getWidth(); } + bool isSecure() const override { return mAllowSecureLayers && mDisplay->isSecure(); } + sp getDisplayDevice() const override { return mDisplay; } bool needsFiltering() const override { // check if the projection from the logical display to the physical // display needs filtering - if (mDevice->needsFiltering()) { + if (mDisplay->needsFiltering()) { return true; } @@ -281,7 +269,7 @@ public: Rect getSourceCrop() const override { // use the projected display viewport by default. if (mSourceCrop.isEmpty()) { - return mDevice->getScissor(); + return mDisplay->getScissor(); } // Recompute the device transformation for the source crop. @@ -289,27 +277,13 @@ public: ui::Transform translatePhysical; ui::Transform translateLogical; ui::Transform scale; - const Rect& viewport = mDevice->getViewport(); - const Rect& scissor = mDevice->getScissor(); - const Rect& frame = mDevice->getFrame(); - - const int orientation = mDevice->getInstallOrientation(); - // Install orientation is transparent to the callers. Apply it now. - uint32_t flags = 0x00; - switch (orientation) { - case DisplayState::eOrientation90: - flags = ui::Transform::ROT_90; - break; - case DisplayState::eOrientation180: - flags = ui::Transform::ROT_180; - break; - case DisplayState::eOrientation270: - flags = ui::Transform::ROT_270; - break; - default: - break; - } + const Rect& viewport = mDisplay->getViewport(); + const Rect& scissor = mDisplay->getScissor(); + const Rect& frame = mDisplay->getFrame(); + + const auto flags = ui::Transform::toRotationFlags(mDisplay->getPhysicalOrientation()); rotation.set(flags, getWidth(), getHeight()); + translateLogical.set(-viewport.left, -viewport.top); translatePhysical.set(scissor.left, scissor.top); scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0, @@ -320,49 +294,44 @@ public: } private: - // Install orientation is transparent to the callers. We need to cancel - // it out by modifying rotation flags. - static ui::Transform::orientation_flags getDisplayRotation( - ui::Transform::orientation_flags rotation, int orientation) { - if (orientation == DisplayState::eOrientationDefault) { - return rotation; - } - - // convert hw orientation into flag presentation - // here inverse transform needed - uint8_t hw_rot_90 = 0x00; - uint8_t hw_flip_hv = 0x00; - switch (orientation) { - case DisplayState::eOrientation90: - hw_rot_90 = ui::Transform::ROT_90; - hw_flip_hv = ui::Transform::ROT_180; + static RotationFlags applyInversePhysicalOrientation(RotationFlags orientation, + ui::Rotation physicalOrientation) { + uint32_t inverseRotate90 = 0; + uint32_t inverseReflect = 0; + + switch (physicalOrientation) { + case ui::ROTATION_0: + return orientation; + + case ui::ROTATION_90: + inverseRotate90 = ui::Transform::ROT_90; + inverseReflect = ui::Transform::ROT_180; break; - case DisplayState::eOrientation180: - hw_flip_hv = ui::Transform::ROT_180; + + case ui::ROTATION_180: + inverseReflect = ui::Transform::ROT_180; break; - case DisplayState::eOrientation270: - hw_rot_90 = ui::Transform::ROT_90; + + case ui::ROTATION_270: + inverseRotate90 = ui::Transform::ROT_90; break; } - // transform flags operation - // 1) flip H V if both have ROT_90 flag - // 2) XOR these flags - uint8_t rotation_rot_90 = rotation & ui::Transform::ROT_90; - uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180; - if (rotation_rot_90 & hw_rot_90) { - rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180; + const uint32_t rotate90 = orientation & ui::Transform::ROT_90; + uint32_t reflect = orientation & ui::Transform::ROT_180; + + // Apply reflection for double rotation. + if (rotate90 & inverseRotate90) { + reflect = ~reflect & ui::Transform::ROT_180; } - return static_cast( - (rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv)); + return static_cast((rotate90 ^ inverseRotate90) | + (reflect ^ inverseReflect)); } - const sp mDevice; + const sp mDisplay; const Rect mSourceCrop; const bool mAllowSecureLayers; }; -}; // namespace android - -#endif // ANDROID_DISPLAY_DEVICE_H +} // namespace android diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 1a60f1ed08..412f9779c8 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -49,7 +49,7 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) } if (mTransformToDisplayInverse) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index a484373caa..73de4f8b78 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -337,19 +337,7 @@ void RegionSamplingThread::captureSample() { } const auto device = mFlinger.getDefaultDisplayDevice(); - const auto orientation = [](uint32_t orientation) { - switch (orientation) { - default: - case DisplayState::eOrientationDefault: - return ui::Transform::ROT_0; - case DisplayState::eOrientation90: - return ui::Transform::ROT_90; - case DisplayState::eOrientation180: - return ui::Transform::ROT_180; - case DisplayState::eOrientation270: - return ui::Transform::ROT_270; - } - }(device->getOrientation()); + const auto orientation = ui::Transform::toRotationFlags(device->getOrientation()); std::vector descriptors; Region sampleRegion; diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 532572f766..a7a6dd5fc1 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -17,13 +17,15 @@ class DisplayDevice; // physical render area. class RenderArea { public: + using RotationFlags = ui::Transform::RotationFlags; + enum class CaptureFill {CLEAR, OPAQUE}; static float getCaptureFillValue(CaptureFill captureFill); RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill, ui::Dataspace reqDataSpace, const Rect& displayViewport, - ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) + RotationFlags rotation = ui::Transform::ROT_0) : mReqWidth(reqWidth), mReqHeight(reqHeight), mReqDataSpace(reqDataSpace), @@ -66,20 +68,20 @@ public: virtual Rect getSourceCrop() const = 0; // Returns the rotation of the source crop and the layers. - ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; + RotationFlags getRotationFlags() const { return mRotationFlags; } // Returns the size of the physical render area. - int getReqWidth() const { return mReqWidth; }; - int getReqHeight() const { return mReqHeight; }; + int getReqWidth() const { return mReqWidth; } + int getReqHeight() const { return mReqHeight; } // Returns the composition data space of the render area. ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } // Returns the fill color of the physical render area. Regions not // covered by any rendered layer should be filled with this color. - CaptureFill getCaptureFill() const { return mCaptureFill; }; + CaptureFill getCaptureFill() const { return mCaptureFill; } - virtual const sp getDisplayDevice() const = 0; + virtual sp getDisplayDevice() const = 0; // Returns the source display viewport. const Rect& getDisplayViewport() const { return mDisplayViewport; } @@ -89,7 +91,7 @@ private: const uint32_t mReqHeight; const ui::Dataspace mReqDataSpace; const CaptureFill mCaptureFill; - const ui::Transform::orientation_flags mRotationFlags; + const RotationFlags mRotationFlags; const Rect mDisplayViewport; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8c1d168cdb..92f40ff00f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,21 +163,6 @@ bool isWideColorMode(const ColorMode colorMode) { return false; } -ui::Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) { - switch (rotation) { - case ISurfaceComposer::eRotateNone: - return ui::Transform::ROT_0; - case ISurfaceComposer::eRotate90: - return ui::Transform::ROT_90; - case ISurfaceComposer::eRotate180: - return ui::Transform::ROT_180; - case ISurfaceComposer::eRotate270: - return ui::Transform::ROT_270; - } - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - return ui::Transform::ROT_0; -} - #pragma clang diagnostic pop class ConditionalLock { @@ -215,7 +200,7 @@ bool SurfaceFlinger::hasSyncFramework; bool SurfaceFlinger::useVrFlinger; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; bool SurfaceFlinger::hasWideColorDisplay; -int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault; +ui::Rotation SurfaceFlinger::internalDisplayOrientation = ui::ROTATION_0; bool SurfaceFlinger::useColorManagement; bool SurfaceFlinger::useContextPriority; Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB; @@ -298,23 +283,21 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI useContextPriority = use_context_priority(true); - auto tmpPrimaryDisplayOrientation = primary_display_orientation( - SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_0); - switch (tmpPrimaryDisplayOrientation) { - case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_90: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation90; + using Values = SurfaceFlingerProperties::primary_display_orientation_values; + switch (primary_display_orientation(Values::ORIENTATION_0)) { + case Values::ORIENTATION_0: break; - case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_180: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation180; + case Values::ORIENTATION_90: + internalDisplayOrientation = ui::ROTATION_90; break; - case SurfaceFlingerProperties::primary_display_orientation_values::ORIENTATION_270: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation270; + case Values::ORIENTATION_180: + internalDisplayOrientation = ui::ROTATION_180; break; - default: - SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault; + case Values::ORIENTATION_270: + internalDisplayOrientation = ui::ROTATION_270; break; } - ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation); + ALOGV("Internal Display Orientation: %s", toCString(internalDisplayOrientation)); mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries(); @@ -789,9 +772,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, } info.density = density; - // TODO: this needs to go away (currently needed only by webkit) const auto display = getDefaultDisplayDeviceLocked(); - info.orientation = display ? display->getOrientation() : 0; + info.orientation = display->getOrientation(); // This is for screenrecord const Rect viewport = display->getViewport(); @@ -804,7 +786,6 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, // TODO: where should this value come from? static const int TV_DENSITY = 213; info.density = TV_DENSITY / 160.0f; - info.orientation = 0; const auto display = getDisplayDeviceLocked(displayToken); info.layerStack = display->getLayerStack(); @@ -835,7 +816,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, info.secure = true; if (displayId == getInternalDisplayIdLocked() && - primaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + (internalDisplayOrientation == ui::ROTATION_90 || + internalDisplayOrientation == ui::ROTATION_270)) { std::swap(info.w, info.h); } @@ -2279,8 +2261,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( nativeWindow->setSwapInterval(nativeWindow.get(), 0); } - creationArgs.displayInstallOrientation = - isInternalDisplay ? primaryDisplayOrientation : DisplayState::eOrientationDefault; + creationArgs.physicalOrientation = + isInternalDisplay ? internalDisplayOrientation : ui::ROTATION_0; // virtual displays are always considered enabled creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; @@ -3817,7 +3799,7 @@ void SurfaceFlinger::onInitializeDisplays() { DisplayState::eLayerStackChanged; d.token = token; d.layerStack = 0; - d.orientation = DisplayState::eOrientationDefault; + d.orientation = ui::ROTATION_0; d.frame.makeInvalid(); d.viewport.makeInvalid(); d.width = 0; @@ -4426,8 +4408,8 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co if (const auto display = getDefaultDisplayDeviceLocked()) { display->getCompositionDisplay()->getState().undefinedRegion.dump(result, "undefinedRegion"); - StringAppendF(&result, " orientation=%d, isPoweredOn=%d\n", display->getOrientation(), - display->isPoweredOn()); + StringAppendF(&result, " orientation=%s, isPoweredOn=%d\n", + toCString(display->getOrientation()), display->isPoweredOn()); } StringAppendF(&result, " transaction-flags : %08x\n" @@ -5004,17 +4986,19 @@ private: status_t SurfaceFlinger::captureScreen(const sp& displayToken, sp* outBuffer, bool& outCapturedSecureLayers, - const Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, - ISurfaceComposer::Rotation rotation, - bool captureSecureLayers) { + Dataspace reqDataspace, ui::PixelFormat reqPixelFormat, + const Rect& sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, bool useIdentityTransform, + ui::Rotation rotation, bool captureSecureLayers) { ATRACE_CALL(); if (!displayToken) return BAD_VALUE; - auto renderAreaRotation = fromSurfaceComposerRotation(rotation); + auto renderAreaRotation = ui::Transform::toRotationFlags(rotation); + if (renderAreaRotation == ui::Transform::ROT_INVALID) { + ALOGE("%s: Invalid rotation: %s", __FUNCTION__, toCString(rotation)); + renderAreaRotation = ui::Transform::ROT_0; + } sp display; { @@ -5076,7 +5060,7 @@ status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* sp display; uint32_t width; uint32_t height; - ui::Transform::orientation_flags captureOrientation; + ui::Transform::RotationFlags captureOrientation; { Mutex::Autolock _l(mStateLock); display = getDisplayByIdOrLayerStack(displayOrLayerStack); @@ -5087,12 +5071,25 @@ status_t SurfaceFlinger::captureScreen(uint64_t displayOrLayerStack, Dataspace* width = uint32_t(display->getViewport().width()); height = uint32_t(display->getViewport().height()); - captureOrientation = fromSurfaceComposerRotation( - static_cast(display->getOrientation())); - if (captureOrientation == ui::Transform::orientation_flags::ROT_90) { - captureOrientation = ui::Transform::orientation_flags::ROT_270; - } else if (captureOrientation == ui::Transform::orientation_flags::ROT_270) { - captureOrientation = ui::Transform::orientation_flags::ROT_90; + const auto orientation = display->getOrientation(); + captureOrientation = ui::Transform::toRotationFlags(orientation); + + switch (captureOrientation) { + case ui::Transform::ROT_90: + captureOrientation = ui::Transform::ROT_270; + break; + + case ui::Transform::ROT_270: + captureOrientation = ui::Transform::ROT_90; + break; + + case ui::Transform::ROT_INVALID: + ALOGE("%s: Invalid orientation: %s", __FUNCTION__, toCString(orientation)); + captureOrientation = ui::Transform::ROT_0; + break; + + default: + break; } *outDataspace = pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode); @@ -5140,7 +5137,7 @@ status_t SurfaceFlinger::captureLayers( } bool isSecure() const override { return false; } bool needsFiltering() const override { return mNeedsFiltering; } - const sp getDisplayDevice() const override { return nullptr; } + sp getDisplayDevice() const override { return nullptr; } Rect getSourceCrop() const override { if (mCrop.isEmpty()) { return getBounds(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2f84b138d2..61876b2b36 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -229,7 +229,7 @@ public: // found on devices with wide color gamut (e.g. Display-P3) display. static bool hasWideColorDisplay; - static int primaryDisplayOrientation; + static ui::Rotation internalDisplayOrientation; // Indicate if device wants color management on its display. static bool useColorManagement; @@ -415,10 +415,10 @@ private: ISurfaceComposer::ConfigChanged configChanged = ISurfaceComposer::eConfigChangedSuppress) override; status_t captureScreen(const sp& displayToken, sp* outBuffer, - bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace, - const ui::PixelFormat reqPixelFormat, Rect sourceCrop, - uint32_t reqWidth, uint32_t reqHeight, - bool useIdentityTransform, ISurfaceComposer::Rotation rotation, bool captureSecureLayers) override; + bool& outCapturedSecureLayers, ui::Dataspace reqDataspace, + ui::PixelFormat reqPixelFormat, const Rect& sourceCrop, + uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform, + ui::Rotation rotation, bool captureSecureLayers) override; status_t captureScreen(uint64_t displayOrLayerStack, ui::Dataspace* outDataspace, sp* outBuffer) override; status_t captureLayers( diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 5e8910a3c5..8e0462ab52 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -137,8 +137,8 @@ void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface); addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack); addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height); - addDisplayProjectionLocked(transaction, display.sequenceId, display.orientation, - display.viewport, display.frame); + addDisplayProjectionLocked(transaction, display.sequenceId, toRotationInt(display.orientation), + display.viewport, display.frame); } status_t SurfaceInterceptor::writeProtoFileLocked() { @@ -467,8 +467,8 @@ void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, addDisplaySizeLocked(transaction, sequenceId, state.width, state.height); } if (state.what & DisplayState::eDisplayProjectionChanged) { - addDisplayProjectionLocked(transaction, sequenceId, state.orientation, state.viewport, - state.frame); + addDisplayProjectionLocked(transaction, sequenceId, toRotationInt(state.orientation), + state.viewport, state.frame); } } diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index b1bb7fdef9..f6188738b2 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -23,7 +23,6 @@ using ui::ColorMode; namespace { const String8 DISPLAY_NAME("Credentials Display Test"); const String8 SURFACE_NAME("Test Surface Name"); -const uint32_t ROTATION = 0; const float FRAME_SCALE = 1.0f; } // namespace @@ -262,7 +261,7 @@ TEST_F(CredentialsTest, CaptureTest) { sp outBuffer; return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/, - 0 /*reqHeight*/, false, ROTATION, &outBuffer); + 0 /*reqHeight*/, false, ui::ROTATION_0, &outBuffer); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 627de7a12e..92698f0142 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -189,12 +189,12 @@ TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) { } TEST_P(LayerRenderTypeTransactionTest, CreateLayer_BufferState) { - uint32_t transformHint = ui::Transform::orientation_flags::ROT_INVALID; + uint32_t transformHint = ui::Transform::ROT_INVALID; sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState, /*parent*/ nullptr, &transformHint)); - ASSERT_NE(ui::Transform::orientation_flags::ROT_INVALID, transformHint); + ASSERT_NE(ui::Transform::ROT_INVALID, transformHint); } void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) { diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp index 35c51e1915..7816c667bb 100644 --- a/services/surfaceflinger/tests/LayerTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -53,7 +53,7 @@ TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) { ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers, ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0, - 0, false, ISurfaceComposer::eRotateNone, true)); + 0, false, ui::ROTATION_0, true)); ASSERT_EQ(true, outCapturedSecureLayers); ScreenCapture sc(outBuffer); sc.expectColor(Rect(0, 0, 32, 32), Color::RED); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 76e8171255..55c3ab8b22 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -2040,8 +2040,8 @@ TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackChanges) { TEST_F(HandleTransactionLockedTest, processesDisplayTransformChanges) { using Case = NonHwcVirtualDisplayCase; - constexpr int oldTransform = 0; - constexpr int newTransform = 2; + constexpr ui::Rotation oldTransform = ui::ROTATION_0; + constexpr ui::Rotation newTransform = ui::ROTATION_180; // -------------------------------------------------------------------- // Preconditions @@ -2414,7 +2414,7 @@ TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfLayerStackCh TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) { using Case = SimplePrimaryDisplayCase; - constexpr int initialOrientation = 180; + constexpr ui::Rotation initialOrientation = ui::ROTATION_180; const Rect initialFrame = {1, 2, 3, 4}; const Rect initialViewport = {5, 6, 7, 8}; @@ -2458,8 +2458,8 @@ TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingIfProjectionDidNo TEST_F(DisplayTransactionTest, setDisplayStateLockedRequestsUpdateIfOrientationChanged) { using Case = SimplePrimaryDisplayCase; - constexpr int initialOrientation = 90; - constexpr int desiredOrientation = 180; + constexpr ui::Rotation initialOrientation = ui::ROTATION_90; + constexpr ui::Rotation desiredOrientation = ui::ROTATION_180; // -------------------------------------------------------------------- // Preconditions @@ -2721,7 +2721,7 @@ TEST_F(DisplayTransactionTest, onInitializeDisplaysSetsUpPrimaryDisplay) { // The layer stack state should be set to zero EXPECT_EQ(0u, primaryDisplayState.layerStack); // The orientation state should be set to zero - EXPECT_EQ(0, primaryDisplayState.orientation); + EXPECT_EQ(ui::ROTATION_0, primaryDisplayState.orientation); // The frame state should be set to INVALID EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.frame); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index b5245e2579..9728c80888 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -371,7 +371,6 @@ public: */ auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; } - auto& mutablePrimaryDisplayOrientation() { return SurfaceFlinger::primaryDisplayOrientation; } auto& mutableUseColorManagement() { return SurfaceFlinger::useColorManagement; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } -- cgit v1.2.3-59-g8ed1b From 1edb92a3a99c3d09cabb121cfec904f02d460d85 Mon Sep 17 00:00:00 2001 From: Zim Date: Thu, 9 Jan 2020 08:48:00 +0000 Subject: Fix installd mount paths with FUSE When parsing mounts from procfs in installd, we should match against /mnt/pass_through/0/ instead of /mnt/pass_through as the former is guaranteed to always be mounted even when multiple users are running. Additionally we can remove the hack added in Iaeb9ea3db373d358251644a95b3390cfa2b8f24a to work around the fact that the pass_through mount may not be mounted in some cases and so fallback on the lower filesystem path. This fallback caused the linked test to fail because sdcardfs cache got out of sync when we deleted directories from the lower fileysystem and bypassed sdcardfs. Bug: 135341433 Test: atest android.appsecurity.cts.StorageHostTest#testCache Change-Id: I77ee304fc2e6c3a619d94ca66cd664df7f1743d6 --- cmds/installd/InstalldNativeService.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'cmds') diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 6b14beefd0..a10baa6b80 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -108,6 +108,8 @@ static constexpr const char* kFuseProp = "persist.sys.fuse"; * Property to control if app data isolation is enabled. */ static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation"; +static constexpr const char* kMntSdcardfs = "/mnt/runtime/default/"; +static constexpr const char* kMntFuse = "/mnt/pass_through/0/"; static std::atomic sAppDataIsolationEnabled(false); @@ -2686,15 +2688,13 @@ binder::Status InstalldNativeService::invalidateMounts() { std::getline(in, ignored); if (android::base::GetBoolProperty(kFuseProp, false)) { - // TODO(b/146139106): Use sdcardfs mounts on devices running sdcardfs so we don't bypass - // it's VFS cache - if (target.compare(0, 17, "/mnt/pass_through") == 0) { + if (target.find(kMntFuse) == 0) { LOG(DEBUG) << "Found storage mount " << source << " at " << target; mStorageMounts[source] = target; } } else { #if !BYPASS_SDCARDFS - if (target.compare(0, 21, "/mnt/runtime/default/") == 0) { + if (target.find(kMntSdcardfs) == 0) { LOG(DEBUG) << "Found storage mount " << source << " at " << target; mStorageMounts[source] = target; } @@ -2792,17 +2792,6 @@ std::string InstalldNativeService::findDataMediaPath( std::lock_guard lock(mMountsLock); const char* uuid_ = uuid ? uuid->c_str() : nullptr; auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str()); - if (android::base::GetBoolProperty(kFuseProp, false)) { - // TODO(b/146139106): This is only safe on devices not running sdcardfs where there is no - // risk of bypassing the sdcardfs VFS cache - - // Always use the lower filesystem path on FUSE enabled devices not running sdcardfs - // The upper filesystem path, /mnt/pass_through/// which was a bind mount - // to the lower filesytem may have been unmounted already when a user is - // removed and the path will now be pointing to a tmpfs without content - return StringPrintf("%s/%u", path.c_str(), userid); - } - auto resolved = mStorageMounts[path]; if (resolved.empty()) { LOG(WARNING) << "Failed to find storage mount for " << path; -- cgit v1.2.3-59-g8ed1b From 30f947d6f62aa725635c8e8f9989ad83d6b29e6e Mon Sep 17 00:00:00 2001 From: Ricky Wai Date: Thu, 19 Dec 2019 17:24:48 +0000 Subject: Enable app data isolation by default Bug: 143937733 Test: Device boots normally Change-Id: I98619e5e520c7a16ba25ef22133d969ab84aa5ef --- cmds/installd/InstalldNativeService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmds') diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index a10baa6b80..e7b0d5d122 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -273,7 +273,7 @@ status_t InstalldNativeService::start() { ps->startThreadPool(); ps->giveThreadPoolName(); sAppDataIsolationEnabled = android::base::GetBoolProperty( - kAppDataIsolationEnabledProperty, false); + kAppDataIsolationEnabledProperty, true); return android::OK; } -- cgit v1.2.3-59-g8ed1b From 19c8f0e4fe37ffa86a7cbc879c23e4da2ff97e1c Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Mon, 25 Nov 2019 17:55:44 -0800 Subject: Add support for background blurs Bug: 141640413 Fixes: 146384234 Test: adb shell setprop debug.sf.disableBlurs 1 Test: adb shell setprop debug.sf.gaussianBlur 0 Test: adb shell setprop ro.surface_flinger.supports_background_blur 1 Test: ./SurfaceFlinger_test --gtest_filter=Layer*Tests/Layer*Test.SetBackgroundBlur* Test: ./librenderengine_test --gtest_filter=*BlurBackground*" Test: atest SurfaceFlinger_test:SurfaceInterceptorTest#InterceptBackgroundBlurRadiusUpdateWorks Change-Id: I5194c910fe7062f33e70943867012539e6c6626a --- cmds/surfacereplayer/proto/src/trace.proto | 5 + cmds/surfacereplayer/replayer/Replayer.cpp | 8 + cmds/surfacereplayer/replayer/Replayer.h | 2 + libs/gui/LayerState.cpp | 6 + libs/gui/SurfaceComposerClient.cpp | 12 ++ libs/gui/include/gui/LayerState.h | 3 + libs/gui/include/gui/SurfaceComposerClient.h | 2 + libs/renderengine/Android.bp | 4 + libs/renderengine/gl/GLESRenderEngine.cpp | 93 ++++++++- libs/renderengine/gl/GLESRenderEngine.h | 10 + libs/renderengine/gl/GLFramebuffer.cpp | 60 +++++- libs/renderengine/gl/GLFramebuffer.h | 9 + libs/renderengine/gl/filters/BlurFilter.cpp | 134 ++++++++++++ libs/renderengine/gl/filters/BlurFilter.h | 69 ++++++ .../renderengine/gl/filters/GaussianBlurFilter.cpp | 174 ++++++++++++++++ libs/renderengine/gl/filters/GaussianBlurFilter.h | 62 ++++++ libs/renderengine/gl/filters/GenericProgram.cpp | 122 +++++++++++ libs/renderengine/gl/filters/GenericProgram.h | 51 +++++ libs/renderengine/gl/filters/LensBlurFilter.cpp | 232 +++++++++++++++++++++ libs/renderengine/gl/filters/LensBlurFilter.h | 65 ++++++ .../include/renderengine/LayerSettings.h | 6 +- .../include/renderengine/RenderEngine.h | 11 +- libs/renderengine/tests/RenderEngineTest.cpp | 62 ++++++ .../compositionengine/LayerFECompositionState.h | 3 + .../include/compositionengine/impl/Output.h | 2 + .../src/LayerFECompositionState.cpp | 1 + .../CompositionEngine/src/Output.cpp | 29 ++- .../CompositionEngine/tests/OutputTest.cpp | 27 +++ services/surfaceflinger/Layer.cpp | 17 ++ services/surfaceflinger/Layer.h | 5 + services/surfaceflinger/SurfaceFlinger.cpp | 12 ++ services/surfaceflinger/SurfaceFlinger.h | 1 + services/surfaceflinger/SurfaceInterceptor.cpp | 11 + services/surfaceflinger/SurfaceInterceptor.h | 2 + .../surfaceflinger/layerproto/LayerProtoParser.cpp | 2 + .../include/layerproto/LayerProtoParser.h | 1 + services/surfaceflinger/layerproto/layers.proto | 2 + .../sysprop/SurfaceFlingerProperties.sysprop | 9 + .../api/SurfaceFlingerProperties-current.txt | 4 + .../LayerTypeAndRenderTypeTransaction_test.cpp | 36 ++++ .../tests/SurfaceInterceptor_test.cpp | 29 +++ 41 files changed, 1377 insertions(+), 18 deletions(-) create mode 100644 libs/renderengine/gl/filters/BlurFilter.cpp create mode 100644 libs/renderengine/gl/filters/BlurFilter.h create mode 100644 libs/renderengine/gl/filters/GaussianBlurFilter.cpp create mode 100644 libs/renderengine/gl/filters/GaussianBlurFilter.h create mode 100644 libs/renderengine/gl/filters/GenericProgram.cpp create mode 100644 libs/renderengine/gl/filters/GenericProgram.h create mode 100644 libs/renderengine/gl/filters/LensBlurFilter.cpp create mode 100644 libs/renderengine/gl/filters/LensBlurFilter.h (limited to 'cmds') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 7f2f94912e..b57409867f 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -51,6 +51,7 @@ message SurfaceChange { RelativeParentChange relative_parent = 18; DetachChildrenChange detach_children = 19; ReparentChildrenChange reparent_children = 20; + BackgroundBlurRadiusChange background_blur_radius = 21; ShadowRadiusChange shadow_radius = 22; } } @@ -73,6 +74,10 @@ message CornerRadiusChange { required float corner_radius = 1; } +message BackgroundBlurRadiusChange { + required float background_blur_radius = 1; +} + message LayerChange { required uint32 layer = 1; } diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 675aad6f81..2b5667d8fe 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -510,6 +510,14 @@ void Replayer::setCornerRadius(SurfaceComposerClient::Transaction& t, t.setCornerRadius(mLayers[id], cc.corner_radius()); } +void Replayer::setBackgroundBlurRadius(SurfaceComposerClient::Transaction& t, + layer_id id, const BackgroundBlurRadiusChange& cc) { + ALOGV("Layer %d: Setting Background Blur Radius -- backgroundBlurRadius=%d", id, + cc.background_blur_radius()); + + t.setBackgroundBlurRadius(mLayers[id], cc.background_blur_radius()); +} + void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc) { ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(), diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index b5478344cb..95857e1e5b 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -94,6 +94,8 @@ class Replayer { layer_id id, const CropChange& cc); void setCornerRadius(SurfaceComposerClient::Transaction& t, layer_id id, const CornerRadiusChange& cc); + void setBackgroundBlurRadius(SurfaceComposerClient::Transaction& t, + layer_id id, const BackgroundBlurRadiusChange& cc); void setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc); void setOverrideScalingMode(SurfaceComposerClient::Transaction& t, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 39b4d4bbb6..5547efc3ad 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -86,6 +86,7 @@ status_t layer_state_t::write(Parcel& output) const memcpy(output.writeInplace(16 * sizeof(float)), colorTransform.asArray(), 16 * sizeof(float)); output.writeFloat(cornerRadius); + output.writeUint32(backgroundBlurRadius); output.writeStrongBinder(cachedBuffer.token.promote()); output.writeUint64(cachedBuffer.id); output.writeParcelable(metadata); @@ -173,6 +174,7 @@ status_t layer_state_t::read(const Parcel& input) colorTransform = mat4(static_cast(input.readInplace(16 * sizeof(float)))); cornerRadius = input.readFloat(); + backgroundBlurRadius = input.readUint32(); cachedBuffer.token = input.readStrongBinder(); cachedBuffer.id = input.readUint64(); input.readParcelable(&metadata); @@ -307,6 +309,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCornerRadiusChanged; cornerRadius = other.cornerRadius; } + if (other.what & eBackgroundBlurRadiusChanged) { + what |= eBackgroundBlurRadiusChanged; + backgroundBlurRadius = other.backgroundBlurRadius; + } if (other.what & eDeferTransaction_legacy) { what |= eDeferTransaction_legacy; barrierHandle_legacy = other.barrierHandle_legacy; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 20614f8d85..69d4269fa6 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -918,6 +918,18 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCorne return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBackgroundBlurRadius( + const sp& sc, int backgroundBlurRadius) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eBackgroundBlurRadiusChanged; + s->backgroundBlurRadius = backgroundBlurRadius; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, const sp& handle, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index cf641939e8..c256a09c40 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -101,6 +101,7 @@ struct layer_state_t { eColorSpaceAgnosticChanged = 0x10'00000000, eFrameRateSelectionPriority = 0x20'00000000, eFrameRateChanged = 0x40'00000000, + eBackgroundBlurRadiusChanged = 0x80'00000000, }; layer_state_t() @@ -117,6 +118,7 @@ struct layer_state_t { reserved(0), crop_legacy(Rect::INVALID_RECT), cornerRadius(0.0f), + backgroundBlurRadius(0), frameNumber_legacy(0), overrideScalingMode(-1), transform(0), @@ -163,6 +165,7 @@ struct layer_state_t { matrix22_t matrix; Rect crop_legacy; float cornerRadius; + uint32_t backgroundBlurRadius; sp barrierHandle_legacy; sp reparentHandle; uint64_t frameNumber_legacy; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 71ee82a72f..228bf33b9a 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -435,6 +435,8 @@ public: float dsdx, float dtdx, float dtdy, float dsdy); Transaction& setCrop_legacy(const sp& sc, const Rect& crop); Transaction& setCornerRadius(const sp& sc, float cornerRadius); + Transaction& setBackgroundBlurRadius(const sp& sc, + int backgroundBlurRadius); Transaction& setLayerStack(const sp& sc, uint32_t layerStack); Transaction& setMetadata(const sp& sc, uint32_t key, const Parcel& p); // Defers applying any changes made in this transaction until the Layer diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 348377e4e3..2e3ab4c9f6 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -57,6 +57,10 @@ filegroup { "gl/ImageManager.cpp", "gl/Program.cpp", "gl/ProgramCache.cpp", + "gl/filters/BlurFilter.cpp", + "gl/filters/LensBlurFilter.cpp", + "gl/filters/GaussianBlurFilter.cpp", + "gl/filters/GenericProgram.cpp", ], } diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 0748dfb848..09659fe209 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -49,6 +49,9 @@ #include "GLShadowVertexGenerator.h" #include "Program.h" #include "ProgramCache.h" +#include "filters/BlurFilter.h" +#include "filters/GaussianBlurFilter.h" +#include "filters/LensBlurFilter.h" extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); @@ -422,6 +425,18 @@ GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisp mTraceGpuCompletion = true; mFlushTracer = std::make_unique(this); } + + if (args.supportsBackgroundBlur) { + char isGaussian[PROPERTY_VALUE_MAX]; + property_get("debug.sf.gaussianBlur", isGaussian, "1"); + if (atoi(isGaussian)) { + mBlurFilter = new GaussianBlurFilter(*this); + } else { + mBlurFilter = new LensBlurFilter(*this); + } + checkErrors("BlurFilter creation"); + } + mImageManager = std::make_unique(this); mDrawingBuffer = createFramebuffer(); } @@ -871,11 +886,19 @@ void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) { } void GLESRenderEngine::checkErrors() const { + checkErrors(nullptr); +} + +void GLESRenderEngine::checkErrors(const char* tag) const { do { // there could be more than one error flag GLenum error = glGetError(); if (error == GL_NO_ERROR) break; - ALOGE("GL error 0x%04x", int(error)); + if (tag == nullptr) { + ALOGE("GL error 0x%04x", int(error)); + } else { + ALOGE("GL error: %s -> 0x%04x", tag, int(error)); + } } while (true); } @@ -957,13 +980,36 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - BindNativeBufferAsFramebuffer fbo(*this, buffer, useFramebufferCache); + std::unique_ptr fbo; + // Let's find the topmost layer requesting background blur (if any.) + // Blurs in multiple layers are not supported, given the cost of the shader. + const LayerSettings* blurLayer = nullptr; + if (CC_LIKELY(mBlurFilter != nullptr)) { + for (auto const& layer : layers) { + if (layer.backgroundBlurRadius > 0) { + blurLayer = &layer; + } + } + } - if (fbo.getStatus() != NO_ERROR) { - ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->handle); - checkErrors(); - return fbo.getStatus(); + if (blurLayer == nullptr) { + fbo = std::make_unique(*this, buffer, useFramebufferCache); + if (fbo->getStatus() != NO_ERROR) { + ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", + buffer->handle); + checkErrors(); + return fbo->getStatus(); + } + setViewportAndProjection(display.physicalDisplay, display.clip); + } else { + setViewportAndProjection(display.physicalDisplay, display.clip); + auto status = mBlurFilter->setAsDrawTarget(display); + if (status != NO_ERROR) { + ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", + buffer->handle); + checkErrors(); + return status; + } } // clear the entire buffer, sometimes when we reuse buffers we'd persist @@ -973,8 +1019,6 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // opaque layers. clearWithColor(0.0, 0.0, 0.0, 0.0); - setViewportAndProjection(display.physicalDisplay, display.clip); - setOutputDataSpace(display.outputDataspace); setDisplayMaxLuminance(display.maxLuminance); @@ -991,7 +1035,36 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, .setTexCoords(2 /* size */) .setCropCoords(2 /* size */) .build(); - for (auto layer : layers) { + for (auto const& layer : layers) { + if (blurLayer == &layer) { + auto status = mBlurFilter->prepare(layer.backgroundBlurRadius); + if (status != NO_ERROR) { + ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", + buffer->handle); + checkErrors("Can't render first blur pass"); + return status; + } + + fbo = std::make_unique(*this, buffer, + useFramebufferCache); + status = fbo->getStatus(); + if (status != NO_ERROR) { + ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", + buffer->handle); + checkErrors("Can't bind native framebuffer"); + return status; + } + setViewportAndProjection(display.physicalDisplay, display.clip); + + status = mBlurFilter->render(); + if (status != NO_ERROR) { + ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", + buffer->handle); + checkErrors("Can't render blur filter"); + return status; + } + } + mState.maxMasteringLuminance = layer.source.buffer.maxMasteringLuminance; mState.maxContentLuminance = layer.source.buffer.maxContentLuminance; mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index f41eda2b63..547235a90d 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -46,6 +46,7 @@ class Texture; namespace gl { class GLImage; +class BlurFilter; class GLESRenderEngine : public impl::RenderEngine { public: @@ -117,6 +118,7 @@ private: std::unique_ptr createFramebuffer(); std::unique_ptr createImage(); void checkErrors() const; + void checkErrors(const char* tag) const; void setScissor(const Rect& region); void disableScissor(); bool waitSync(EGLSyncKHR sync, EGLint flags); @@ -228,6 +230,9 @@ private: std::unique_ptr mDrawingBuffer; + // Blur effect processor, only instantiated when a layer requests it. + BlurFilter* mBlurFilter = nullptr; + class FlushTracer { public: FlushTracer(GLESRenderEngine* engine); @@ -251,6 +256,11 @@ private: }; friend class FlushTracer; friend class ImageManager; + friend class GLFramebuffer; + friend class BlurFilter; + friend class GaussianBlurFilter; + friend class LensBlurFilter; + friend class GenericProgram; std::unique_ptr mFlushTracer; std::unique_ptr mImageManager = std::make_unique(this); }; diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp index 5fbb5ba7d7..091eac90b2 100644 --- a/libs/renderengine/gl/GLFramebuffer.cpp +++ b/libs/renderengine/gl/GLFramebuffer.cpp @@ -20,8 +20,8 @@ #include #include -#include #include +#include #include #include #include @@ -32,14 +32,23 @@ namespace renderengine { namespace gl { GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine) + : GLFramebuffer(engine, false /* multiTarget */) {} + +GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine, bool multiTarget) : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) { glGenTextures(1, &mTextureName); + if (multiTarget) { + glGenTextures(1, &mSecondaryTextureName); + } glGenFramebuffers(1, &mFramebufferName); } GLFramebuffer::~GLFramebuffer() { glDeleteFramebuffers(1, &mFramebufferName); glDeleteTextures(1, &mTextureName); + if (mSecondaryTextureName != -1) { + glDeleteTextures(1, &mSecondaryTextureName); + } } bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected, @@ -68,6 +77,55 @@ bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, boo return true; } +void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height) { + ATRACE_CALL(); + + glBindTexture(GL_TEXTURE_2D, mTextureName); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + + const bool multiTarget = mSecondaryTextureName != -1; + if (multiTarget) { + glBindTexture(GL_TEXTURE_2D, mSecondaryTextureName); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + } + + mBufferHeight = height; + mBufferWidth = width; + mEngine.checkErrors("Allocating Fbo texture"); + + bind(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureName, 0); + if (multiTarget) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, + mSecondaryTextureName, 0); + GLenum buffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; + glDrawBuffers(2, buffers); + } + mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + unbind(); + glBindTexture(GL_TEXTURE_2D, 0); + + if (mStatus != GL_FRAMEBUFFER_COMPLETE) { + ALOGE("Frame buffer is not complete. Error %d", mStatus); + } +} + +void GLFramebuffer::bind() const { + glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName); +} + +void GLFramebuffer::unbind() const { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + } // namespace gl } // namespace renderengine } // namespace android diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h index b7650bbfd9..668685afd1 100644 --- a/libs/renderengine/gl/GLFramebuffer.h +++ b/libs/renderengine/gl/GLFramebuffer.h @@ -20,6 +20,7 @@ #include #include +#include #include struct ANativeWindowBuffer; @@ -33,22 +34,30 @@ class GLESRenderEngine; class GLFramebuffer : public renderengine::Framebuffer { public: explicit GLFramebuffer(GLESRenderEngine& engine); + explicit GLFramebuffer(GLESRenderEngine& engine, bool multiTarget); ~GLFramebuffer() override; bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected, const bool useFramebufferCache) override; + void allocateBuffers(uint32_t width, uint32_t height); EGLImageKHR getEGLImage() const { return mEGLImage; } uint32_t getTextureName() const { return mTextureName; } + uint32_t getSecondaryTextureName() const { return mSecondaryTextureName; } uint32_t getFramebufferName() const { return mFramebufferName; } int32_t getBufferHeight() const { return mBufferHeight; } int32_t getBufferWidth() const { return mBufferWidth; } + GLenum getStatus() const { return mStatus; } + void bind() const; + void unbind() const; private: GLESRenderEngine& mEngine; EGLDisplay mEGLDisplay; EGLImageKHR mEGLImage; bool usingFramebufferCache = false; + GLenum mStatus = GL_FRAMEBUFFER_UNSUPPORTED; uint32_t mTextureName, mFramebufferName; + uint32_t mSecondaryTextureName = -1; int32_t mBufferHeight = 0; int32_t mBufferWidth = 0; diff --git a/libs/renderengine/gl/filters/BlurFilter.cpp b/libs/renderengine/gl/filters/BlurFilter.cpp new file mode 100644 index 0000000000..a55468741d --- /dev/null +++ b/libs/renderengine/gl/filters/BlurFilter.cpp @@ -0,0 +1,134 @@ +/* + * 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. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BlurFilter.h" +#include +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace renderengine { +namespace gl { + +BlurFilter::BlurFilter(GLESRenderEngine& engine) + : mEngine(engine), mCompositionFbo(engine), mBlurredFbo(engine), mSimpleProgram(engine) { + mSimpleProgram.compile(getVertexShader(), getSimpleFragShader()); + mSPosLoc = mSimpleProgram.getAttributeLocation("aPosition"); + mSUvLoc = mSimpleProgram.getAttributeLocation("aUV"); + mSTextureLoc = mSimpleProgram.getUniformLocation("uTexture"); +} + +status_t BlurFilter::setAsDrawTarget(const DisplaySettings& display) { + ATRACE_NAME("BlurFilter::setAsDrawTarget"); + + if (!mTexturesAllocated) { + const uint32_t fboWidth = floorf(display.physicalDisplay.width() * kFboScale); + const uint32_t fboHeight = floorf(display.physicalDisplay.height() * kFboScale); + mCompositionFbo.allocateBuffers(fboWidth, fboHeight); + mBlurredFbo.allocateBuffers(fboWidth, fboHeight); + allocateTextures(); + mTexturesAllocated = true; + } + + if (mBlurredFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) { + ALOGE("Invalid blur buffer"); + return mBlurredFbo.getStatus(); + } + if (mCompositionFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) { + ALOGE("Invalid composition buffer"); + return mCompositionFbo.getStatus(); + } + + mCompositionFbo.bind(); + glViewport(0, 0, mCompositionFbo.getBufferWidth(), mCompositionFbo.getBufferHeight()); + return NO_ERROR; +} + +void BlurFilter::drawMesh(GLuint uv, GLuint position) { + GLfloat positions[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f}; + GLfloat texCoords[] = {0.0, 0.0, 0.0, 1.0f, 1.0f, 1.0f, 1.0f, 0}; + + // set attributes + glEnableVertexAttribArray(uv); + glVertexAttribPointer(uv, 2 /* size */, GL_FLOAT, GL_FALSE, 0, texCoords); + glEnableVertexAttribArray(position); + glVertexAttribPointer(position, 2 /* size */, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), + positions); + + // draw mesh + glDrawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */); + mEngine.checkErrors("Drawing blur mesh"); +} + +status_t BlurFilter::render() { + ATRACE_NAME("BlurFilter::render"); + + // Now let's scale our blur up + mSimpleProgram.useProgram(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mBlurredFbo.getTextureName()); + glUniform1i(mSTextureLoc, 0); + mEngine.checkErrors("Setting final pass uniforms"); + + drawMesh(mSUvLoc, mSPosLoc); + + glUseProgram(0); + return NO_ERROR; +} + +string BlurFilter::getVertexShader() const { + return R"SHADER( + #version 310 es + precision lowp float; + + in vec2 aPosition; + in mediump vec2 aUV; + out mediump vec2 vUV; + + void main() { + vUV = aUV; + gl_Position = vec4(aPosition, 0.0, 1.0); + } + )SHADER"; +} + +string BlurFilter::getSimpleFragShader() const { + string shader = R"SHADER( + #version 310 es + precision lowp float; + + in mediump vec2 vUV; + out vec4 fragColor; + + uniform sampler2D uTexture; + + void main() { + fragColor = texture(uTexture, vUV); + } + )SHADER"; + return shader; +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/filters/BlurFilter.h b/libs/renderengine/gl/filters/BlurFilter.h new file mode 100644 index 0000000000..2b5ea5830b --- /dev/null +++ b/libs/renderengine/gl/filters/BlurFilter.h @@ -0,0 +1,69 @@ +/* + * 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 +#include "../GLESRenderEngine.h" +#include "../GLFramebuffer.h" +#include "GenericProgram.h" + +using namespace std; + +namespace android { +namespace renderengine { +namespace gl { + +class BlurFilter { +public: + // Downsample FBO to improve performance + static constexpr float kFboScale = 0.35f; + + explicit BlurFilter(GLESRenderEngine& engine); + virtual ~BlurFilter(){}; + + // Set up render targets, redirecting output to offscreen texture. + status_t setAsDrawTarget(const DisplaySettings&); + // Allocate any textures needed for the filter. + virtual void allocateTextures() = 0; + // Execute blur passes, rendering to offscreen texture. + virtual status_t prepare(uint32_t radius) = 0; + // Render blur to the bound framebuffer (screen). + status_t render(); + +protected: + void drawMesh(GLuint uv, GLuint position); + string getSimpleFragShader() const; + string getVertexShader() const; + + GLESRenderEngine& mEngine; + // Frame buffer holding the composited background. + GLFramebuffer mCompositionFbo; + // Frame buffer holding the blur result. + GLFramebuffer mBlurredFbo; + +private: + bool mTexturesAllocated = false; + + GenericProgram mSimpleProgram; + GLuint mSPosLoc; + GLuint mSUvLoc; + GLuint mSTextureLoc; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/filters/GaussianBlurFilter.cpp b/libs/renderengine/gl/filters/GaussianBlurFilter.cpp new file mode 100644 index 0000000000..b1ad72ccef --- /dev/null +++ b/libs/renderengine/gl/filters/GaussianBlurFilter.cpp @@ -0,0 +1,174 @@ +/* + * 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. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "GaussianBlurFilter.h" +#include +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace renderengine { +namespace gl { + +GaussianBlurFilter::GaussianBlurFilter(GLESRenderEngine& engine) + : BlurFilter(engine), + mVerticalPassFbo(engine), + mVerticalProgram(engine), + mHorizontalProgram(engine) { + mVerticalProgram.compile(getVertexShader(), getFragmentShader(false)); + mVPosLoc = mVerticalProgram.getAttributeLocation("aPosition"); + mVUvLoc = mVerticalProgram.getAttributeLocation("aUV"); + mVTextureLoc = mVerticalProgram.getUniformLocation("uTexture"); + mVSizeLoc = mVerticalProgram.getUniformLocation("uSize"); + mVRadiusLoc = mVerticalProgram.getUniformLocation("uRadius"); + + mHorizontalProgram.compile(getVertexShader(), getFragmentShader(true)); + mHPosLoc = mHorizontalProgram.getAttributeLocation("aPosition"); + mHUvLoc = mHorizontalProgram.getAttributeLocation("aUV"); + mHTextureLoc = mHorizontalProgram.getUniformLocation("uTexture"); + mHSizeLoc = mHorizontalProgram.getUniformLocation("uSize"); + mHRadiusLoc = mHorizontalProgram.getUniformLocation("uRadius"); +} + +void GaussianBlurFilter::allocateTextures() { + mVerticalPassFbo.allocateBuffers(mBlurredFbo.getBufferWidth(), mBlurredFbo.getBufferHeight()); +} + +status_t GaussianBlurFilter::prepare(uint32_t radius) { + ATRACE_NAME("GaussianBlurFilter::prepare"); + + if (mVerticalPassFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) { + ALOGE("Invalid vertical FBO"); + return mVerticalPassFbo.getStatus(); + } + if (!mVerticalProgram.isValid()) { + ALOGE("Invalid vertical shader"); + return GL_INVALID_OPERATION; + } + if (!mHorizontalProgram.isValid()) { + ALOGE("Invalid horizontal shader"); + return GL_INVALID_OPERATION; + } + + // First, we'll apply the vertical pass, that receives the flattened background layers. + mVerticalPassFbo.bind(); + mVerticalProgram.useProgram(); + + // set uniforms + auto width = mVerticalPassFbo.getBufferWidth(); + auto height = mVerticalPassFbo.getBufferHeight(); + glViewport(0, 0, width, height); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName()); + glUniform1i(mVTextureLoc, 0); + glUniform2f(mVSizeLoc, width, height); + glUniform1f(mVRadiusLoc, radius * kFboScale); + mEngine.checkErrors("Setting vertical-diagonal pass uniforms"); + + drawMesh(mVUvLoc, mVPosLoc); + + // Blur vertically on a secondary pass + mBlurredFbo.bind(); + mHorizontalProgram.useProgram(); + + // set uniforms + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mVerticalPassFbo.getTextureName()); + glUniform1i(mHTextureLoc, 0); + glUniform2f(mHSizeLoc, width, height); + glUniform1f(mHRadiusLoc, radius * kFboScale); + mEngine.checkErrors("Setting vertical pass uniforms"); + + drawMesh(mHUvLoc, mHPosLoc); + + // reset active texture + mBlurredFbo.unbind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + + // unbind program + glUseProgram(0); + + return NO_ERROR; +} + +string GaussianBlurFilter::getFragmentShader(bool horizontal) const { + string shader = "#version 310 es\n#define DIRECTION "; + shader += (horizontal ? "1" : "0"); + shader += R"SHADER( + precision lowp float; + + uniform sampler2D uTexture; + uniform vec2 uSize; + uniform float uRadius; + + in mediump vec2 vUV; + + out vec4 fragColor; + + #define PI 3.14159265359 + #define THETA 0.352 + #define MU 0.0 + #define A 1.0 / (THETA * sqrt(2.0 * PI)) + #define K 1.0 / (2.0 * THETA * THETA) + #define MAX_SAMPLES 12 + + float gaussianBellCurve(float x) { + float tmp = (x - MU); + return exp(-K * tmp * tmp); + } + + vec3 gaussianBlur(sampler2D texture, mediump vec2 uv, float size, + vec2 direction, float radius) { + float totalWeight = 0.0; + vec3 blurred = vec3(0.); + int samples = min(int(floor(radius / 2.0)), MAX_SAMPLES); + float inc = radius / (size * 2.0); + + for (int i = -samples; i <= samples; i++) { + float normalized = (float(i) / float(samples)); + float weight = gaussianBellCurve(normalized); + float radInc = inc * normalized; + blurred += weight * (texture(texture, uv + radInc * direction)).rgb;; + totalWeight += weight; + } + + return blurred / totalWeight; + } + + void main() { + #if DIRECTION == 1 + vec3 color = gaussianBlur(uTexture, vUV, uSize.x, vec2(1.0, 0.0), uRadius); + #else + vec3 color = gaussianBlur(uTexture, vUV, uSize.y, vec2(0.0, 1.0), uRadius); + #endif + fragColor = vec4(color.r, color.g, color.b, texture(uTexture, vUV).a); + } + + )SHADER"; + return shader; +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/filters/GaussianBlurFilter.h b/libs/renderengine/gl/filters/GaussianBlurFilter.h new file mode 100644 index 0000000000..acf0f07d36 --- /dev/null +++ b/libs/renderengine/gl/filters/GaussianBlurFilter.h @@ -0,0 +1,62 @@ +/* + * 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 +#include "../GLESRenderEngine.h" +#include "../GLFramebuffer.h" +#include "BlurFilter.h" +#include "GenericProgram.h" + +using namespace std; + +namespace android { +namespace renderengine { +namespace gl { + +class GaussianBlurFilter : public BlurFilter { +public: + explicit GaussianBlurFilter(GLESRenderEngine& engine); + status_t prepare(uint32_t radius) override; + void allocateTextures() override; + +private: + string getFragmentShader(bool horizontal) const; + + // Initial, vertical render pass + GLFramebuffer mVerticalPassFbo; + + // Vertical pass and its uniforms + GenericProgram mVerticalProgram; + GLuint mVPosLoc; + GLuint mVUvLoc; + GLuint mVTextureLoc; + GLuint mVSizeLoc; + GLuint mVRadiusLoc; + + // Horizontal pass and its uniforms + GenericProgram mHorizontalProgram; + GLuint mHPosLoc; + GLuint mHUvLoc; + GLuint mHTextureLoc; + GLuint mHSizeLoc; + GLuint mHRadiusLoc; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android \ No newline at end of file diff --git a/libs/renderengine/gl/filters/GenericProgram.cpp b/libs/renderengine/gl/filters/GenericProgram.cpp new file mode 100644 index 0000000000..bb35889665 --- /dev/null +++ b/libs/renderengine/gl/filters/GenericProgram.cpp @@ -0,0 +1,122 @@ +/* + * 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 "GenericProgram.h" + +#include +#include +#include +#include + +namespace android { +namespace renderengine { +namespace gl { + +GenericProgram::GenericProgram(GLESRenderEngine& engine) : mEngine(engine) {} + +GenericProgram::~GenericProgram() { + if (mVertexShaderHandle != 0) { + if (mProgramHandle != 0) { + glDetachShader(mProgramHandle, mVertexShaderHandle); + } + glDeleteShader(mVertexShaderHandle); + } + + if (mFragmentShaderHandle != 0) { + if (mProgramHandle != 0) { + glDetachShader(mProgramHandle, mFragmentShaderHandle); + } + glDeleteShader(mFragmentShaderHandle); + } + + if (mProgramHandle != 0) { + glDeleteProgram(mProgramHandle); + } +} + +void GenericProgram::compile(string vertexShader, string fragmentShader) { + mVertexShaderHandle = compileShader(GL_VERTEX_SHADER, vertexShader); + mFragmentShaderHandle = compileShader(GL_FRAGMENT_SHADER, fragmentShader); + if (mVertexShaderHandle == 0 || mFragmentShaderHandle == 0) { + ALOGE("Aborting program creation."); + return; + } + mProgramHandle = createAndLink(mVertexShaderHandle, mFragmentShaderHandle); + mEngine.checkErrors("Linking program"); +} + +void GenericProgram::useProgram() const { + glUseProgram(mProgramHandle); +} + +GLuint GenericProgram::compileShader(GLuint type, string src) const { + const GLuint shader = glCreateShader(type); + if (shader == 0) { + mEngine.checkErrors("Creating shader"); + return 0; + } + const GLchar* charSrc = (const GLchar*)src.c_str(); + glShaderSource(shader, 1, &charSrc, nullptr); + glCompileShader(shader); + + GLint isCompiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); + if (isCompiled == GL_FALSE) { + GLint maxLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + string errorLog; + errorLog.reserve(maxLength); + glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data()); + glDeleteShader(shader); + ALOGE("Error compiling shader: %s", errorLog.c_str()); + return 0; + } + return shader; +} +GLuint GenericProgram::createAndLink(GLuint vertexShader, GLuint fragmentShader) const { + const GLuint program = glCreateProgram(); + mEngine.checkErrors("Creating program"); + + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + mEngine.checkErrors("Linking program"); + return program; +} + +GLuint GenericProgram::getUniformLocation(const string name) const { + if (mProgramHandle == 0) { + ALOGE("Can't get location of %s on an invalid program.", name.c_str()); + return -1; + } + return glGetUniformLocation(mProgramHandle, (const GLchar*)name.c_str()); +} + +GLuint GenericProgram::getAttributeLocation(const string name) const { + if (mProgramHandle == 0) { + ALOGE("Can't get location of %s on an invalid program.", name.c_str()); + return -1; + } + return glGetAttribLocation(mProgramHandle, (const GLchar*)name.c_str()); +} + +bool GenericProgram::isValid() const { + return mProgramHandle != 0; +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/filters/GenericProgram.h b/libs/renderengine/gl/filters/GenericProgram.h new file mode 100644 index 0000000000..6da2a5af58 --- /dev/null +++ b/libs/renderengine/gl/filters/GenericProgram.h @@ -0,0 +1,51 @@ +/* + * 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 +#include "../GLESRenderEngine.h" +#include "../GLFramebuffer.h" + +using namespace std; + +namespace android { +namespace renderengine { +namespace gl { + +class GenericProgram { +public: + explicit GenericProgram(GLESRenderEngine& renderEngine); + ~GenericProgram(); + void compile(string vertexShader, string fragmentShader); + bool isValid() const; + void useProgram() const; + GLuint getAttributeLocation(const string name) const; + GLuint getUniformLocation(const string name) const; + +private: + GLuint compileShader(GLuint type, const string src) const; + GLuint createAndLink(GLuint vertexShader, GLuint fragmentShader) const; + + GLESRenderEngine& mEngine; + GLuint mVertexShaderHandle = 0; + GLuint mFragmentShaderHandle = 0; + GLuint mProgramHandle = 0; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/filters/LensBlurFilter.cpp b/libs/renderengine/gl/filters/LensBlurFilter.cpp new file mode 100644 index 0000000000..386bd91322 --- /dev/null +++ b/libs/renderengine/gl/filters/LensBlurFilter.cpp @@ -0,0 +1,232 @@ +/* + * 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. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "LensBlurFilter.h" +#include +#include +#include +#include +#include +#include + +#include + +namespace android { +namespace renderengine { +namespace gl { + +// Number of blur samples in shader (for loop) +static constexpr auto kNumSamples = 12; + +LensBlurFilter::LensBlurFilter(GLESRenderEngine& engine) + : BlurFilter(engine), + mVerticalDiagonalPassFbo(engine, true /* multiTarget */), + mVerticalDiagonalProgram(engine), + mCombinedProgram(engine) { + mVerticalDiagonalProgram.compile(getVertexShader(), getFragmentShader(false)); + mCombinedProgram.compile(getVertexShader(), getFragmentShader(true)); + + mVDPosLoc = mVerticalDiagonalProgram.getAttributeLocation("aPosition"); + mVDUvLoc = mVerticalDiagonalProgram.getAttributeLocation("aUV"); + mVDTexture0Loc = mVerticalDiagonalProgram.getUniformLocation("uTexture0"); + mVDSizeLoc = mVerticalDiagonalProgram.getUniformLocation("uSize"); + mVDRadiusLoc = mVerticalDiagonalProgram.getUniformLocation("uRadius"); + mVDNumSamplesLoc = mVerticalDiagonalProgram.getUniformLocation("uNumSamples"); + + mCPosLoc = mCombinedProgram.getAttributeLocation("aPosition"); + mCUvLoc = mCombinedProgram.getAttributeLocation("aUV"); + mCTexture0Loc = mCombinedProgram.getUniformLocation("uTexture0"); + mCTexture1Loc = mCombinedProgram.getUniformLocation("uTexture1"); + mCSizeLoc = mCombinedProgram.getUniformLocation("uSize"); + mCRadiusLoc = mCombinedProgram.getUniformLocation("uRadius"); + mCNumSamplesLoc = mCombinedProgram.getUniformLocation("uNumSamples"); +} + +void LensBlurFilter::allocateTextures() { + mVerticalDiagonalPassFbo.allocateBuffers(mBlurredFbo.getBufferWidth(), + mBlurredFbo.getBufferHeight()); +} + +status_t LensBlurFilter::prepare(uint32_t radius) { + ATRACE_NAME("LensBlurFilter::prepare"); + + if (mVerticalDiagonalPassFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) { + ALOGE("Invalid vertical-diagonal FBO"); + return mVerticalDiagonalPassFbo.getStatus(); + } + if (!mVerticalDiagonalProgram.isValid()) { + ALOGE("Invalid vertical-diagonal shader"); + return GL_INVALID_OPERATION; + } + if (!mCombinedProgram.isValid()) { + ALOGE("Invalid blur shader"); + return GL_INVALID_OPERATION; + } + + // First, we'll apply the vertical/diagonal pass, that receives the flattened background layers, + // and writes the output to two textures (vertical and diagonal.) + mVerticalDiagonalPassFbo.bind(); + mVerticalDiagonalProgram.useProgram(); + + // set uniforms + auto width = mVerticalDiagonalPassFbo.getBufferWidth(); + auto height = mVerticalDiagonalPassFbo.getBufferHeight(); + glViewport(0, 0, width, height); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName()); + glUniform1i(mVDTexture0Loc, 0); + glUniform2f(mVDSizeLoc, width, height); + glUniform1f(mVDRadiusLoc, radius * kFboScale); + glUniform1i(mVDNumSamplesLoc, kNumSamples); + mEngine.checkErrors("Setting vertical-diagonal pass uniforms"); + + drawMesh(mVDUvLoc, mVDPosLoc); + + // Now we'll combine the multi render pass into a blurred image + mBlurredFbo.bind(); + mCombinedProgram.useProgram(); + + // set uniforms + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mVerticalDiagonalPassFbo.getTextureName()); + glUniform1i(mCTexture0Loc, 0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, mVerticalDiagonalPassFbo.getSecondaryTextureName()); + glUniform1i(mCTexture1Loc, 1); + glUniform2f(mCSizeLoc, width, height); + glUniform1f(mCRadiusLoc, radius * kFboScale); + glUniform1i(mCNumSamplesLoc, kNumSamples); + mEngine.checkErrors("Setting vertical pass uniforms"); + + drawMesh(mCUvLoc, mCPosLoc); + + // reset active texture + mBlurredFbo.unbind(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + + // unbind program + glUseProgram(0); + + return NO_ERROR; +} + +string LensBlurFilter::getFragmentShader(bool forComposition) const { + string shader = "#version 310 es\n#define DIRECTION "; + shader += (forComposition ? "1" : "0"); + shader += R"SHADER( + precision lowp float; + + #define BOKEH_ANGLE 0.0 + #define PI 3.14159265359 + + uniform sampler2D uTexture0; + uniform vec2 uSize; + uniform float uRadius; + uniform int uNumSamples; + + in mediump vec2 vUV; + + #if DIRECTION == 0 + layout(location = 0) out vec4 fragColor0; + layout(location = 1) out vec4 fragColor1; + #else + uniform sampler2D uTexture1; + out vec4 fragColor; + #endif + + vec4 blur(const sampler2D tex, in vec2 uv, const vec2 direction, float radius, + in int samples, float intensity) { + vec4 finalColor = vec4(vec3(0.0), 1.0); + float blurAmount = 0.0; + uv += direction * 0.5; + + for (int i = 0; i < samples; i++){ + float delta = radius * float(i) / float(samples); + vec4 color = texture(tex, uv + direction * delta); + color.rgb *= intensity; + color *= color.a; + blurAmount += color.a; + finalColor += color; + } + + return finalColor / blurAmount; + } + + vec4 blur(const sampler2D tex, in vec2 uv, const vec2 direction, float radius, + in int samples) { + return blur(tex, uv, direction, radius, samples, 1.0); + } + + vec4[2] verticalDiagonalLensBlur (vec2 uv, sampler2D texture, vec2 resolution, + float radius, int samples) { + float coc = texture(texture, uv).a; + + // Vertical Blur + vec2 blurDirV = (coc / resolution.xy) * vec2(cos(BOKEH_ANGLE + PI / 2.0), + sin(BOKEH_ANGLE + PI / 2.0)); + vec3 colorV = blur(texture, uv, blurDirV, radius, samples).rgb * coc; + + // Diagonal Blur + vec2 blurDirD = (coc / resolution.xy) * vec2(cos(BOKEH_ANGLE - PI / 6.0), + sin(BOKEH_ANGLE - PI / 6.0)); + vec3 colorD = blur(texture, uv, blurDirD, radius, samples).rgb * coc; + + vec4 composed[2]; + composed[0] = vec4(colorV, coc); + // added * 0.5, to remap + composed[1] = vec4((colorD + colorV) * 0.5, coc); + + return composed; + } + + vec4 rhombiLensBlur (vec2 uv, sampler2D texture0, sampler2D texture1, vec2 resolution, + float radius, int samples) { + float coc1 = texture(texture0, uv).a; + float coc2 = texture(texture1, uv).a; + + vec2 blurDirection1 = coc1 / resolution.xy * vec2(cos(BOKEH_ANGLE - PI / 6.0), sin(BOKEH_ANGLE - PI / 6.0)); + vec3 color1 = blur(texture0, uv, blurDirection1, radius, samples).rgb * coc1; + + vec2 blurDirection2 = coc2 / resolution.xy * vec2(cos(BOKEH_ANGLE - 5.0 * PI / 6.0), sin(BOKEH_ANGLE - 5.0 * PI / 6.0)); + vec3 color2 = blur(texture1, uv, blurDirection2, radius, samples, 2.0).rgb * coc2; + + return vec4((color1 + color2) * 0.33, 1.0); + } + + void main() { + #if DIRECTION == 0 + // First pass: outputs two textures + vec4 colorOut[] = verticalDiagonalLensBlur(vUV, uTexture0, uSize, uRadius, uNumSamples); + fragColor0 = colorOut[0]; + fragColor1 = colorOut[1]; + #else + // Second pass: combines both textures into a blurred one. + fragColor = rhombiLensBlur(vUV, uTexture0, uTexture1, uSize, uRadius, uNumSamples); + #endif + } + + )SHADER"; + return shader; +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/filters/LensBlurFilter.h b/libs/renderengine/gl/filters/LensBlurFilter.h new file mode 100644 index 0000000000..8543f0db4f --- /dev/null +++ b/libs/renderengine/gl/filters/LensBlurFilter.h @@ -0,0 +1,65 @@ +/* + * 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 +#include "../GLESRenderEngine.h" +#include "../GLFramebuffer.h" +#include "BlurFilter.h" +#include "GenericProgram.h" + +using namespace std; + +namespace android { +namespace renderengine { +namespace gl { + +class LensBlurFilter : public BlurFilter { +public: + explicit LensBlurFilter(GLESRenderEngine& engine); + status_t prepare(uint32_t radius) override; + void allocateTextures() override; + +private: + string getFragmentShader(bool forComposition) const; + + // Intermediate render pass + GLFramebuffer mVerticalDiagonalPassFbo; + + // Vertical/diagonal pass and its uniforms + GenericProgram mVerticalDiagonalProgram; + GLuint mVDPosLoc; + GLuint mVDUvLoc; + GLuint mVDTexture0Loc; + GLuint mVDSizeLoc; + GLuint mVDRadiusLoc; + GLuint mVDNumSamplesLoc; + + // Blur composition pass and its uniforms + GenericProgram mCombinedProgram; + GLuint mCPosLoc; + GLuint mCUvLoc; + GLuint mCTexture0Loc; + GLuint mCTexture1Loc; + GLuint mCSizeLoc; + GLuint mCRadiusLoc; + GLuint mCNumSamplesLoc; +}; + +} // namespace gl +} // namespace renderengine +} // namespace android \ No newline at end of file diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 5aa3f3bd69..3dc198f398 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -149,6 +149,8 @@ struct LayerSettings { bool disableBlending = false; ShadowSettings shadow; + + int backgroundBlurRadius = 0; }; static inline bool operator==(const Buffer& lhs, const Buffer& rhs) { @@ -182,7 +184,8 @@ static inline bool operator==(const LayerSettings& lhs, const LayerSettings& rhs return lhs.geometry == rhs.geometry && lhs.source == rhs.source && lhs.alpha == rhs.alpha && lhs.sourceDataspace == rhs.sourceDataspace && lhs.colorTransform == rhs.colorTransform && - lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow; + lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow && + lhs.backgroundBlurRadius == rhs.backgroundBlurRadius; } // Defining PrintTo helps with Google Tests. @@ -243,6 +246,7 @@ static inline void PrintTo(const LayerSettings& settings, ::std::ostream* os) { PrintTo(settings.sourceDataspace, os); *os << "\n .colorTransform = " << settings.colorTransform; *os << "\n .disableBlending = " << settings.disableBlending; + *os << "\n .backgroundBlurRadius = " << settings.backgroundBlurRadius; *os << "\n .shadow = "; PrintTo(settings.shadow, os); *os << "\n}"; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 4db5c57d6d..e3c2d84e86 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -174,6 +174,7 @@ struct RenderEngineCreationArgs { bool useColorManagement; bool enableProtectedContext; bool precacheToneMapperShaderOnly; + bool supportsBackgroundBlur; RenderEngine::ContextPriority contextPriority; struct Builder; @@ -186,12 +187,14 @@ private: bool _useColorManagement, bool _enableProtectedContext, bool _precacheToneMapperShaderOnly, + bool _supportsBackgroundBlur, RenderEngine::ContextPriority _contextPriority) : pixelFormat(_pixelFormat) , imageCacheSize(_imageCacheSize) , useColorManagement(_useColorManagement) , enableProtectedContext(_enableProtectedContext) , precacheToneMapperShaderOnly(_precacheToneMapperShaderOnly) + , supportsBackgroundBlur(_supportsBackgroundBlur) , contextPriority(_contextPriority) {} RenderEngineCreationArgs() = delete; }; @@ -219,13 +222,18 @@ struct RenderEngineCreationArgs::Builder { this->precacheToneMapperShaderOnly = precacheToneMapperShaderOnly; return *this; } + Builder& setSupportsBackgroundBlur(bool supportsBackgroundBlur) { + this->supportsBackgroundBlur = supportsBackgroundBlur; + return *this; + } Builder& setContextPriority(RenderEngine::ContextPriority contextPriority) { this->contextPriority = contextPriority; return *this; } RenderEngineCreationArgs build() const { return RenderEngineCreationArgs(pixelFormat, imageCacheSize, useColorManagement, - enableProtectedContext, precacheToneMapperShaderOnly, contextPriority); + enableProtectedContext, precacheToneMapperShaderOnly, + supportsBackgroundBlur, contextPriority); } private: @@ -235,6 +243,7 @@ private: bool useColorManagement = true; bool enableProtectedContext = false; bool precacheToneMapperShaderOnly = false; + bool supportsBackgroundBlur = false; RenderEngine::ContextPriority contextPriority = RenderEngine::ContextPriority::MEDIUM; }; diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 7700b2e01f..e676740c6a 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,7 @@ struct RenderEngineTest : public ::testing::Test { .setUseColorManagerment(false) .setEnableProtectedContext(false) .setPrecacheToneMapperShaderOnly(false) + .setSupportsBackgroundBlur(true) .setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM) .build()); } @@ -327,6 +329,9 @@ struct RenderEngineTest : public ::testing::Test { template void fillBufferWithRoundedCorners(); + template + void fillBufferAndBlurBackground(); + template void overlayCorners(); @@ -705,6 +710,51 @@ void RenderEngineTest::fillBufferWithRoundedCorners() { 255); } +template +void RenderEngineTest::fillBufferAndBlurBackground() { + char value[PROPERTY_VALUE_MAX]; + property_get("ro.surface_flinger.supports_background_blur", value, "0"); + if (!atoi(value)) { + // This device doesn't support blurs, no-op. + return; + } + + auto blurRadius = 50; + auto center = DEFAULT_DISPLAY_WIDTH / 2; + + renderengine::DisplaySettings settings; + settings.physicalDisplay = fullscreenRect(); + settings.clip = fullscreenRect(); + + std::vector layers; + + renderengine::LayerSettings backgroundLayer; + backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); + SourceVariant::fillColor(backgroundLayer, 0.0f, 1.0f, 0.0f, this); + backgroundLayer.alpha = 1.0f; + layers.push_back(backgroundLayer); + + renderengine::LayerSettings leftLayer; + leftLayer.geometry.boundaries = + Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT).toFloatRect(); + SourceVariant::fillColor(leftLayer, 1.0f, 0.0f, 0.0f, this); + leftLayer.alpha = 1.0f; + layers.push_back(leftLayer); + + renderengine::LayerSettings blurLayer; + blurLayer.geometry.boundaries = fullscreenRect().toFloatRect(); + blurLayer.backgroundBlurRadius = blurRadius; + blurLayer.alpha = 0; + layers.push_back(blurLayer); + + invokeDraw(settings, layers, mBuffer); + + expectBufferColor(Rect(center - 1, center - 5, center, center + 5), 150, 150, 0, 255, + 50 /* tolerance */); + expectBufferColor(Rect(center, center - 5, center + 1, center + 5), 150, 150, 0, 255, + 50 /* tolerance */); +} + template void RenderEngineTest::overlayCorners() { renderengine::DisplaySettings settings; @@ -1032,6 +1082,10 @@ TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) { fillBufferWithRoundedCorners(); } +TEST_F(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_colorSource) { + fillBufferAndBlurBackground(); +} + TEST_F(RenderEngineTest, drawLayers_overlayCorners_colorSource) { overlayCorners(); } @@ -1084,6 +1138,10 @@ TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) fillBufferWithRoundedCorners>(); } +TEST_F(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_opaqueBufferSource) { + fillBufferAndBlurBackground>(); +} + TEST_F(RenderEngineTest, drawLayers_overlayCorners_opaqueBufferSource) { overlayCorners>(); } @@ -1136,6 +1194,10 @@ TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) { fillBufferWithRoundedCorners>(); } +TEST_F(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_bufferSource) { + fillBufferAndBlurBackground>(); +} + TEST_F(RenderEngineTest, drawLayers_overlayCorners_bufferSource) { overlayCorners>(); } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index a64fdbf88a..3dbd25e173 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -63,6 +63,9 @@ struct LayerFECompositionState { // The alpha value for this layer float alpha{1.f}; + // Background blur in pixels + int backgroundBlurRadius{0}; + // The transform from layer local coordinates to composition coordinates ui::Transform geomLayerTransform; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 159e928761..3a9776d57a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -116,6 +116,7 @@ protected: private: void dirtyEntireOutput(); + compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const; ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const; compositionengine::Output::ColorProfile pickColorProfile( const compositionengine::CompositionRefreshArgs&) const; @@ -126,6 +127,7 @@ private: std::unique_ptr mRenderSurface; ReleasedLayers mReleasedLayers; + OutputLayer* mLayerRequestingBackgroundBlur = nullptr; }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index 085e83838e..8065e658d5 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -61,6 +61,7 @@ void LayerFECompositionState::dump(std::string& out) const { out.append("\n "); dumpVal(out, "blend", toString(blendMode), blendMode); dumpVal(out, "alpha", alpha); + dumpVal(out, "backgroundBlurRadius", backgroundBlurRadius); out.append("\n "); dumpVal(out, "type", type); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 01413b9478..650b5c1d29 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -578,15 +578,33 @@ void Output::updateAndWriteCompositionState( return; } + mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition(); + bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr; + for (auto* layer : getOutputLayersOrderedByZ()) { layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame, - refreshArgs.devOptForceClientComposition); + refreshArgs.devOptForceClientComposition || + forceClientComposition); + + if (mLayerRequestingBackgroundBlur == layer) { + forceClientComposition = false; + } // Send the updated state to the HWC, if appropriate. layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame); } } +compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const { + compositionengine::OutputLayer* layerRequestingBgComposition = nullptr; + for (auto* layer : getOutputLayersOrderedByZ()) { + if (layer->getLayer().getFEState().backgroundBlurRadius > 0) { + layerRequestingBgComposition = layer; + } + } + return layerRequestingBgComposition; +} + void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) { setColorProfile(pickColorProfile(refreshArgs)); } @@ -854,11 +872,12 @@ std::optional Output::composeSurfaces(const Region& debugRegion } // We boost GPU frequency here because there will be color spaces conversion - // and it's expensive. We boost the GPU frequency so that GPU composition can - // finish in time. We must reset GPU frequency afterwards, because high frequency - // consumes extra battery. + // or complex GPU shaders and it's expensive. We boost the GPU frequency so that + // GPU composition can finish in time. We must reset GPU frequency afterwards, + // because high frequency consumes extra battery. const bool expensiveRenderingExpected = - clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3; + clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3 || + mLayerRequestingBackgroundBlur != nullptr; if (expensiveRenderingExpected) { setExpensiveRenderingExpected(true); } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 24311c7e5b..6761b866c4 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -138,6 +138,10 @@ struct OutputLatchFEStateTest : public OutputTest { EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState)); EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState)); EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState)); + + EXPECT_CALL(mLayer1, getFEState()).WillRepeatedly(ReturnRef(mLayer1FEState)); + EXPECT_CALL(mLayer2, getFEState()).WillRepeatedly(ReturnRef(mLayer2FEState)); + EXPECT_CALL(mLayer3, getFEState()).WillRepeatedly(ReturnRef(mLayer3FEState)); } void injectLayer(std::unique_ptr layer) { @@ -3637,6 +3641,29 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace)); } +TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) { + // Layer requesting blur, or below, should request client composition. + EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true)); + EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false)); + EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true)); + EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false)); + EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false)); + EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false)); + + mLayer2FEState.backgroundBlurRadius = 10; + + injectLayer(std::move(mOutputLayer1)); + injectLayer(std::move(mOutputLayer2)); + injectLayer(std::move(mOutputLayer3)); + + mOutput->editState().isEnabled = true; + + CompositionRefreshArgs args; + args.updatingGeometryThisFrame = false; + args.devOptForceClientComposition = false; + mOutput->updateAndWriteCompositionState(args); +} + TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) { // In split-screen landscape mode, the screen is rotated 90 degrees, with // one layer on the left covering the left side of the output, and one layer diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9c4a784883..f4d4329f6d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -109,6 +109,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.hdrMetadata.validTypes = 0; mCurrentState.surfaceDamageRegion = Region::INVALID_REGION; mCurrentState.cornerRadius = 0.0f; + mCurrentState.backgroundBlurRadius = 0; mCurrentState.api = -1; mCurrentState.hasColorTransform = false; mCurrentState.colorSpaceAgnostic = false; @@ -448,6 +449,7 @@ void Layer::latchBasicGeometry(compositionengine::LayerFECompositionState& compo compositionState.blendMode = static_cast(blendMode); compositionState.alpha = alpha; + compositionState.backgroundBlurRadius = drawingState.backgroundBlurRadius; } void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const { @@ -575,6 +577,7 @@ std::optional Layer::prepareClientComposition( layerSettings.alpha = alpha; layerSettings.sourceDataspace = getDataSpace(); + layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); return layerSettings; } @@ -1103,6 +1106,16 @@ bool Layer::setCornerRadius(float cornerRadius) { return true; } +bool Layer::setBackgroundBlurRadius(int backgroundBlurRadius) { + if (mCurrentState.backgroundBlurRadius == backgroundBlurRadius) return false; + + mCurrentState.sequence++; + mCurrentState.backgroundBlurRadius = backgroundBlurRadius; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms) { ui::Transform t; @@ -1873,6 +1886,10 @@ half4 Layer::getColor() const { return half4(color.r, color.g, color.b, getAlpha()); } +int32_t Layer::getBackgroundBlurRadius() const { + return getDrawingState().backgroundBlurRadius; +} + Layer::RoundedCornerState Layer::getRoundedCornerState() const { const auto& p = mDrawingParent.promote(); if (p != nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 025309894a..ffe004f9e9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -179,6 +179,7 @@ public: half4 color; float cornerRadius; + int backgroundBlurRadius; bool inputInfoChanged; InputWindowInfo inputInfo; @@ -299,6 +300,9 @@ public: // The shape of the rounded corner rectangle is specified by the crop rectangle of the layer // from which we inferred the rounded corner radius. virtual bool setCornerRadius(float cornerRadius); + // When non-zero, everything below this layer will be blurred by backgroundBlurRadius, which + // is specified in pixels. + virtual bool setBackgroundBlurRadius(int backgroundBlurRadius); virtual bool setTransparentRegionHint(const Region& transparent); virtual bool setFlags(uint8_t flags, uint8_t mask); virtual bool setLayerStack(uint32_t layerStack); @@ -663,6 +667,7 @@ public: // down the hierarchy). half getAlpha() const; half4 getColor() const; + int32_t getBackgroundBlurRadius() const; // Returns how rounded corners should be drawn for this layer. // This will traverse the hierarchy until it reaches its root, finding topmost rounded diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0a33830937..ba57d3763f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -338,6 +338,14 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mLayerTripleBufferingDisabled = atoi(value); ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering"); + property_get("ro.surface_flinger.supports_background_blur", value, "0"); + bool supportsBlurs = atoi(value); + property_get("debug.sf.disableBlurs", value, "0"); + bool disableBlurs = atoi(value); + mEnableBlurs = supportsBlurs && !disableBlurs; + ALOGI_IF(!mEnableBlurs, "Disabling blur effects. supported: %d, disabled: %d", supportsBlurs, + disableBlurs); + const size_t defaultListSize = MAX_LAYERS; auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; @@ -580,6 +588,7 @@ void SurfaceFlinger::init() { .setUseColorManagerment(useColorManagement) .setEnableProtectedContext(enable_protected_contents(false)) .setPrecacheToneMapperShaderOnly(false) + .setSupportsBackgroundBlur(mEnableBlurs) .setContextPriority(useContextPriority ? renderengine::RenderEngine::ContextPriority::HIGH : renderengine::RenderEngine::ContextPriority::MEDIUM) @@ -3379,6 +3388,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (layer->setCornerRadius(s.cornerRadius)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eBackgroundBlurRadiusChanged) { + if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eLayerStackChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); // We only allow setting layer stacks for top level layers, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 723e332ad1..b9f230d982 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1025,6 +1025,7 @@ private: const std::shared_ptr mTimeStats; const std::unique_ptr mFrameTracer; bool mUseHwcVirtualDisplays = false; + bool mEnableBlurs = false; std::atomic mFrameMissedCount = 0; std::atomic mHwcFrameMissedCount = 0; std::atomic mGpuFrameMissedCount = 0; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 79123f979b..6884b4c42e 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -114,6 +114,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy); addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius); + addBackgroundBlurRadiusLocked(transaction, layerId, layer->mCurrentState.backgroundBlurRadius); if (layer->mCurrentState.barrierLayer_legacy != nullptr) { addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer_legacy.promote(), @@ -322,6 +323,13 @@ void SurfaceInterceptor::addCornerRadiusLocked(Transaction* transaction, int32_t cornerRadiusChange->set_corner_radius(cornerRadius); } +void SurfaceInterceptor::addBackgroundBlurRadiusLocked(Transaction* transaction, int32_t layerId, + int32_t backgroundBlurRadius) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + BackgroundBlurRadiusChange* blurRadiusChange(change->mutable_background_blur_radius()); + blurRadiusChange->set_background_blur_radius(backgroundBlurRadius); +} + void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber) { @@ -422,6 +430,9 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eCornerRadiusChanged) { addCornerRadiusLocked(transaction, layerId, state.cornerRadius); } + if (state.what & layer_state_t::eBackgroundBlurRadiusChanged) { + addBackgroundBlurRadiusLocked(transaction, layerId, state.backgroundBlurRadius); + } if (state.what & layer_state_t::eDeferTransaction_legacy) { sp otherLayer = nullptr; if (state.barrierHandle_legacy != nullptr) { diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index c6f9e8a9a1..a665f62ad7 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -152,6 +152,8 @@ private: void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack); void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect); void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius); + void addBackgroundBlurRadiusLocked(Transaction* transaction, int32_t layerId, + int32_t backgroundBlurRadius); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber); void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index ef27847e55..8fce0c9bf3 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -106,6 +106,7 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP layer.refreshPending = layerProto.refresh_pending(); layer.isProtected = layerProto.is_protected(); layer.cornerRadius = layerProto.corner_radius(); + layer.backgroundBlurRadius = layerProto.background_blur_radius(); for (const auto& entry : layerProto.metadata()) { const std::string& dataStr = entry.second; std::vector& outData = layer.metadata.mMap[entry.first]; @@ -290,6 +291,7 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate); StringAppendF(&result, "dataspace=%s, ", dataspace.c_str()); StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str()); + StringAppendF(&result, "backgroundBlurRadius=%1d, ", backgroundBlurRadius); StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ", static_cast(color.r), static_cast(color.g), static_cast(color.b), static_cast(color.a), flags); diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 774b0e15f0..52b916555f 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -110,6 +110,7 @@ public: bool refreshPending; bool isProtected; float cornerRadius; + int backgroundBlurRadius; LayerMetadata metadata; LayerProtoParser::FloatRect cornerRadiusCrop; float shadowRadius; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 41ecafadd2..8afe5039f8 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -104,6 +104,8 @@ message LayerProto { ColorTransformProto color_transform = 50; bool is_relative_of = 51; + // Layer's background blur radius in pixels. + int32 background_blur_radius = 52; } message PositionProto { diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index 049c872f07..ed2b220e86 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -371,3 +371,12 @@ prop { access: Readonly prop_name: "ro.surface_flinger.support_kernel_idle_timer" } + +# Indicates whether background blurs are supported. +prop { + api_name: "supports_background_blur" + type: Boolean + scope: Public + access: Readonly + prop_name: "ro.surface_flinger.supports_background_blur" +} diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt index 2d525073b9..d24ad18eaf 100644 --- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt +++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt @@ -103,6 +103,10 @@ props { api_name: "support_kernel_idle_timer" prop_name: "ro.surface_flinger.support_kernel_idle_timer" } + prop { + api_name: "supports_background_blur" + prop_name: "ro.surface_flinger.supports_background_blur" + } prop { api_name: "use_color_management" prop_name: "ro.surface_flinger.use_color_management" diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index 71f01b0c1d..3bbd12a242 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -18,6 +18,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#include #include #include "TransactionTestHarnesses.h" @@ -243,6 +244,41 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK); } } + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadius) { + char value[PROPERTY_VALUE_MAX]; + property_get("ro.surface_flinger.supports_background_blur", value, "0"); + if (!atoi(value)) { + // This device doesn't support blurs, no-op. + return; + } + + auto size = 256; + auto center = size / 2; + auto blurRadius = 50; + + sp backgroundLayer; + ASSERT_NO_FATAL_FAILURE(backgroundLayer = createLayer("background", size, size)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(backgroundLayer, Color::GREEN, size, size)); + + sp leftLayer; + ASSERT_NO_FATAL_FAILURE(leftLayer = createLayer("left", size / 2, size)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(leftLayer, Color::RED, size / 2, size)); + + sp blurLayer; + ASSERT_NO_FATAL_FAILURE(blurLayer = createLayer("blur", size, size)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(blurLayer, Color::TRANSPARENT, size, size)); + + Transaction().setBackgroundBlurRadius(blurLayer, blurRadius).apply(); + + auto shot = getScreenCapture(); + // Edges are mixed + shot->expectColor(Rect(center - 1, center - 5, center, center + 5), Color{150, 150, 0, 255}, + 50 /* tolerance */); + shot->expectColor(Rect(center, center - 5, center + 1, center + 5), Color{150, 150, 0, 255}, + 50 /* tolerance */); +} + TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) { sp bufferLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 75d0761907..4a2ab7c080 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -53,6 +53,7 @@ constexpr uint64_t DEFERRED_UPDATE = 0; constexpr int32_t RELATIVE_Z = 42; constexpr float ALPHA_UPDATE = 0.29f; constexpr float CORNER_RADIUS_UPDATE = 0.2f; +constexpr int BACKGROUND_BLUR_RADIUS_UPDATE = 24; constexpr float POSITION_UPDATE = 121; const Rect CROP_UPDATE(16, 16, 32, 32); const float SHADOW_RADIUS_UPDATE = 35.0f; @@ -183,6 +184,8 @@ public: bool layerUpdateFound(const SurfaceChange& change, bool foundLayer); bool cropUpdateFound(const SurfaceChange& change, bool foundCrop); bool cornerRadiusUpdateFound(const SurfaceChange& change, bool foundCornerRadius); + bool backgroundBlurRadiusUpdateFound(const SurfaceChange& change, + bool foundBackgroundBlurRadius); bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix); bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode); bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion); @@ -220,6 +223,7 @@ public: void layerUpdate(Transaction&); void cropUpdate(Transaction&); void cornerRadiusUpdate(Transaction&); + void backgroundBlurRadiusUpdate(Transaction&); void matrixUpdate(Transaction&); void overrideScalingModeUpdate(Transaction&); void transparentRegionHintUpdate(Transaction&); @@ -355,6 +359,10 @@ void SurfaceInterceptorTest::cornerRadiusUpdate(Transaction& t) { t.setCornerRadius(mBGSurfaceControl, CORNER_RADIUS_UPDATE); } +void SurfaceInterceptorTest::backgroundBlurRadiusUpdate(Transaction& t) { + t.setBackgroundBlurRadius(mBGSurfaceControl, BACKGROUND_BLUR_RADIUS_UPDATE); +} + void SurfaceInterceptorTest::layerUpdate(Transaction& t) { t.setLayer(mBGSurfaceControl, LAYER_UPDATE); } @@ -432,6 +440,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::sizeUpdate); runInTransaction(&SurfaceInterceptorTest::alphaUpdate); runInTransaction(&SurfaceInterceptorTest::cornerRadiusUpdate); + runInTransaction(&SurfaceInterceptorTest::backgroundBlurRadiusUpdate); runInTransaction(&SurfaceInterceptorTest::layerUpdate); runInTransaction(&SurfaceInterceptorTest::cropUpdate); runInTransaction(&SurfaceInterceptorTest::matrixUpdate); @@ -509,6 +518,18 @@ bool SurfaceInterceptorTest::cornerRadiusUpdateFound(const SurfaceChange &change return foundCornerRadius; } +bool SurfaceInterceptorTest::backgroundBlurRadiusUpdateFound(const SurfaceChange& change, + bool foundBackgroundBlur) { + bool hasBackgroundBlur(change.background_blur_radius().background_blur_radius() == + BACKGROUND_BLUR_RADIUS_UPDATE); + if (hasBackgroundBlur && !foundBackgroundBlur) { + foundBackgroundBlur = true; + } else if (hasBackgroundBlur && foundBackgroundBlur) { + []() { FAIL(); }(); + } + return foundBackgroundBlur; +} + bool SurfaceInterceptorTest::layerUpdateFound(const SurfaceChange& change, bool foundLayer) { bool hasLayer(change.layer().layer() == LAYER_UPDATE); if (hasLayer && !foundLayer) { @@ -705,6 +726,9 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kCornerRadius: foundUpdate = cornerRadiusUpdateFound(change, foundUpdate); break; + case SurfaceChange::SurfaceChangeCase::kBackgroundBlurRadius: + foundUpdate = backgroundBlurRadiusUpdateFound(change, foundUpdate); + break; case SurfaceChange::SurfaceChangeCase::kMatrix: foundUpdate = matrixUpdateFound(change, foundUpdate); break; @@ -887,6 +911,11 @@ TEST_F(SurfaceInterceptorTest, InterceptCornerRadiusUpdateWorks) { SurfaceChange::SurfaceChangeCase::kCornerRadius); } +TEST_F(SurfaceInterceptorTest, InterceptBackgroundBlurRadiusUpdateWorks) { + captureTest(&SurfaceInterceptorTest::backgroundBlurRadiusUpdate, + SurfaceChange::SurfaceChangeCase::kBackgroundBlurRadius); +} + TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) { captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix); } -- cgit v1.2.3-59-g8ed1b From 9308a5444065a5847769104e81ee361cf060115b Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Tue, 28 Jan 2020 16:24:05 -0800 Subject: [installd] Remove boot complete marker ART doesn't load the boot image from /data anymore and the marker is useless. Test: device boots Bug: 143899228 Change-Id: I78defa45b52b868da9861a3aac28d15d8c453d16 --- cmds/installd/InstalldNativeService.cpp | 20 -------------------- cmds/installd/InstalldNativeService.h | 1 - cmds/installd/binder/android/os/IInstalld.aidl | 1 - 3 files changed, 22 deletions(-) (limited to 'cmds') diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index e7b0d5d122..cfd6a3eb9f 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -2250,26 +2250,6 @@ binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath, return *_aidl_return ? ok() : error("viewcompiler failed"); } -binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) { - ENFORCE_UID(AID_SYSTEM); - std::lock_guard lock(mLock); - - const char* instruction_set = instructionSet.c_str(); - - char boot_marker_path[PKG_PATH_MAX]; - sprintf(boot_marker_path, - "%s/%s/%s/.booting", - android_data_dir.c_str(), - DALVIK_CACHE, - instruction_set); - - ALOGV("mark_boot_complete : %s", boot_marker_path); - if (unlink(boot_marker_path) != 0) { - return error(StringPrintf("Failed to unlink %s", boot_marker_path)); - } - return ok(); -} - binder::Status InstalldNativeService::linkNativeLibraryDirectory( const std::unique_ptr& uuid, const std::string& packageName, const std::string& nativeLibPath32, int32_t userId) { diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index bf11002da0..dd56de6a81 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -130,7 +130,6 @@ public: const std::string& profileName); binder::Status rmPackageDir(const std::string& packageDir); - binder::Status markBootComplete(const std::string& instructionSet); binder::Status freeCache(const std::unique_ptr& uuid, int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags); binder::Status linkNativeLibraryDirectory(const std::unique_ptr& uuid, diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 891b26dc43..07ced0d013 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -81,7 +81,6 @@ interface IInstalld { void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String profileName); void rmPackageDir(@utf8InCpp String packageDir); - void markBootComplete(@utf8InCpp String instructionSet); void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes, long cacheReservedBytes, int flags); void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid, -- cgit v1.2.3-59-g8ed1b From 3cb3d4e3906eb43a01464e8862772295dab50f78 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Thu, 21 Nov 2019 11:14:45 -0800 Subject: SF: Redesign API to query display information The DisplayInfo list returned by ISurfaceComposer for display configs contains display information/state redundant across configs. Extract config information to DisplayConfig, and repurpose DisplayInfo for immutable information about a physical display. In a future CL, SF will populate DisplayInfo with additional data (e.g. connection type, EDID fields) on initial connection. DisplayConfigs retain the ability to reload on subsequent connections. Introduce ui::DisplayState for transactional state applicable to both physical and virtual displays. Bug: 144601064 Test: dumpsys display Change-Id: I72003e8ef71483ef483d0de85d28b859a6c9f5fc --- cmds/flatland/GLHelper.cpp | 19 +- libs/gui/ISurfaceComposer.cpp | 72 ++++++-- libs/gui/SurfaceComposerClient.cpp | 25 ++- libs/gui/include/gui/ISurfaceComposer.h | 48 +++-- libs/gui/include/gui/SurfaceComposerClient.h | 33 ++-- libs/gui/tests/BLASTBufferQueue_test.cpp | 13 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 8 +- libs/gui/tests/Surface_test.cpp | 11 +- libs/nativedisplay/ADisplay.cpp | 29 +-- libs/ui/include/ui/DisplayConfig.h | 40 +++++ libs/ui/include/ui/DisplayInfo.h | 33 +--- libs/ui/include/ui/DisplayState.h | 40 +++++ libs/ui/include_vndk/ui/DisplayConfig.h | 1 + libs/ui/include_vndk/ui/DisplayState.h | 1 + opengl/tests/lib/WindowSurface.cpp | 40 +++-- services/automotive/display/CarWindowService.cpp | 44 +++-- services/surfaceflinger/DisplayDevice.cpp | 8 +- services/surfaceflinger/DisplayDevice.h | 18 +- services/surfaceflinger/SurfaceFlinger.cpp | 178 ++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 15 +- services/surfaceflinger/tests/Credentials_test.cpp | 37 ++-- .../surfaceflinger/tests/DisplayConfigs_test.cpp | 17 +- services/surfaceflinger/tests/IPC_test.cpp | 18 +- .../surfaceflinger/tests/LayerTransactionTest.h | 25 ++- services/surfaceflinger/tests/LayerUpdate_test.cpp | 14 +- .../tests/MultiDisplayLayerBounds_test.cpp | 21 ++- .../tests/SurfaceInterceptor_test.cpp | 25 ++- .../tests/TransactionTestHarnesses.h | 55 ++---- .../tests/fakehwc/SFFakeHwc_test.cpp | 194 +++++++++++---------- 29 files changed, 607 insertions(+), 475 deletions(-) create mode 100644 libs/ui/include/ui/DisplayConfig.h create mode 100644 libs/ui/include/ui/DisplayState.h create mode 120000 libs/ui/include_vndk/ui/DisplayConfig.h create mode 120000 libs/ui/include_vndk/ui/DisplayState.h (limited to 'cmds') diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp index d398559ee8..3a3df08534 100644 --- a/cmds/flatland/GLHelper.cpp +++ b/cmds/flatland/GLHelper.cpp @@ -14,15 +14,14 @@ * limitations under the License. */ +#include "GLHelper.h" + #include #include - -#include #include +#include -#include "GLHelper.h" - - namespace android { +namespace android { GLHelper::GLHelper() : mDisplay(EGL_NO_DISPLAY), @@ -228,15 +227,15 @@ bool GLHelper::computeWindowScale(uint32_t w, uint32_t h, float* scale) { return false; } - DisplayInfo info; - status_t err = mSurfaceComposerClient->getDisplayInfo(dpy, &info); + DisplayConfig config; + status_t err = mSurfaceComposerClient->getActiveDisplayConfig(dpy, &config); if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::getDisplayInfo failed: %#x\n", err); + fprintf(stderr, "SurfaceComposer::getActiveDisplayConfig failed: %#x\n", err); return false; } - float scaleX = float(info.w) / float(w); - float scaleY = float(info.h) / float(h); + float scaleX = static_cast(config.resolution.getWidth()) / w; + float scaleY = static_cast(config.resolution.getHeight()) / h; *scale = scaleX < scaleY ? scaleX : scaleY; return true; diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 073543cbf3..2f27fd20fd 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -34,8 +34,10 @@ #include +#include #include #include +#include #include #include @@ -351,22 +353,43 @@ public: remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply); } - virtual status_t getDisplayConfigs(const sp& display, - Vector* configs) - { + virtual status_t getDisplayState(const sp& display, ui::DisplayState* state) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_STATE, data, &reply); + const status_t result = reply.readInt32(); + if (result == NO_ERROR) { + memcpy(state, reply.readInplace(sizeof(ui::DisplayState)), sizeof(ui::DisplayState)); + } + return result; + } + + virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info) { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply); + const status_t result = reply.readInt32(); + if (result == NO_ERROR) { + memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo)); + } + return result; + } + + virtual status_t getDisplayConfigs(const sp& display, Vector* configs) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply); - status_t result = reply.readInt32(); + const status_t result = reply.readInt32(); if (result == NO_ERROR) { - size_t numConfigs = reply.readUint32(); + const size_t numConfigs = reply.readUint32(); configs->clear(); configs->resize(numConfigs); for (size_t c = 0; c < numConfigs; ++c) { - memcpy(&(configs->editItemAt(c)), - reply.readInplace(sizeof(DisplayInfo)), - sizeof(DisplayInfo)); + memcpy(&(configs->editItemAt(c)), reply.readInplace(sizeof(DisplayConfig)), + sizeof(DisplayConfig)); } } return result; @@ -1297,17 +1320,40 @@ status_t BnSurfaceComposer::onTransact( reply->writeStrongBinder(display); return NO_ERROR; } + case GET_DISPLAY_STATE: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + ui::DisplayState state; + const sp display = data.readStrongBinder(); + const status_t result = getDisplayState(display, &state); + reply->writeInt32(result); + if (result == NO_ERROR) { + memcpy(reply->writeInplace(sizeof(ui::DisplayState)), &state, + sizeof(ui::DisplayState)); + } + return NO_ERROR; + } + case GET_DISPLAY_INFO: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + DisplayInfo info; + const sp display = data.readStrongBinder(); + const status_t result = getDisplayInfo(display, &info); + reply->writeInt32(result); + if (result == NO_ERROR) { + memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo)); + } + return NO_ERROR; + } case GET_DISPLAY_CONFIGS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector configs; - sp display = data.readStrongBinder(); - status_t result = getDisplayConfigs(display, &configs); + Vector configs; + const sp display = data.readStrongBinder(); + const status_t result = getDisplayConfigs(display, &configs); reply->writeInt32(result); if (result == NO_ERROR) { reply->writeUint32(static_cast(configs.size())); for (size_t c = 0; c < configs.size(); ++c) { - memcpy(reply->writeInplace(sizeof(DisplayInfo)), - &configs[c], sizeof(DisplayInfo)); + memcpy(reply->writeInplace(sizeof(DisplayConfig)), &configs[c], + sizeof(DisplayConfig)); } } return NO_ERROR; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 63dc33376d..43bccf6c04 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -31,8 +31,6 @@ #include -#include - #include #include #include @@ -41,6 +39,7 @@ #include #include #include +#include #ifndef NO_INPUT #include