Merge "Status: toString8, include stringified status_t"
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 40b8dc7..bb92fd3 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -20,9 +20,11 @@
"android.hardware.vibrator@1.2",
"android.hardware.vibrator@1.3",
"libbase",
+ "libbinder",
"libhidlbase",
"liblog",
"libutils",
+ "vintf-vibrator-cpp",
],
cflags: [
"-DLOG_TAG=\"idlcli\"",
@@ -34,6 +36,7 @@
defaults: ["idlcli-defaults"],
srcs: [
"CommandVibrator.cpp",
+ "vibrator/CommandGetCapabilities.cpp",
"vibrator/CommandOff.cpp",
"vibrator/CommandOn.cpp",
"vibrator/CommandPerform.cpp",
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
index bcb207b..2f11923 100644
--- a/cmds/idlcli/vibrator.h
+++ b/cmds/idlcli/vibrator.h
@@ -18,6 +18,8 @@
#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
#include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IServiceManager.h>
#include "utils.h"
@@ -31,9 +33,25 @@
// Creates a Return<R> with STATUS::EX_NULL_POINTER.
template <class R>
-inline Return<R> NullptrStatus() {
+inline R NullptrStatus() {
using ::android::hardware::Status;
- return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+}
+
+template <>
+inline binder::Status NullptrStatus() {
+ using binder::Status;
+ return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+}
+
+template <typename I>
+inline sp<I> getService() {
+ return I::getService();
+}
+
+template <>
+inline sp<hardware::vibrator::IVibrator> getService() {
+ return waitForVintfService<hardware::vibrator::IVibrator>();
}
template <typename I>
@@ -42,12 +60,12 @@
static std::unique_ptr<HalWrapper> Create() {
// Assume that if getService returns a nullptr, HAL is not available on the
// device.
- auto hal = I::getService();
+ auto hal = getService<I>();
return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
}
template <class R, class... Args0, class... Args1>
- Return<R> call(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+ R call(R (I::*fn)(Args0...), Args1&&... args1) {
return (*mHal.*fn)(std::forward<Args1>(args1)...);
}
@@ -65,7 +83,7 @@
}
template <class R, class I, class... Args0, class... Args1>
-Return<R> halCall(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+R halCall(R (I::*fn)(Args0...), Args1&&... args1) {
auto hal = getHal<I>();
return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
}
@@ -77,6 +95,7 @@
namespace V1_1 = ::android::hardware::vibrator::V1_1;
namespace V1_2 = ::android::hardware::vibrator::V1_2;
namespace V1_3 = ::android::hardware::vibrator::V1_3;
+namespace aidl = ::android::hardware::vibrator;
} // namespace vibrator
} // namespace idlcli
diff --git a/cmds/idlcli/vibrator/CommandGetCapabilities.cpp b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
new file mode 100644
index 0000000..30d8587
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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 "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetCapabilities : public Command {
+ std::string getDescription() const override { return "Retrieves vibrator capabilities."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ std::string statusStr;
+ int32_t cap;
+ Status ret;
+
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::getCapabilities, &cap);
+ statusStr = status.toString8();
+ ret = status.isOk() ? OK : ERROR;
+ } else {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << statusStr << std::endl;
+ std::cout << "Capabilities: " << std::bitset<32>(cap) << std::endl;
+
+ return ret;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandGetCapabilities>("getCapabilities");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp
index a674f01..53fada0 100644
--- a/cmds/idlcli/vibrator/CommandOff.cpp
+++ b/cmds/idlcli/vibrator/CommandOff.cpp
@@ -42,15 +42,24 @@
}
Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::off);
+ std::string statusStr;
+ Status ret;
- if (!ret.isOk()) {
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::off);
+ statusStr = status.toString8();
+ ret = status.isOk() ? OK : ERROR;
+ } else if (auto hal = getHal<V1_0::IVibrator>()) {
+ auto status = hal->call(&V1_0::IVibrator::off);
+ statusStr = toString(status);
+ ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+ } else {
return UNAVAILABLE;
}
- std::cout << "Status: " << toString(ret) << std::endl;
+ std::cout << "Status: " << statusStr << std::endl;
- return ret == V1_0::Status::OK ? OK : ERROR;
+ return ret;
}
};
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
index 2164b7d..ccb3c19 100644
--- a/cmds/idlcli/vibrator/CommandOn.cpp
+++ b/cmds/idlcli/vibrator/CommandOn.cpp
@@ -50,15 +50,24 @@
}
Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::on, mDuration);
+ std::string statusStr;
+ Status ret;
- if (!ret.isOk()) {
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::on, mDuration, nullptr);
+ statusStr = status.toString8();
+ ret = status.isOk() ? OK : ERROR;
+ } else if (auto hal = getHal<V1_0::IVibrator>()) {
+ auto status = hal->call(&V1_0::IVibrator::on, mDuration);
+ statusStr = toString(status);
+ ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+ } else {
return UNAVAILABLE;
}
- std::cout << "Status: " << toString(ret) << std::endl;
+ std::cout << "Status: " << statusStr << std::endl;
- return ret == V1_0::Status::OK ? OK : ERROR;
+ return ret;
}
uint32_t mDuration;
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
index 688cbd8..58d4e0a 100644
--- a/cmds/idlcli/vibrator/CommandPerform.cpp
+++ b/cmds/idlcli/vibrator/CommandPerform.cpp
@@ -23,6 +23,34 @@
namespace vibrator {
+/*
+ * The following static asserts are only relevant here because the argument
+ * parser uses a single implementation for determining the string names.
+ */
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
+ static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
+ static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
+ static_cast<uint8_t>(aidl::EffectStrength::STRONG));
+static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD));
+static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP));
+static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
+static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
+ static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
+
using V1_0::EffectStrength;
using V1_3::Effect;
@@ -62,38 +90,50 @@
}
Status doMain(Args && /*args*/) override {
- Return<void> ret;
- V1_0::Status status;
+ std::string statusStr;
uint32_t lengthMs;
- auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
- status = retStatus;
- lengthMs = retLengthMs;
- };
+ Status ret;
- if (auto hal = getHal<V1_3::IVibrator>()) {
- ret = hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
- mStrength, callback);
- } else if (auto hal = getHal<V1_2::IVibrator>()) {
- ret = hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
- mStrength, callback);
- } else if (auto hal = getHal<V1_1::IVibrator>()) {
- ret = hal->call(&V1_1::IVibrator::perform_1_1, static_cast<V1_1::Effect_1_1>(mEffect),
- mStrength, callback);
- } else if (auto hal = getHal<V1_0::IVibrator>()) {
- ret = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
- mStrength, callback);
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ int32_t aidlLengthMs;
+ auto status =
+ hal->call(&aidl::IVibrator::perform, static_cast<aidl::Effect>(mEffect),
+ static_cast<aidl::EffectStrength>(mStrength), nullptr, &aidlLengthMs);
+ statusStr = status.toString8();
+ lengthMs = static_cast<uint32_t>(aidlLengthMs);
+ ret = status.isOk() ? OK : ERROR;
} else {
- ret = NullptrStatus<void>();
+ Return<void> hidlRet;
+ V1_0::Status status;
+ auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
+ status = retStatus;
+ lengthMs = retLengthMs;
+ };
+
+ if (auto hal = getHal<V1_3::IVibrator>()) {
+ hidlRet = hal->call(&V1_3::IVibrator::perform_1_3,
+ static_cast<V1_3::Effect>(mEffect), mStrength, callback);
+ } else if (auto hal = getHal<V1_2::IVibrator>()) {
+ hidlRet = hal->call(&V1_2::IVibrator::perform_1_2,
+ static_cast<V1_2::Effect>(mEffect), mStrength, callback);
+ } else if (auto hal = getHal<V1_1::IVibrator>()) {
+ hidlRet = hal->call(&V1_1::IVibrator::perform_1_1,
+ static_cast<V1_1::Effect_1_1>(mEffect), mStrength, callback);
+ } else if (auto hal = getHal<V1_0::IVibrator>()) {
+ hidlRet = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
+ mStrength, callback);
+ } else {
+ return UNAVAILABLE;
+ }
+
+ statusStr = toString(status);
+ ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
}
- if (!ret.isOk()) {
- return UNAVAILABLE;
- }
-
- std::cout << "Status: " << toString(status) << std::endl;
+ std::cout << "Status: " << statusStr << std::endl;
std::cout << "Length: " << lengthMs << std::endl;
- return status == V1_0::Status::OK ? OK : ERROR;
+ return ret;
}
Effect mEffect;
diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
index 38a1dc2..6e2261f 100644
--- a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
+++ b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
@@ -50,15 +50,24 @@
}
Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_0::IVibrator::setAmplitude, mAmplitude);
+ std::string statusStr;
+ Status ret;
- if (!ret.isOk()) {
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::setAmplitude, mAmplitude);
+ statusStr = status.toString8();
+ ret = status.isOk() ? OK : ERROR;
+ } else if (auto hal = getHal<V1_0::IVibrator>()) {
+ auto status = hal->call(&V1_0::IVibrator::setAmplitude, mAmplitude);
+ statusStr = toString(status);
+ ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+ } else {
return UNAVAILABLE;
}
- std::cout << "Status: " << toString(ret) << std::endl;
+ std::cout << "Status: " << statusStr << std::endl;
- return ret == V1_0::Status::OK ? OK : ERROR;
+ return ret;
}
uint8_t mAmplitude;
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
index 5fb1fac..5bc827e 100644
--- a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
+++ b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
@@ -48,15 +48,24 @@
}
Status doMain(Args && /*args*/) override {
- auto ret = halCall(&V1_3::IVibrator::setExternalControl, mEnable);
+ std::string statusStr;
+ Status ret;
- if (!ret.isOk()) {
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::setExternalControl, mEnable);
+ statusStr = status.toString8();
+ ret = status.isOk() ? OK : ERROR;
+ } else if (auto hal = getHal<V1_3::IVibrator>()) {
+ auto status = hal->call(&V1_3::IVibrator::setExternalControl, mEnable);
+ statusStr = toString(status);
+ ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+ } else {
return UNAVAILABLE;
}
- std::cout << "Status: " << toString(ret) << std::endl;
+ std::cout << "Status: " << statusStr << std::endl;
- return ret == V1_0::Status::OK ? OK : ERROR;
+ return ret;
}
bool mEnable;
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 838d11d..f95e445 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -339,6 +339,10 @@
? "dalvik.vm.dex2oat-threads"
: "dalvik.vm.boot-dex2oat-threads";
std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
+ const char* cpu_set_property = post_bootcomplete
+ ? "dalvik.vm.dex2oat-cpu-set"
+ : "dalvik.vm.boot-dex2oat-cpu-set";
+ std::string dex2oat_cpu_set_arg = MapPropertyToArg(cpu_set_property, "--cpu-set=%s");
std::string bootclasspath;
char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
@@ -518,6 +522,7 @@
AddArg(image_block_size_arg);
AddArg(dex2oat_compiler_filter_arg);
AddArg(dex2oat_threads_arg);
+ AddArg(dex2oat_cpu_set_arg);
AddArg(dex2oat_swap_fd);
AddArg(dex2oat_image_fd);
@@ -708,11 +713,13 @@
}
}
-static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
-static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
-static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
-static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
-static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
+static constexpr int PROFMAN_BIN_RETURN_CODE_SUCCESS = 0;
+static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 1;
+static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 2;
+static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 3;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 4;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 5;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_DIFFERENT_VERSIONS = 6;
class RunProfman : public ExecVHelper {
public:
@@ -720,7 +727,9 @@
const unique_fd& reference_profile_fd,
const std::vector<unique_fd>& apk_fds,
const std::vector<std::string>& dex_locations,
- bool copy_and_update) {
+ bool copy_and_update,
+ bool for_snapshot,
+ bool for_boot_image) {
// TODO(calin): Assume for now we run in the bg compile job (which is in
// most of the invocation). With the current data flow, is not very easy or
@@ -752,6 +761,14 @@
AddArg("--copy-and-update-profile-key");
}
+ if (for_snapshot) {
+ AddArg("--force-merge");
+ }
+
+ if (for_boot_image) {
+ AddArg("--boot-image-merge");
+ }
+
// Do not add after dex2oat_flags, they should override others for debugging.
PrepareArgs(profman_bin);
}
@@ -759,12 +776,16 @@
void SetupMerge(const std::vector<unique_fd>& profiles_fd,
const unique_fd& reference_profile_fd,
const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
- const std::vector<std::string>& dex_locations = std::vector<std::string>()) {
+ const std::vector<std::string>& dex_locations = std::vector<std::string>(),
+ bool for_snapshot = false,
+ bool for_boot_image = false) {
SetupArgs(profiles_fd,
reference_profile_fd,
apk_fds,
dex_locations,
- /*copy_and_update=*/false);
+ /*copy_and_update=*/ false,
+ for_snapshot,
+ for_boot_image);
}
void SetupCopyAndUpdate(unique_fd&& profile_fd,
@@ -781,7 +802,9 @@
reference_profile_fd_,
apk_fds_,
dex_locations,
- /*copy_and_update=*/true);
+ /*copy_and_update=*/true,
+ /*for_snapshot*/false,
+ /*for_boot_image*/false);
}
void SetupDump(const std::vector<unique_fd>& profiles_fd,
@@ -795,7 +818,9 @@
reference_profile_fd,
apk_fds,
dex_locations,
- /*copy_and_update=*/false);
+ /*copy_and_update=*/false,
+ /*for_snapshot*/false,
+ /*for_boot_image*/false);
}
void Exec() {
@@ -870,9 +895,14 @@
should_clear_current_profiles = false;
should_clear_reference_profile = false;
break;
+ case PROFMAN_BIN_RETURN_CODE_ERROR_DIFFERENT_VERSIONS:
+ need_to_compile = false;
+ should_clear_current_profiles = true;
+ should_clear_reference_profile = true;
+ break;
default:
// Unknown return code or error. Unlink profiles.
- LOG(WARNING) << "Unknown error code while processing profiles for location "
+ LOG(WARNING) << "Unexpected error code while processing profiles for location "
<< location << ": " << return_code;
need_to_compile = false;
should_clear_current_profiles = true;
@@ -2741,7 +2771,7 @@
}
RunProfman args;
- args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations);
+ args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations, /*for_snapshot=*/true);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -2756,6 +2786,13 @@
return false;
}
+ // Verify that profman finished successfully.
+ int profman_code = WEXITSTATUS(return_code);
+ if (profman_code != PROFMAN_BIN_RETURN_CODE_SUCCESS) {
+ LOG(WARNING) << "profman error for " << package_name << ":" << profile_name
+ << ":" << profman_code;
+ return false;
+ }
return true;
}
@@ -2818,19 +2855,29 @@
// We do this to avoid opening a huge a amount of files.
static constexpr size_t kAggregationBatchSize = 10;
- std::vector<unique_fd> profiles_fd;
for (size_t i = 0; i < profiles.size(); ) {
+ std::vector<unique_fd> profiles_fd;
for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) {
unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY);
if (fd.get() >= 0) {
profiles_fd.push_back(std::move(fd));
}
}
+
+ // We aggregate (read & write) into the same fd multiple times in a row.
+ // We need to reset the cursor every time to ensure we read the whole file every time.
+ if (TEMP_FAILURE_RETRY(lseek(snapshot_fd, 0, SEEK_SET)) == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Cannot reset position for snapshot profile";
+ return false;
+ }
+
RunProfman args;
args.SetupMerge(profiles_fd,
snapshot_fd,
apk_fds,
- dex_locations);
+ dex_locations,
+ /*for_snapshot=*/true,
+ /*for_boot_image=*/true);
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -2843,12 +2890,21 @@
/* parent */
int return_code = wait_child(pid);
+
if (!WIFEXITED(return_code)) {
PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
return false;
}
- return true;
+
+ // Verify that profman finished successfully.
+ int profman_code = WEXITSTATUS(return_code);
+ if (profman_code != PROFMAN_BIN_RETURN_CODE_SUCCESS) {
+ LOG(WARNING) << "profman error for " << package_name << ":" << profile_name
+ << ":" << profman_code;
+ return false;
+ }
}
+
return true;
}
diff --git a/cmds/installd/migrate_legacy_obb_data.sh b/cmds/installd/migrate_legacy_obb_data.sh
index 0e6d7b9..7399681 100644
--- a/cmds/installd/migrate_legacy_obb_data.sh
+++ b/cmds/installd/migrate_legacy_obb_data.sh
@@ -15,17 +15,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-rm -rf /data/media/Android/obb/test_probe
-mkdir -p /data/media/Android/obb/
-touch /data/media/Android/obb/test_probe
+rm -rf /data/media/0/Android/obb/test_probe
+mkdir -p /data/media/0/Android/obb/
+touch /data/media/0/Android/obb/test_probe
if ! test -f /data/media/0/Android/obb/test_probe ; then
log -p i -t migrate_legacy_obb_data "No support for 'unshared_obb'. Not migrating"
- rm -rf /data/media/Android/obb/test_probe
+ rm -rf /data/media/0/Android/obb/test_probe
exit 0
fi
# Delete the test file, and remove the obb folder if it is empty
-rm -rf /data/media/Android/obb/test_probe
+rm -rf /data/media/0/Android/obb/test_probe
rmdir /data/media/obb
if ! test -d /data/media/obb ; then
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index db36ce3..eefbe4f 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -480,6 +480,10 @@
"-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=",
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 0212bc5..69fefa1 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -897,7 +897,9 @@
std::string expected_profile_content = snap_profile_ + ".expected";
run_cmd("rm -f " + expected_profile_content);
run_cmd("touch " + expected_profile_content);
- run_cmd("profman --profile-file=" + cur_profile_ +
+ // We force merging when creating the expected profile to make sure
+ // that the random profiles do not affect the output.
+ run_cmd("profman --force-merge --profile-file=" + cur_profile_ +
" --profile-file=" + ref_profile_ +
" --reference-profile-file=" + expected_profile_content +
" --apk=" + apk_path_);
@@ -1130,16 +1132,60 @@
class BootProfileTest : public ProfileTest {
public:
- virtual void setup() {
+ std::vector<const std::string> extra_apps_;
+ std::vector<int64_t> extra_ce_data_inodes_;
+
+ virtual void SetUp() {
+
ProfileTest::SetUp();
intial_android_profiles_dir = android_profiles_dir;
+ // Generate profiles for some extra apps.
+ // When merging boot profile we split profiles into small groups to avoid
+ // opening a lot of file descriptors at the same time.
+ // (Currently the group size for aggregation is 10)
+ //
+ // To stress test that works fine, create profile for more apps.
+ createAppProfilesForBootMerge(21);
}
virtual void TearDown() {
android_profiles_dir = intial_android_profiles_dir;
+ deleteAppProfilesForBootMerge();
ProfileTest::TearDown();
}
+ void createAppProfilesForBootMerge(size_t number_of_profiles) {
+ for (size_t i = 0; i < number_of_profiles; i++) {
+ int64_t ce_data_inode;
+ std::string package_name = "dummy_test_pkg" + std::to_string(i);
+ LOG(INFO) << package_name;
+ ASSERT_BINDER_SUCCESS(service_->createAppData(
+ volume_uuid_,
+ package_name,
+ kTestUserId,
+ kAppDataFlags,
+ kTestAppUid,
+ se_info_,
+ kOSdkVersion,
+ &ce_data_inode));
+ extra_apps_.push_back(package_name);
+ extra_ce_data_inodes_.push_back(ce_data_inode);
+ std::string profile = create_current_profile_path(
+ kTestUserId, package_name, kPrimaryProfile, /*is_secondary_dex*/ false);
+ SetupProfile(profile, kTestAppUid, kTestAppGid, 0600, 1);
+ }
+ }
+
+ void deleteAppProfilesForBootMerge() {
+ if (kDebug) {
+ return;
+ }
+ for (size_t i = 0; i < extra_apps_.size(); i++) {
+ service_->destroyAppData(
+ volume_uuid_, extra_apps_[i], kTestUserId, kAppDataFlags, extra_ce_data_inodes_[i]);
+ }
+ }
+
void UpdateAndroidProfilesDir(const std::string& profile_dir) {
android_profiles_dir = profile_dir;
// We need to create the reference profile directory in the new profile dir.
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 861401c..2d2af3c 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -68,7 +68,15 @@
}
#endif // !VENDORSERVICEMANAGER
-ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
+ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {
+#ifndef VENDORSERVICEMANAGER
+ // can process these at any times, don't want to delay first VINTF client
+ std::thread([] {
+ vintf::VintfObject::GetDeviceHalManifest();
+ vintf::VintfObject::GetFrameworkHalManifest();
+ }).detach();
+#endif // !VENDORSERVICEMANAGER
+}
ServiceManager::~ServiceManager() {
// this should only happen in tests
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 7f5177b..6efa4f7 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -21,7 +21,7 @@
/**
* @file sharedmem.h
- * @brief Shared memory buffers that can be shared across process.
+ * @brief Shared memory buffers that can be shared between processes.
*/
#ifndef ANDROID_SHARED_MEMORY_H
@@ -61,11 +61,15 @@
*
* Use close() to release the shared memory region.
*
+ * Use {@link android.os.ParcelFileDescriptor} to pass the file descriptor to
+ * another process. File descriptors may also be sent to other processes over a Unix domain
+ * socket with sendmsg and SCM_RIGHTS. See sendmsg(3) and cmsg(3) man pages for more information.
+ *
* Available since API level 26.
*
* \param name an optional name.
* \param size size of the shared memory region
- * \return file descriptor that denotes the shared memory; error code on failure.
+ * \return file descriptor that denotes the shared memory; -1 and sets errno on failure, or -EINVAL if the error is that size was 0.
*/
int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
@@ -109,7 +113,7 @@
* \param fd file descriptor of the shared memory region.
* \param prot any bitwise-or'ed combination of PROT_READ, PROT_WRITE, PROT_EXEC denoting
* updated access. Note access can only be removed, but not added back.
- * \return 0 for success, error code on failure.
+ * \return 0 for success, -1 and sets errno on failure.
*/
int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index ea61dc5..ce2cd99 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -385,6 +385,12 @@
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
+
+// TODO(b/139016109): enforce in build system
+#if defined(__ANDROID_APEX__) && !defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__)
+ LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
+#endif
+
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 8c7ebba..b965881 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -58,7 +58,7 @@
* Returns null if the service does not exist.
*/
@UnsupportedAppUsage
- IBinder getService(@utf8InCpp String name);
+ @nullable IBinder getService(@utf8InCpp String name);
/**
* Retrieve an existing service called @a name from the service
@@ -66,7 +66,7 @@
* exist.
*/
@UnsupportedAppUsage
- IBinder checkService(@utf8InCpp String name);
+ @nullable IBinder checkService(@utf8InCpp String name);
/**
* Place a new @a service called @a name into the service
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index f3bc31b..7871667 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -441,6 +441,42 @@
}
/**
+ * Writes a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
+ * to 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_writeStdVectorParcelableElement<ScopedFileDescriptor>(
+ AParcel* parcel, const void* vectorData, size_t index) {
+ const std::vector<ScopedFileDescriptor>* vector =
+ static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData);
+ int writeFd = vector->at(index).get();
+ if (writeFd < 0) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+ return AParcel_writeParcelFileDescriptor(parcel, writeFd);
+}
+
+/**
+ * Reads a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
+ * from 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_readStdVectorParcelableElement<ScopedFileDescriptor>(
+ const AParcel* parcel, void* vectorData, size_t index) {
+ std::vector<ScopedFileDescriptor>* vector =
+ static_cast<std::vector<ScopedFileDescriptor>*>(vectorData);
+ int readFd;
+ binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+ if (status == STATUS_OK) {
+ if (readFd < 0) {
+ return STATUS_UNEXPECTED_NULL;
+ }
+ vector->at(index).set(readFd);
+ }
+ return status;
+}
+
+/**
* Convenience API for writing a std::vector<P>
*/
template <typename P>
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index 2a4ded8..56d95a7 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -56,9 +56,11 @@
/**
* This interface has the stability of the system image.
*/
-void AIBinder_markSystemStability(AIBinder* binder);
+__attribute__((weak)) void AIBinder_markSystemStability(AIBinder* binder);
static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+ if (AIBinder_markSystemStability == nullptr) return;
+
AIBinder_markSystemStability(binder);
}
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d4d5387..d59d6e4 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -89,12 +89,12 @@
AStatus_getStatus;
AStatus_isOk;
AStatus_newOk;
- ABinderProcess_joinThreadPool; # apex vndk
- ABinderProcess_setThreadPoolMaxThreadCount; # apex vndk
- ABinderProcess_startThreadPool; # apex vndk
- AServiceManager_addService; # apex vndk
- AServiceManager_checkService; # apex vndk
- AServiceManager_getService; # apex vndk
+ ABinderProcess_joinThreadPool; # apex llndk
+ ABinderProcess_setThreadPoolMaxThreadCount; # apex llndk
+ ABinderProcess_startThreadPool; # apex llndk
+ AServiceManager_addService; # apex llndk
+ AServiceManager_checkService; # apex llndk
+ AServiceManager_getService; # apex llndk
local:
*;
};
@@ -105,8 +105,8 @@
AIBinder_setExtension;
AIBinder_markSystemStability; # apex
- AIBinder_markVendorStability; # vndk
- AIBinder_markVintfStability; # apex vndk
+ AIBinder_markVendorStability; # llndk
+ AIBinder_markVintfStability; # apex llndk
local:
*;
};
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index bad8b11..fece733 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -2,9 +2,9 @@
global:
AHardwareBuffer_acquire;
AHardwareBuffer_allocate;
- AHardwareBuffer_createFromHandle; # vndk
+ AHardwareBuffer_createFromHandle; # llndk
AHardwareBuffer_describe;
- AHardwareBuffer_getNativeHandle; # vndk
+ AHardwareBuffer_getNativeHandle; # llndk
AHardwareBuffer_isSupported; # introduced=29
AHardwareBuffer_lock;
AHardwareBuffer_lockAndGetInfo; # introduced=29
@@ -13,32 +13,32 @@
AHardwareBuffer_release;
AHardwareBuffer_sendHandleToUnixSocket;
AHardwareBuffer_unlock;
- ANativeWindowBuffer_getHardwareBuffer; # vndk
- ANativeWindow_OemStorageGet; # vndk
- ANativeWindow_OemStorageSet; # vndk
+ ANativeWindowBuffer_getHardwareBuffer; # llndk
+ ANativeWindow_OemStorageGet; # llndk
+ ANativeWindow_OemStorageSet; # llndk
ANativeWindow_acquire;
- ANativeWindow_cancelBuffer; # vndk
- ANativeWindow_dequeueBuffer; # vndk
+ ANativeWindow_cancelBuffer; # llndk
+ ANativeWindow_dequeueBuffer; # llndk
ANativeWindow_getBuffersDataSpace; # introduced=28
ANativeWindow_getFormat;
ANativeWindow_getHeight;
ANativeWindow_getWidth;
ANativeWindow_lock;
- ANativeWindow_query; # vndk
- ANativeWindow_queryf; # vndk
- ANativeWindow_queueBuffer; # vndk
+ ANativeWindow_query; # llndk
+ ANativeWindow_queryf; # llndk
+ ANativeWindow_queueBuffer; # llndk
ANativeWindow_release;
- ANativeWindow_setAutoRefresh; # vndk
- ANativeWindow_setBufferCount; # vndk
+ ANativeWindow_setAutoRefresh; # llndk
+ ANativeWindow_setBufferCount; # llndk
ANativeWindow_setBuffersDataSpace; # introduced=28
- ANativeWindow_setBuffersDimensions; # vndk
- ANativeWindow_setBuffersFormat; # vndk
+ ANativeWindow_setBuffersDimensions; # llndk
+ ANativeWindow_setBuffersFormat; # llndk
ANativeWindow_setBuffersGeometry;
- ANativeWindow_setBuffersTimestamp; # vndk
+ ANativeWindow_setBuffersTimestamp; # llndk
ANativeWindow_setBuffersTransform;
- ANativeWindow_setSharedBufferMode; # vndk
- ANativeWindow_setSwapInterval; # vndk
- ANativeWindow_setUsage; # vndk
+ ANativeWindow_setSharedBufferMode; # llndk
+ ANativeWindow_setSwapInterval; # llndk
+ ANativeWindow_setUsage; # llndk
ANativeWindow_unlockAndPost;
local:
*;
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index ac01dc8..9b1b522 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -379,14 +379,12 @@
// any symbol dependencies will be resolved by system libraries. They
// can't safely use libc++_shared, for example. Which is one reason
// (among several) we only allow them in non-user builds.
- void* handle = nullptr;
auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
if (app_namespace && !android::base::StartsWith(layer, kSystemLayerLibraryDir)) {
- bool native_bridge = false;
char* error_message = nullptr;
- handle = OpenNativeLibraryInNamespace(
- app_namespace, layer.c_str(), &native_bridge, &error_message);
- if (!handle) {
+ dlhandle_ = OpenNativeLibraryInNamespace(
+ app_namespace, layer.c_str(), &native_bridge_, &error_message);
+ if (!dlhandle_) {
ALOGE("Failed to load layer %s with error: %s", layer.c_str(),
error_message);
android::NativeLoaderFreeErrorMessage(error_message);
@@ -394,11 +392,11 @@
}
} else {
- handle = dlopen(layer.c_str(), RTLD_NOW | RTLD_LOCAL);
+ dlhandle_ = dlopen(layer.c_str(), RTLD_NOW | RTLD_LOCAL);
}
- if (handle) {
- ALOGV("Loaded layer handle (%llu) for layer %s", (unsigned long long)handle,
+ if (dlhandle_) {
+ ALOGV("Loaded layer handle (%llu) for layer %s", (unsigned long long)dlhandle_,
layers[i].c_str());
} else {
// If the layer is found but can't be loaded, try setenforce 0
@@ -411,8 +409,7 @@
std::string init_func = "AndroidGLESLayer_Initialize";
ALOGV("Looking for entrypoint %s", init_func.c_str());
- layer_init_func LayerInit =
- reinterpret_cast<layer_init_func>(dlsym(handle, init_func.c_str()));
+ layer_init_func LayerInit = GetTrampoline<layer_init_func>(init_func.c_str());
if (LayerInit) {
ALOGV("Found %s for layer %s", init_func.c_str(), layer.c_str());
layer_init_.push_back(LayerInit);
@@ -425,8 +422,7 @@
std::string setup_func = "AndroidGLESLayer_GetProcAddress";
ALOGV("Looking for entrypoint %s", setup_func.c_str());
- layer_setup_func LayerSetup =
- reinterpret_cast<layer_setup_func>(dlsym(handle, setup_func.c_str()));
+ layer_setup_func LayerSetup = GetTrampoline<layer_setup_func>(setup_func.c_str());
if (LayerSetup) {
ALOGV("Found %s for layer %s", setup_func.c_str(), layer.c_str());
layer_setup_.push_back(LayerSetup);
diff --git a/opengl/libs/EGL/egl_layers.h b/opengl/libs/EGL/egl_layers.h
index e401b44..1e2783f 100644
--- a/opengl/libs/EGL/egl_layers.h
+++ b/opengl/libs/EGL/egl_layers.h
@@ -21,10 +21,15 @@
#include <unordered_map>
#include <vector>
-#include <EGL/egldefs.h>
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <EGL/egldefs.h>
#include "egl_platform_entries.h"
+#include <nativebridge/native_bridge.h>
+#include <nativeloader/native_loader.h>
+
typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
namespace android {
@@ -54,10 +59,21 @@
std::vector<layer_setup_func> layer_setup_;
private:
- LayerLoader() : layers_loaded_(false), initialized_(false), current_layer_(0){};
+ LayerLoader() : layers_loaded_(false), initialized_(false), current_layer_(0), dlhandle_(nullptr), native_bridge_(false){};
bool layers_loaded_;
bool initialized_;
unsigned current_layer_;
+ void* dlhandle_;
+ bool native_bridge_;
+
+ template<typename Func = void*>
+ Func GetTrampoline(const char* name) const {
+ if (native_bridge_) {
+ return reinterpret_cast<Func>(android::NativeBridgeGetTrampoline(
+ dlhandle_, name, nullptr, 0));
+ }
+ return reinterpret_cast<Func>(dlsym(dlhandle_, name));
+ }
};
}; // namespace android
diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt
index b2d7957..0c14e01 100644
--- a/opengl/libs/libEGL.map.txt
+++ b/opengl/libs/libEGL.map.txt
@@ -28,7 +28,7 @@
eglDestroySurface;
eglDestroySync; # introduced=29
eglDestroySyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
- eglDupNativeFenceFDANDROID; # vndk
+ eglDupNativeFenceFDANDROID; # llndk
eglGetConfigAttrib;
eglGetConfigs;
eglGetCurrentContext;
@@ -54,7 +54,7 @@
eglQueryStreamTimeKHR; # introduced=23
eglQueryStreamu64KHR; # introduced=23
eglQueryString;
- eglQueryStringImplementationANDROID; # vndk
+ eglQueryStringImplementationANDROID; # llndk
eglQuerySurface;
eglReleaseTexImage;
eglReleaseThread;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3057ed1..cb6dd8b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1808,6 +1808,7 @@
preComposition();
rebuildLayerStacks();
calculateWorkingSet();
+ long compositionTime = elapsedRealtimeNano();
for (const auto& [token, display] : mDisplays) {
beginFrame(display);
prepareFrame(display);
@@ -1837,7 +1838,7 @@
if (mVisibleRegionsDirty) {
mVisibleRegionsDirty = false;
if (mTracingEnabled) {
- mTracing.notify("visibleRegionsDirty");
+ mTracing.notify(compositionTime, "visibleRegionsDirty");
}
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8049b61..5b1abec 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -509,9 +509,9 @@
using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
struct ActiveConfigInfo {
- RefreshRateType type;
- int configId;
- Scheduler::ConfigEvent event;
+ RefreshRateType type = RefreshRateType::DEFAULT;
+ int configId = 0;
+ Scheduler::ConfigEvent event = Scheduler::ConfigEvent::None;
bool operator!=(const ActiveConfigInfo& other) const {
return type != other.type || configId != other.configId || event != other.event;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 9053f2c..5d9be0b 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -68,8 +68,9 @@
return mEnabled;
}
-void SurfaceTracing::notify(const char* where) {
+void SurfaceTracing::notify(long compositionTime, const char* where) {
std::scoped_lock lock(mSfLock);
+ mCompositionTime = compositionTime;
mWhere = where;
mCanStartTrace.notify_one();
}
@@ -160,7 +161,7 @@
ATRACE_CALL();
LayersTraceProto entry;
- entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
+ entry.set_elapsed_realtime_nanos(mCompositionTime);
entry.set_where(where);
LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
entry.mutable_layers()->Swap(&layers);
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 4773307..395d562 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -46,7 +46,7 @@
bool disable();
status_t writeToFile();
bool isEnabled() const;
- void notify(const char* where);
+ void notify(long compositionTime, const char* where);
void setBufferSize(size_t bufferSizeInByte);
void writeToFileAsync();
@@ -81,6 +81,8 @@
std::queue<LayersTraceProto> mStorage;
};
+ long mCompositionTime;
+
void mainLoop();
void addFirstEntry();
LayersTraceProto traceWhenNotified();