Merge "Add layered buffer support to libui and libgui."
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 3987fce..e11bf30 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -58,8 +58,9 @@
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder
LOCAL_C_INCLUDES := $(LOCAL_PATH)/binder
LOCAL_SRC_FILES := \
+ binder/android/os/IDumpstate.aidl \
binder/android/os/IDumpstateListener.aidl \
- binder/android/os/IDumpstate.aidl
+ binder/android/os/IDumpstateToken.aidl
include $(BUILD_SHARED_LIBRARY)
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index a2a9018..f2dcf2b 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -25,6 +25,10 @@
namespace android {
namespace os {
+namespace {
+class DumpstateToken : public BnDumpstateToken {};
+}
+
DumpstateService::DumpstateService() : ds_(Dumpstate::GetInstance()) {
}
@@ -45,32 +49,36 @@
}
binder::Status DumpstateService::setListener(const std::string& name,
- const sp<IDumpstateListener>& listener, bool* set) {
+ const sp<IDumpstateListener>& listener,
+ sp<IDumpstateToken>* returned_token) {
+ *returned_token = nullptr;
if (name.empty()) {
MYLOGE("setListener(): name not set\n");
- *set = false;
return binder::Status::ok();
}
if (listener == nullptr) {
MYLOGE("setListener(): listener not set\n");
- *set = false;
return binder::Status::ok();
}
std::lock_guard<std::mutex> lock(lock_);
if (ds_.listener_ != nullptr) {
MYLOGE("setListener(%s): already set (%s)\n", name.c_str(), ds_.listener_name_.c_str());
- *set = false;
return binder::Status::ok();
}
+
ds_.listener_name_ = name;
ds_.listener_ = listener;
- *set = true;
+ *returned_token = new DumpstateToken();
+
return binder::Status::ok();
}
status_t DumpstateService::dump(int fd, const Vector<String16>&) {
dprintf(fd, "id: %d\n", ds_.id_);
dprintf(fd, "pid: %d\n", ds_.pid_);
+ dprintf(fd, "update_progress: %s\n", ds_.update_progress_ ? "true" : "false");
+ dprintf(fd, "update_progress_threshold: %d\n", ds_.update_progress_threshold_);
+ dprintf(fd, "last_updated_progress: %d\n", ds_.last_updated_progress_);
dprintf(fd, "progress:\n");
ds_.progress_->Dump(fd, " ");
dprintf(fd, "args: %s\n", ds_.args_.c_str());
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 544a7b6..4352d3d 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -23,6 +23,7 @@
#include <binder/BinderService.h>
#include "android/os/BnDumpstate.h"
+#include "android/os/BnDumpstateToken.h"
#include "dumpstate.h"
namespace android {
@@ -37,7 +38,7 @@
status_t dump(int fd, const Vector<String16>& args) override;
binder::Status setListener(const std::string& name, const sp<IDumpstateListener>& listener,
- bool* set) override;
+ sp<IDumpstateToken>* returned_token) override;
private:
Dumpstate& ds_;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index e585a0e..4becccf 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -17,6 +17,7 @@
package android.os;
import android.os.IDumpstateListener;
+import android.os.IDumpstateToken;
/**
* Binder interface for the currently running dumpstate process.
@@ -25,9 +26,10 @@
interface IDumpstate {
/*
- * Sets the listener for dumpstate progress.
+ * Sets the listener for this dumpstate progress.
*
- * Returns true if the listener was set (it's like a Highlander: There Can be Only One).
+ * Returns a token used to monitor dumpstate death, or `nullptr` if the listener was already
+ * set (the listener behaves like a Highlander: There Can be Only One).
*/
- boolean setListener(@utf8InCpp String name, IDumpstateListener listener);
+ IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener);
}
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl b/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl
new file mode 100644
index 0000000..7f74ceb
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Token used by the IDumpstateListener to watch for dumpstate death.
+ * {@hide}
+ */
+interface IDumpstateToken {
+}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 9124f94..3d3d7ed 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -390,6 +390,13 @@
// Whether progress updates should be published.
bool update_progress_ = false;
+ // How frequently the progess should be updated;the listener will only be notificated when the
+ // delta from the previous update is more than the threshold.
+ int32_t update_progress_threshold_ = 100;
+
+ // Last progress that triggered a listener updated
+ int32_t last_updated_progress_;
+
// Whether it should take an screenshot earlier in the process.
bool do_early_screenshot_ = false;
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2fcf321..0d68901 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -38,7 +38,9 @@
using namespace android;
using ::testing::EndsWith;
+using ::testing::IsNull;
using ::testing::IsEmpty;
+using ::testing::NotNull;
using ::testing::StrEq;
using ::testing::StartsWith;
using ::testing::Test;
@@ -49,6 +51,7 @@
using os::DumpstateService;
using os::IDumpstateListener;
+using os::IDumpstateToken;
// Not used on test cases yet...
void dumpstate_board(void) {
@@ -106,6 +109,7 @@
SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
ds.progress_.reset(new Progress());
ds.update_progress_ = false;
+ ds.update_progress_threshold_ = 0;
}
// Runs a command and capture `stdout` and `stderr`.
@@ -149,55 +153,32 @@
ASSERT_EQ(2000, (int)uid);
}
- void SetProgress(long progress, long initial_max) {
+ void SetProgress(long progress, long initial_max, long threshold = 0) {
ds.update_progress_ = true;
+ ds.update_progress_threshold_ = threshold;
+ ds.last_updated_progress_ = 0;
ds.progress_.reset(new Progress(initial_max, progress, 1.2));
}
- // TODO: remove when progress is set by Binder callbacks.
- void AssertSystemProperty(const std::string& key, const std::string& expected_value) {
- std::string actualValue = android::base::GetProperty(key, "not set");
- EXPECT_THAT(expected_value, StrEq(actualValue)) << "invalid value for property " << key;
- }
-
- // TODO: remove when progress is set by Binder callbacks.
- std::string GetProgressMessageAndAssertSystemProperties(int progress, int max, int old_max = 0) {
- EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
- EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
-
- AssertSystemProperty(android::base::StringPrintf("dumpstate.%d.progress", getpid()),
- std::to_string(progress));
-
- bool max_increased = old_max > 0;
-
- std::string adjustment_message = "";
- if (max_increased) {
- AssertSystemProperty(android::base::StringPrintf("dumpstate.%d.max", getpid()),
- std::to_string(max));
- adjustment_message =
- android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
- }
-
- return android::base::StringPrintf("%sSetting progress (dumpstate.%d.progress): %d/%d\n",
- adjustment_message.c_str(), getpid(), progress, max);
- }
-
std::string GetProgressMessage(const std::string& listener_name, int progress, int max,
- int old_max = 0) {
+ int old_max = 0, bool update_progress = true) {
EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
bool max_increased = old_max > 0;
- std::string adjustment_message = "";
+ std::string message = "";
if (max_increased) {
- adjustment_message =
+ message =
android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
}
- return android::base::StringPrintf("%sSetting progress (%s): %d/%d\n",
- adjustment_message.c_str(), listener_name.c_str(),
- progress, max);
+ if (update_progress) {
+ message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
+ listener_name.c_str(), progress, max);
+ }
+
+ return message;
}
// `stdout` and `stderr` from the last command ran.
@@ -346,33 +327,6 @@
" --pid --sleep 20' failed: killed by signal 15\n"));
}
-TEST_F(DumpstateTest, RunCommandProgressNoListener) {
- SetProgress(0, 30);
-
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
- std::string progress_message = GetProgressMessageAndAssertSystemProperties(20, 30);
- EXPECT_THAT(out, StrEq("stdout\n"));
- EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
-
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
- progress_message = GetProgressMessageAndAssertSystemProperties(30, 30);
- EXPECT_THAT(out, StrEq("stdout\n"));
- EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
-
- // Run a command that will increase maximum timeout.
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
- progress_message = GetProgressMessageAndAssertSystemProperties(31, 37, 30); // 20% increase
- EXPECT_THAT(out, StrEq("stdout\n"));
- EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
-
- // Make sure command ran while in dry_run is counted.
- SetDryRun(true);
- EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
- progress_message = GetProgressMessageAndAssertSystemProperties(35, 37);
- EXPECT_THAT(out, IsEmpty());
- EXPECT_THAT(err, StrEq(progress_message));
-}
-
TEST_F(DumpstateTest, RunCommandProgress) {
sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
ds.listener_ = listener;
@@ -410,6 +364,42 @@
ds.listener_.clear();
}
+TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
+ sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
+ ds.listener_ = listener;
+ ds.listener_name_ = "FoxMulder";
+ SetProgress(0, 8, 5); // 8 max, 5 threshold
+
+ // First update should always be sent.
+ EXPECT_CALL(*listener, onProgressUpdated(1));
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
+ std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+ // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n"));
+
+ // Third update should be sent because it reaches threshold (6 - 1 = 5).
+ EXPECT_CALL(*listener, onProgressUpdated(6));
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
+ progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+ // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
+ // But max update should be sent.
+ EXPECT_CALL(*listener, onMaxProgressUpdated(10)); // 9 * 120% = 10.8 = 10
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
+ progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
+ EXPECT_THAT(out, StrEq("stdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
+
+ ds.listener_.clear();
+}
+
TEST_F(DumpstateTest, RunCommandDropRoot) {
// First check root case - only available when running with 'adb root'.
uid_t uid = getuid();
@@ -499,18 +489,6 @@
EXPECT_THAT(err, IsEmpty());
}
-TEST_F(DumpstateTest, DumpFileUpdateProgressNoListener) {
- SetProgress(0, 30);
-
- EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
-
- std::string progress_message =
- GetProgressMessageAndAssertSystemProperties(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
-
- EXPECT_THAT(err, StrEq(progress_message));
- EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
-}
-
TEST_F(DumpstateTest, DumpFileUpdateProgress) {
sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
ds.listener_ = listener;
@@ -535,27 +513,28 @@
TEST_F(DumpstateServiceTest, SetListenerNoName) {
sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
- bool result;
- EXPECT_TRUE(dss.setListener("", listener, &result).isOk());
- EXPECT_FALSE(result);
+ sp<IDumpstateToken> token;
+ EXPECT_TRUE(dss.setListener("", listener, &token).isOk());
+ ASSERT_THAT(token, IsNull());
}
TEST_F(DumpstateServiceTest, SetListenerNoPointer) {
- bool result;
- EXPECT_TRUE(dss.setListener("whatever", nullptr, &result).isOk());
- EXPECT_FALSE(result);
+ sp<IDumpstateToken> token;
+ EXPECT_TRUE(dss.setListener("whatever", nullptr, &token).isOk());
+ ASSERT_THAT(token, IsNull());
}
TEST_F(DumpstateServiceTest, SetListenerTwice) {
sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
- bool result;
- EXPECT_TRUE(dss.setListener("whatever", listener, &result).isOk());
- EXPECT_TRUE(result);
-
+ sp<IDumpstateToken> token;
+ EXPECT_TRUE(dss.setListener("whatever", listener, &token).isOk());
+ ASSERT_THAT(token, NotNull());
EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
- EXPECT_TRUE(dss.setListener("whatever", listener, &result).isOk());
- EXPECT_FALSE(result);
+ token.clear();
+ EXPECT_TRUE(dss.setListener("whatsoever", listener, &token).isOk());
+ ASSERT_THAT(token, IsNull());
+ EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
}
class ProgressTest : public DumpstateBaseTest {
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index d33460c..b5f328d 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -1451,27 +1451,19 @@
// ...but only notifiy listeners when necessary.
if (!update_progress_) return;
- // TODO: remove property support once Shell uses IDumpstateListener
- char key[PROPERTY_KEY_MAX];
- char value[PROPERTY_VALUE_MAX];
+ int progress = progress_->Get();
+ int max = progress_->GetMax();
// adjusts max on the fly
- if (max_changed) {
- if (listener_ != nullptr) {
- listener_->onMaxProgressUpdated(progress_->GetMax());
- } else {
- snprintf(key, sizeof(key), "dumpstate.%d.max", pid_);
- snprintf(value, sizeof(value), "%d", progress_->GetMax());
- int status = property_set(key, value);
- if (status != 0) {
- MYLOGE("Could not update max weight by setting system property %s to %s: %d\n", key,
- value, status);
- }
- }
+ if (max_changed && listener_ != nullptr) {
+ listener_->onMaxProgressUpdated(max);
}
- int32_t progress = progress_->Get();
- int32_t max = progress_->GetMax();
+ int32_t last_update_delta = progress - last_updated_progress_;
+ if (last_updated_progress_ > 0 && last_update_delta < update_progress_threshold_) {
+ return;
+ }
+ last_updated_progress_ = progress;
if (control_socket_fd_ >= 0) {
dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
@@ -1488,24 +1480,6 @@
fprintf(stderr, "Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
}
listener_->onProgressUpdated(progress);
- } else {
- snprintf(key, sizeof(key), "dumpstate.%d.progress", pid_);
- snprintf(value, sizeof(value), "%d", progress);
-
- if (progress % 100 == 0) {
- // We don't want to spam logcat, so only log multiples of 100.
- MYLOGD("Setting progress (%s): %s/%d\n", key, value, max);
- } else {
- // stderr is ignored on normal invocations, but useful when calling
- // /system/bin/dumpstate directly for debuggging.
- fprintf(stderr, "Setting progress (%s): %s/%d\n", key, value, max);
- }
-
- int status = property_set(key, value);
- if (status) {
- MYLOGE("Could not update progress by setting system property %s to %s: %d\n", key,
- value, status);
- }
}
}
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 078db26..5ffc0c2 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -797,7 +797,7 @@
ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
}
-static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd,
+static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
const char* input_file_name, const char* output_file_name, int swap_fd,
const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
@@ -881,7 +881,8 @@
char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
- char vdex_fd_arg[strlen("--vdex-fd=") + MAX_INT_LEN];
+ char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN];
+ char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN];
char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
@@ -897,7 +898,8 @@
sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
- sprintf(vdex_fd_arg, "--vdex-fd=%d", vdex_fd);
+ sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
+ sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
@@ -960,7 +962,7 @@
ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
- const char* argv[8 // program name, mandatory arguments and the final NULL
+ const char* argv[9 // program name, mandatory arguments and the final NULL
+ (have_dex2oat_isa_variant ? 1 : 0)
+ (have_dex2oat_isa_features ? 1 : 0)
+ (have_dex2oat_Xms_flag ? 2 : 0)
@@ -981,7 +983,8 @@
argv[i++] = DEX2OAT_BIN;
argv[i++] = zip_fd_arg;
argv[i++] = zip_location_arg;
- argv[i++] = vdex_fd_arg;
+ argv[i++] = input_vdex_fd_arg;
+ argv[i++] = output_vdex_fd_arg;
argv[i++] = oat_fd_arg;
argv[i++] = oat_location_arg;
argv[i++] = instruction_set_arg;
@@ -1507,6 +1510,14 @@
return true;
}
+static bool IsOutputDalvikCache(const char* oat_dir) {
+ // InstallerConnection.java (which invokes installd) transforms Java null arguments
+ // into '!'. Play it safe by handling it both.
+ // TODO: ensure we never get null.
+ // TODO: pass a flag instead of inferring if the output is dalvik cache.
+ return oat_dir == nullptr || oat_dir[0] == '!';
+}
+
static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
const char* oat_dir, /*out*/ char* out_oat_path) {
// Early best-effort check whether we can fit the the path into our buffers.
@@ -1518,9 +1529,9 @@
return false;
}
- if (oat_dir != NULL && oat_dir[0] != '!') {
+ if (!IsOutputDalvikCache(oat_dir)) {
if (validate_apk_path(oat_dir)) {
- ALOGE("invalid oat_dir '%s'\n", oat_dir);
+ ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
return false;
}
if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
@@ -1709,22 +1720,6 @@
return -1;
}
- // If invoking patchoat, open the VDEX associated with the OAT too.
- std::string in_vdex_path_str;
- base::unique_fd input_vdex_fd;
- if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
- || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
- in_vdex_path_str = create_vdex_filename(input_file);
- if (in_vdex_path_str.empty()) {
- return -1;
- }
- input_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
- if (input_vdex_fd.get() < 0) {
- ALOGE("installd cannot open '%s' for input during dexopt\n", in_vdex_path_str.c_str());
- return -1;
- }
- }
-
// Create the output OAT file.
const std::string out_oat_path_str(out_oat_path);
Dex2oatFileWrapper<std::function<void ()>> out_oat_fd(
@@ -1738,6 +1733,47 @@
return -1;
}
+ // Open the existing VDEX. We do this before creating the new output VDEX, which will
+ // unlink the old one.
+ base::unique_fd in_vdex_fd;
+ std::string in_vdex_path_str;
+ if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
+ || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
+ // `input_file` is the OAT file to be relocated. The VDEX has to be there as well.
+ in_vdex_path_str = create_vdex_filename(input_file);
+ if (in_vdex_path_str.empty()) {
+ ALOGE("installd cannot compute input vdex location for '%s'\n", input_file);
+ return -1;
+ }
+ in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+ if (in_vdex_fd.get() < 0) {
+ ALOGE("installd cannot open '%s' for input during dexopt: %s\n",
+ in_vdex_path_str.c_str(), strerror(errno));
+ return -1;
+ }
+ } else {
+ // Open the possibly existing vdex in the `out_oat_path`. If none exist, we pass -1
+ // to dex2oat for input-vdex-fd.
+ in_vdex_path_str = create_vdex_filename(out_oat_path);
+ if (in_vdex_path_str.empty()) {
+ ALOGE("installd cannot compute input vdex location for '%s'\n", out_oat_path);
+ return -1;
+ }
+ in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+ // If there is no vdex file in out_oat_path, check if we have a vdex
+ // file next to the odex file. For other failures, we will just pass a -1 fd.
+ if (in_vdex_fd.get() < 0 && (errno == ENOENT) && IsOutputDalvikCache(oat_dir)) {
+ if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
+ in_vdex_path_str = create_vdex_filename(std::string(in_odex_path));
+ if (in_vdex_path_str.empty()) {
+ ALOGE("installd cannot compute input vdex location for '%s'\n", in_odex_path);
+ return -1;
+ }
+ in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+ }
+ }
+ }
+
// Infer the name of the output VDEX and create it.
const std::string out_vdex_path_str = create_vdex_filename(out_oat_path_str);
if (out_vdex_path_str.empty()) {
@@ -1832,7 +1868,7 @@
if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
|| dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
run_patchoat(input_fd.get(),
- input_vdex_fd.get(),
+ in_vdex_fd.get(),
out_oat_fd.get(),
out_vdex_fd.get(),
input_file,
@@ -1846,6 +1882,7 @@
const char *input_file_name = get_location_from_path(input_file);
run_dex2oat(input_fd.get(),
out_oat_fd.get(),
+ in_vdex_fd.get(),
out_vdex_fd.get(),
image_fd.get(),
input_file_name,
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 7fbf312..ee4c58c 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -716,6 +716,7 @@
}
sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
+ Mutex::Autolock lock(mCore->mMutex);
return mCore->mSidebandStream;
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 9241c7c..81d4f31 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1376,6 +1376,7 @@
String8 BufferQueueProducer::getConsumerName() const {
ATRACE_CALL();
+ Mutex::Autolock lock(mCore->mMutex);
BQ_LOGV("getConsumerName: %s", mConsumerName.string());
return mConsumerName;
}
diff --git a/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index 081aca9..4ea3b96 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -217,8 +217,8 @@
"SMPTE RP 431-2-2007 DCI (P3)",
{{float2{0.680f, 0.320f}, {0.265f, 0.690f}, {0.150f, 0.060f}}},
{0.3127f, 0.3290f},
- std::bind(saturate<float>, std::bind(powf, _1, 1.0f / 2.6f)),
- std::bind(saturate<float>, std::bind(powf, _1, 2.6f))
+ std::bind(powf, _1, 1.0f / 2.6f),
+ std::bind(powf, _1, 2.6f)
};
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 99a9265..37fd70d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -91,19 +91,6 @@
EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-// Workaround for b/30067360: /proc/self/environ inaccessible in SurfaceFlinger
-// => ASan fails to read ASAN_OPTIONS => alloc-dealloc-mismatch bug is not
-// suppressed and prevents the device from booting.
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-#if __has_feature(address_sanitizer)
-__attribute__((visibility("default")))
-extern "C" const char* __asan_default_options() {
- return "alloc_dealloc_mismatch=0";
-}
-#endif
-
namespace android {
// This is the phase offset in nanoseconds of the software vsync event
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 3ae2c04..8e5c565 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -93,19 +93,6 @@
EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-// Workaround for b/30067360: /proc/self/environ inaccessible in SurfaceFlinger
-// => ASan fails to read ASAN_OPTIONS => alloc-dealloc-mismatch bug is not
-// suppressed and prevents the device from booting.
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-#if __has_feature(address_sanitizer)
-__attribute__((visibility("default")))
-extern "C" const char *__asan_default_options() {
- return "alloc_dealloc_mismatch=0";
-}
-#endif
-
namespace android {
// This is the phase offset in nanoseconds of the software vsync event