diff options
25 files changed, 335 insertions, 215 deletions
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp index 8dad47502f..be2c702034 100644 --- a/cmds/cmd/cmd.cpp +++ b/cmds/cmd/cmd.cpp @@ -185,7 +185,7 @@ int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, Te int argc = argv.size(); if (argc == 0) { - errorLog << "cmd: No service specified; use -l to list all services" << endl; + errorLog << "cmd: No service specified; use -l to list all running services. Use -w to start and wait for a service." << endl; return 20; } @@ -203,14 +203,22 @@ int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, Te return 0; } - const auto cmd = argv[0]; + bool waitForService = ((argc > 1) && (argv[0] == "-w")); + int serviceIdx = (waitForService) ? 1 : 0; + const auto cmd = argv[serviceIdx]; Vector<String16> args; String16 serviceName = String16(cmd.data(), cmd.size()); - for (int i = 1; i < argc; i++) { + for (int i = serviceIdx + 1; i < argc; i++) { args.add(String16(argv[i].data(), argv[i].size())); } - sp<IBinder> service = sm->checkService(serviceName); + sp<IBinder> service; + if(waitForService) { + service = sm->waitForService(serviceName); + } else { + service = sm->checkService(serviceName); + } + if (service == nullptr) { if (runMode == RunMode::kStandalone) { ALOGW("Can't find service %.*s", static_cast<int>(cmd.size()), cmd.data()); diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index a0b9cbbe20..1824943eb2 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -148,14 +148,13 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, } binder::Status DumpstateService::cancelBugreport() { - // This is a no-op since the cancellation is done from java side via setting sys properties. - // See BugreportManagerServiceImpl. - // TODO(b/111441001): maybe make native and java sides use different binder interface - // to avoid these annoyances. + std::lock_guard<std::mutex> lock(lock_); + ds_->Cancel(); return binder::Status::ok(); } status_t DumpstateService::dump(int fd, const Vector<String16>&) { + std::lock_guard<std::mutex> lock(lock_); if (ds_ == nullptr) { dprintf(fd, "Bugreport not in progress yet"); return NO_ERROR; diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index ec2b92255f..772b9fe069 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -239,6 +239,9 @@ static bool CopyFileToFd(const std::string& input_file, int out_fd) { } static bool UnlinkAndLogOnError(const std::string& file) { + if (file.empty()) { + return false; + } if (unlink(file.c_str())) { MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno)); return false; @@ -246,7 +249,6 @@ static bool UnlinkAndLogOnError(const std::string& file) { return true; } - int64_t GetModuleMetadataVersion() { auto binder = defaultServiceManager()->getService(android::String16("package_native")); if (binder == nullptr) { @@ -2171,7 +2173,7 @@ static void PrepareToWriteToFile() { } if (ds.options_->do_screenshot) { - ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.png" : ".png"); + ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png"); } ds.tmp_path_ = ds.GetPath(".tmp"); ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt"); @@ -2190,7 +2192,7 @@ static void PrepareToWriteToFile() { ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); if (ds.options_->do_zip_file) { - ds.path_ = ds.GetPath(ds.CalledByApi() ? "-tmp.zip" : ".zip"); + ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".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")); @@ -2419,6 +2421,17 @@ Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& call return status; } +void Dumpstate::Cancel() { + CleanupTmpFiles(); + android::os::UnlinkAndLogOnError(log_path_); + for (int i = 0; i < NUM_OF_DUMPS; i++) { + android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" + + kDumpstateBoardFiles[i]); + } + tombstone_data_.clear(); + anr_data_.clear(); +} + /* * Dumps relevant information to a bugreport based on the given options. * @@ -2755,7 +2768,7 @@ bool Dumpstate::CalledByApi() const { return ds.options_->bugreport_fd.get() != -1 ? true : false; } -void Dumpstate::CleanupFiles() { +void Dumpstate::CleanupTmpFiles() { android::os::UnlinkAndLogOnError(tmp_path_); android::os::UnlinkAndLogOnError(screenshot_path_); android::os::UnlinkAndLogOnError(path_); @@ -2763,7 +2776,7 @@ void Dumpstate::CleanupFiles() { Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() { MYLOGD("User denied consent; deleting files and returning\n"); - CleanupFiles(); + CleanupTmpFiles(); return USER_CONSENT_DENIED; } diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 7b8d2821e5..9ce662b255 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -334,6 +334,9 @@ class Dumpstate { RunStatus ParseCommandlineAndRun(int argc, char* argv[]); + /* Deletes in-progress files */ + void Cancel(); + /* Sets runtime options. */ void SetOptions(std::unique_ptr<DumpOptions> options); @@ -502,7 +505,7 @@ class Dumpstate { // Removes the in progress files output files (tmp file, zip/txt file, screenshot), // but leaves the log file alone. - void CleanupFiles(); + void CleanupTmpFiles(); RunStatus HandleUserConsentDenied(); diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp index eefbe4ffe2..d773790091 100644 --- a/cmds/installd/otapreopt.cpp +++ b/cmds/installd/otapreopt.cpp @@ -138,10 +138,10 @@ class OTAPreoptService { return 4; } - PrepareEnvironment(); + PrepareEnvironmentVariables(); - if (!PrepareBootImage(/* force */ false)) { - LOG(ERROR) << "Failed preparing boot image."; + if (!EnsureBootImageAndDalvikCache()) { + LOG(ERROR) << "Bad boot image."; return 5; } @@ -302,7 +302,7 @@ private: return parameters_.ReadArguments(argc, const_cast<const char**>(argv)); } - void PrepareEnvironment() { + void PrepareEnvironmentVariables() { environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_classpath_.c_str())); environ_.push_back(StringPrintf("ANDROID_DATA=%s", GetOTADataDirectory().c_str())); environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root_.c_str())); @@ -312,9 +312,8 @@ private: } } - // Ensure that we have the right boot image. The first time any app is - // compiled, we'll try to generate it. - bool PrepareBootImage(bool force) const { + // Ensure that we have the right boot image and cache file structures. + bool EnsureBootImageAndDalvikCache() const { if (parameters_.instruction_set == nullptr) { LOG(ERROR) << "Instruction set missing."; return false; @@ -340,34 +339,19 @@ private: } } - // Check whether we have files in /data. - // TODO: check that the files are correct wrt/ jars. - std::string art_path = isa_path + "/system@framework@boot.art"; - std::string oat_path = isa_path + "/system@framework@boot.oat"; - bool cleared = false; - if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) { - // Files exist, assume everything is alright if not forced. Otherwise clean up. - if (!force) { - return true; - } - ClearDirectory(isa_path); - cleared = true; - } + // Clear cached artifacts. + ClearDirectory(isa_path); - // Check whether we have an image in /system. + // Check whether we have a boot image. // TODO: check that the files are correct wrt/ jars. - std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa); - if (access(preopted_boot_art_path.c_str(), F_OK) == 0) { - // Note: we ignore |force| here. - return true; - } - - - if (!cleared) { - ClearDirectory(isa_path); + std::string preopted_boot_art_path = + StringPrintf("/apex/com.android.art/javalib/%s/boot.art", isa); + if (access(preopted_boot_art_path.c_str(), F_OK) != 0) { + PLOG(ERROR) << "Bad access() to " << preopted_boot_art_path; + return false; } - return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa); + return true; } static bool CreatePath(const std::string& path) { @@ -432,77 +416,6 @@ private: CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory."; } - bool Dex2oatBootImage(const std::string& boot_cp, - const std::string& art_path, - const std::string& oat_path, - const char* isa) const { - // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc. - std::vector<std::string> cmd; - cmd.push_back(kDex2oatPath); - cmd.push_back(StringPrintf("--image=%s", art_path.c_str())); - for (const std::string& boot_part : Split(boot_cp, ":")) { - cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str())); - } - cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str())); - - int32_t base_offset = ChooseRelocationOffsetDelta( - art::imagevalues::GetImageMinBaseAddressDelta(), - art::imagevalues::GetImageMaxBaseAddressDelta()); - cmd.push_back(StringPrintf("--base=0x%x", - art::imagevalues::GetImageBaseAddress() + base_offset)); - - cmd.push_back(StringPrintf("--instruction-set=%s", isa)); - - // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp. - AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms", - "-Xms", - true, - cmd); - AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx", - "-Xmx", - true, - cmd); - AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter", - "--compiler-filter=", - false, - cmd); - cmd.push_back("--profile-file=/system/etc/boot-image.prof"); - // TODO: Compiled-classes. - const std::string* extra_opts = - system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags"); - if (extra_opts != nullptr) { - std::vector<std::string> extra_vals = Split(*extra_opts, " "); - cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end()); - } - // TODO: Should we lower this? It's usually set close to max, because - // normally there's not much else going on at boot. - AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads", - "-j", - false, - cmd); - AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-cpu-set", - "--cpu-set=", - false, - cmd); - AddCompilerOptionFromSystemProperty( - StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(), - "--instruction-set-variant=", - false, - cmd); - AddCompilerOptionFromSystemProperty( - StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(), - "--instruction-set-features=", - false, - cmd); - - std::string error_msg; - bool result = Exec(cmd, &error_msg); - if (!result) { - LOG(ERROR) << "Could not generate boot image: " << error_msg; - } - return result; - } - static const char* ParseNull(const char* arg) { return (strcmp(arg, "!") == 0) ? nullptr : arg; } @@ -592,22 +505,6 @@ private: return 0; } - // If the dexopt failed, we may have a stale boot image from a previous OTA run. - // Then regenerate and retry. - if (WEXITSTATUS(dexopt_result) == - static_cast<int>(::art::dex2oat::ReturnCode::kCreateRuntime)) { - if (!PrepareBootImage(/* force */ true)) { - LOG(ERROR) << "Forced boot image creating failed. Original error return was " - << dexopt_result; - return dexopt_result; - } - - int dexopt_result_boot_image_retry = Dexopt(); - if (dexopt_result_boot_image_retry == 0) { - return 0; - } - } - // If this was a profile-guided run, we may have profile version issues. Try to downgrade, // if possible. if ((parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) { diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index abe64365f3..cbbea128a6 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -522,6 +522,11 @@ Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IB return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); } + if (serviceIt->second.guaranteeClient) { + LOG(INFO) << "Tried to unregister " << name << ", but there is about to be a client."; + return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); + } + int clients = handleServiceClientCallback(name, false); // clients < 0: feature not implemented or other error. Assume clients. @@ -532,6 +537,8 @@ Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IB if (clients < 0 || clients > 2) { // client callbacks are either disabled or there are other clients LOG(INFO) << "Tried to unregister " << name << ", but there are clients: " << clients; + // Set this flag to ensure the clients are acknowledged in the next callback + serviceIt->second.guaranteeClient = true; return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE); } diff --git a/include/android/thermal.h b/include/android/thermal.h index 0f4b4d9b8d..3247fa167b 100644 --- a/include/android/thermal.h +++ b/include/android/thermal.h @@ -109,7 +109,7 @@ typedef struct AThermalManager AThermalManager; * It's passed the updated thermal status as parameter, as well as the * pointer provided by the client that registered a callback. */ -typedef int (*AThermal_StatusCallback)(void *data, AThermalStatus status); +typedef void (*AThermal_StatusCallback)(void *data, AThermalStatus status); /** * Acquire an instance of the thermal manager. This must be freed using diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp index 5e4c98fc7a..4f2709d91a 100644 --- a/libs/binder/ActivityManager.cpp +++ b/libs/binder/ActivityManager.cpp @@ -98,6 +98,15 @@ int32_t ActivityManager::getUidProcessState(const uid_t uid, const String16& cal return PROCESS_STATE_UNKNOWN; } +bool ActivityManager::isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) +{ + sp<IActivityManager> service = getService(); + if (service != nullptr) { + return service->isUidActiveOrForeground(uid, callingPackage); + } + return false; +} + status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) { sp<IActivityManager> service = getService(); if (service != nullptr) { diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp index 1eb5363ae2..9e1249baf4 100644 --- a/libs/binder/IActivityManager.cpp +++ b/libs/binder/IActivityManager.cpp @@ -104,6 +104,18 @@ public: } return reply.readInt32(); } + + virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) + { + Parcel data, reply; + data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor()); + data.writeInt32(uid); + data.writeString16(callingPackage); + remote()->transact(IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION, data, &reply); + // fail on exception + if (reply.readExceptionCode() != 0) return false; + return reply.readInt32() == 1; + } }; // ------------------------------------------------------------------------------------ diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp index 71d8130df9..74aece81f7 100644 --- a/libs/binder/LazyServiceRegistrar.cpp +++ b/libs/binder/LazyServiceRegistrar.cpp @@ -31,11 +31,16 @@ using AidlServiceManager = android::os::IServiceManager; class ClientCounterCallback : public ::android::os::BnClientCallback { public: - ClientCounterCallback() : mNumConnectedServices(0) {} + ClientCounterCallback() : mNumConnectedServices(0), mForcePersist(false) {} bool registerService(const sp<IBinder>& service, const std::string& name, bool allowIsolated, int dumpFlags); + /** + * Set a flag to prevent services from automatically shutting down + */ + void forcePersist(bool persist); + protected: Status onClients(const sp<IBinder>& service, bool clients) override; @@ -60,6 +65,8 @@ private: * Map of registered names and services */ std::map<std::string, Service> mRegisteredServices; + + bool mForcePersist; }; bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name, @@ -88,6 +95,14 @@ bool ClientCounterCallback::registerService(const sp<IBinder>& service, const st return true; } +void ClientCounterCallback::forcePersist(bool persist) { + mForcePersist = persist; + if(!mForcePersist) { + // Attempt a shutdown in case the number of clients hit 0 while the flag was on + tryShutdown(); + } +} + /** * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple * invocations could occur on different threads however. @@ -103,14 +118,21 @@ Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients mNumConnectedServices, mRegisteredServices.size(), String8(service->getInterfaceDescriptor()).string(), clients); - if (mNumConnectedServices == 0) { - tryShutdown(); - } - + tryShutdown(); return Status::ok(); } void ClientCounterCallback::tryShutdown() { + if(mNumConnectedServices > 0) { + // Should only shut down if there are no clients + return; + } + + if(mForcePersist) { + ALOGI("Shutdown prevented by forcePersist override flag."); + return; + } + ALOGI("Trying to shut down the service. No clients in use for any service in process."); auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); @@ -165,5 +187,9 @@ status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const return OK; } +void LazyServiceRegistrar::forcePersist(bool persist) { + mClientCC->forcePersist(persist); +} + } // namespace hardware } // namespace android
\ No newline at end of file diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h index 9108e31758..0bb6d28da4 100644 --- a/libs/binder/include/binder/ActivityManager.h +++ b/libs/binder/include/binder/ActivityManager.h @@ -46,25 +46,24 @@ public: PROCESS_STATE_PERSISTENT = 0, PROCESS_STATE_PERSISTENT_UI = 1, PROCESS_STATE_TOP = 2, - PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3, - PROCESS_STATE_BOUND_TOP = 4, - PROCESS_STATE_FOREGROUND_SERVICE = 5, - PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6, - PROCESS_STATE_IMPORTANT_FOREGROUND = 7, - PROCESS_STATE_IMPORTANT_BACKGROUND = 8, - PROCESS_STATE_TRANSIENT_BACKGROUND = 9, - PROCESS_STATE_BACKUP = 10, - PROCESS_STATE_SERVICE = 11, - PROCESS_STATE_RECEIVER = 12, - PROCESS_STATE_TOP_SLEEPING = 13, - PROCESS_STATE_HEAVY_WEIGHT = 14, - PROCESS_STATE_HOME = 15, - PROCESS_STATE_LAST_ACTIVITY = 16, - PROCESS_STATE_CACHED_ACTIVITY = 17, - PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18, - PROCESS_STATE_CACHED_RECENT = 19, - PROCESS_STATE_CACHED_EMPTY = 20, - PROCESS_STATE_NONEXISTENT = 21, + PROCESS_STATE_BOUND_TOP = 3, + PROCESS_STATE_FOREGROUND_SERVICE = 4, + PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5, + PROCESS_STATE_IMPORTANT_FOREGROUND = 6, + PROCESS_STATE_IMPORTANT_BACKGROUND = 7, + PROCESS_STATE_TRANSIENT_BACKGROUND = 8, + PROCESS_STATE_BACKUP = 9, + PROCESS_STATE_SERVICE = 10, + PROCESS_STATE_RECEIVER = 11, + PROCESS_STATE_TOP_SLEEPING = 12, + PROCESS_STATE_HEAVY_WEIGHT = 13, + PROCESS_STATE_HOME = 14, + PROCESS_STATE_LAST_ACTIVITY = 15, + PROCESS_STATE_CACHED_ACTIVITY = 16, + PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17, + PROCESS_STATE_CACHED_RECENT = 18, + PROCESS_STATE_CACHED_EMPTY = 19, + PROCESS_STATE_NONEXISTENT = 20, }; ActivityManager(); @@ -77,6 +76,7 @@ public: void unregisterUidObserver(const sp<IUidObserver>& observer); bool isUidActive(const uid_t uid, const String16& callingPackage); int getUidProcessState(const uid_t uid, const String16& callingPackage); + bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage); status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient); diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h index e0248f6624..1815ecc67f 100644 --- a/libs/binder/include/binder/IActivityManager.h +++ b/libs/binder/include/binder/IActivityManager.h @@ -39,13 +39,15 @@ public: virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0; virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0; virtual int32_t getUidProcessState(const uid_t uid, const String16& callingPackage) = 0; + virtual bool isUidActiveOrForeground(const uid_t uid, const String16& callingPackage) = 0; enum { OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, REGISTER_UID_OBSERVER_TRANSACTION, UNREGISTER_UID_OBSERVER_TRANSACTION, IS_UID_ACTIVE_TRANSACTION, - GET_UID_PROCESS_STATE_TRANSACTION + GET_UID_PROCESS_STATE_TRANSACTION, + IS_UID_ACTIVE_OR_FOREGROUND_TRANSACTION, }; }; diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h index efdecc4eca..6d711bc10f 100644 --- a/libs/binder/include/binder/LazyServiceRegistrar.h +++ b/libs/binder/include/binder/LazyServiceRegistrar.h @@ -34,6 +34,12 @@ class LazyServiceRegistrar { const std::string& name = "default", bool allowIsolated = false, int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT); + /** + * Force the service to persist, even when it has 0 clients. + * If setting this flag from the server side, make sure to do so before calling registerService, + * or there may be a race with the default dynamic shutdown. + */ + void forcePersist(bool persist); private: std::shared_ptr<internal::ClientCounterCallback> mClientCC; diff --git a/libs/gui/tests/AndroidTest.xml b/libs/gui/tests/AndroidTest.xml index c02e020be6..5e09fff6bb 100644 --- a/libs/gui/tests/AndroidTest.xml +++ b/libs/gui/tests/AndroidTest.xml @@ -18,6 +18,10 @@ <option name="cleanup" value="true" /> <option name="push" value="libgui_test->/data/local/tmp/libgui_test" /> </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device --> + <option name="screen-always-on" value="on" /> + </target_preparer> <option name="test-suite-tag" value="apct" /> <test class="com.android.tradefed.testtype.GTest" > <option name="native-test-device-path" value="/data/local/tmp" /> diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h index c2cda17a6f..f1e825286e 100644 --- a/libs/ui/include/ui/Size.h +++ b/libs/ui/include/ui/Size.h @@ -109,11 +109,11 @@ struct Size { // Takes a value of type FromType, and ensures it can be represented as a value of type ToType, // clamping the input value to the output range if necessary. template <typename ToType, typename FromType> - static Size::remove_cv_reference_t<ToType> clamp( - typename std::enable_if< - std::numeric_limits<Size::remove_cv_reference_t<ToType>>::is_bounded && - std::numeric_limits<Size::remove_cv_reference_t<FromType>>::is_bounded, - FromType&&>::type v) { + static Size::remove_cv_reference_t<ToType> + clamp(typename std::enable_if< + std::numeric_limits<Size::remove_cv_reference_t<ToType>>::is_specialized && + std::numeric_limits<Size::remove_cv_reference_t<FromType>>::is_specialized, + FromType>::type v) { using BareToType = remove_cv_reference_t<ToType>; using BareFromType = remove_cv_reference_t<FromType>; static constexpr auto toHighest = std::numeric_limits<BareToType>::max(); @@ -121,21 +121,58 @@ struct Size { static constexpr auto fromHighest = std::numeric_limits<BareFromType>::max(); static constexpr auto fromLowest = std::numeric_limits<BareFromType>::lowest(); - // A clamp is needed if the range of FromType is not a subset of the range of ToType - static constexpr bool isClampNeeded = (toLowest > fromLowest) || (toHighest < fromHighest); + // Get the closest representation of [toLowest, toHighest] in type + // FromType to use to clamp the input value before conversion. + + // std::common_type<...> is used to get a value-preserving type for the + // top end of the range. + using CommonHighestType = std::common_type_t<BareToType, BareFromType>; + + // std::make_signed<std::common_type<...>> is used to get a + // value-preserving type for the bottom end of the range, except this is + // a bit trickier for non-integer types like float. + using CommonLowestType = + std::conditional_t<std::numeric_limits<CommonHighestType>::is_integer, + std::make_signed_t<std::conditional_t< + std::numeric_limits<CommonHighestType>::is_integer, + CommonHighestType, int /* not used */>>, + CommonHighestType>; + + // We can then compute the clamp range in a way that can be later + // trivially converted to either the 'from' or 'to' types, and be + // representabile in either. + static constexpr auto commonClampHighest = + std::min(static_cast<CommonHighestType>(fromHighest), + static_cast<CommonHighestType>(toHighest)); + static constexpr auto commonClampLowest = + std::max(static_cast<CommonLowestType>(fromLowest), + static_cast<CommonLowestType>(toLowest)); + + static constexpr auto fromClampHighest = static_cast<BareFromType>(commonClampHighest); + static constexpr auto fromClampLowest = static_cast<BareFromType>(commonClampLowest); + + // A clamp is needed only if the range we are clamping to is not the + // same as the range of the input. + static constexpr bool isClampNeeded = + (fromLowest != fromClampLowest) || (fromHighest != fromClampHighest); // If a clamp is not needed, the conversion is just a trivial cast. if (!isClampNeeded) { - return static_cast<ToType>(v); + return static_cast<BareToType>(v); } - // Otherwise we need to carefully compare the limits of ToType (casted - // for the comparisons to be warning free to FromType) while still - // ensuring we return a value clamped to the range of ToType. - return v < static_cast<const BareFromType>(toLowest) - ? toLowest - : (v > static_cast<const BareFromType>(toHighest) ? toHighest - : static_cast<ToType>(v)); + // Note: Clang complains about the value of INT32_MAX not being + // convertible back to int32_t from float if this is made "constexpr", + // when clamping a float value to an int32_t value. This is however + // covered by a test case to ensure the run-time cast works correctly. + const auto toClampHighest = static_cast<BareToType>(commonClampHighest); + const auto toClampLowest = static_cast<BareToType>(commonClampLowest); + + // Otherwise clamping is done by using the already computed endpoints + // for each type. + return (v <= fromClampLowest) + ? toClampLowest + : ((v >= fromClampHighest) ? toClampHighest : static_cast<BareToType>(v)); } }; diff --git a/libs/ui/tests/Size_test.cpp b/libs/ui/tests/Size_test.cpp index 40dc702a8b..38f37ad827 100644 --- a/libs/ui/tests/Size_test.cpp +++ b/libs/ui/tests/Size_test.cpp @@ -186,9 +186,34 @@ TEST(SizeTest, Int8RangeIsNotClamped) { TEST(SizeTest, FloatRangeIsClamped) { ClampTest(std::numeric_limits<float>::max(), std::numeric_limits<int32_t>::max()); + ClampTest(nexttowardf(std::numeric_limits<int32_t>::max(), std::numeric_limits<float>::max()), + std::numeric_limits<int32_t>::max()); + ClampTest(static_cast<float>(std::numeric_limits<int32_t>::max()), + std::numeric_limits<int32_t>::max()); + ClampTest(nexttowardf(std::numeric_limits<int32_t>::max(), 0), + static_cast<int32_t>(nexttowardf(std::numeric_limits<int32_t>::max(), 0))); ClampTest(float(0), int32_t(0)); + ClampTest(nexttowardf(std::numeric_limits<int32_t>::lowest(), 0), + static_cast<int32_t>(nexttowardf(std::numeric_limits<int32_t>::lowest(), 0))); + ClampTest(static_cast<float>(std::numeric_limits<int32_t>::lowest()), + std::numeric_limits<int32_t>::lowest()); + ClampTest(nexttowardf(std::numeric_limits<int32_t>::lowest(), + std::numeric_limits<float>::lowest()), + std::numeric_limits<int32_t>::lowest()); ClampTest(std::numeric_limits<float>::lowest(), std::numeric_limits<int32_t>::lowest()); } +TEST(SizeTest, Uint32RangeIsClamped) { + ClampTest(std::numeric_limits<uint32_t>::max(), std::numeric_limits<int32_t>::max()); + ClampTest(std::numeric_limits<uint32_t>::max() - 1, std::numeric_limits<int32_t>::max()); + ClampTest(static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) + 1, + std::numeric_limits<int32_t>::max()); + ClampTest(static_cast<uint32_t>(std::numeric_limits<int32_t>::max()), + std::numeric_limits<int32_t>::max()); + ClampTest(static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) - 1, + std::numeric_limits<int32_t>::max() - 1); + ClampTest(uint32_t(0), int32_t(0)); +} + } // namespace ui } // namespace android diff --git a/opengl/TEST_MAPPING b/opengl/TEST_MAPPING new file mode 100644 index 0000000000..d391dce2de --- /dev/null +++ b/opengl/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "CtsGpuToolsHostTestCases" + } + ] +} diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp index 8ff0711f55..c3da216002 100644 --- a/services/automotive/display/Android.bp +++ b/services/automotive/display/Android.bp @@ -40,4 +40,8 @@ cc_binary { cflags: [ "-DLOG_TAG=\"AutomotiveDisplayService\"" ], + + vintf_fragments: [ + "manifest_android.frameworks.automotive.display@1.0.xml", + ], } diff --git a/services/automotive/display/manifest_android.frameworks.automotive.display@1.0.xml b/services/automotive/display/manifest_android.frameworks.automotive.display@1.0.xml new file mode 100644 index 0000000000..464dcac8bb --- /dev/null +++ b/services/automotive/display/manifest_android.frameworks.automotive.display@1.0.xml @@ -0,0 +1,11 @@ +<manifest version="1.0" type="framework"> + <hal> + <name>android.frameworks.automotive.display</name> + <transport>hwbinder</transport> + <version>1.0</version> + <interface> + <name>IAutomotiveDisplayProxyService</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index aeffb0e185..4c3b3e502d 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -183,10 +183,7 @@ void FramebufferSurface::onFrameCommitted() { } ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) { - // TODO(b/149495759): Use the ui::Size constructor once it no longer is broken. - ui::Size framebufferSize; - framebufferSize.width = width; - framebufferSize.height = height; + ui::Size framebufferSize(width, height); bool wasLimited = true; if (width > mMaxWidth && mMaxWidth != 0) { float aspectRatio = float(width) / float(height); diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 920f0ec331..cd6075f5b4 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -419,20 +419,6 @@ void Scheduler::registerLayer(Layer* layer) { mRefreshRateConfigs.getMaxRefreshRate().fps, scheduler::LayerHistory::LayerVoteType::Heuristic); } - - // TODO(146935143): Simulate youtube app vote. This should be removed once youtube calls the - // API to set desired rate - { - const auto vote = property_get_int32("experimental.sf.force_youtube_vote", 0); - if (vote != 0 && - layer->getName() == - "SurfaceView - " - "com.google.android.youtube/" - "com.google.android.apps.youtube.app.WatchWhileActivity#0") { - layer->setFrameRate( - Layer::FrameRate(vote, Layer::FrameRateCompatibility::ExactOrMultiple)); - } - } } } diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index 20c8d7a3aa..a9c33327c8 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -129,7 +129,12 @@ void SurfaceTracing::enable() { } status_t SurfaceTracing::writeToFile() { - mThread.join(); + std::thread thread; + { + std::scoped_lock lock(mTraceLock); + thread = std::move(mThread); + } + thread.join(); return mLastErr; } diff --git a/services/surfaceflinger/tests/AndroidTest.xml b/services/surfaceflinger/tests/AndroidTest.xml index 8315037b94..000628f598 100644 --- a/services/surfaceflinger/tests/AndroidTest.xml +++ b/services/surfaceflinger/tests/AndroidTest.xml @@ -18,6 +18,7 @@ <option name="cleanup" value="true" /> <option name="push" value="SurfaceFlinger_test->/data/local/tmp/SurfaceFlinger_test" /> </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> <option name="test-suite-tag" value="apct" /> <test class="com.android.tradefed.testtype.GTest" > <option name="native-test-device-path" value="/data/local/tmp" /> diff --git a/vulkan/TEST_MAPPING b/vulkan/TEST_MAPPING new file mode 100644 index 0000000000..d391dce2de --- /dev/null +++ b/vulkan/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "CtsGpuToolsHostTestCases" + } + ] +} diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index e607b058eb..5b9affd03a 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -1196,6 +1196,23 @@ bool EnsureInitialized() { return initialized; } +template <typename Functor> +void ForEachLayerFromSettings(Functor functor) { + const std::string layersSetting = + android::GraphicsEnv::getInstance().getDebugLayers(); + if (!layersSetting.empty()) { + std::vector<std::string> layers = + android::base::Split(layersSetting, ":"); + for (uint32_t i = 0; i < layers.size(); i++) { + const Layer* layer = FindLayer(layers[i].c_str()); + if (!layer) { + continue; + } + functor(layer); + } + } +} + } // anonymous namespace VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, @@ -1291,28 +1308,18 @@ VkResult EnumerateInstanceExtensionProperties( std::unordered_set<std::string> extensionNames; // Expose extensions from implicitly enabled layers. - const std::string layersSetting = - android::GraphicsEnv::getInstance().getDebugLayers(); - if (!layersSetting.empty()) { - std::vector<std::string> layers = - android::base::Split(layersSetting, ":"); - for (uint32_t i = 0; i < layers.size(); i++) { - const Layer* layer = FindLayer(layers[i].c_str()); - if (!layer) { - continue; - } - uint32_t count = 0; - const VkExtensionProperties* props = - GetLayerInstanceExtensions(*layer, count); - if (count > 0) { - for (uint32_t i = 0; i < count; ++i) { - if (extensionNames.emplace(props[i].extensionName).second) { - properties.push_back(props[i]); - } + ForEachLayerFromSettings([&](const Layer* layer) { + uint32_t count = 0; + const VkExtensionProperties* props = + GetLayerInstanceExtensions(*layer, count); + if (count > 0) { + for (uint32_t i = 0; i < count; ++i) { + if (extensionNames.emplace(props[i].extensionName).second) { + properties.push_back(props[i]); } } } - } + }); // TODO(b/143293104): Parse debug.vulkan.layers properties @@ -1393,10 +1400,57 @@ VkResult EnumerateDeviceExtensionProperties( return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS; } - // TODO(b/143293104): expose extensions from implicitly enabled layers - const InstanceData& data = GetData(physicalDevice); - return data.dispatch.EnumerateDeviceExtensionProperties( - physicalDevice, nullptr, pPropertyCount, pProperties); + // If the pLayerName is nullptr, we must advertise all device extensions + // from all implicitly enabled layers and the driver implementation. If + // there are duplicates among layers and the driver implementation, always + // only preserve the top layer closest to the application regardless of the + // spec version. + std::vector<VkExtensionProperties> properties; + std::unordered_set<std::string> extensionNames; + + // Expose extensions from implicitly enabled layers. + ForEachLayerFromSettings([&](const Layer* layer) { + uint32_t count = 0; + const VkExtensionProperties* props = + GetLayerDeviceExtensions(*layer, count); + if (count > 0) { + for (uint32_t i = 0; i < count; ++i) { + if (extensionNames.emplace(props[i].extensionName).second) { + properties.push_back(props[i]); + } + } + } + }); + + // TODO(b/143293104): Parse debug.vulkan.layers properties + + // Expose extensions from driver implementation. + { + const InstanceData& data = GetData(physicalDevice); + uint32_t count = 0; + VkResult result = data.dispatch.EnumerateDeviceExtensionProperties( + physicalDevice, nullptr, &count, nullptr); + if (result == VK_SUCCESS && count > 0) { + std::vector<VkExtensionProperties> props(count); + result = data.dispatch.EnumerateDeviceExtensionProperties( + physicalDevice, nullptr, &count, props.data()); + for (auto prop : props) { + if (extensionNames.emplace(prop.extensionName).second) { + properties.push_back(prop); + } + } + } + } + + uint32_t totalCount = properties.size(); + if (!pProperties || *pPropertyCount > totalCount) { + *pPropertyCount = totalCount; + } + if (pProperties) { + std::copy(properties.data(), properties.data() + *pPropertyCount, + pProperties); + } + return *pPropertyCount < totalCount ? VK_INCOMPLETE : VK_SUCCESS; } VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) { |