Merge "Create new ephemeral app directory"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 8b04b01..812d6fa 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -17,8 +17,10 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <libgen.h>
#include <limits.h>
#include <memory>
+#include <regex>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -747,46 +749,57 @@
redirect_to_socket(stdout, "dumpstate");
}
- /* redirect output if needed */
- std::string text_path, zip_path, tmp_path, entry_name;
+ /* full path of the directory where the bug report files will be written */
+ std::string bugreport_dir;
+
+ /* full path of the temporary file containing the bug report */
+ std::string tmp_path;
+
+ /* base name (without suffix or extensions) of the bug report files */
+ std::string base_name;
+
+ /* suffix of the bug report files - it's typically the date (when invoked with -d),
+ * although it could be changed by the user using a system property */
+ std::string suffix;
/* pointer to the actual path, be it zip or text */
std::string path;
time_t now = time(NULL);
+ /* redirect output if needed */
bool is_redirecting = !use_socket && use_outfile;
if (is_redirecting) {
- text_path = use_outfile;
+ bugreport_dir = dirname(use_outfile);
+ base_name = basename(use_outfile);
if (do_add_date) {
char date[80];
- strftime(date, sizeof(date), "-%Y-%m-%d-%H-%M-%S", localtime(&now));
- text_path += date;
+ strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
+ suffix = date;
+ } else {
+ suffix = "undated";
}
if (do_fb) {
- screenshot_path = text_path + ".png";
+ // TODO: if dumpstate was an object, the paths could be internal variables and then
+ // we could have a function to calculate the derived values, such as:
+ // screenshot_path = GetPath(".png");
+ screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
}
- zip_path = text_path + ".zip";
- text_path += ".txt";
- tmp_path = text_path + ".tmp";
- entry_name = basename(text_path.c_str());
+ tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
- ALOGD("Temporary path: %s\ntext path: %s\nzip path: %s\nzip entry: %s",
- tmp_path.c_str(), text_path.c_str(), zip_path.c_str(), entry_name.c_str());
+ ALOGD("Bugreport dir: %s\nBase name: %s\nSuffix: %s\nTemporary path: %s\n"
+ "Screenshot path: %s\n", bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
+ tmp_path.c_str(), screenshot_path.c_str());
if (do_update_progress) {
- if (!entry_name.empty()) {
- std::vector<std::string> am_args = {
- "--receiver-permission", "android.permission.DUMP",
- "--es", "android.intent.extra.NAME", entry_name,
- "--ei", "android.intent.extra.PID", std::to_string(getpid()),
- "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
- };
- send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
- } else {
- ALOGE("Skipping started broadcast because entry name could not be inferred\n");
- }
+ std::vector<std::string> am_args = {
+ "--receiver-permission", "android.permission.DUMP",
+ "--es", "android.intent.extra.NAME", suffix,
+ "--ei", "android.intent.extra.PID", std::to_string(getpid()),
+ "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
+ };
+ send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
}
}
@@ -852,8 +865,6 @@
}
if (is_redirecting) {
- ALOGD("Temporary path: %s\ntext path: %s\nzip path: %s\nzip entry: %s",
- tmp_path.c_str(), text_path.c_str(), zip_path.c_str(), entry_name.c_str());
/* TODO: rather than generating a text file now and zipping it later,
it would be more efficient to redirect stdout to the zip entry
directly, but the libziparchive doesn't support that option yet. */
@@ -877,10 +888,42 @@
/* rename or zip the (now complete) .tmp file to its final location */
if (use_outfile) {
+
+ /* check if user changed the suffix using system properties */
+ char key[PROPERTY_KEY_MAX];
+ char value[PROPERTY_VALUE_MAX];
+ sprintf(key, "dumpstate.%d.name", getpid());
+ property_get(key, value, "");
+ bool change_suffix= false;
+ if (value[0]) {
+ /* must whitelist which characters are allowed, otherwise it could cross directories */
+ std::regex valid_regex("^[-_a-zA-Z0-9]+$");
+ if (std::regex_match(value, valid_regex)) {
+ change_suffix = true;
+ } else {
+ ALOGE("invalid suffix provided by user: %s", value);
+ }
+ }
+ if (change_suffix) {
+ ALOGI("changing suffix from %s to %s", suffix.c_str(), value);
+ suffix = value;
+ if (!screenshot_path.empty()) {
+ std::string new_screenshot_path =
+ bugreport_dir + "/" + base_name + "-" + suffix + ".png";
+ if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
+ ALOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
+ new_screenshot_path.c_str(), strerror(errno));
+ } else {
+ screenshot_path = new_screenshot_path;
+ }
+ }
+ }
+
bool do_text_file = true;
if (do_zip_file) {
- path = zip_path;
- if (!generate_zip_file(tmp_path, zip_path, entry_name, now)) {
+ ALOGD("Generating .zip bugreport");
+ path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
+ if (!generate_zip_file(tmp_path, path, base_name + "-" + suffix + ".txt", now)) {
ALOGE("Failed to generate zip file; sending text bugreport instead\n");
do_text_file = true;
} else {
@@ -888,9 +931,10 @@
}
}
if (do_text_file) {
- path = text_path;
- if (rename(tmp_path.c_str(), text_path.c_str())) {
- ALOGE("rename(%s, %s): %s\n", tmp_path.c_str(), text_path.c_str(), strerror(errno));
+ ALOGD("Generating .txt bugreport");
+ path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
+ if (rename(tmp_path.c_str(), path.c_str())) {
+ ALOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
path.clear();
}
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 2ba5ccb..c7e7f52 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -51,8 +51,12 @@
* can be calculated by dividing the all completed weight by the total weight.
*
* This value is defined empirically and it need to be adjusted as more sections are added.
- * It does not need to match the exact sum of all sections, but it should to be more than it,
- * otherwise the calculated progress would be more than 100%.
+ *
+ * It does not need to match the exact sum of all sections, but ideally it should to be slight more
+ * than such sum: a value too high will cause the bugreport to finish before the user expected (for
+ * example, jumping from 70% to 100%), while a value too low will cause the progress to fluctuate
+ * down (for example, from 70% to 50%, since the actual max will be automatically increased every
+ * time it is reached).
*/
static const int WEIGHT_TOTAL = 4000;
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 8683155..a7637d8 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -553,7 +553,7 @@
void send_broadcast(const std::string& action, const std::vector<std::string>& args) {
if (args.size() > 1000) {
- fprintf(stderr, "send_broadcast: too many arguments (%d)\n", args.size());
+ fprintf(stderr, "send_broadcast: too many arguments (%d)\n", (int) args.size());
return;
}
const char *am_args[1024] = { "/system/bin/am", "broadcast", "--user", "0",
@@ -841,6 +841,7 @@
/* overall progress */
int progress = 0;
int do_update_progress = 0; // Set by dumpstate.cpp
+int weight_total = WEIGHT_TOTAL;
// TODO: make this function thread safe if sections are generated in parallel.
void update_progress(int delta) {
@@ -850,12 +851,27 @@
char key[PROPERTY_KEY_MAX];
char value[PROPERTY_VALUE_MAX];
+
+ // adjusts max on the fly
+ if (progress > weight_total) {
+ int new_total = weight_total * 1.2;
+ fprintf(stderr, "Adjusting total weight from %d to %d\n", weight_total, new_total);
+ weight_total = new_total;
+ sprintf(key, "dumpstate.%d.max", getpid());
+ sprintf(value, "%d", weight_total);
+ int status = property_set(key, value);
+ if (status) {
+ ALOGW("Could not update max weight by setting system property %s to %s: %d\n",
+ key, value, status);
+ }
+ }
+
sprintf(key, "dumpstate.%d.progress", getpid());
sprintf(value, "%d", progress);
// 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, WEIGHT_TOTAL);
+ fprintf(stderr, "Setting progress (%s): %s/%d\n", key, value, weight_total);
int status = property_set(key, value);
if (status) {
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 17201d5..3b2a086 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -16,8 +16,8 @@
#include "installd.h"
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
#include <logwrap/logwrap.h>
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index cb76f33..a7202b6 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -16,7 +16,7 @@
#include "installd.h"
-#include <base/logging.h>
+#include <android-base/logging.h>
#include <sys/capability.h>
#include <sys/prctl.h>
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index e51e731..750a136 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -16,8 +16,8 @@
#include "installd.h"
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
#define CACHE_NOISY(x) //x
diff --git a/data/etc/android.hardware.sensor.ambient_temperature.xml b/data/etc/android.hardware.sensor.ambient_temperature.xml
new file mode 100644
index 0000000..8ad140e
--- /dev/null
+++ b/data/etc/android.hardware.sensor.ambient_temperature.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Feature for devices with an ambient temperature sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.ambient_temperature" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.relative_humidity.xml b/data/etc/android.hardware.sensor.relative_humidity.xml
new file mode 100644
index 0000000..b9432d3
--- /dev/null
+++ b/data/etc/android.hardware.sensor.relative_humidity.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Feature for devices with a relative humidity sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.relative_humidity" />
+</permissions>
diff --git a/include/binder/Status.h b/include/binder/Status.h
index 04738f8..d19824d 100644
--- a/include/binder/Status.h
+++ b/include/binder/Status.h
@@ -60,31 +60,31 @@
EX_ILLEGAL_STATE = -5,
EX_NETWORK_MAIN_THREAD = -6,
EX_UNSUPPORTED_OPERATION = -7,
- EX_TRANSACTION_FAILED = -8,
// This is special and Java specific; see Parcel.java.
EX_HAS_REPLY_HEADER = -128,
+ // This is special, and indicates to C++ binder proxies that the
+ // transaction has failed at a low level.
+ EX_TRANSACTION_FAILED = -129,
};
- // Allow authors to explicitly pick whether their integer is a status_t or
- // exception code.
- static Status fromExceptionCode(int32_t exception_code);
- static Status fromStatusT(status_t status);
// A more readable alias for the default constructor.
static Status ok();
+ // Allow authors to explicitly pick whether their integer is a status_t or
+ // exception code.
+ static Status fromExceptionCode(int32_t exceptionCode);
+ static Status fromExceptionCode(int32_t exceptionCode,
+ const String8& message);
+ static Status fromStatusT(status_t status);
Status() = default;
- Status(int32_t exception_code, const String8& message);
- Status(int32_t exception_code, const char* message);
-
+ ~Status() = default;
// Status objects are copyable and contain just simple data.
Status(const Status& status) = default;
Status(Status&& status) = default;
Status& operator=(const Status& status) = default;
- ~Status() = default;
-
// Bear in mind that if the client or service is a Java endpoint, this
// is not the logic which will provide/interpret the data here.
status_t readFromParcel(const Parcel& parcel);
@@ -92,16 +92,17 @@
// Set one of the pre-defined exception types defined above.
void setException(int32_t ex, const String8& message);
- // A few of the status_t values map to exception codes, but most of them
- // simply map to "transaction failed."
+ // Setting a |status| != OK causes generated code to return |status|
+ // from Binder transactions, rather than writing an exception into the
+ // reply Parcel.
void setFromStatusT(status_t status);
// Get information about an exception.
- // Any argument may be given as nullptr.
- void getException(int32_t* returned_exception,
- String8* returned_message) const;
int32_t exceptionCode() const { return mException; }
const String8& exceptionMessage() const { return mMessage; }
+ status_t transactionError() const {
+ return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
+ }
bool isOk() const { return mException == EX_NONE; }
@@ -109,9 +110,17 @@
String8 toString8() const;
private:
- // We always write |mException| to the parcel.
- // If |mException| != EX_NONE, we write message as well.
+ Status(int32_t exception_code);
+ Status(int32_t exception_code, const String8& message);
+
+ // If |mException| == EX_TRANSACTION_FAILED, generated code will return
+ // |mErrorCode| as the result of the transaction rather than write an
+ // exception to the reply parcel.
+ //
+ // Otherwise, we always write |mException| to the parcel.
+ // If |mException| != EX_NONE, we write |mMessage| as well.
int32_t mException = EX_NONE;
+ int32_t mErrorCode = 0;
String8 mMessage;
}; // class Status
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 41fff3d..67f0d59 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -19,8 +19,17 @@
namespace android {
namespace binder {
-Status Status::fromExceptionCode(int32_t exception_code) {
- return Status(exception_code, "");
+Status Status::ok() {
+ return Status();
+}
+
+Status Status::fromExceptionCode(int32_t exceptionCode) {
+ return Status(exceptionCode);
+}
+
+Status Status::fromExceptionCode(int32_t exceptionCode,
+ const String8& message) {
+ return Status(exceptionCode, message);
}
Status Status::fromStatusT(status_t status) {
@@ -29,16 +38,9 @@
return ret;
}
-Status Status::ok() {
- return Status();
-}
-
-Status::Status(int32_t exception_code, const String8& message)
- : mException(exception_code),
- mMessage(message) {}
-
-Status::Status(int32_t exception_code, const char* message)
- : mException(exception_code),
+Status::Status(int32_t exceptionCode) : mException(exceptionCode) {}
+Status::Status(int32_t exceptionCode, const String8& message)
+ : mException(exceptionCode),
mMessage(message) {}
status_t Status::readFromParcel(const Parcel& parcel) {
@@ -69,12 +71,24 @@
}
// The remote threw an exception. Get the message back.
- mMessage = String8(parcel.readString16());
+ String16 message;
+ status = parcel.readString16(&message);
+ if (status != OK) {
+ setFromStatusT(status);
+ return status;
+ }
+ mMessage = String8(message);
return status;
}
status_t Status::writeToParcel(Parcel* parcel) const {
+ // Something really bad has happened, and we're not going to even
+ // try returning rich error data.
+ if (mException == EX_TRANSACTION_FAILED) {
+ return mErrorCode;
+ }
+
status_t status = parcel->writeInt32(mException);
if (status != OK) { return status; }
if (mException == EX_NONE) {
@@ -86,43 +100,26 @@
}
void Status::setFromStatusT(status_t status) {
- switch (status) {
- case NO_ERROR:
- mException = EX_NONE;
- mMessage.clear();
- break;
- case UNEXPECTED_NULL:
- mException = EX_NULL_POINTER;
- mMessage.setTo("Unexpected null reference in Parcel");
- break;
- default:
- mException = EX_TRANSACTION_FAILED;
- mMessage.setTo("Transaction failed");
- break;
- }
+ mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
+ mErrorCode = status;
+ mMessage.clear();
}
void Status::setException(int32_t ex, const String8& message) {
mException = ex;
+ mErrorCode = NO_ERROR; // an exception, not a transaction failure.
mMessage.setTo(message);
}
-void Status::getException(int32_t* returned_exception,
- String8* returned_message) const {
- if (returned_exception) {
- *returned_exception = mException;
- }
- if (returned_message) {
- returned_message->setTo(mMessage);
- }
-}
-
String8 Status::toString8() const {
String8 ret;
if (mException == EX_NONE) {
ret.append("No error");
} else {
ret.appendFormat("Status(%d): '", mException);
+ if (mException == EX_TRANSACTION_FAILED) {
+ ret.appendFormat("%d: ", mErrorCode);
+ }
ret.append(String8(mMessage));
ret.append("'");
}
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 5ba387d..e0d7339 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -322,6 +322,7 @@
mNumResyncSamples = 0;
mFirstResyncSample = 0;
mNumResyncSamplesSincePresent = 0;
+ mNumPresentWithoutResyncSamples = 0;
resetErrorLocked();
}
@@ -346,6 +347,15 @@
updateErrorLocked();
+ // This is a workaround for b/25845510.
+ // If we have no resync samples after many presents, something is wrong with
+ // HW vsync. Tell SF to disable HW vsync now and re-enable it next time.
+ if (mNumResyncSamples == 0 &&
+ mNumPresentWithoutResyncSamples++ > MAX_PRESENT_WITHOUT_RESYNC_SAMPLES) {
+ mNumPresentWithoutResyncSamples = 0;
+ return false;
+ }
+
return !mModelUpdated || mError > kErrorThreshold;
}
@@ -354,6 +364,7 @@
mModelUpdated = false;
mNumResyncSamples = 0;
+ mNumPresentWithoutResyncSamples = 0;
}
bool DispSync::addResyncSample(nsecs_t timestamp) {
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index a8524b9..1ee0865 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -140,6 +140,7 @@
enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
enum { NUM_PRESENT_SAMPLES = 8 };
enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+ enum { MAX_PRESENT_WITHOUT_RESYNC_SAMPLES = 8 };
// mPeriod is the computed period of the modeled vsync events in
// nanoseconds.
@@ -168,6 +169,7 @@
size_t mFirstResyncSample;
size_t mNumResyncSamples;
int mNumResyncSamplesSincePresent;
+ int mNumPresentWithoutResyncSamples;
// These member variables store information about the present fences used
// to validate the currently computed model.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2b6e0ec..d484708 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -147,10 +147,6 @@
}
Layer::~Layer() {
- sp<Client> c(mClientRef.promote());
- if (c != 0) {
- c->detachLayer(this);
- }
mFlinger->deleteTextureAsync(mTextureName);
mFrameTracker.logAndResetStats(mName);
}
@@ -252,6 +248,10 @@
// the layer has been remove from the current state list (and just before
// it's removed from the drawing state list)
void Layer::onRemoved() {
+ sp<Client> c(mClientRef.promote());
+ if (c != 0) {
+ c->detachLayer(this);
+ }
mSurfaceFlingerConsumer->abandon();
}