Merge "SF: Initialize mSingleBufferMode"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 7560416..237b64a 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -299,7 +299,7 @@
run_command("UPTIME", 10, "uptime", NULL);
dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
dump_file("MEMORY INFO", "/proc/meminfo");
- run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
+ run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
dump_file("VMALLOC INFO", "/proc/vmallocinfo");
@@ -726,7 +726,6 @@
/* redirect output if needed */
char path[PATH_MAX], tmp_path[PATH_MAX];
- pid_t gzip_pid = -1;
if (!use_socket && use_outfile) {
strlcpy(path, use_outfile, sizeof(path));
@@ -757,10 +756,9 @@
fclose(vibrator);
}
- /* wait for gzip to finish, otherwise it might get killed when we exit */
- if (gzip_pid > 0) {
+ /* close output if needed */
+ if (!use_socket && use_outfile) {
fclose(stdout);
- waitpid(gzip_pid, NULL, 0);
}
/* rename the (now complete) .tmp file to its final location */
@@ -770,11 +768,12 @@
/* tell activity manager we're done */
if (do_broadcast && use_outfile && do_fb) {
- run_command(NULL, 5, "/system/bin/am", "broadcast", "--user", "0",
+ const char *args[] = { "/system/bin/am", "broadcast", "--user", "0",
"-a", "android.intent.action.BUGREPORT_FINISHED",
"--es", "android.intent.extra.BUGREPORT", path,
"--es", "android.intent.extra.SCREENSHOT", screenshot_path,
- "--receiver-permission", "android.permission.DUMP", NULL);
+ "--receiver-permission", "android.permission.DUMP", NULL };
+ run_command_always(NULL, 5, args);
}
ALOGI("done\n");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index f10ec46..f9f20d2 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -17,6 +17,18 @@
#ifndef _DUMPSTATE_H_
#define _DUMPSTATE_H_
+/* When defined, skips the real dumps and just print the section headers.
+ Useful when debugging dumpstate itself. */
+//#define _DUMPSTATE_DRY_RUN_
+
+#ifdef _DUMPSTATE_DRY_RUN_
+#define ON_DRY_RUN_RETURN(X) return X
+#endif
+#ifndef _DUMPSTATE_DRY_RUN_
+#define ON_DRY_RUN_RETURN(X)
+#endif
+
+
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
@@ -52,6 +64,11 @@
/* forks a command and waits for it to finish -- terminate args with NULL */
int run_command(const char *title, int timeout_seconds, const char *command, ...);
+/* forks a command and waits for it to finish
+ first element of args is the command, and last must be NULL.
+ command is always ran, even when _DUMPSTATE_DRY_RUN_ is defined. */
+int run_command_always(const char *title, int timeout_seconds, const char *args[]);
+
/* prints all the system properties */
void print_properties();
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 12f44ae..e6594ec 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -60,6 +60,7 @@
}
void for_each_userid(void (*func)(int), const char *header) {
+ ON_DRY_RUN_RETURN();
DIR *d;
struct dirent *de;
@@ -122,6 +123,7 @@
}
void for_each_pid(for_each_pid_func func, const char *header) {
+ ON_DRY_RUN_RETURN();
__for_each_pid(for_each_pid_helper, header, (void *)func);
}
@@ -174,10 +176,12 @@
}
void for_each_tid(for_each_tid_func func, const char *header) {
+ ON_DRY_RUN_RETURN();
__for_each_pid(for_each_tid_helper, header, (void *) func);
}
void show_wchan(int pid, int tid, const char *name) {
+ ON_DRY_RUN_RETURN();
char path[255];
char buffer[255];
int fd;
@@ -208,6 +212,7 @@
void do_dmesg() {
printf("------ KERNEL LOG (dmesg) ------\n");
+ ON_DRY_RUN_RETURN();
/* Get size of kernel buffer */
int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
if (size <= 0) {
@@ -299,10 +304,12 @@
/* prints the contents of a file */
int dump_file(const char *title, const char *path) {
+ if (title) printf("------ %s (%s) ------\n", title, path);
+ ON_DRY_RUN_RETURN(0);
+
int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
if (fd < 0) {
int err = errno;
- if (title) printf("------ %s (%s) ------\n", title, path);
printf("*** %s: %s\n", path, strerror(err));
if (title) printf("\n");
return -1;
@@ -328,6 +335,7 @@
if (title) {
printf("------ %s (%s) ------\n", title, dir);
}
+ ON_DRY_RUN_RETURN(0);
if (dir[strlen(dir) - 1] == '/') {
++slash;
@@ -384,6 +392,7 @@
* stuck.
*/
int dump_file_from_fd(const char *title, const char *path, int fd) {
+ ON_DRY_RUN_RETURN(0);
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
@@ -442,6 +451,29 @@
/* forks a command and waits for it to finish */
int run_command(const char *title, int timeout_seconds, const char *command, ...) {
fflush(stdout);
+
+ const char *args[1024] = {command};
+ size_t arg;
+ va_list ap;
+ va_start(ap, command);
+ if (title) printf("------ %s (%s", title, command);
+ for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
+ args[arg] = va_arg(ap, const char *);
+ if (args[arg] == NULL) break;
+ if (title) printf(" %s", args[arg]);
+ }
+ if (title) printf(") ------\n");
+ fflush(stdout);
+
+ ON_DRY_RUN_RETURN(0);
+
+ return run_command_always(title, timeout_seconds, args);
+}
+
+/* forks a command and waits for it to finish */
+int run_command_always(const char *title, int timeout_seconds, const char *args[]) {
+ const char *command = args[0];
+
uint64_t start = nanotime();
pid_t pid = fork();
@@ -453,8 +485,6 @@
/* handle child case */
if (pid == 0) {
- const char *args[1024] = {command};
- size_t arg;
/* make sure the child dies when dumpstate dies */
prctl(PR_SET_PDEATHSIG, SIGKILL);
@@ -465,17 +495,6 @@
sigact.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sigact, NULL);
- va_list ap;
- va_start(ap, command);
- if (title) printf("------ %s (%s", title, command);
- for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
- args[arg] = va_arg(ap, const char *);
- if (args[arg] == NULL) break;
- if (title) printf(" %s", args[arg]);
- }
- if (title) printf(") ------\n");
- fflush(stdout);
-
execvp(command, (char**) args);
printf("*** exec(%s): %s\n", command, strerror(errno));
fflush(stdout);
@@ -532,12 +551,13 @@
/* prints all the system properties */
void print_properties() {
+ printf("------ SYSTEM PROPERTIES ------\n");
+ ON_DRY_RUN_RETURN();
size_t i;
num_props = 0;
property_list(print_prop, NULL);
qsort(&props, num_props, sizeof(props[0]), compare_prop);
- printf("------ SYSTEM PROPERTIES ------\n");
for (i = 0; i < num_props; ++i) {
fputs(props[i], stdout);
free(props[i]);
@@ -611,6 +631,7 @@
/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
const char *dump_traces() {
+ ON_DRY_RUN_RETURN(NULL);
const char* result = NULL;
char traces_path[PROPERTY_VALUE_MAX] = "";
@@ -764,6 +785,7 @@
}
void dump_route_tables() {
+ ON_DRY_RUN_RETURN();
const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
dump_file("RT_TABLES", RT_TABLES_PATH);
FILE* fp = fopen(RT_TABLES_PATH, "re");
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 46d72fd..b48fbc1 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -43,36 +43,40 @@
static const char* kCpPath = "/system/bin/cp";
-int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
-{
+int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) {
if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
ALOGE("invalid uid/gid: %d %d\n", uid, gid);
return -1;
}
- std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
- const char* pkgdir = _pkgdir.c_str();
+ std::string ce_package_path(create_data_user_package_path(uuid, 0, pkgname));
+ std::string de_package_path(create_data_user_de_package_path(uuid, 0, pkgname));
- if (mkdir(pkgdir, 0751) < 0) {
- ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
+ const char* c_ce_package_path = ce_package_path.c_str();
+ const char* c_de_package_path = de_package_path.c_str();
+
+ if (fs_prepare_dir(c_ce_package_path, 0751, uid, gid) == -1) {
+ PLOG(ERROR) << "Failed to prepare " << ce_package_path;
+ unlink(c_ce_package_path);
return -1;
}
- if (chmod(pkgdir, 0751) < 0) {
- ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(pkgdir);
+ if (selinux_android_setfilecon(c_ce_package_path, pkgname, seinfo, uid) < 0) {
+ PLOG(ERROR) << "Failed to setfilecon " << ce_package_path;
+ unlink(c_ce_package_path);
return -1;
}
- if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
- ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(pkgdir);
- return -errno;
- }
-
- if (chown(pkgdir, uid, gid) < 0) {
- ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(pkgdir);
- return -1;
+ if (property_get_bool("vold.has_fbe", false)) {
+ if (fs_prepare_dir(c_de_package_path, 0751, uid, gid) == -1) {
+ PLOG(ERROR) << "Failed to prepare " << de_package_path;
+ unlink(c_de_package_path);
+ return -1;
+ }
+ if (selinux_android_setfilecon(c_de_package_path, pkgname, seinfo, uid) < 0) {
+ PLOG(ERROR) << "Failed to setfilecon " << de_package_path;
+ unlink(c_de_package_path);
+ return -1;
+ }
}
return 0;
@@ -89,23 +93,6 @@
return delete_dir_contents(pkgdir, 1, NULL);
}
-int renamepkg(const char *oldpkgname, const char *newpkgname)
-{
- char oldpkgdir[PKG_PATH_MAX];
- char newpkgdir[PKG_PATH_MAX];
-
- if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
- return -1;
- if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
- return -1;
-
- if (rename(oldpkgdir, newpkgdir) < 0) {
- ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
- return -errno;
- }
- return 0;
-}
-
int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid)
{
struct stat s;
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 7a16150..52f7b9c 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -72,11 +72,6 @@
return uninstall(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_rename(char **arg, char reply[REPLY_MAX] __unused)
-{
- return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
-}
-
static int do_fixuid(char **arg, char reply[REPLY_MAX] __unused)
{
return fix_uid(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */
@@ -198,7 +193,6 @@
{ "movedex", 3, do_move_dex },
{ "rmdex", 2, do_rm_dex },
{ "remove", 3, do_remove },
- { "rename", 2, do_rename },
{ "fixuid", 4, do_fixuid },
{ "freecache", 2, do_free_cache },
{ "rmcache", 3, do_rm_cache },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index df13fe4..6a73457 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -171,10 +171,14 @@
std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
+// TODO: finish refactoring to "_ce"
std::string create_data_user_path(const char* volume_uuid, userid_t userid);
+std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
std::string create_data_user_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
+std::string create_data_user_de_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index e58391f..e586caa 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -64,6 +64,15 @@
create_data_user_path(volume_uuid, user).c_str(), package_name);
}
+std::string create_data_user_de_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name) {
+ CHECK(is_valid_filename(package_name));
+ CHECK(is_valid_package_name(package_name) == 0);
+
+ return StringPrintf("%s/%s",
+ create_data_user_de_path(volume_uuid, user).c_str(), package_name);
+}
+
int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
const char *postfix, userid_t userid) {
if (is_valid_package_name(pkgname) != 0) {
@@ -115,6 +124,14 @@
}
/**
+ * Create the path name for device encrypted user data for a certain userid.
+ */
+std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) {
+ std::string data(create_data_path(volume_uuid));
+ return StringPrintf("%s/user_de/%u", data.c_str(), userid);
+}
+
+/**
* Create the path name for media for a certain userid.
*/
std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index 521c223..f746a69 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -509,7 +509,7 @@
OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
- /** Event when tunneled decoder has rendered an output
+ /** Event when tunneled decoder has rendered an output or reached EOS
* nData1 must contain the number of timestamps returned
* pEventData must point to an array of the OMX_VIDEO_RENDEREVENTTYPE structs containing the
* render-timestamps of each frame. Component may batch rendered timestamps using this event,
@@ -518,6 +518,10 @@
*
* If component is doing frame-rate conversion, it must signal the render time of each
* converted frame, and must interpolate media timestamps for in-between frames.
+ *
+ * When the component reached EOS, it must signal an EOS timestamp using the same mechanism.
+ * This is in addition to the timestamp of the last rendered frame, and should follow that
+ * frame.
*/
OMX_EventOutputRendered = 0x7F000001,
OMX_EventMax = 0x7FFFFFFF
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 34c0405..3971bc5 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -203,10 +203,17 @@
OMX_BOOL bEnableLoopFilterAcrossSlices;
} OMX_VIDEO_SLICESEGMENTSTYPE;
-/** Structure to return timestamps of rendered output frames for tunneled components */
+/** Structure to return timestamps of rendered output frames as well as EOS
+ * for tunneled components.
+ */
typedef struct OMX_VIDEO_RENDEREVENTTYPE {
OMX_S64 nMediaTimeUs; // timestamp of rendered video frame
OMX_S64 nSystemTimeNs; // system monotonic time at the time frame was rendered
+ // Use INT64_MAX for nMediaTimeUs to signal that the EOS
+ // has been reached. In this case, nSystemTimeNs MUST be
+ // the system time when the last frame was rendered.
+ // This MUST be done in addition to returning (and
+ // following) the render information for the last frame.
} OMX_VIDEO_RENDEREVENTTYPE;
#ifdef __cplusplus
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 56cde8a..b8f5436 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -338,6 +338,39 @@
return BAD_TYPE;
}
+namespace {
+
+template<typename T>
+status_t readTypedVector(std::vector<T>* val, const Parcel* p,
+ status_t(Parcel::*read_func)(T*) const) {
+ val->clear();
+
+ int32_t size;
+ status_t status = p->readInt32(&size);
+
+ if (status != OK) {
+ return status;
+ }
+
+ if (size < 0) {
+ return UNEXPECTED_NULL;
+ }
+
+ val->resize(size);
+
+ for (auto& v: *val) {
+ status = (p->*read_func)(&v);
+
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ return OK;
+}
+
+} // namespace
+
// ---------------------------------------------------------------------------
Parcel::Parcel()
@@ -743,6 +776,46 @@
return NULL;
}
+namespace {
+
+template<typename T, typename U>
+status_t unsafeWriteTypedVector(const std::vector<T>& val, Parcel* p,
+ status_t(Parcel::*write_func)(U)) {
+ if (val.size() > std::numeric_limits<int32_t>::max()) {
+ return BAD_VALUE;
+ }
+
+ status_t status = p->writeInt32(val.size());
+
+ if (status != OK) {
+ return status;
+ }
+
+ for (const auto& item : val) {
+ status = (p->*write_func)(item);
+
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ return OK;
+}
+
+template<typename T>
+status_t writeTypedVector(const std::vector<T>& val, Parcel* p,
+ status_t(Parcel::*write_func)(const T&)) {
+ return unsafeWriteTypedVector(val, p, write_func);
+}
+
+template<typename T>
+status_t writeTypedVector(const std::vector<T>& val, Parcel* p,
+ status_t(Parcel::*write_func)(T)) {
+ return unsafeWriteTypedVector(val, p, write_func);
+}
+
+} // namespace
+
status_t Parcel::writeByteVector(const std::vector<int8_t>& val)
{
status_t status;
@@ -768,163 +841,37 @@
status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeInt32(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeInt32);
}
status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeInt64(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeInt64);
}
status_t Parcel::writeFloatVector(const std::vector<float>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeFloat(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeFloat);
}
status_t Parcel::writeDoubleVector(const std::vector<double>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeDouble(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeDouble);
}
status_t Parcel::writeBoolVector(const std::vector<bool>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeBool(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeBool);
}
status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeChar(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeChar);
}
status_t Parcel::writeString16Vector(const std::vector<String16>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeString16(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeString16);
}
status_t Parcel::writeInt32(int32_t val)
@@ -1073,52 +1020,11 @@
status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
{
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- return BAD_VALUE;
- }
-
- status_t status = writeInt32(val.size());
-
- if (status != OK) {
- return status;
- }
-
- for (const auto& item : val) {
- status = writeStrongBinder(item);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return writeTypedVector(val, this, &Parcel::writeStrongBinder);
}
status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->resize(size);
-
- for (auto& v : *val) {
- status = readStrongBinder(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readStrongBinder);
}
status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
@@ -1417,10 +1323,15 @@
return status;
}
- if (size < 0 || size_t(size) > dataAvail()) {
+ if (size < 0) {
+ status = UNEXPECTED_NULL;
+ return status;
+ }
+ if (size_t(size) > dataAvail()) {
status = BAD_VALUE;
return status;
}
+
const void* data = readInplace(size);
if (!data) {
status = BAD_VALUE;
@@ -1433,111 +1344,19 @@
}
status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->resize(size);
-
- for (auto& v: *val) {
- status = readInt32(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readInt32);
}
status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->resize(size);
-
- for (auto& v : *val) {
- status = readInt64(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readInt64);
}
status_t Parcel::readFloatVector(std::vector<float>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->resize(size);
-
- for (auto& v : *val) {
- status = readFloat(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readFloat);
}
status_t Parcel::readDoubleVector(std::vector<double>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->resize(size);
-
- for (auto& v : *val) {
- status = readDouble(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readDouble);
}
status_t Parcel::readBoolVector(std::vector<bool>* val) const {
@@ -1551,7 +1370,7 @@
}
if (size < 0) {
- return BAD_VALUE;
+ return UNEXPECTED_NULL;
}
val->resize(size);
@@ -1573,61 +1392,11 @@
}
status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->resize(size);
-
- for (auto& v : *val) {
- status = readChar(&v);
-
- if (status != OK) {
- return status;
- }
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readChar);
}
status_t Parcel::readString16Vector(std::vector<String16>* val) const {
- val->clear();
-
- int32_t size;
- status_t status = readInt32(&size);
-
- if (status != OK) {
- return status;
- }
-
- if (size < 0) {
- return BAD_VALUE;
- }
-
- val->reserve(size);
-
- while (size-- > 0) {
- const char16_t *data;
- size_t size;
- data = readString16Inplace(&size);
-
- if (data == nullptr) {
- return UNKNOWN_ERROR;
- }
-
- val->emplace_back(data, size);
- }
-
- return OK;
+ return readTypedVector(val, this, &Parcel::readString16);
}
@@ -1834,7 +1603,7 @@
return 0;
} else {
*pArg = String16();
- return UNKNOWN_ERROR;
+ return UNEXPECTED_NULL;
}
}