Merge "Align transaction trace timestamps with wm and sf trace" into rvc-dev
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 8dad475..be2c702 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -185,7 +185,7 @@
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 @@
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 a0b9cbb..1824943 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -148,14 +148,13 @@
}
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 ec2b922..772b9fe 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -239,6 +239,9 @@
}
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 @@
return true;
}
-
int64_t GetModuleMetadataVersion() {
auto binder = defaultServiceManager()->getService(android::String16("package_native"));
if (binder == nullptr) {
@@ -2171,7 +2173,7 @@
}
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 @@
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 @@
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 @@
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 @@
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 7b8d282..9ce662b 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -334,6 +334,9 @@
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 @@
// 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 eefbe4f..d773790 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -138,10 +138,10 @@
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 @@
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 @@
}
}
- // 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 @@
}
}
- // Check whether we have files in /data.
+ // Clear cached artifacts.
+ ClearDirectory(isa_path);
+
+ // Check whether we have a boot image.
// 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;
+ 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;
}
- // Check whether we have an image in /system.
- // 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);
- }
-
- return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
+ return true;
}
static bool CreatePath(const std::string& path) {
@@ -432,77 +416,6 @@
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 @@
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 abe6436..cbbea12 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -522,6 +522,11 @@
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 @@
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 0f4b4d9..3247fa1 100644
--- a/include/android/thermal.h
+++ b/include/android/thermal.h
@@ -109,7 +109,7 @@
* 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 5e4c98f..4f2709d 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -98,6 +98,15 @@
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 1eb5363..9e1249b 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -104,6 +104,18 @@
}
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 71d8130..74aece8 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -31,11 +31,16 @@
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 @@
* 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 @@
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 @@
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 @@
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 9108e31..0bb6d28 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -46,25 +46,24 @@
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 @@
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 e0248f6..1815ecc 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -39,13 +39,15 @@
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 efdecc4..6d711bc 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -34,6 +34,12 @@
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 c02e020..5e09fff 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 c2cda17..f1e8252 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -109,11 +109,11 @@
// 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 @@
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 40dc702..38f37ad 100644
--- a/libs/ui/tests/Size_test.cpp
+++ b/libs/ui/tests/Size_test.cpp
@@ -186,9 +186,34 @@
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 0000000..d391dce
--- /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 8ff0711..c3da216 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -40,4 +40,8 @@
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 0000000..464dcac
--- /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 aeffb0e..4c3b3e5 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -183,10 +183,7 @@
}
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 920f0ec..cd6075f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -419,20 +419,6 @@
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 20c8d7a..a9c3332 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -129,7 +129,12 @@
}
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 8315037..000628f 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 0000000..d391dce
--- /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 e607b05..5b9affd 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -1196,6 +1196,23 @@
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 @@
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 @@
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) {