am 5ea7ea44: (-s ours) Merge "DO NOT MERGE. Cancel touches as well as pointer gestures." into cw-d-mr1-dev
* commit '5ea7ea44a23d0ab81f24eb290840db10d766b122':
DO NOT MERGE. Cancel touches as well as pointer gestures.
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index a3d210a..9def406 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -23,6 +23,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
#include <zlib.h>
@@ -34,6 +35,7 @@
#include <cutils/properties.h>
#include <utils/String8.h>
+#include <utils/Timers.h>
#include <utils/Trace.h>
using namespace android;
@@ -135,6 +137,9 @@
{ REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable" },
{ REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable" },
} },
+ { "regulators", "Voltage and Current Regulators", 0, {
+ { REQ, "/sys/kernel/debug/tracing/events/regulator/enable" },
+ } },
};
/* Command line options */
@@ -191,6 +196,9 @@
static const char* k_tracePath =
"/sys/kernel/debug/tracing/trace";
+static const char* k_traceMarkerPath =
+ "/sys/kernel/debug/tracing/trace_marker";
+
// Check whether a file exists.
static bool fileExists(const char* filename) {
return access(filename, F_OK) != -1;
@@ -253,6 +261,14 @@
return _writeStr(filename, str, O_APPEND|O_WRONLY);
}
+static void writeClockSyncMarker()
+{
+ char buffer[128];
+ float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
+ snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
+ writeStr(k_traceMarkerPath, buffer);
+}
+
// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
// file.
static bool setKernelOptionEnable(const char* filename, bool enable)
@@ -630,6 +646,7 @@
// Disable tracing in the kernel.
static void stopTrace()
{
+ writeClockSyncMarker();
setTracingEnabled(false);
}
@@ -648,7 +665,7 @@
uint8_t *in, *out;
int result, flush;
- bzero(&zs, sizeof(zs));
+ memset(&zs, 0, sizeof(zs));
result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
if (result != Z_OK) {
fprintf(stderr, "error initializing zlib: %d\n", result);
@@ -883,7 +900,7 @@
g_traceOverwrite = true;
} else if (!strcmp(long_options[option_index].name, "async_stop")) {
async = true;
- traceStop = false;
+ traceStart = false;
} else if (!strcmp(long_options[option_index].name, "async_dump")) {
async = true;
traceStart = false;
diff --git a/cmds/bugreport/Android.mk b/cmds/bugreport/Android.mk
index f476f5e..ced5d30 100644
--- a/cmds/bugreport/Android.mk
+++ b/cmds/bugreport/Android.mk
@@ -1,10 +1,12 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= bugreport.c
+LOCAL_SRC_FILES:= bugreport.cpp
LOCAL_MODULE:= bugreport
+LOCAL_CFLAGS := -Wall
+
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreport/bugreport.c b/cmds/bugreport/bugreport.c
deleted file mode 100644
index 11e9057..0000000
--- a/cmds/bugreport/bugreport.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-
-int main(int argc, char *argv[]) {
- char buffer[65536];
- int i, s;
-
- /* start the dumpstate service */
- property_set("ctl.start", "dumpstate");
-
- /* socket will not be available until service starts */
- for (i = 0; i < 20; i++) {
- s = socket_local_client("dumpstate",
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
- if (s >= 0)
- break;
- /* try again in 1 second */
- sleep(1);
- }
-
- if (s < 0) {
- fprintf(stderr, "Failed to connect to dumpstate service\n");
- exit(1);
- }
-
- while (1) {
- int length = read(s, buffer, sizeof(buffer));
- if (length <= 0)
- break;
- fwrite(buffer, 1, length, stdout);
- }
-
- close(s);
- return 0;
-}
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
new file mode 100644
index 0000000..6892b57
--- /dev/null
+++ b/cmds/bugreport/bugreport.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+// This program will trigger the dumpstate service to start a call to
+// dumpstate, then connect to the dumpstate local client to read the
+// output. All of the dumpstate output is written to stdout, including
+// any errors encountered while reading/writing the output.
+int main() {
+ // Start the dumpstate service.
+ property_set("ctl.start", "dumpstate");
+
+ // Socket will not be available until service starts.
+ int s;
+ for (int i = 0; i < 20; i++) {
+ s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (s >= 0)
+ break;
+ // Try again in 1 second.
+ sleep(1);
+ }
+
+ if (s == -1) {
+ printf("Failed to connect to dumpstate service: %s\n", strerror(errno));
+ return 1;
+ }
+
+ // Set a timeout so that if nothing is read in 3 minutes, we'll stop
+ // reading and quit. No timeout in dumpstate is longer than 60 seconds,
+ // so this gives lots of leeway in case of unforeseen time outs.
+ struct timeval tv;
+ tv.tv_sec = 3 * 60;
+ tv.tv_usec = 0;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
+ printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+ }
+
+ while (1) {
+ char buffer[65536];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)));
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read == -1) {
+ // EAGAIN really means time out, so change the errno.
+ if (errno == EAGAIN) {
+ errno = ETIMEDOUT;
+ }
+ printf("\nBugreport read terminated abnormally (%s).\n", strerror(errno));
+ break;
+ }
+
+ ssize_t bytes_to_send = bytes_read;
+ ssize_t bytes_written;
+ do {
+ bytes_written = TEMP_FAILURE_RETRY(write(STDOUT_FILENO,
+ buffer + bytes_read - bytes_to_send,
+ bytes_to_send));
+ if (bytes_written == -1) {
+ printf("Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
+ bytes_read, bytes_to_send, strerror(errno));
+ return 1;
+ }
+ bytes_to_send -= bytes_written;
+ } while (bytes_written != 0 && bytes_to_send > 0);
+ }
+
+ close(s);
+ return 0;
+}
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index dc1ada0..1d9e6b8 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -64,7 +65,8 @@
time_t thirty_minutes_ago = time(NULL) - 60*30;
for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
- int fd = open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+ int fd = TEMP_FAILURE_RETRY(open(data[i].name,
+ O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
struct stat st;
if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
(time_t) st.st_mtime >= thirty_minutes_ago) {
@@ -98,8 +100,170 @@
closedir(d);
}
+static bool skip_not_stat(const char *path) {
+ static const char stat[] = "/stat";
+ size_t len = strlen(path);
+ if (path[len - 1] == '/') { /* Directory? */
+ return false;
+ }
+ return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
+}
+
+static const char mmcblk0[] = "/sys/block/mmcblk0/";
+unsigned long worst_write_perf = 20000; /* in KB/s */
+
+static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
+ unsigned long fields[11], read_perf, write_perf;
+ bool z;
+ char *cp, *buffer = NULL;
+ size_t i = 0;
+ FILE *fp = fdopen(fd, "rb");
+ getline(&buffer, &i, fp);
+ fclose(fp);
+ if (!buffer) {
+ return -errno;
+ }
+ i = strlen(buffer);
+ while ((i > 0) && (buffer[i - 1] == '\n')) {
+ buffer[--i] = '\0';
+ }
+ if (!*buffer) {
+ free(buffer);
+ return 0;
+ }
+ z = true;
+ for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
+ fields[i] = strtol(cp, &cp, 0);
+ if (fields[i] != 0) {
+ z = false;
+ }
+ }
+ if (z) { /* never accessed */
+ free(buffer);
+ return 0;
+ }
+
+ if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
+ path += sizeof(mmcblk0) - 1;
+ }
+
+ printf("%s: %s\n", path, buffer);
+ free(buffer);
+
+ read_perf = 0;
+ if (fields[3]) {
+ read_perf = 512 * fields[2] / fields[3];
+ }
+ write_perf = 0;
+ if (fields[7]) {
+ write_perf = 512 * fields[6] / fields[7];
+ }
+ printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
+ if ((write_perf > 1) && (write_perf < worst_write_perf)) {
+ worst_write_perf = write_perf;
+ }
+ return 0;
+}
+
+/* Copied policy from system/core/logd/LogBuffer.cpp */
+
+#define LOG_BUFFER_SIZE (256 * 1024)
+#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
+#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
+
+static bool valid_size(unsigned long value) {
+ if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
+ return false;
+ }
+
+ long pages = sysconf(_SC_PHYS_PAGES);
+ if (pages < 1) {
+ return true;
+ }
+
+ long pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize <= 1) {
+ pagesize = PAGE_SIZE;
+ }
+
+ // maximum memory impact a somewhat arbitrary ~3%
+ pages = (pages + 31) / 32;
+ unsigned long maximum = pages * pagesize;
+
+ if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
+ return true;
+ }
+
+ return value <= maximum;
+}
+
+static unsigned long property_get_size(const char *key) {
+ unsigned long value;
+ char *cp, property[PROPERTY_VALUE_MAX];
+
+ property_get(key, property, "");
+ value = strtoul(property, &cp, 10);
+
+ switch(*cp) {
+ case 'm':
+ case 'M':
+ value *= 1024;
+ /* FALLTHRU */
+ case 'k':
+ case 'K':
+ value *= 1024;
+ /* FALLTHRU */
+ case '\0':
+ break;
+
+ default:
+ value = 0;
+ }
+
+ if (!valid_size(value)) {
+ value = 0;
+ }
+
+ return value;
+}
+
+/* timeout in ms */
+static unsigned long logcat_timeout(char *name) {
+ static const char global_tuneable[] = "persist.logd.size"; // Settings App
+ static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
+ char key[PROP_NAME_MAX];
+ unsigned long property_size, default_size;
+
+ default_size = property_get_size(global_tuneable);
+ if (!default_size) {
+ default_size = property_get_size(global_default);
+ }
+
+ snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
+ property_size = property_get_size(key);
+
+ if (!property_size) {
+ snprintf(key, sizeof(key), "%s.%s", global_default, name);
+ property_size = property_get_size(key);
+ }
+
+ if (!property_size) {
+ property_size = default_size;
+ }
+
+ if (!property_size) {
+ property_size = LOG_BUFFER_SIZE;
+ }
+
+ /* Engineering margin is ten-fold our guess */
+ return 10 * (property_size + worst_write_perf) / worst_write_perf;
+}
+
+/* End copy from system/core/logd/LogBuffer.cpp */
+
/* dumps the current system state to stdout */
static void dumpstate() {
+ unsigned long timeout;
time_t now = time(NULL);
char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
@@ -132,7 +296,7 @@
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
run_command("UPTIME", 10, "uptime", NULL);
- dump_file("MMC PERF", "/sys/block/mmcblk0/stat");
+ 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("PROCRANK", 20, "procrank", NULL);
@@ -148,7 +312,6 @@
dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
dump_file("KERNEL SYNC", "/d/sync");
- dump_file("KERNEL BLUEDROID", "/d/bluedroid");
run_command("PROCESSES", 10, "ps", "-P", NULL);
run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
@@ -168,9 +331,22 @@
}
// dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
- run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
- run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
- run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
+ // calculate timeout
+ timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
+ timeout = logcat_timeout("events");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
+ timeout = logcat_timeout("radio");
+ if (timeout < 20000) {
+ timeout = 20000;
+ }
+ run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
/* show the traces we collected in main(), if that was done */
if (dump_traces_path != NULL) {
@@ -184,7 +360,8 @@
if (!anr_traces_path[0]) {
printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
} else {
- int fd = open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+ int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
+ O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
if (fd < 0) {
printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
} else {
@@ -236,13 +413,13 @@
dump_file("LAST KMSG", "/proc/last_kmsg");
}
- dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console");
- dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads");
-
- for_each_userid(do_dump_settings, NULL);
+ /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
+ run_command("LAST LOGCAT", 10, "logcat", "-L", "-v", "threadtime",
+ "-b", "all", "-d", "*:v", NULL);
/* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
- run_command("NETWORK INTERFACES", 10, SU_PATH, "root", "netcfg", NULL);
+
+ run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
@@ -255,6 +432,8 @@
run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
+ run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
+
run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
@@ -358,6 +537,7 @@
run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
+ run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL);
printf("========================================================\n");
printf("== Running Application Activities\n");
@@ -387,7 +567,6 @@
fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q]\n"
" -o: write to file (instead of stdout)\n"
" -d: append date to filename (requires -o)\n"
- " -z: gzip output (requires -o)\n"
" -p: capture screenshot to filename.png (requires -o)\n"
" -s: write output to control socket (for init)\n"
" -b: play sound file instead of vibrate, at beginning of job\n"
@@ -410,7 +589,6 @@
int main(int argc, char *argv[]) {
struct sigaction sigact;
int do_add_date = 0;
- int do_compress = 0;
int do_vibrate = 1;
char* use_outfile = 0;
int use_socket = 0;
@@ -435,7 +613,7 @@
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
- FILE *oom_adj = fopen("/proc/self/oom_adj", "w");
+ FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
if (oom_adj) {
fputs("-17", oom_adj);
fclose(oom_adj);
@@ -450,7 +628,6 @@
case 's': use_socket = 1; break;
case 'v': break; // compatibility no-op
case 'q': do_vibrate = 0; break;
- case 'z': do_compress = 6; break;
case 'p': do_fb = 1; break;
case 'B': do_broadcast = 1; break;
case '?': printf("\n");
@@ -469,15 +646,14 @@
/* open the vibrator before dropping root */
FILE *vibrator = 0;
if (do_vibrate) {
- vibrator = fopen("/sys/class/timed_output/vibrator/enable", "w");
+ vibrator = fopen("/sys/class/timed_output/vibrator/enable", "we");
if (vibrator) {
- fcntl(fileno(vibrator), F_SETFD, FD_CLOEXEC);
vibrate(vibrator, 150);
}
}
/* read /proc/cmdline before dropping root */
- FILE *cmdline = fopen("/proc/cmdline", "r");
+ FILE *cmdline = fopen("/proc/cmdline", "re");
if (cmdline != NULL) {
fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
fclose(cmdline);
@@ -545,10 +721,9 @@
strlcat(screenshot_path, ".png", sizeof(screenshot_path));
}
strlcat(path, ".txt", sizeof(path));
- if (do_compress) strlcat(path, ".gz", sizeof(path));
strlcpy(tmp_path, path, sizeof(tmp_path));
strlcat(tmp_path, ".tmp", sizeof(tmp_path));
- gzip_pid = redirect_to_file(stdout, tmp_path, do_compress);
+ redirect_to_file(stdout, tmp_path);
}
dumpstate();
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 53bfff6..c5d3044 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -26,14 +26,25 @@
typedef void (for_each_pid_func)(int, const char *);
typedef void (for_each_tid_func)(int, int, const char *);
-typedef void (for_each_userid_func)(int);
/* prints the contents of a file */
int dump_file(const char *title, const char *path);
-/* prints the contents of the fd */
+/* prints the contents of the fd
+ * fd must have been opened with the flag O_NONBLOCK.
+ */
int dump_file_from_fd(const char *title, const char *path, int fd);
+/* calls skip to gate calling dump_from_fd recursively
+ * in the specified directory. dump_from_fd defaults to
+ * dump_file_from_fd above when set to NULL. skip defaults
+ * to false when set to NULL. dump_from_fd will always be
+ * called with title NULL.
+ */
+int dump_files(const char *title, const char *dir,
+ bool (*skip)(const char *path),
+ int (*dump_from_fd)(const char *title, const char *path, int fd));
+
/* 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, ...);
@@ -43,8 +54,8 @@
/* redirect output to a service control socket */
void redirect_to_socket(FILE *redirect, const char *service);
-/* redirect output to a file, optionally gzipping; returns gzip pid */
-pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level);
+/* redirect output to a file */
+void redirect_to_file(FILE *redirect, char *path);
/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
const char *dump_traces();
@@ -55,9 +66,6 @@
/* for each thread in the system, run the specified function */
void for_each_tid(for_each_tid_func func, const char *header);
-/* for each user id in the system, run the specified function */
-void for_each_userid(for_each_userid_func func, const char *header);
-
/* Displays a blocked processes in-kernel wait channel */
void show_wchan(int pid, int tid, const char *name);
@@ -67,9 +75,6 @@
/* Gets the dmesg output for the kernel */
void do_dmesg();
-/* Dumps settings for a given user id */
-void do_dump_settings(int userid);
-
/* Prints the contents of all the routing tables, both IPv4 and IPv6. */
void dump_route_tables();
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 3e0b24be..d679787 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -53,6 +53,12 @@
NULL,
};
+static uint64_t nanotime() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (uint64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
+}
+
void for_each_userid(void (*func)(int), const char *header) {
DIR *d;
struct dirent *de;
@@ -98,7 +104,7 @@
sprintf(cmdpath,"/proc/%d/cmdline", pid);
memset(cmdline, 0, sizeof(cmdline));
- if ((fd = open(cmdpath, O_RDONLY)) < 0) {
+ if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) < 0) {
strcpy(cmdline, "N/A");
} else {
read(fd, cmdline, sizeof(cmdline) - 1);
@@ -149,7 +155,7 @@
sprintf(commpath,"/proc/%d/comm", tid);
memset(comm, 0, sizeof(comm));
- if ((fd = open(commpath, O_RDONLY)) < 0) {
+ if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
strcpy(comm, "N/A");
} else {
char *c;
@@ -180,7 +186,7 @@
memset(buffer, 0, sizeof(buffer));
sprintf(path, "/proc/%d/wchan", tid);
- if ((fd = open(path, O_RDONLY)) < 0) {
+ if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
printf("Failed to open '%s' (%s)\n", path, strerror(errno));
return;
}
@@ -200,22 +206,6 @@
return;
}
-void do_dump_settings(int userid) {
- char title[255];
- char dbpath[255];
- char sql[255];
- sprintf(title, "SYSTEM SETTINGS (user %d)", userid);
- if (userid == 0) {
- strcpy(dbpath, "/data/data/com.android.providers.settings/databases/settings.db");
- strcpy(sql, "pragma user_version; select * from system; select * from secure; select * from global;");
- } else {
- sprintf(dbpath, "/data/system/users/%d/settings.db", userid);
- strcpy(sql, "pragma user_version; select * from system; select * from secure;");
- }
- run_command(title, 20, SU_PATH, "root", "sqlite3", dbpath, sql, NULL);
- return;
-}
-
void do_dmesg() {
printf("------ KERNEL LOG (dmesg) ------\n");
/* Get size of kernel buffer */
@@ -250,22 +240,7 @@
run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL);
}
-/* prints the contents of a file */
-int dump_file(const char *title, const char *path) {
- int fd = open(path, O_RDONLY);
- 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;
- }
- return dump_file_from_fd(title, path, fd);
-}
-
-int dump_file_from_fd(const char *title, const char *path, int fd) {
- char buffer[32768];
-
+static int _dump_file_from_fd(const char *title, const char *path, int fd) {
if (title) printf("------ %s (%s", title, path);
if (title) {
@@ -279,14 +254,41 @@
printf(") ------\n");
}
- int newline = 0;
- for (;;) {
- int ret = read(fd, buffer, sizeof(buffer));
- if (ret > 0) {
- newline = (buffer[ret - 1] == '\n');
- ret = fwrite(buffer, ret, 1, stdout);
+ bool newline = false;
+ fd_set read_set;
+ struct timeval tm;
+ while (1) {
+ FD_ZERO(&read_set);
+ FD_SET(fd, &read_set);
+ /* Timeout if no data is read for 30 seconds. */
+ tm.tv_sec = 30;
+ tm.tv_usec = 0;
+ uint64_t elapsed = nanotime();
+ int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm));
+ if (ret == -1) {
+ printf("*** %s: select failed: %s\n", path, strerror(errno));
+ newline = true;
+ break;
+ } else if (ret == 0) {
+ elapsed = nanotime() - elapsed;
+ printf("*** %s: Timed out after %.3fs\n", path,
+ (float) elapsed / NANOS_PER_SEC);
+ newline = true;
+ break;
+ } else {
+ char buffer[65536];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+ if (bytes_read > 0) {
+ fwrite(buffer, bytes_read, 1, stdout);
+ newline = (buffer[bytes_read-1] == '\n');
+ } else {
+ if (bytes_read == -1) {
+ printf("*** %s: Failed to read from fd: %s", path, strerror(errno));
+ newline = true;
+ }
+ break;
+ }
}
- if (ret <= 0) break;
}
close(fd);
@@ -295,16 +297,152 @@
return 0;
}
-static int64_t nanotime() {
+/* prints the contents of a file */
+int dump_file(const char *title, const char *path) {
+ 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;
+ }
+ return _dump_file_from_fd(title, path, fd);
+}
+
+/* calls skip to gate calling dump_from_fd recursively
+ * in the specified directory. dump_from_fd defaults to
+ * dump_file_from_fd above when set to NULL. skip defaults
+ * to false when set to NULL. dump_from_fd will always be
+ * called with title NULL.
+ */
+int dump_files(const char *title, const char *dir,
+ bool (*skip)(const char *path),
+ int (*dump_from_fd)(const char *title, const char *path, int fd)) {
+ DIR *dirp;
+ struct dirent *d;
+ char *newpath = NULL;
+ char *slash = "/";
+ int fd, retval = 0;
+
+ if (title) {
+ printf("------ %s (%s) ------\n", title, dir);
+ }
+
+ if (dir[strlen(dir) - 1] == '/') {
+ ++slash;
+ }
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ retval = -errno;
+ fprintf(stderr, "%s: %s\n", dir, strerror(errno));
+ return retval;
+ }
+
+ if (!dump_from_fd) {
+ dump_from_fd = dump_file_from_fd;
+ }
+ for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
+ if ((d->d_name[0] == '.')
+ && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
+ || (d->d_name[1] == '\0'))) {
+ continue;
+ }
+ asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
+ (d->d_type == DT_DIR) ? "/" : "");
+ if (!newpath) {
+ retval = -errno;
+ continue;
+ }
+ if (skip && (*skip)(newpath)) {
+ continue;
+ }
+ if (d->d_type == DT_DIR) {
+ int ret = dump_files(NULL, newpath, skip, dump_from_fd);
+ if (ret < 0) {
+ retval = ret;
+ }
+ continue;
+ }
+ fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+ if (fd < 0) {
+ retval = fd;
+ printf("*** %s: %s\n", newpath, strerror(errno));
+ continue;
+ }
+ (*dump_from_fd)(NULL, newpath, fd);
+ }
+ closedir(dirp);
+ if (title) {
+ printf("\n");
+ }
+ return retval;
+}
+
+/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
+ * it's possible to avoid issues where opening the file itself can get
+ * stuck.
+ */
+int dump_file_from_fd(const char *title, const char *path, int fd) {
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
+ return -1;
+ } else if (!(flags & O_NONBLOCK)) {
+ printf("*** %s: fd must have O_NONBLOCK set.\n", path);
+ return -1;
+ }
+ return _dump_file_from_fd(title, path, fd);
+}
+
+bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
+ sigset_t child_mask, old_mask;
+ sigemptyset(&child_mask);
+ sigaddset(&child_mask, SIGCHLD);
+
+ if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
+ printf("*** sigprocmask failed: %s\n", strerror(errno));
+ return false;
+ }
+
struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return (int64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
+ ts.tv_sec = timeout_seconds;
+ ts.tv_nsec = 0;
+ int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
+ int saved_errno = errno;
+ // Set the signals back the way they were.
+ if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
+ printf("*** sigprocmask failed: %s\n", strerror(errno));
+ if (ret == 0) {
+ return false;
+ }
+ }
+ if (ret == -1) {
+ errno = saved_errno;
+ if (errno == EAGAIN) {
+ errno = ETIMEDOUT;
+ } else {
+ printf("*** sigtimedwait failed: %s\n", strerror(errno));
+ }
+ return false;
+ }
+
+ pid_t child_pid = waitpid(pid, status, WNOHANG);
+ if (child_pid != pid) {
+ if (child_pid != -1) {
+ printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
+ } else {
+ printf("*** waitpid failed: %s\n", strerror(errno));
+ }
+ return false;
+ }
+ return true;
}
/* forks a command and waits for it to finish */
int run_command(const char *title, int timeout_seconds, const char *command, ...) {
fflush(stdout);
- int64_t start = nanotime();
+ uint64_t start = nanotime();
pid_t pid = fork();
/* handle error case */
@@ -345,28 +483,35 @@
}
/* handle parent case */
- for (;;) {
- int status;
- pid_t p = waitpid(pid, &status, WNOHANG);
- int64_t elapsed = nanotime() - start;
- if (p == pid) {
- if (WIFSIGNALED(status)) {
- printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
- } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
- printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
+ int status;
+ bool ret = waitpid_with_timeout(pid, timeout_seconds, &status);
+ uint64_t elapsed = nanotime() - start;
+ if (!ret) {
+ if (errno == ETIMEDOUT) {
+ printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command,
+ (float) elapsed / NANOS_PER_SEC, pid);
+ } else {
+ printf("*** %s: Error after %.4fs (killing pid %d)\n", command,
+ (float) elapsed / NANOS_PER_SEC, pid);
+ }
+ kill(pid, SIGTERM);
+ if (!waitpid_with_timeout(pid, 5, NULL)) {
+ kill(pid, SIGKILL);
+ if (!waitpid_with_timeout(pid, 5, NULL)) {
+ printf("*** %s: Cannot kill %d even with SIGKILL.\n", command, pid);
}
- if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC);
- return status;
}
-
- if (timeout_seconds && elapsed / NANOS_PER_SEC > timeout_seconds) {
- printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command, (float) elapsed / NANOS_PER_SEC, pid);
- kill(pid, SIGTERM);
- return -1;
- }
-
- usleep(100000); // poll every 0.1 sec
+ return -1;
}
+
+ if (WIFSIGNALED(status)) {
+ printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
+ } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
+ printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
+ }
+ if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC);
+
+ return status;
}
size_t num_props = 0;
@@ -407,6 +552,7 @@
fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno));
exit(1);
}
+ fcntl(s, F_SETFD, FD_CLOEXEC);
if (listen(s, 4) < 0) {
fprintf(stderr, "listen(control socket): %s\n", strerror(errno));
exit(1);
@@ -425,8 +571,8 @@
close(fd);
}
-/* redirect output to a file, optionally gzipping; returns gzip pid (or -1) */
-pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level) {
+/* redirect output to a file */
+void redirect_to_file(FILE *redirect, char *path) {
char *chp = path;
/* skip initial slash */
@@ -443,52 +589,15 @@
}
}
- int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
if (fd < 0) {
fprintf(stderr, "%s: %s\n", path, strerror(errno));
exit(1);
}
- pid_t gzip_pid = -1;
- if (gzip_level > 0) {
- int fds[2];
- if (pipe(fds)) {
- fprintf(stderr, "pipe: %s\n", strerror(errno));
- exit(1);
- }
-
- fflush(redirect);
- fflush(stdout);
-
- gzip_pid = fork();
- if (gzip_pid < 0) {
- fprintf(stderr, "fork: %s\n", strerror(errno));
- exit(1);
- }
-
- if (gzip_pid == 0) {
- dup2(fds[0], STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
-
- close(fd);
- close(fds[0]);
- close(fds[1]);
-
- char level[10];
- snprintf(level, sizeof(level), "-%d", gzip_level);
- execlp("gzip", "gzip", level, NULL);
- fprintf(stderr, "exec(gzip): %s\n", strerror(errno));
- _exit(-1);
- }
-
- close(fd);
- close(fds[0]);
- fd = fds[1];
- }
-
- dup2(fd, fileno(redirect));
+ TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
close(fd);
- return gzip_pid;
}
static bool should_dump_native_traces(const char* path) {
@@ -536,7 +645,8 @@
}
/* create a new, empty traces.txt file to receive stack dumps */
- int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666); /* -rw-rw-rw- */
+ int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
+ 0666)); /* -rw-rw-rw- */
if (fd < 0) {
fprintf(stderr, "%s: %s\n", traces_path, strerror(errno));
return NULL;
@@ -586,7 +696,7 @@
if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
/* skip zygote -- it won't dump its stack anyway */
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
- int cfd = open(path, O_RDONLY);
+ int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
len = read(cfd, data, sizeof(data) - 1);
close(cfd);
if (len <= 0) {
@@ -598,7 +708,7 @@
}
++dalvik_found;
- int64_t start = nanotime();
+ uint64_t start = nanotime();
if (kill(pid, SIGQUIT)) {
fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
continue;
@@ -628,7 +738,7 @@
fprintf(stderr, "lseek: %s\n", strerror(errno));
} else {
static uint16_t timeout_failures = 0;
- int64_t start = nanotime();
+ uint64_t start = nanotime();
/* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
if (timeout_failures == 3) {
@@ -671,7 +781,7 @@
void dump_route_tables() {
const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
dump_file("RT_TABLES", RT_TABLES_PATH);
- FILE* fp = fopen(RT_TABLES_PATH, "r");
+ FILE* fp = fopen(RT_TABLES_PATH, "re");
if (!fp) {
printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
return;
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 8224e94..6dec7f6 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,6 +1,6 @@
LOCAL_PATH := $(call my-dir)
-common_src_files := commands.c utils.c
+common_src_files := commands.cpp utils.cpp
common_cflags := -Wall -Werror
#
@@ -12,7 +12,12 @@
LOCAL_MODULE_TAGS := eng tests
LOCAL_SRC_FILES := $(common_src_files)
LOCAL_CFLAGS := $(common_cflags)
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ liblogwrap \
+
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_CLANG := true
include $(BUILD_STATIC_LIBRARY)
#
@@ -23,8 +28,15 @@
LOCAL_MODULE := installd
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := $(common_cflags)
-LOCAL_SRC_FILES := installd.c $(common_src_files)
-LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux
+LOCAL_SRC_FILES := installd.cpp $(common_src_files)
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ libcutils \
+ liblog \
+ liblogwrap \
+ libselinux \
+
LOCAL_STATIC_LIBRARIES := libdiskusage
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_CLANG := true
include $(BUILD_EXECUTABLE)
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.cpp
similarity index 65%
rename from cmds/installd/commands.c
rename to cmds/installd/commands.cpp
index 367f13a..7090b36 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.cpp
@@ -14,13 +14,22 @@
** limitations under the License.
*/
-#include <inttypes.h>
-#include <sys/capability.h>
#include "installd.h"
+
+#include <base/stringprintf.h>
+#include <base/logging.h>
#include <cutils/sched_policy.h>
#include <diskusage/dirsize.h>
-#include <selinux/android.h>
+#include <logwrap/logwrap.h>
#include <system/thread_defs.h>
+#include <selinux/android.h>
+
+#include <inttypes.h>
+#include <sys/capability.h>
+#include <sys/file.h>
+#include <unistd.h>
+
+using android::base::StringPrintf;
/* Directory records that are used in execution of commands. */
dir_rec_t android_data_dir;
@@ -29,34 +38,20 @@
dir_rec_t android_app_private_dir;
dir_rec_t android_app_lib_dir;
dir_rec_t android_media_dir;
+dir_rec_t android_mnt_expand_dir;
dir_rec_array_t android_system_dirs;
-int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
-{
- char pkgdir[PKG_PATH_MAX];
- char libsymlink[PKG_PATH_MAX];
- char applibdir[PKG_PATH_MAX];
- struct stat libStat;
+static const char* kCpPath = "/system/bin/cp";
+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;
}
- if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
- ALOGE("cannot create package path\n");
- return -1;
- }
-
- if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) {
- ALOGE("cannot create package lib symlink origin path\n");
- return -1;
- }
-
- if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
- ALOGE("cannot create package lib symlink dest path\n");
- return -1;
- }
+ std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
if (mkdir(pkgdir, 0751) < 0) {
ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
@@ -68,42 +63,14 @@
return -1;
}
- if (lstat(libsymlink, &libStat) < 0) {
- if (errno != ENOENT) {
- ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
- return -1;
- }
- } else {
- if (S_ISDIR(libStat.st_mode)) {
- if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
- ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
- return -1;
- }
- } else if (S_ISLNK(libStat.st_mode)) {
- if (unlink(libsymlink) < 0) {
- ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
- return -1;
- }
- }
- }
-
if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
- if (symlink(applibdir, libsymlink) < 0) {
- ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
- strerror(errno));
- unlink(pkgdir);
- return -1;
- }
-
if (chown(pkgdir, uid, gid) < 0) {
ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(libsymlink);
unlink(pkgdir);
return -1;
}
@@ -111,12 +78,10 @@
return 0;
}
-int uninstall(const char *pkgname, userid_t userid)
+int uninstall(const char *uuid, const char *pkgname, userid_t userid)
{
- char pkgdir[PKG_PATH_MAX];
-
- if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
- return -1;
+ std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
remove_profile_file(pkgname);
@@ -141,21 +106,17 @@
return 0;
}
-int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
+int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid)
{
- char pkgdir[PKG_PATH_MAX];
struct stat s;
- int rc = 0;
if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
ALOGE("invalid uid/gid: %d %d\n", uid, gid);
return -1;
}
- if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
- ALOGE("cannot create package path\n");
- return -1;
- }
+ std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
if (stat(pkgdir, &s) < 0) return -1;
@@ -178,35 +139,18 @@
return 0;
}
-int delete_user_data(const char *pkgname, userid_t userid)
+int delete_user_data(const char *uuid, const char *pkgname, userid_t userid)
{
- char pkgdir[PKG_PATH_MAX];
-
- if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
- return -1;
+ std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
return delete_dir_contents(pkgdir, 0, NULL);
}
-int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
+int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
{
- char pkgdir[PKG_PATH_MAX];
- char applibdir[PKG_PATH_MAX];
- char libsymlink[PKG_PATH_MAX];
- struct stat libStat;
-
- // Create the data dir for the package
- if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) {
- return -1;
- }
- if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) {
- ALOGE("cannot create package lib symlink origin path\n");
- return -1;
- }
- if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
- ALOGE("cannot create package lib symlink dest path\n");
- return -1;
- }
+ std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
if (mkdir(pkgdir, 0751) < 0) {
ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
@@ -218,47 +162,14 @@
return -errno;
}
- if (lstat(libsymlink, &libStat) < 0) {
- if (errno != ENOENT) {
- ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
- unlink(pkgdir);
- return -1;
- }
- } else {
- if (S_ISDIR(libStat.st_mode)) {
- if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
- ALOGE("couldn't delete lib directory during install for non-primary: %s",
- libsymlink);
- unlink(pkgdir);
- return -1;
- }
- } else if (S_ISLNK(libStat.st_mode)) {
- if (unlink(libsymlink) < 0) {
- ALOGE("couldn't unlink lib directory during install for non-primary: %s",
- libsymlink);
- unlink(pkgdir);
- return -1;
- }
- }
- }
-
if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
- if (symlink(applibdir, libsymlink) < 0) {
- ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
- applibdir, strerror(errno));
- unlink(pkgdir);
- return -1;
- }
-
if (chown(pkgdir, uid, uid) < 0) {
ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
- unlink(libsymlink);
unlink(pkgdir);
return -errno;
}
@@ -266,6 +177,115 @@
return 0;
}
+int copy_complete_app(const char *from_uuid, const char *to_uuid,
+ const char *package_name, const char *data_app_name, appid_t appid,
+ const char* seinfo) {
+ std::vector<userid_t> users = get_known_users(from_uuid);
+
+ // Copy app
+ {
+ std::string from(create_data_app_package_path(from_uuid, data_app_name));
+ std::string to(create_data_app_package_path(to_uuid, data_app_name));
+ std::string to_parent(create_data_app_path(to_uuid));
+
+ char *argv[] = {
+ (char*) kCpPath,
+ (char*) "-F", /* delete any existing destination file first (--remove-destination) */
+ (char*) "-p", /* preserve timestamps, ownership, and permissions */
+ (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
+ (char*) "-P", /* Do not follow symlinks [default] */
+ (char*) "-d", /* don't dereference symlinks */
+ (char*) from.c_str(),
+ (char*) to_parent.c_str()
+ };
+
+ LOG(DEBUG) << "Copying " << from << " to " << to;
+ int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
+
+ if (rc != 0) {
+ LOG(ERROR) << "Failed copying " << from << " to " << to
+ << ": status " << rc;
+ goto fail;
+ }
+
+ if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
+ LOG(ERROR) << "Failed to restorecon " << to;
+ goto fail;
+ }
+ }
+
+ // Copy private data for all known users
+ for (auto user : users) {
+ std::string from(create_data_user_package_path(from_uuid, user, package_name));
+ std::string to(create_data_user_package_path(to_uuid, user, package_name));
+ std::string to_parent(create_data_user_path(to_uuid, user));
+
+ // Data source may not exist for all users; that's okay
+ if (access(from.c_str(), F_OK) != 0) {
+ LOG(INFO) << "Missing source " << from;
+ continue;
+ }
+
+ std::string user_path(create_data_user_path(to_uuid, user));
+ if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
+ LOG(ERROR) << "Failed to prepare user target " << user_path;
+ goto fail;
+ }
+
+ uid_t uid = multiuser_get_uid(user, appid);
+ if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) {
+ LOG(ERROR) << "Failed to create package target " << to;
+ goto fail;
+ }
+
+ char *argv[] = {
+ (char*) kCpPath,
+ (char*) "-F", /* delete any existing destination file first (--remove-destination) */
+ (char*) "-p", /* preserve timestamps, ownership, and permissions */
+ (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
+ (char*) "-P", /* Do not follow symlinks [default] */
+ (char*) "-d", /* don't dereference symlinks */
+ (char*) from.c_str(),
+ (char*) to_parent.c_str()
+ };
+
+ LOG(DEBUG) << "Copying " << from << " to " << to;
+ int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true);
+
+ if (rc != 0) {
+ LOG(ERROR) << "Failed copying " << from << " to " << to
+ << ": status " << rc;
+ goto fail;
+ }
+ }
+
+ if (restorecon_data(to_uuid, package_name, seinfo, multiuser_get_uid(0, appid)) != 0) {
+ LOG(ERROR) << "Failed to restorecon";
+ goto fail;
+ }
+
+ // We let the framework scan the new location and persist that before
+ // deleting the data in the old location; this ordering ensures that
+ // we can recover from things like battery pulls.
+ return 0;
+
+fail:
+ // Nuke everything we might have already copied
+ {
+ std::string to(create_data_app_package_path(to_uuid, data_app_name));
+ if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
+ LOG(WARNING) << "Failed to rollback " << to;
+ }
+ }
+ for (auto user : users) {
+ std::string to(create_data_user_package_path(to_uuid, user, package_name));
+ if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
+ LOG(WARNING) << "Failed to rollback " << to;
+ }
+ }
+ return -1;
+}
+
int make_user_config(userid_t userid)
{
if (ensure_config_user_dirs(userid) == -1) {
@@ -275,49 +295,49 @@
return 0;
}
-int delete_user(userid_t userid)
+int delete_user(const char *uuid, userid_t userid)
{
int status = 0;
- char data_path[PKG_PATH_MAX];
- if ((create_user_path(data_path, userid) != 0)
- || (delete_dir_contents(data_path, 1, NULL) != 0)) {
+ std::string data_path(create_data_user_path(uuid, userid));
+ if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) {
status = -1;
}
- char media_path[PATH_MAX];
- if ((create_user_media_path(media_path, userid) != 0)
- || (delete_dir_contents(media_path, 1, NULL) != 0)) {
+ std::string media_path(create_data_media_path(uuid, userid));
+ if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) {
status = -1;
}
- char config_path[PATH_MAX];
- if ((create_user_config_path(config_path, userid) != 0)
- || (delete_dir_contents(config_path, 1, NULL) != 0)) {
- status = -1;
+ // Config paths only exist on internal storage
+ if (uuid == nullptr) {
+ char config_path[PATH_MAX];
+ if ((create_user_config_path(config_path, userid) != 0)
+ || (delete_dir_contents(config_path, 1, NULL) != 0)) {
+ status = -1;
+ }
}
return status;
}
-int delete_cache(const char *pkgname, userid_t userid)
+int delete_cache(const char *uuid, const char *pkgname, userid_t userid)
{
- char cachedir[PKG_PATH_MAX];
-
- if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid))
- return -1;
+ std::string _cachedir(
+ create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX);
+ const char* cachedir = _cachedir.c_str();
/* delete contents, not the directory, no exceptions */
return delete_dir_contents(cachedir, 0, NULL);
}
-int delete_code_cache(const char *pkgname, userid_t userid)
+int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid)
{
- char codecachedir[PKG_PATH_MAX];
- struct stat s;
+ std::string _codecachedir(
+ create_data_user_package_path(uuid, userid, pkgname) + CODE_CACHE_DIR_POSTFIX);
+ const char* codecachedir = _codecachedir.c_str();
- if (create_pkg_path(codecachedir, pkgname, CODE_CACHE_DIR_POSTFIX, userid))
- return -1;
+ struct stat s;
/* it's okay if code cache is missing */
if (lstat(codecachedir, &s) == -1 && errno == ENOENT) {
@@ -335,7 +355,7 @@
* also require that apps constantly modify file metadata even
* when just reading from the cache, which is pretty awful.
*/
-int free_cache(int64_t free_size)
+int free_cache(const char *uuid, int64_t free_size)
{
cache_t* cache;
int64_t avail;
@@ -344,7 +364,9 @@
char tmpdir[PATH_MAX];
char *dirpos;
- avail = data_disk_free();
+ std::string data_path(create_data_path(uuid));
+
+ avail = data_disk_free(data_path);
if (avail < 0) return -1;
ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
@@ -352,15 +374,16 @@
cache = start_cache_collection();
- // Collect cache files for primary user.
- if (create_user_path(tmpdir, 0) == 0) {
- //ALOGI("adding cache files from %s\n", tmpdir);
- add_cache_files(cache, tmpdir, "cache");
+ // Special case for owner on internal storage
+ if (uuid == nullptr) {
+ std::string _tmpdir(create_data_user_path(nullptr, 0));
+ add_cache_files(cache, _tmpdir.c_str(), "cache");
}
// Search for other users and add any cache files from them.
- snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path,
- SECONDARY_USER_PREFIX);
+ std::string _tmpdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX);
+ strcpy(tmpdir, _tmpdir.c_str());
+
dirpos = tmpdir + strlen(tmpdir);
d = opendir(tmpdir);
if (d != NULL) {
@@ -412,10 +435,10 @@
closedir(d);
}
- clear_cache_files(cache, free_size);
+ clear_cache_files(data_path, cache, free_size);
finish_cache_collection(cache);
- return data_disk_free() >= free_size ? 0 : -1;
+ return data_disk_free(data_path) >= free_size ? 0 : -1;
}
int move_dex(const char *src, const char *dst, const char *instruction_set)
@@ -466,7 +489,7 @@
}
}
-int get_size(const char *pkgname, userid_t userid, const char *apkpath,
+int get_size(const char *uuid, const char *pkgname, int userid, const char *apkpath,
const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
int64_t *_cachesize, int64_t* _asecsize)
@@ -482,30 +505,38 @@
int64_t cachesize = 0;
int64_t asecsize = 0;
- /* count the source apk as code -- but only if it's not
- * on the /system partition and its not on the sdcard.
- */
+ /* count the source apk as code -- but only if it's not
+ * on the /system partition and its not on the sdcard. */
if (validate_system_app_path(apkpath) &&
strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
if (stat(apkpath, &s) == 0) {
codesize += stat_size(&s);
+ if (S_ISDIR(s.st_mode)) {
+ d = opendir(apkpath);
+ if (d != NULL) {
+ dfd = dirfd(d);
+ codesize += calculate_dir_size(dfd);
+ closedir(d);
+ }
+ }
}
}
- /* count the forward locked apk as code if it is given
- */
+
+ /* count the forward locked apk as code if it is given */
if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
if (stat(fwdlock_apkpath, &s) == 0) {
codesize += stat_size(&s);
}
}
- /* count the cached dexfile as code */
+
+ /* count the cached dexfile as code */
if (!create_cache_path(path, apkpath, instruction_set)) {
if (stat(path, &s) == 0) {
codesize += stat_size(&s);
}
}
- /* add in size of any libraries */
+ /* add in size of any libraries */
if (libdirpath != NULL && libdirpath[0] != '!') {
d = opendir(libdirpath);
if (d != NULL) {
@@ -515,69 +546,76 @@
}
}
- /* compute asec size if it is given
- */
+ /* compute asec size if it is given */
if (asecpath != NULL && asecpath[0] != '!') {
if (stat(asecpath, &s) == 0) {
asecsize += stat_size(&s);
}
}
- if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) {
- goto done;
+ std::vector<userid_t> users;
+ if (userid == -1) {
+ users = get_known_users(uuid);
+ } else {
+ users.push_back(userid);
}
- d = opendir(path);
- if (d == NULL) {
- goto done;
- }
- dfd = dirfd(d);
+ for (auto user : users) {
+ std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
+ const char* pkgdir = _pkgdir.c_str();
- /* most stuff in the pkgdir is data, except for the "cache"
- * directory and below, which is cache, and the "lib" directory
- * and below, which is code...
- */
- while ((de = readdir(d))) {
- const char *name = de->d_name;
+ d = opendir(pkgdir);
+ if (d == NULL) {
+ PLOG(WARNING) << "Failed to open " << pkgdir;
+ continue;
+ }
+ dfd = dirfd(d);
- if (de->d_type == DT_DIR) {
- int subfd;
- int64_t statsize = 0;
- int64_t dirsize = 0;
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0) continue;
- if ((name[1] == '.') && (name[2] == 0)) continue;
- }
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- statsize = stat_size(&s);
- }
- subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
- if (subfd >= 0) {
- dirsize = calculate_dir_size(subfd);
- }
- if(!strcmp(name,"lib")) {
- codesize += dirsize + statsize;
- } else if(!strcmp(name,"cache")) {
- cachesize += dirsize + statsize;
+ /* most stuff in the pkgdir is data, except for the "cache"
+ * directory and below, which is cache, and the "lib" directory
+ * and below, which is code...
+ */
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
+
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ int64_t statsize = 0;
+ int64_t dirsize = 0;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ statsize = stat_size(&s);
+ }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ dirsize = calculate_dir_size(subfd);
+ }
+ if(!strcmp(name,"lib")) {
+ codesize += dirsize + statsize;
+ } else if(!strcmp(name,"cache")) {
+ cachesize += dirsize + statsize;
+ } else {
+ datasize += dirsize + statsize;
+ }
+ } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
+ // This is the symbolic link to the application's library
+ // code. We'll count this as code instead of data, since
+ // it is not something that the app creates.
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ codesize += stat_size(&s);
+ }
} else {
- datasize += dirsize + statsize;
- }
- } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
- // This is the symbolic link to the application's library
- // code. We'll count this as code instead of data, since
- // it is not something that the app creates.
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- codesize += stat_size(&s);
- }
- } else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- datasize += stat_size(&s);
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ datasize += stat_size(&s);
+ }
}
}
+ closedir(d);
}
- closedir(d);
-done:
*_codesize = codesize;
*_datasize = datasize;
*_cachesize = cachesize;
@@ -625,30 +663,40 @@
return 0;
}
-static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
- const char* output_file_name)
+static int split_count(const char *str)
{
- /* platform-specific flags affecting optimization and verification */
- char dexopt_flags[PROPERTY_VALUE_MAX];
- property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
- ALOGV("dalvik.vm.dexopt-flags=%s\n", dexopt_flags);
+ char *ctx;
+ int count = 0;
+ char buf[PROPERTY_VALUE_MAX];
- static const char* DEX_OPT_BIN = "/system/bin/dexopt";
- static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
- char zip_num[MAX_INT_LEN];
- char odex_num[MAX_INT_LEN];
+ strncpy(buf, str, sizeof(buf));
+ char *pBuf = buf;
- sprintf(zip_num, "%d", zip_fd);
- sprintf(odex_num, "%d", odex_fd);
+ while(strtok_r(pBuf, " ", &ctx) != NULL) {
+ count++;
+ pBuf = NULL;
+ }
- ALOGV("Running %s in=%s out=%s\n", DEX_OPT_BIN, input_file_name, output_file_name);
- execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
- dexopt_flags, (char*) NULL);
- ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
+ return count;
+}
+
+static int split(char *buf, const char **argv)
+{
+ char *ctx;
+ int count = 0;
+ char *tok;
+ char *pBuf = buf;
+
+ while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
+ argv[count++] = tok;
+ pBuf = NULL;
+ }
+
+ return count;
}
static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
- const char* output_file_name, const char *pkgname, const char *instruction_set)
+ const char* output_file_name, const char *pkgname __unused, const char *instruction_set)
{
static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -670,7 +718,7 @@
sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
- ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
+ ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
/* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
@@ -687,9 +735,18 @@
ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
}
+static bool check_boolean_property(const char* property_name, bool default_value = false) {
+ char tmp_property_value[PROPERTY_VALUE_MAX];
+ bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
+ if (!have_property) {
+ return default_value;
+ }
+ return strcmp(tmp_property_value, "true") == 0;
+}
+
static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
- bool vm_safe_mode)
+ bool vm_safe_mode, bool debuggable)
{
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -726,8 +783,18 @@
bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
dex2oat_isa_features, NULL) > 0;
+ char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
+ sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
+ char dex2oat_isa_variant[PROPERTY_VALUE_MAX];
+ bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key,
+ dex2oat_isa_variant, NULL) > 0;
+
+ const char *dex2oat_norelocation = "-Xnorelocate";
+ bool have_dex2oat_relocation_skip_flag = false;
+
char dex2oat_flags[PROPERTY_VALUE_MAX];
- bool have_dex2oat_flags = property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, NULL) > 0;
+ int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags",
+ dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
// If we booting without the real /data, don't spend time compiling.
@@ -737,6 +804,9 @@
(strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
(strcmp(vold_decrypt, "1") == 0)));
+ bool use_jit = check_boolean_property("debug.usejit");
+ bool generate_debug_info = check_boolean_property("debug.generate-debug-info");
+
static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
static const char* RUNTIME_ARG = "--runtime-arg";
@@ -748,6 +818,7 @@
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];
+ char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX];
char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
@@ -762,6 +833,7 @@
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);
+ sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
if (swap_fd >= 0) {
have_dex2oat_swap_fd = true;
@@ -795,32 +867,50 @@
if (skip_compilation) {
strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
have_dex2oat_compiler_filter_flag = true;
+ have_dex2oat_relocation_skip_flag = true;
} else if (vm_safe_mode) {
strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
have_dex2oat_compiler_filter_flag = true;
+ } else if (use_jit) {
+ strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
+ have_dex2oat_compiler_filter_flag = true;
} else if (have_dex2oat_compiler_filter_flag) {
sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
}
+ // Check whether all apps should be compiled debuggable.
+ if (!debuggable) {
+ debuggable =
+ (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
+ (prop_buf[0] == '1');
+ }
+
ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
- char* argv[7 // program name, mandatory arguments and the final NULL
- + (have_dex2oat_isa_features ? 1 : 0)
- + (have_profile_file ? 1 : 0)
- + (have_top_k_profile_threshold ? 1 : 0)
- + (have_dex2oat_Xms_flag ? 2 : 0)
- + (have_dex2oat_Xmx_flag ? 2 : 0)
- + (have_dex2oat_compiler_filter_flag ? 1 : 0)
- + (have_dex2oat_threads_flag ? 1 : 0)
- + (have_dex2oat_flags ? 1 : 0)
- + (have_dex2oat_swap_fd ? 1 : 0)];
+ const char* argv[7 // program name, mandatory arguments and the final NULL
+ + (have_dex2oat_isa_variant ? 1 : 0)
+ + (have_dex2oat_isa_features ? 1 : 0)
+ + (have_profile_file ? 1 : 0)
+ + (have_top_k_profile_threshold ? 1 : 0)
+ + (have_dex2oat_Xms_flag ? 2 : 0)
+ + (have_dex2oat_Xmx_flag ? 2 : 0)
+ + (have_dex2oat_compiler_filter_flag ? 1 : 0)
+ + (have_dex2oat_threads_flag ? 1 : 0)
+ + (have_dex2oat_swap_fd ? 1 : 0)
+ + (have_dex2oat_relocation_skip_flag ? 2 : 0)
+ + (generate_debug_info ? 1 : 0)
+ + (debuggable ? 1 : 0)
+ + dex2oat_flags_count];
int i = 0;
- argv[i++] = (char*)DEX2OAT_BIN;
+ argv[i++] = DEX2OAT_BIN;
argv[i++] = zip_fd_arg;
argv[i++] = zip_location_arg;
argv[i++] = oat_fd_arg;
argv[i++] = oat_location_arg;
argv[i++] = instruction_set_arg;
+ if (have_dex2oat_isa_variant) {
+ argv[i++] = instruction_set_variant_arg;
+ }
if (have_dex2oat_isa_features) {
argv[i++] = instruction_set_features_arg;
}
@@ -831,30 +921,40 @@
argv[i++] = top_k_profile_threshold_arg;
}
if (have_dex2oat_Xms_flag) {
- argv[i++] = (char*)RUNTIME_ARG;
+ argv[i++] = RUNTIME_ARG;
argv[i++] = dex2oat_Xms_arg;
}
if (have_dex2oat_Xmx_flag) {
- argv[i++] = (char*)RUNTIME_ARG;
+ argv[i++] = RUNTIME_ARG;
argv[i++] = dex2oat_Xmx_arg;
}
if (have_dex2oat_compiler_filter_flag) {
argv[i++] = dex2oat_compiler_filter_arg;
}
- if (have_dex2oat_flags) {
- argv[i++] = dex2oat_flags;
- }
if (have_dex2oat_threads_flag) {
argv[i++] = dex2oat_threads_arg;
}
if (have_dex2oat_swap_fd) {
argv[i++] = dex2oat_swap_fd;
}
+ if (generate_debug_info) {
+ argv[i++] = "--generate-debug-info";
+ }
+ if (debuggable) {
+ argv[i++] = "--debuggable";
+ }
+ if (dex2oat_flags_count) {
+ i += split(dex2oat_flags, argv + i);
+ }
+ if (have_dex2oat_relocation_skip_flag) {
+ argv[i++] = RUNTIME_ARG;
+ argv[i++] = dex2oat_norelocation;
+ }
// Do not add after dex2oat_flags, they should override others for debugging.
argv[i] = NULL;
- execv(DEX2OAT_BIN, (char* const *)argv);
- ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
+ execv(DEX2OAT_BIN, (char * const *)argv);
+ ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
}
static int wait_child(pid_t pid)
@@ -884,32 +984,95 @@
}
/*
- * Whether dexopt should use a swap file when compiling an APK. If kAlwaysProvideSwapFile, do this
- * on all devices (dex2oat will make a more informed decision itself, anyways). Otherwise, only do
- * this on a low-mem device.
+ * Whether dexopt should use a swap file when compiling an APK.
+ *
+ * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
+ * itself, anyways).
+ *
+ * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
+ *
+ * Otherwise, return true if this is a low-mem device.
+ *
+ * Otherwise, return default value.
*/
-static bool kAlwaysProvideSwapFile = true;
+static bool kAlwaysProvideSwapFile = false;
+static bool kDefaultProvideSwapFile = true;
static bool ShouldUseSwapFileForDexopt() {
if (kAlwaysProvideSwapFile) {
return true;
}
- char low_mem_buf[PROPERTY_VALUE_MAX];
- property_get("ro.config.low_ram", low_mem_buf, "");
- return (strcmp(low_mem_buf, "true") == 0);
+ // Check the "override" property. If it exists, return value == "true".
+ char dex2oat_prop_buf[PROPERTY_VALUE_MAX];
+ if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
+ if (strcmp(dex2oat_prop_buf, "true") == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // Shortcut for default value. This is an implementation optimization for the process sketched
+ // above. If the default value is true, we can avoid to check whether this is a low-mem device,
+ // as low-mem is never returning false. The compiler will optimize this away if it can.
+ if (kDefaultProvideSwapFile) {
+ return true;
+ }
+
+ bool is_low_mem = check_boolean_property("ro.config.low_ram");
+ if (is_low_mem) {
+ return true;
+ }
+
+ // Default value must be false here.
+ return kDefaultProvideSwapFile;
+}
+
+/*
+ * Computes the odex file for the given apk_path and instruction_set.
+ * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
+ *
+ * Returns false if it failed to determine the odex file path.
+ */
+static bool calculate_odex_file_path(char path[PKG_PATH_MAX],
+ const char *apk_path,
+ const char *instruction_set)
+{
+ if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
+ + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
+ ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
+ return false;
+ }
+
+ strcpy(path, apk_path);
+ char *end = strrchr(path, '/');
+ if (end == NULL) {
+ ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+ return false;
+ }
+ const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
+
+ strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0
+ strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
+ strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0
+ end = strrchr(path, '.');
+ if (end == NULL) {
+ ALOGE("apk_path '%s' has no extension.\n", apk_path);
+ return false;
+ }
+ strcpy(end + 1, "odex");
+ return true;
}
int dexopt(const char *apk_path, uid_t uid, bool is_public,
- const char *pkgname, const char *instruction_set,
- bool vm_safe_mode, bool is_patchoat)
+ const char *pkgname, const char *instruction_set, int dexopt_needed,
+ bool vm_safe_mode, bool debuggable, const char* oat_dir)
{
struct utimbuf ut;
- struct stat input_stat, dex_stat;
+ struct stat input_stat;
char out_path[PKG_PATH_MAX];
- char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];
char swap_file_name[PKG_PATH_MAX];
- char *end;
const char *input_file;
char in_odex_path[PKG_PATH_MAX];
int res, input_fd=-1, out_fd=-1, swap_fd=-1;
@@ -918,55 +1081,43 @@
// Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
// without a swap file, if necessary.
if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
+ ALOGE("apk_path too long '%s'\n", apk_path);
return -1;
}
- /* The command to run depend on the value of persist.sys.dalvik.vm.lib */
- property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so");
-
- if (is_patchoat && strncmp(persist_sys_dalvik_vm_lib, "libart", 6) != 0) {
- /* We may only patch if we are libart */
- ALOGE("Patching is only supported in libart\n");
- return -1;
- }
-
- /* Before anything else: is there a .odex file? If so, we have
- * precompiled the apk and there is nothing to do here.
- *
- * We skip this if we are doing a patchoat.
- */
- strcpy(out_path, apk_path);
- end = strrchr(out_path, '.');
- if (end != NULL && !is_patchoat) {
- strcpy(end, ".odex");
- if (stat(out_path, &dex_stat) == 0) {
- return 0;
- }
- }
-
- if (create_cache_path(out_path, apk_path, instruction_set)) {
- return -1;
- }
-
- if (is_patchoat) {
- /* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */
- strcpy(in_odex_path, apk_path);
- end = strrchr(in_odex_path, '/');
- if (end == NULL) {
- ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+ if (oat_dir != NULL && oat_dir[0] != '!') {
+ if (validate_apk_path(oat_dir)) {
+ ALOGE("invalid oat_dir '%s'\n", oat_dir);
return -1;
}
- const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/');
- strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0
- strcat(in_odex_path, apk_end);
- end = strrchr(in_odex_path, '.');
- if (end == NULL) {
+ if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
return -1;
}
- strcpy(end + 1, "odex");
- input_file = in_odex_path;
} else {
- input_file = apk_path;
+ if (create_cache_path(out_path, apk_path, instruction_set)) {
+ return -1;
+ }
+ }
+
+ switch (dexopt_needed) {
+ case DEXOPT_DEX2OAT_NEEDED:
+ input_file = apk_path;
+ break;
+
+ case DEXOPT_PATCHOAT_NEEDED:
+ if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
+ return -1;
+ }
+ input_file = in_odex_path;
+ break;
+
+ case DEXOPT_SELF_PATCHOAT_NEEDED:
+ input_file = out_path;
+ break;
+
+ default:
+ ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
+ exit(72);
}
memset(&input_stat, 0, sizeof(input_stat));
@@ -1001,7 +1152,7 @@
}
// Create a swap file if necessary.
- if (!is_patchoat && ShouldUseSwapFileForDexopt()) {
+ if (ShouldUseSwapFileForDexopt()) {
// Make sure there really is enough space.
size_t out_len = strlen(out_path);
if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) {
@@ -1060,17 +1211,21 @@
exit(67);
}
- if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
- run_dexopt(input_fd, out_fd, input_file, out_path);
- } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
- if (is_patchoat) {
- run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
+ if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
+ || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
+ run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
+ } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
+ const char *input_file_name = strrchr(input_file, '/');
+ if (input_file_name == NULL) {
+ input_file_name = input_file;
} else {
- run_dex2oat(input_fd, out_fd, input_file, out_path, swap_fd, pkgname,
- instruction_set, vm_safe_mode);
+ input_file_name++;
}
+ run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
+ instruction_set, vm_safe_mode, debuggable);
} else {
- exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */
+ ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
+ exit(73);
}
exit(68); /* only get here on exec failure */
} else {
@@ -1380,21 +1535,16 @@
return 0;
}
-int linklib(const char* pkgname, const char* asecLibDir, int userId)
+int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId)
{
- char pkgdir[PKG_PATH_MAX];
- char libsymlink[PKG_PATH_MAX];
struct stat s, libStat;
int rc = 0;
- if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
- ALOGE("cannot create package path\n");
- return -1;
- }
- if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
- ALOGE("cannot create package lib symlink origin path\n");
- return -1;
- }
+ std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
+ std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
+
+ const char* pkgdir = _pkgdir.c_str();
+ const char* libsymlink = _libsymlink.c_str();
if (stat(pkgdir, &s) < 0) return -1;
@@ -1563,14 +1713,12 @@
return -1;
}
-int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
+int restorecon_data(const char* uuid, const char* pkgName,
+ const char* seinfo, uid_t uid)
{
struct dirent *entry;
DIR *d;
struct stat s;
- char *userdir;
- char *primarydir;
- char *pkgdir;
int ret = 0;
// SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
@@ -1581,26 +1729,20 @@
return -1;
}
- if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) {
- return -1;
- }
+ // Special case for owner on internal storage
+ if (uuid == nullptr) {
+ std::string path(create_data_user_package_path(nullptr, 0, pkgName));
- // Relabel for primary user.
- if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) {
- ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno));
- ret |= -1;
- }
-
- if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) {
- free(primarydir);
- return -1;
+ if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) {
+ PLOG(ERROR) << "restorecon failed for " << path;
+ ret |= -1;
+ }
}
// Relabel package directory for all secondary users.
- d = opendir(userdir);
+ std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX);
+ d = opendir(userdir.c_str());
if (d == NULL) {
- free(primarydir);
- free(userdir);
return -1;
}
@@ -1621,25 +1763,100 @@
continue;
}
- if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) {
+ std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName));
+ if (stat(pkgdir.c_str(), &s) < 0) {
continue;
}
- if (stat(pkgdir, &s) < 0) {
- free(pkgdir);
- continue;
- }
-
- if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, uid, flags) < 0) {
- ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno));
+ if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) {
+ PLOG(ERROR) << "restorecon failed for " << pkgdir;
ret |= -1;
}
- free(pkgdir);
}
closedir(d);
- free(primarydir);
- free(userdir);
return ret;
}
+int create_oat_dir(const char* oat_dir, const char* instruction_set)
+{
+ char oat_instr_dir[PKG_PATH_MAX];
+
+ if (validate_apk_path(oat_dir)) {
+ ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir);
+ return -1;
+ }
+ if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
+ return -1;
+ }
+ if (selinux_android_restorecon(oat_dir, 0)) {
+ ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno));
+ return -1;
+ }
+ snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
+ if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
+ return -1;
+ }
+ return 0;
+}
+
+int rm_package_dir(const char* apk_path)
+{
+ if (validate_apk_path(apk_path)) {
+ ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path);
+ return -1;
+ }
+ return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
+}
+
+int link_file(const char* relative_path, const char* from_base, const char* to_base) {
+ char from_path[PKG_PATH_MAX];
+ char to_path[PKG_PATH_MAX];
+ snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path);
+ snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path);
+
+ if (validate_apk_path_subdirs(from_path)) {
+ ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path);
+ return -1;
+ }
+
+ if (validate_apk_path_subdirs(to_path)) {
+ ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path);
+ return -1;
+ }
+
+ const int ret = link(from_path, to_path);
+ if (ret < 0) {
+ ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
+ const char *instruction_set) {
+ char *file_name_start;
+ char *file_name_end;
+
+ file_name_start = strrchr(apk_path, '/');
+ if (file_name_start == NULL) {
+ ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
+ return -1;
+ }
+ file_name_end = strrchr(apk_path, '.');
+ if (file_name_end < file_name_start) {
+ ALOGE("apk_path '%s' has no extension\n", apk_path);
+ return -1;
+ }
+
+ // Calculate file_name
+ int file_name_len = file_name_end - file_name_start - 1;
+ char file_name[file_name_len + 1];
+ memcpy(file_name, file_name_start + 1, file_name_len);
+ file_name[file_name_len] = '\0';
+
+ // <apk_parent_dir>/oat/<isa>/<file_name>.odex
+ snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
+ return 0;
+}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.cpp
similarity index 75%
rename from cmds/installd/installd.c
rename to cmds/installd/installd.cpp
index 5b8a1e3..13e3168 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.cpp
@@ -1,90 +1,101 @@
/*
** Copyright 2008, 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
+** 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
+** 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
+** 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 "installd.h"
+
+#include <base/logging.h>
+
#include <sys/capability.h>
#include <sys/prctl.h>
#include <selinux/android.h>
#include <selinux/avc.h>
-#include "installd.h"
-
-
#define BUFFER_MAX 1024 /* input buffer for commands */
-#define TOKEN_MAX 8 /* max number of arguments in buffer */
+#define TOKEN_MAX 16 /* max number of arguments in buffer */
#define REPLY_MAX 256 /* largest reply allowed */
-static int do_ping(char **arg, char reply[REPLY_MAX])
+static char* parse_null(char* arg) {
+ if (strcmp(arg, "!") == 0) {
+ return nullptr;
+ } else {
+ return arg;
+ }
+}
+
+static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused)
{
return 0;
}
-static int do_install(char **arg, char reply[REPLY_MAX])
+static int do_install(char **arg, char reply[REPLY_MAX] __unused)
{
- return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */
+ return install(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); /* uuid, pkgname, uid, gid, seinfo */
}
-static int do_dexopt(char **arg, char reply[REPLY_MAX])
+static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
{
- /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate */
- return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), 0);
+ /* apk_path, uid, is_public, pkgname, instruction_set,
+ * dexopt_needed, vm_safe_mode, debuggable, oat_dir */
+ return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]),
+ atoi(arg[6]), atoi(arg[7]), arg[8]);
}
-static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX])
+static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
{
return mark_boot_complete(arg[0] /* instruction set */);
}
-static int do_move_dex(char **arg, char reply[REPLY_MAX])
+static int do_move_dex(char **arg, char reply[REPLY_MAX] __unused)
{
return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */
}
-static int do_rm_dex(char **arg, char reply[REPLY_MAX])
+static int do_rm_dex(char **arg, char reply[REPLY_MAX] __unused)
{
return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
}
-static int do_remove(char **arg, char reply[REPLY_MAX])
+static int do_remove(char **arg, char reply[REPLY_MAX] __unused)
{
- return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
+ return uninstall(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_rename(char **arg, char reply[REPLY_MAX])
+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])
+static int do_fixuid(char **arg, char reply[REPLY_MAX] __unused)
{
- return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
+ return fix_uid(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */
}
-static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
+static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int:free_size */
{
- return free_cache((int64_t)atoll(arg[0])); /* free_size */
+ return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
}
-static int do_rm_cache(char **arg, char reply[REPLY_MAX])
+static int do_rm_cache(char **arg, char reply[REPLY_MAX] __unused)
{
- return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */
+ return delete_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_rm_code_cache(char **arg, char reply[REPLY_MAX])
+static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] __unused)
{
- return delete_code_cache(arg[0], atoi(arg[1])); /* pkgname, userid */
+ return delete_code_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
static int do_get_size(char **arg, char reply[REPLY_MAX])
@@ -95,9 +106,9 @@
int64_t asecsize = 0;
int res = 0;
- /* pkgdir, userid, apkpath */
- res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5],
- arg[6], &codesize, &datasize, &cachesize, &asecsize);
+ /* uuid, pkgdir, userid, apkpath */
+ res = get_size(parse_null(arg[0]), arg[1], atoi(arg[2]), arg[3], arg[4], arg[5], arg[6],
+ arg[7], &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
@@ -108,51 +119,70 @@
return res;
}
-static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
+static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused)
{
- return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */
+ return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_mk_user_data(char **arg, char reply[REPLY_MAX])
+static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] __unused)
{
- return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]);
- /* pkgname, uid, userid, seinfo */
+ // from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
+ return copy_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
}
-static int do_mk_user_config(char **arg, char reply[REPLY_MAX])
+static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused)
+{
+ return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]);
+ /* uuid, pkgname, uid, userid, seinfo */
+}
+
+static int do_mk_user_config(char **arg, char reply[REPLY_MAX] __unused)
{
return make_user_config(atoi(arg[0])); /* userid */
}
-static int do_rm_user(char **arg, char reply[REPLY_MAX])
+static int do_rm_user(char **arg, char reply[REPLY_MAX] __unused)
{
- return delete_user(atoi(arg[0])); /* userid */
+ return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
}
-static int do_movefiles(char **arg, char reply[REPLY_MAX])
+static int do_movefiles(char **arg __unused, char reply[REPLY_MAX] __unused)
{
return movefiles();
}
-static int do_linklib(char **arg, char reply[REPLY_MAX])
+static int do_linklib(char **arg, char reply[REPLY_MAX] __unused)
{
- return linklib(arg[0], arg[1], atoi(arg[2]));
+ return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
}
-static int do_idmap(char **arg, char reply[REPLY_MAX])
+static int do_idmap(char **arg, char reply[REPLY_MAX] __unused)
{
return idmap(arg[0], arg[1], atoi(arg[2]));
}
static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused)))
{
- return restorecon_data(arg[0], arg[1], atoi(arg[2]));
- /* pkgName, seinfo, uid*/
+ return restorecon_data(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
+ /* uuid, pkgName, seinfo, uid*/
}
-static int do_patchoat(char **arg, char reply[REPLY_MAX]) {
- /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate */
- return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0, 1);
+static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] __unused)
+{
+ /* oat_dir, instruction_set */
+ return create_oat_dir(arg[0], arg[1]);
+}
+
+static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] __unused)
+{
+ /* oat_dir */
+ return rm_package_dir(arg[0]);
+}
+
+static int do_link_file(char **arg, char reply[REPLY_MAX] __unused)
+{
+ /* relative_path, from_base, to_base */
+ return link_file(arg[0], arg[1], arg[2]);
}
struct cmdinfo {
@@ -163,32 +193,35 @@
struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
- { "install", 4, do_install },
- { "dexopt", 6, do_dexopt },
+ { "install", 5, do_install },
+ { "dexopt", 9, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "movedex", 3, do_move_dex },
{ "rmdex", 2, do_rm_dex },
- { "remove", 2, do_remove },
+ { "remove", 3, do_remove },
{ "rename", 2, do_rename },
- { "fixuid", 3, do_fixuid },
- { "freecache", 1, do_free_cache },
- { "rmcache", 2, do_rm_cache },
- { "rmcodecache", 2, do_rm_code_cache },
- { "getsize", 7, do_get_size },
- { "rmuserdata", 2, do_rm_user_data },
+ { "fixuid", 4, do_fixuid },
+ { "freecache", 2, do_free_cache },
+ { "rmcache", 3, do_rm_cache },
+ { "rmcodecache", 3, do_rm_code_cache },
+ { "getsize", 8, do_get_size },
+ { "rmuserdata", 3, do_rm_user_data },
+ { "cpcompleteapp", 6, do_cp_complete_app },
{ "movefiles", 0, do_movefiles },
- { "linklib", 3, do_linklib },
- { "mkuserdata", 4, do_mk_user_data },
+ { "linklib", 4, do_linklib },
+ { "mkuserdata", 5, do_mk_user_data },
{ "mkuserconfig", 1, do_mk_user_config },
- { "rmuser", 1, do_rm_user },
+ { "rmuser", 2, do_rm_user },
{ "idmap", 3, do_idmap },
- { "restorecondata", 3, do_restorecon_data },
- { "patchoat", 5, do_patchoat },
+ { "restorecondata", 4, do_restorecon_data },
+ { "createoatdir", 2, do_create_oat_dir },
+ { "rmpackagedir", 1, do_rm_package_dir },
+ { "linkfile", 3, do_link_file }
};
static int readx(int s, void *_buf, int count)
{
- char *buf = _buf;
+ char *buf = (char *) _buf;
int n = 0, r;
if (count < 0) return -1;
while (n < count) {
@@ -209,7 +242,7 @@
static int writex(int s, const void *_buf, int count)
{
- const char *buf = _buf;
+ const char *buf = (const char *) _buf;
int n = 0, r;
if (count < 0) return -1;
while (n < count) {
@@ -255,7 +288,9 @@
goto done;
}
}
- cmd++;
+ if (*cmd) {
+ cmd++;
+ }
}
for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
@@ -333,10 +368,15 @@
return -1;
}
+ // Get the android external app directory.
+ if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) {
+ return -1;
+ }
+
// Take note of the system and vendor directories.
android_system_dirs.count = 4;
- android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
+ android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
if (android_system_dirs.dirs == NULL) {
ALOGE("Couldn't allocate array for dirs; aborting\n");
return -1;
@@ -354,10 +394,10 @@
android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
- android_system_dirs.dirs[2].path = "/vendor/app/";
+ android_system_dirs.dirs[2].path = strdup("/vendor/app/");
android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
- android_system_dirs.dirs[3].path = "/oem/app/";
+ android_system_dirs.dirs[3].path = strdup("/oem/app/");
android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
return 0;
@@ -501,7 +541,7 @@
version = 2;
}
- if (ensure_media_user_dirs(0) == -1) {
+ if (ensure_media_user_dirs(nullptr, 0) == -1) {
ALOGE("Failed to setup media for user 0");
goto fail;
}
@@ -596,46 +636,6 @@
return res;
}
-static void drop_privileges() {
- if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
- ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
- exit(1);
- }
-
- if (setgid(AID_INSTALL) < 0) {
- ALOGE("setgid() can't drop privileges; exiting.\n");
- exit(1);
- }
-
- if (setuid(AID_INSTALL) < 0) {
- ALOGE("setuid() can't drop privileges; exiting.\n");
- exit(1);
- }
-
- struct __user_cap_header_struct capheader;
- struct __user_cap_data_struct capdata[2];
- memset(&capheader, 0, sizeof(capheader));
- memset(&capdata, 0, sizeof(capdata));
- capheader.version = _LINUX_CAPABILITY_VERSION_3;
- capheader.pid = 0;
-
- capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE);
- capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN);
- capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
- capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
- capdata[CAP_TO_INDEX(CAP_FOWNER)].permitted |= CAP_TO_MASK(CAP_FOWNER);
-
- capdata[0].effective = capdata[0].permitted;
- capdata[1].effective = capdata[1].permitted;
- capdata[0].inheritable = 0;
- capdata[1].inheritable = 0;
-
- if (capset(&capheader, &capdata[0]) < 0) {
- ALOGE("capset failed: %s\n", strerror(errno));
- exit(1);
- }
-}
-
static int log_callback(int type, const char *fmt, ...) {
va_list ap;
int priority;
@@ -657,13 +657,16 @@
return 0;
}
-int main(const int argc, const char *argv[]) {
+int main(const int argc __unused, char *argv[]) {
char buf[BUFFER_MAX];
struct sockaddr addr;
socklen_t alen;
- int lsocket, s, count;
+ int lsocket, s;
int selinux_enabled = (is_selinux_enabled() > 0);
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(argv);
+
ALOGI("installd firing up\n");
union selinux_callback cb;
@@ -685,8 +688,6 @@
exit(1);
}
- drop_privileges();
-
lsocket = android_get_control_socket(SOCKET_PATH);
if (lsocket < 0) {
ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index a3a5c16..7ec5793 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -31,6 +31,8 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <string>
+#include <vector>
#include <cutils/fs.h>
#include <cutils/sockets.h>
@@ -40,7 +42,7 @@
#include <private/android_filesystem_config.h>
-#if INCLUDE_SYS_MOUNT_FOR_STATFS
+#if defined(__APPLE__)
#include <sys/mount.h>
#else
#include <sys/statfs.h>
@@ -83,6 +85,13 @@
#define PKG_NAME_MAX 128 /* largest allowed package name */
#define PKG_PATH_MAX 256 /* max size of any path we use */
+/* dexopt needed flags matching those in dalvik.system.DexFile */
+#define DEXOPT_DEX2OAT_NEEDED 1
+#define DEXOPT_PATCHOAT_NEEDED 2
+#define DEXOPT_SELF_PATCHOAT_NEEDED 3
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
/* data structures */
typedef struct {
@@ -101,6 +110,7 @@
extern dir_rec_t android_data_dir;
extern dir_rec_t android_asec_dir;
extern dir_rec_t android_media_dir;
+extern dir_rec_t android_mnt_expand_dir;
extern dir_rec_array_t android_system_dirs;
typedef struct cache_dir_struct {
@@ -132,20 +142,25 @@
/* util.c */
-int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
- const dir_rec_t* dir,
- const char* pkgname,
- const char* postfix);
-
int create_pkg_path(char path[PKG_PATH_MAX],
const char *pkgname,
const char *postfix,
userid_t userid);
-int create_user_path(char path[PKG_PATH_MAX],
- userid_t userid);
+std::string create_data_path(const char* volume_uuid);
-int create_user_media_path(char path[PKG_PATH_MAX], userid_t userid);
+std::string create_data_app_path(const char* volume_uuid);
+
+std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
+
+std::string create_data_user_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_media_path(const char* volume_uuid, userid_t userid);
+
+std::vector<userid_t> get_known_users(const char* volume_uuid);
int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);
@@ -169,13 +184,13 @@
int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
-int64_t data_disk_free();
+int64_t data_disk_free(const std::string& data_path);
cache_t* start_cache_collection();
void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
-void clear_cache_files(cache_t* cache, int64_t free_size);
+void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size);
void finish_cache_collection(cache_t* cache);
@@ -188,41 +203,56 @@
int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
int validate_apk_path(const char *path);
+int validate_apk_path_subdirs(const char *path);
int append_and_increment(char** dst, const char* src, size_t* dst_size);
-char *build_string2(char *s1, char *s2);
-char *build_string3(char *s1, char *s2, char *s3);
+char *build_string2(const char *s1, const char *s2);
+char *build_string3(const char *s1, const char *s2, const char *s3);
int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(userid_t userid);
+int ensure_media_user_dirs(const char* uuid, userid_t userid);
int ensure_config_user_dirs(userid_t userid);
int create_profile_file(const char *pkgname, gid_t gid);
void remove_profile_file(const char *pkgname);
/* commands.c */
-int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
-int uninstall(const char *pkgname, userid_t userid);
+int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
+int uninstall(const char *uuid, const char *pkgname, userid_t userid);
int renamepkg(const char *oldpkgname, const char *newpkgname);
-int fix_uid(const char *pkgname, uid_t uid, gid_t gid);
-int delete_user_data(const char *pkgname, userid_t userid);
-int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo);
+int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid);
+int delete_user_data(const char *uuid, const char *pkgname, userid_t userid);
+int make_user_data(const char *uuid, const char *pkgname, uid_t uid,
+ userid_t userid, const char* seinfo);
+int copy_complete_app(const char* from_uuid, const char *to_uuid,
+ const char *package_name, const char *data_app_name, appid_t appid,
+ const char* seinfo);
int make_user_config(userid_t userid);
-int delete_user(userid_t userid);
-int delete_cache(const char *pkgname, userid_t userid);
-int delete_code_cache(const char *pkgname, userid_t userid);
+int delete_user(const char *uuid, userid_t userid);
+int delete_cache(const char *uuid, const char *pkgname, userid_t userid);
+int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid);
int move_dex(const char *src, const char *dst, const char *instruction_set);
int rm_dex(const char *path, const char *instruction_set);
int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath,
- const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set,
- int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
-int free_cache(int64_t free_size);
+int get_size(const char *uuid, const char *pkgname, int userid,
+ const char *apkpath, const char *libdirpath,
+ const char *fwdlock_apkpath, const char *asecpath,
+ const char *instruction_set, int64_t *codesize, int64_t *datasize,
+ int64_t *cachesize, int64_t *asecsize);
+int free_cache(const char *uuid, int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
- const char *instruction_set, bool vm_safe_mode, bool should_relocate);
+ const char *instruction_set, int dexopt_needed, bool vm_safe_mode,
+ bool debuggable, const char* oat_dir);
int mark_boot_complete(const char *instruction_set);
int movefiles();
-int linklib(const char* target, const char* source, int userId);
+int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
int idmap(const char *target_path, const char *overlay_path, uid_t uid);
-int restorecon_data();
+int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid);
+int create_oat_dir(const char* oat_dir, const char *instruction_set);
+int rm_package_dir(const char* apk_path);
+int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
+ const char *instruction_set);
+int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
+ const char *instruction_set);
+int link_file(const char *relative_path, const char *from_base, const char *to_base);
diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk
index 4faf3c0..38a9f69 100644
--- a/cmds/installd/tests/Android.mk
+++ b/cmds/installd/tests/Android.mk
@@ -1,21 +1,20 @@
# Build the unit tests for installd
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
# Build the unit tests.
test_src_files := \
installd_utils_test.cpp
shared_libraries := \
+ libbase \
libutils \
libcutils \
- libstlport
static_libraries := \
libinstalld \
libdiskusage \
- libgtest \
- libgtest_main
c_includes := \
frameworks/native/cmds/installd
@@ -27,5 +26,6 @@
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_C_INCLUDES := $(c_includes)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
+ $(eval LOCAL_CLANG := true) \
$(eval include $(BUILD_NATIVE_TEST)) \
)
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 94e4792..5e397f9 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -17,19 +17,18 @@
#include <stdlib.h>
#include <string.h>
-#define LOG_TAG "utils_test"
-#include <utils/Log.h>
-
#include <gtest/gtest.h>
-extern "C" {
#include "installd.h"
-}
+
+#undef LOG_TAG
+#define LOG_TAG "utils_test"
#define TEST_DATA_DIR "/data/"
#define TEST_APP_DIR "/data/app/"
#define TEST_APP_PRIVATE_DIR "/data/app-private/"
#define TEST_ASEC_DIR "/mnt/asec/"
+#define TEST_EXPAND_DIR "/mnt/expand/"
#define TEST_SYSTEM_DIR1 "/system/app/"
#define TEST_SYSTEM_DIR2 "/vendor/app/"
@@ -49,25 +48,28 @@
class UtilsTest : public testing::Test {
protected:
virtual void SetUp() {
- android_app_dir.path = TEST_APP_DIR;
+ android_app_dir.path = (char*) TEST_APP_DIR;
android_app_dir.len = strlen(TEST_APP_DIR);
- android_app_private_dir.path = TEST_APP_PRIVATE_DIR;
+ android_app_private_dir.path = (char*) TEST_APP_PRIVATE_DIR;
android_app_private_dir.len = strlen(TEST_APP_PRIVATE_DIR);
- android_data_dir.path = TEST_DATA_DIR;
+ android_data_dir.path = (char*) TEST_DATA_DIR;
android_data_dir.len = strlen(TEST_DATA_DIR);
- android_asec_dir.path = TEST_ASEC_DIR;
+ android_asec_dir.path = (char*) TEST_ASEC_DIR;
android_asec_dir.len = strlen(TEST_ASEC_DIR);
+ android_mnt_expand_dir.path = (char*) TEST_EXPAND_DIR;
+ android_mnt_expand_dir.len = strlen(TEST_EXPAND_DIR);
+
android_system_dirs.count = 2;
android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
- android_system_dirs.dirs[0].path = TEST_SYSTEM_DIR1;
+ android_system_dirs.dirs[0].path = (char*) TEST_SYSTEM_DIR1;
android_system_dirs.dirs[0].len = strlen(TEST_SYSTEM_DIR1);
- android_system_dirs.dirs[1].path = TEST_SYSTEM_DIR2;
+ android_system_dirs.dirs[1].path = (char*) TEST_SYSTEM_DIR2;
android_system_dirs.dirs[1].len = strlen(TEST_SYSTEM_DIR2);
}
@@ -319,6 +321,7 @@
const char *prefix = TEST_DATA_DIR PRIMARY_USER_PREFIX;
size_t offset = strlen(prefix);
+
EXPECT_STREQ(pkgname, path + offset)
<< "Package path should be a really long string of a's";
}
@@ -369,40 +372,6 @@
<< "Package path should be in /data/user/";
}
-TEST_F(UtilsTest, CreatePkgPathInDir_ProtectedDir) {
- char path[PKG_PATH_MAX];
-
- dir_rec_t dir;
- dir.path = "/data/app-private/";
- dir.len = strlen(dir.path);
-
- EXPECT_EQ(0, create_pkg_path_in_dir(path, &dir, "com.example.package", ".apk"))
- << "Should successfully create package path.";
-
- EXPECT_STREQ("/data/app-private/com.example.package.apk", path)
- << "Package path should be in /data/app-private/";
-}
-
-TEST_F(UtilsTest, CreatePersonaPath_Primary) {
- char path[PKG_PATH_MAX];
-
- EXPECT_EQ(0, create_user_path(path, 0))
- << "Should successfully build primary user path.";
-
- EXPECT_STREQ("/data/data/", path)
- << "Primary user should have correct path";
-}
-
-TEST_F(UtilsTest, CreatePersonaPath_Secondary) {
- char path[PKG_PATH_MAX];
-
- EXPECT_EQ(0, create_user_path(path, 1))
- << "Should successfully build primary user path.";
-
- EXPECT_STREQ("/data/user/1/", path)
- << "Primary user should have correct path";
-}
-
TEST_F(UtilsTest, CreateMovePath_Primary) {
char path[PKG_PATH_MAX];
@@ -432,7 +401,7 @@
dir_rec_t dst;
dir_rec_t src;
- src.path = "/data/";
+ src.path = (char*) "/data/";
src.len = strlen(src.path);
EXPECT_EQ(0, copy_and_append(&dst, &src, "app/"))
@@ -480,4 +449,54 @@
<< "String should fail because it's too large to fit";
}
+TEST_F(UtilsTest, CreateDataPath) {
+ EXPECT_EQ("/data", create_data_path(nullptr));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b",
+ create_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b"));
+}
+
+TEST_F(UtilsTest, CreateDataAppPath) {
+ EXPECT_EQ("/data/app", create_data_app_path(nullptr));
+
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app",
+ create_data_app_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b"));
+}
+
+TEST_F(UtilsTest, CreateDataUserPath) {
+ EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
+ EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10));
+
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0",
+ create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10",
+ create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
+}
+
+TEST_F(UtilsTest, CreateDataMediaPath) {
+ EXPECT_EQ("/data/media/0", create_data_media_path(nullptr, 0));
+ EXPECT_EQ("/data/media/10", create_data_media_path(nullptr, 10));
+
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/media/0",
+ create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/media/10",
+ create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
+}
+
+TEST_F(UtilsTest, CreateDataAppPackagePath) {
+ EXPECT_EQ("/data/app/com.example", create_data_app_package_path(nullptr, "com.example"));
+
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app/com.example",
+ create_data_app_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example"));
+}
+
+TEST_F(UtilsTest, CreateDataUserPackagePath) {
+ EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example"));
+ EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example"));
+
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example",
+ create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example",
+ create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
+}
+
}
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.cpp
similarity index 84%
rename from cmds/installd/utils.c
rename to cmds/installd/utils.cpp
index e381aef..7db3fb9 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.cpp
@@ -16,137 +16,141 @@
#include "installd.h"
+#include <base/stringprintf.h>
+#include <base/logging.h>
+
#define CACHE_NOISY(x) //x
-int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
- const dir_rec_t* dir,
- const char* pkgname,
- const char* postfix)
-{
- const size_t postfix_len = strlen(postfix);
+using android::base::StringPrintf;
- const size_t pkgname_len = strlen(pkgname);
- if (pkgname_len > PKG_NAME_MAX) {
- return -1;
- }
-
- if (is_valid_package_name(pkgname) < 0) {
- return -1;
- }
-
- if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) {
- return -1;
- }
-
- char *dst = path;
- size_t dst_size = PKG_PATH_MAX;
-
- if (append_and_increment(&dst, dir->path, &dst_size) < 0
- || append_and_increment(&dst, pkgname, &dst_size) < 0
- || append_and_increment(&dst, postfix, &dst_size) < 0) {
- ALOGE("Error building APK path");
- return -1;
- }
-
- return 0;
+/**
+ * Check that given string is valid filename, and that it attempts no
+ * parent or child directory traversal.
+ */
+static bool is_valid_filename(const std::string& name) {
+ if (name.empty() || (name == ".") || (name == "..")
+ || (name.find('/') != std::string::npos)) {
+ return false;
+ } else {
+ return true;
+ }
}
/**
- * Create the package path name for a given package name with a postfix for
- * a certain userid. Returns 0 on success, and -1 on failure.
+ * Create the path name where package app contents should be stored for
+ * the given volume UUID and package name. An empty UUID is assumed to
+ * be internal storage.
*/
-int create_pkg_path(char path[PKG_PATH_MAX],
- const char *pkgname,
- const char *postfix,
- userid_t userid)
-{
- size_t userid_len;
- char* userid_prefix;
- if (userid == 0) {
- userid_prefix = PRIMARY_USER_PREFIX;
- userid_len = 0;
- } else {
- userid_prefix = SECONDARY_USER_PREFIX;
- userid_len = snprintf(NULL, 0, "%d", userid);
- }
+std::string create_data_app_package_path(const char* volume_uuid,
+ const char* package_name) {
+ CHECK(is_valid_filename(package_name));
+ CHECK(is_valid_package_name(package_name) == 0);
- const size_t prefix_len = android_data_dir.len + strlen(userid_prefix)
- + userid_len + 1 /*slash*/;
- char prefix[prefix_len + 1];
+ return StringPrintf("%s/%s",
+ create_data_app_path(volume_uuid).c_str(), package_name);
+}
- char *dst = prefix;
- size_t dst_size = sizeof(prefix);
+/**
+ * Create the path name where package data should be stored for the given
+ * volume UUID, package name, and user ID. An empty UUID is assumed to be
+ * internal storage.
+ */
+std::string create_data_user_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);
- if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
- || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
- ALOGE("Error building prefix for APK path");
+ return StringPrintf("%s/%s",
+ create_data_user_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) {
+ path[0] = '\0';
return -1;
}
- if (userid != 0) {
- int ret = snprintf(dst, dst_size, "%d/", userid);
- if (ret < 0 || (size_t) ret != userid_len + 1) {
- ALOGW("Error appending UID to APK path");
- return -1;
- }
+ std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
+ const char* tmp = _tmp.c_str();
+ if (strlen(tmp) >= PKG_PATH_MAX) {
+ path[0] = '\0';
+ return -1;
+ } else {
+ strcpy(path, tmp);
+ return 0;
}
+}
- dir_rec_t dir;
- dir.path = prefix;
- dir.len = prefix_len;
+std::string create_data_path(const char* volume_uuid) {
+ if (volume_uuid == nullptr) {
+ return "/data";
+ } else {
+ CHECK(is_valid_filename(volume_uuid));
+ return StringPrintf("/mnt/expand/%s", volume_uuid);
+ }
+}
- return create_pkg_path_in_dir(path, &dir, pkgname, postfix);
+/**
+ * Create the path name for app data.
+ */
+std::string create_data_app_path(const char* volume_uuid) {
+ return StringPrintf("%s/app", create_data_path(volume_uuid).c_str());
}
/**
* Create the path name for user data for a certain userid.
- * Returns 0 on success, and -1 on failure.
*/
-int create_user_path(char path[PKG_PATH_MAX],
- userid_t userid)
-{
- size_t userid_len;
- char* userid_prefix;
- if (userid == 0) {
- userid_prefix = PRIMARY_USER_PREFIX;
- userid_len = 0;
+std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
+ std::string data(create_data_path(volume_uuid));
+ if (volume_uuid == nullptr) {
+ if (userid == 0) {
+ return StringPrintf("%s/data", data.c_str());
+ } else {
+ return StringPrintf("%s/user/%u", data.c_str(), userid);
+ }
} else {
- userid_prefix = SECONDARY_USER_PREFIX;
- userid_len = snprintf(NULL, 0, "%d/", userid);
+ return StringPrintf("%s/user/%u", data.c_str(), userid);
}
-
- char *dst = path;
- size_t dst_size = PKG_PATH_MAX;
-
- if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
- || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
- ALOGE("Error building prefix for user path");
- return -1;
- }
-
- if (userid != 0) {
- if (dst_size < userid_len + 1) {
- ALOGE("Error building user path");
- return -1;
- }
- int ret = snprintf(dst, dst_size, "%d/", userid);
- if (ret < 0 || (size_t) ret != userid_len) {
- ALOGE("Error appending userid to path");
- return -1;
- }
- }
- return 0;
}
/**
* Create the path name for media for a certain userid.
- * Returns 0 on success, and -1 on failure.
*/
-int create_user_media_path(char path[PATH_MAX], userid_t userid) {
- if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
- return -1;
+std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
+ return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
+}
+
+std::vector<userid_t> get_known_users(const char* volume_uuid) {
+ std::vector<userid_t> users;
+
+ // We always have an owner
+ users.push_back(0);
+
+ std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX);
+ DIR* dir = opendir(path.c_str());
+ if (dir == NULL) {
+ // Unable to discover other users, but at least return owner
+ PLOG(ERROR) << "Failed to opendir " << path;
+ return users;
}
- return 0;
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_type != DT_DIR) {
+ continue;
+ }
+
+ char* end;
+ userid_t user = strtol(ent->d_name, &end, 10);
+ if (*end == '\0' && user != 0) {
+ LOG(DEBUG) << "Found valid user " << user;
+ users.push_back(user);
+ }
+ }
+ closedir(dir);
+
+ return users;
}
/**
@@ -163,7 +167,7 @@
int create_move_path(char path[PKG_PATH_MAX],
const char* pkgname,
const char* leaf,
- userid_t userid)
+ userid_t userid __unused)
{
if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
>= PKG_PATH_MAX) {
@@ -182,6 +186,10 @@
const char *x = pkgname;
int alpha = -1;
+ if (strlen(pkgname) > PKG_NAME_MAX) {
+ return -1;
+ }
+
while (*x) {
if (isalnum(*x) || (*x == '_')) {
/* alphanumeric or underscore are fine */
@@ -239,7 +247,7 @@
}
if (de->d_type == DT_DIR) {
- int r, subfd;
+ int subfd;
DIR *subdir;
/* always skip "." and ".." */
@@ -472,13 +480,13 @@
return -1;
}
-int64_t data_disk_free()
+int64_t data_disk_free(const std::string& data_path)
{
struct statfs sfs;
- if (statfs(android_data_dir.path, &sfs) == 0) {
+ if (statfs(data_path.c_str(), &sfs) == 0) {
return sfs.f_bavail * sfs.f_bsize;
} else {
- ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
+ PLOG(ERROR) << "Couldn't statfs " << data_path;
return -1;
}
}
@@ -516,7 +524,7 @@
int8_t* res = cache->curMemBlockAvail;
int8_t* nextPos = res + len;
if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) {
- int8_t* newBlock = malloc(CACHE_BLOCK_SIZE);
+ int8_t* newBlock = (int8_t*) malloc(CACHE_BLOCK_SIZE);
if (newBlock == NULL) {
return NULL;
}
@@ -836,7 +844,7 @@
return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0);
}
-void clear_cache_files(cache_t* cache, int64_t free_size)
+void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size)
{
size_t i;
int skip = 0;
@@ -861,7 +869,7 @@
for (i=0; i<cache->numFiles; i++) {
skip++;
if (skip > 10) {
- if (data_disk_free() > free_size) {
+ if (data_disk_free(data_path) > free_size) {
return;
}
skip = 0;
@@ -881,7 +889,7 @@
void finish_cache_collection(cache_t* cache)
{
- size_t i;
+ CACHE_NOISY(size_t i;)
CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles));
CACHE_NOISY(
@@ -910,14 +918,14 @@
* The path is allowed to have at most one subdirectory and no indirections
* to top level directories (i.e. have "..").
*/
-static int validate_path(const dir_rec_t* dir, const char* path) {
+static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) {
size_t dir_len = dir->len;
const char* subdir = strchr(path + dir_len, '/');
// Only allow the path to have at most one subdirectory.
if (subdir != NULL) {
++subdir;
- if (strchr(subdir, '/') != NULL) {
+ if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) {
ALOGE("invalid apk path '%s' (subdir?)\n", path);
return -1;
}
@@ -942,7 +950,7 @@
for (i = 0; i < android_system_dirs.count; i++) {
const size_t dir_len = android_system_dirs.dirs[i].len;
if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) {
- return validate_path(android_system_dirs.dirs + i, path);
+ return validate_path(android_system_dirs.dirs + i, path, 1);
}
}
@@ -1000,7 +1008,7 @@
// Add space for slash and terminating null.
size_t dst_size = path_len + 2;
- rec->path = malloc(dst_size);
+ rec->path = (char*) malloc(dst_size);
if (rec->path == NULL) {
return -1;
}
@@ -1035,25 +1043,37 @@
}
/**
- * Check whether path points to a valid path for an APK file. Only one level of
- * subdirectory names is allowed. Returns -1 when an invalid path is encountered
- * and 0 when a valid path is encountered.
+ * Check whether path points to a valid path for an APK file. The path must
+ * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within
+ * that path. Returns -1 when an invalid path is encountered and 0 when a valid path
+ * is encountered.
*/
-int validate_apk_path(const char *path)
-{
+static int validate_apk_path_internal(const char *path, int maxSubdirs) {
const dir_rec_t* dir = NULL;
-
if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
dir = &android_app_dir;
} else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
dir = &android_app_private_dir;
} else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
dir = &android_asec_dir;
+ } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) {
+ dir = &android_mnt_expand_dir;
+ if (maxSubdirs < 2) {
+ maxSubdirs = 2;
+ }
} else {
return -1;
}
- return validate_path(dir, path);
+ return validate_path(dir, path, maxSubdirs);
+}
+
+int validate_apk_path(const char* path) {
+ return validate_apk_path_internal(path, 1 /* maxSubdirs */);
+}
+
+int validate_apk_path_subdirs(const char* path) {
+ return validate_apk_path_internal(path, 3 /* maxSubdirs */);
}
int append_and_increment(char** dst, const char* src, size_t* dst_size) {
@@ -1066,13 +1086,13 @@
return 0;
}
-char *build_string2(char *s1, char *s2) {
+char *build_string2(const char *s1, const char *s2) {
if (s1 == NULL || s2 == NULL) return NULL;
int len_s1 = strlen(s1);
int len_s2 = strlen(s2);
int len = len_s1 + len_s2 + 1;
- char *result = malloc(len);
+ char *result = (char *) malloc(len);
if (result == NULL) return NULL;
strcpy(result, s1);
@@ -1081,14 +1101,14 @@
return result;
}
-char *build_string3(char *s1, char *s2, char *s3) {
+char *build_string3(const char *s1, const char *s2, const char *s3) {
if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL;
int len_s1 = strlen(s1);
int len_s2 = strlen(s2);
int len_s3 = strlen(s3);
int len = len_s1 + len_s2 + len_s3 + 1;
- char *result = malloc(len);
+ char *result = (char *) malloc(len);
if (result == NULL) return NULL;
strcpy(result, s1);
@@ -1099,13 +1119,9 @@
}
/* Ensure that /data/media directories are prepared for given user. */
-int ensure_media_user_dirs(userid_t userid) {
- char media_user_path[PATH_MAX];
- char path[PATH_MAX];
-
- // Ensure /data/media/<userid> exists
- create_user_media_path(media_user_path, userid);
- if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+int ensure_media_user_dirs(const char* uuid, userid_t userid) {
+ std::string media_user_path(create_data_media_path(uuid, userid));
+ if (fs_prepare_dir(media_user_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
return -1;
}
@@ -1114,7 +1130,6 @@
int ensure_config_user_dirs(userid_t userid) {
char config_user_path[PATH_MAX];
- char path[PATH_MAX];
// writable by system, readable by any app within the same user
const int uid = multiuser_get_uid(userid, AID_SYSTEM);
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index 97fc47c..428b87c 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -146,6 +146,15 @@
break;
}
data.writeInt32(atoi(argv[optind++]));
+ } else if (strcmp(argv[optind], "i64") == 0) {
+ optind++;
+ if (optind >= argc) {
+ aerr << "service: no integer supplied for 'i64'" << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ data.writeInt64(atoll(argv[optind++]));
} else if (strcmp(argv[optind], "s16") == 0) {
optind++;
if (optind >= argc) {
@@ -155,6 +164,24 @@
break;
}
data.writeString16(String16(argv[optind++]));
+ } else if (strcmp(argv[optind], "f") == 0) {
+ optind++;
+ if (optind >= argc) {
+ aerr << "service: no number supplied for 'f'" << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ data.writeFloat(atof(argv[optind++]));
+ } else if (strcmp(argv[optind], "d") == 0) {
+ optind++;
+ if (optind >= argc) {
+ aerr << "service: no number supplied for 'd'" << endl;
+ wantsUsage = true;
+ result = 10;
+ break;
+ }
+ data.writeDouble(atof(argv[optind++]));
} else if (strcmp(argv[optind], "null") == 0) {
optind++;
data.writeStrongBinder(NULL);
@@ -272,9 +299,12 @@
aout << "Usage: service [-h|-?]\n"
" service list\n"
" service check SERVICE\n"
- " service call SERVICE CODE [i32 INT | s16 STR] ...\n"
+ " service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...\n"
"Options:\n"
- " i32: Write the integer INT into the send parcel.\n"
+ " i32: Write the 32-bit integer N into the send parcel.\n"
+ " i64: Write the 64-bit integer N into the send parcel.\n"
+ " f: Write the 32-bit single-precision number N into the send parcel.\n"
+ " d: Write the 64-bit double-precision number N into the send parcel.\n"
" s16: Write the UTF-16 string STR into the send parcel.\n";
// " intent: Write and Intent int the send parcel. ARGS can be\n"
// " action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
index e02b45d..fd91633 100644
--- a/cmds/servicemanager/bctest.c
+++ b/cmds/servicemanager/bctest.c
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include "binder.h"
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index db7632d..6eecee1 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -4,6 +4,7 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
@@ -112,7 +113,9 @@
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
- fprintf(stderr, "binder: driver version differs from user space\n");
+ fprintf(stderr,
+ "binder: kernel driver version (%d) differs from user space version (%d)\n",
+ vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
goto fail_open;
}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index f37427a..7fa9a39 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -1,10 +1,12 @@
/* Copyright 2008 The Android Open Source Project
*/
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <private/android_filesystem_config.h>
@@ -21,8 +23,6 @@
#include <cutils/log.h>
#endif
-uint32_t svcmgr_handle;
-
const char *str8(const uint16_t *x, size_t x_len)
{
static char buf[128];
@@ -169,28 +169,26 @@
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
- struct svcinfo *si;
+ struct svcinfo *si = find_svc(s, len);
+
+ if (!si || !si->handle) {
+ return 0;
+ }
+
+ if (!si->allow_isolated) {
+ // If this service doesn't allow access from isolated processes,
+ // then check the uid to see if it is isolated.
+ uid_t appid = uid % AID_USER;
+ if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
+ return 0;
+ }
+ }
if (!svc_can_find(s, len, spid)) {
- ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n",
- str8(s, len), uid);
return 0;
}
- si = find_svc(s, len);
- //ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0);
- if (si && si->handle) {
- if (!si->allow_isolated) {
- // If this service doesn't allow access from isolated processes,
- // then check the uid to see if it is isolated.
- uid_t appid = uid % AID_USER;
- if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
- return 0;
- }
- }
- return si->handle;
- } else {
- return 0;
- }
+
+ return si->handle;
}
int do_add_service(struct binder_state *bs,
@@ -255,10 +253,10 @@
uint32_t strict_policy;
int allow_isolated;
- //ALOGI("target=%x code=%d pid=%d uid=%d\n",
- // txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid);
+ //ALOGI("target=%p code=%d pid=%d uid=%d\n",
+ // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
- if (txn->target.handle != svcmgr_handle)
+ if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
@@ -363,6 +361,7 @@
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
+ selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
@@ -382,7 +381,6 @@
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
- svcmgr_handle = BINDER_SERVICE_MANAGER;
binder_loop(bs, svcmgr_handler);
return 0;
diff --git a/data/etc/android.hardware.sensor.hifi_sensors.xml b/data/etc/android.hardware.sensor.hifi_sensors.xml
new file mode 100644
index 0000000..bb3901c
--- /dev/null
+++ b/data/etc/android.hardware.sensor.hifi_sensors.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 supporting hifi sensors. -->
+<permissions>
+ <feature name="android.hardware.sensor.hifi_sensors" />
+</permissions>
diff --git a/data/etc/android.software.midi.xml b/data/etc/android.software.midi.xml
new file mode 100644
index 0000000..a03cd55
--- /dev/null
+++ b/data/etc/android.software.midi.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<permissions>
+ <feature name="android.software.midi" />
+</permissions>
diff --git a/docs/Doxyfile b/docs/Doxyfile
new file mode 100644
index 0000000..46d6d84
--- /dev/null
+++ b/docs/Doxyfile
@@ -0,0 +1,1902 @@
+# Doxyfile 1.8.3.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = "NDK API"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = ""
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO = logo.png
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if section-label ... \endif
+# and \cond section-label ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 26
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path. Do not use
+# file names with spaces, bibtex cannot handle them.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../include/android
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.for \
+ *.vhd \
+ *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page (index.html).
+# This can be useful if you have a project on for instance GitHub and want reuse
+# the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = $(HTML_OUTPUT)
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER = $(HTML_HEADER)
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = $(HTML_FOOTER)
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 0
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
+# SVG. The default value is HTML-CSS, which is slower, but has the best
+# compatibility.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax. However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript.
+# There are two flavours of web server based search depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools.
+# See the manual for details.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain
+# the search results. Doxygen ships with an example indexer (doxyindexer) and
+# search engine (doxysearch.cgi) which are based on the open source search engine
+# library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will returned the search results when EXTERNAL_SEARCH is enabled.
+# Doxygen ships with an example search engine (doxysearch) which is based on
+# the open source search engine library Xapian. See the manual for configuration
+# details.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
+# of to a relative location where the documentation can be found.
+# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..5104d81
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,13 @@
+HEADERS := $(wildcard ../include/android/*.h)
+
+all: html jd
+
+html: $(HEADERS) Doxyfile
+ mkdir -p html
+ doxygen
+
+jd: $(HEADERS) Doxyfile header.jd
+ mkdir -p jd
+ HTML_HEADER=header.jd HTML_FOOTER=footer.jd HTML_OUTPUT=jd doxygen
+ for file in jd/*.html; do mv "$${file}" "$${file/.html/.jd}"; done
+ rm -f jd/index.jd
diff --git a/docs/footer.jd b/docs/footer.jd
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/docs/footer.jd
diff --git a/docs/header.jd b/docs/header.jd
new file mode 100644
index 0000000..e50f41b
--- /dev/null
+++ b/docs/header.jd
@@ -0,0 +1,3 @@
+page.title=$title
+page.customHeadTag=<link rel="stylesheet" type="text/css" href="doxygen-dac.css">
+@jd:body
diff --git a/include/android/asset_manager.h b/include/android/asset_manager.h
index f5df46b..d654839 100644
--- a/include/android/asset_manager.h
+++ b/include/android/asset_manager.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Asset
+ * @{
+ */
+
+/**
+ * @file asset_manager.h
+ */
#ifndef ANDROID_ASSET_MANAGER_H
#define ANDROID_ASSET_MANAGER_H
@@ -23,19 +31,49 @@
#endif
struct AAssetManager;
+/**
+ * {@link AAssetManager} provides access to an application's raw assets by
+ * creating {@link AAsset} objects.
+ *
+ * AAssetManager is a wrapper to the low-level native implementation
+ * of the java {@link AAssetManager}, a pointer can be obtained using
+ * AAssetManager_fromJava().
+ *
+ * The asset hierarchy may be examined like a filesystem, using
+ * {@link AAssetDir} objects to peruse a single directory.
+ *
+ * A native {@link AAssetManager} pointer may be shared across multiple threads.
+ */
typedef struct AAssetManager AAssetManager;
struct AAssetDir;
+/**
+ * {@link AAssetDir} provides access to a chunk of the asset hierarchy as if
+ * it were a single directory. The contents are populated by the
+ * {@link AAssetManager}.
+ *
+ * The list of files will be sorted in ascending order by ASCII value.
+ */
typedef struct AAssetDir AAssetDir;
struct AAsset;
+/**
+ * {@link AAsset} provides access to a read-only asset.
+ *
+ * {@link AAsset} objects are NOT thread-safe, and should not be shared across
+ * threads.
+ */
typedef struct AAsset AAsset;
-/* Available modes for opening assets */
+/** Available access modes for opening assets with {@link AAssetManager_open} */
enum {
+ /** No specific information about how data will be accessed. **/
AASSET_MODE_UNKNOWN = 0,
+ /** Read chunks, and seek forward and backward. */
AASSET_MODE_RANDOM = 1,
+ /** Read sequentially, with an occasional forward seek. */
AASSET_MODE_STREAMING = 2,
+ /** Caller plans to ask for a read-only buffer with all data. */
AASSET_MODE_BUFFER = 3
};
@@ -173,3 +211,5 @@
#endif
#endif // ANDROID_ASSET_MANAGER_H
+
+/** @} */
diff --git a/include/android/asset_manager_jni.h b/include/android/asset_manager_jni.h
index aec2d3c..dcee17e 100644
--- a/include/android/asset_manager_jni.h
+++ b/include/android/asset_manager_jni.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Asset
+ * @{
+ */
+
+/**
+ * @file asset_manager_jni.h
+ */
#ifndef ANDROID_ASSET_MANAGER_JNI_H
#define ANDROID_ASSET_MANAGER_JNI_H
@@ -38,3 +46,5 @@
#endif
#endif // ANDROID_ASSET_MANAGER_JNI_H
+
+/** @} */
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 6e18763..261e64f 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Bitmap
+ * @{
+ */
+
+/**
+ * @file bitmap.h
+ */
+
#ifndef ANDROID_BITMAP_H
#define ANDROID_BITMAP_H
@@ -24,33 +33,52 @@
extern "C" {
#endif
-#define ANDROID_BITMAP_RESULT_SUCCESS 0
-#define ANDROID_BITMAP_RESULT_BAD_PARAMETER -1
-#define ANDROID_BITMAP_RESULT_JNI_EXCEPTION -2
-#define ANDROID_BITMAP_RESULT_ALLOCATION_FAILED -3
+/** AndroidBitmap functions result code. */
+enum {
+ /** Operation was successful. */
+ ANDROID_BITMAP_RESULT_SUCCESS = 0,
+ /** Bad parameter. */
+ ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1,
+ /** JNI exception occured. */
+ ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2,
+ /** Allocation failed. */
+ ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3,
+};
-/* Backward compatibility: this macro used to be misspelled. */
+/** Backward compatibility: this macro used to be misspelled. */
#define ANDROID_BITMAP_RESUT_SUCCESS ANDROID_BITMAP_RESULT_SUCCESS
+/** Bitmap pixel format. */
enum AndroidBitmapFormat {
+ /** No format. */
ANDROID_BITMAP_FORMAT_NONE = 0,
+ /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,
+ /** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
ANDROID_BITMAP_FORMAT_RGB_565 = 4,
+ /** Red: 4 bits, Green: 4 bits, Blue: 4 bits, Alpha: 4 bits. **/
ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,
+ /** Deprecated. */
ANDROID_BITMAP_FORMAT_A_8 = 8,
};
+/** Bitmap info, see AndroidBitmap_getInfo(). */
typedef struct {
+ /** The bitmap width in pixels. */
uint32_t width;
+ /** The bitmap height in pixels. */
uint32_t height;
+ /** The number of byte per row. */
uint32_t stride;
+ /** The bitmap pixel format. See {@link AndroidBitmapFormat} */
int32_t format;
+ /** Unused. */
uint32_t flags; // 0 for now
} AndroidBitmapInfo;
/**
- * Given a java bitmap object, fill out the AndroidBitmap struct for it.
- * If the call fails, the info parameter will be ignored
+ * Given a java bitmap object, fill out the AndroidBitmapInfo struct for it.
+ * If the call fails, the info parameter will be ignored.
*/
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info);
@@ -71,7 +99,7 @@
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
/**
- * Call this to balanace a successful call to AndroidBitmap_lockPixels
+ * Call this to balance a successful call to AndroidBitmap_lockPixels.
*/
int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
@@ -80,3 +108,5 @@
#endif
#endif
+
+/** @} */
diff --git a/include/android/configuration.h b/include/android/configuration.h
index be00066..81f71a9 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Configuration
+ * @{
+ */
+
+/**
+ * @file configuration.h
+ */
+
#ifndef ANDROID_CONFIGURATION_H
#define ANDROID_CONFIGURATION_H
@@ -24,98 +33,400 @@
#endif
struct AConfiguration;
+/**
+ * {@link AConfiguration} is an opaque type used to get and set
+ * various subsystem configurations.
+ *
+ * A {@link AConfiguration} pointer can be obtained using:
+ * - AConfiguration_new()
+ * - AConfiguration_fromAssetManager()
+ */
typedef struct AConfiguration AConfiguration;
+
+/**
+ * Define flags and constants for various subsystem configurations.
+ */
enum {
+ /** Orientation: not specified. */
ACONFIGURATION_ORIENTATION_ANY = 0x0000,
+ /**
+ * Orientation: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#OrientationQualifier">port</a>
+ * resource qualifier.
+ */
ACONFIGURATION_ORIENTATION_PORT = 0x0001,
+ /**
+ * Orientation: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#OrientationQualifier">land</a>
+ * resource qualifier.
+ */
ACONFIGURATION_ORIENTATION_LAND = 0x0002,
+ /** @deprecated Not currently supported or used. */
ACONFIGURATION_ORIENTATION_SQUARE = 0x0003,
+ /** Touchscreen: not specified. */
ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000,
+ /**
+ * Touchscreen: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a>
+ * resource qualifier.
+ */
ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001,
+ /** @deprecated Not currently supported or used. */
ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002,
+ /**
+ * Touchscreen: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
+ * resource qualifier.
+ */
ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003,
+ /** Density: default density. */
ACONFIGURATION_DENSITY_DEFAULT = 0,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">ldpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_LOW = 120,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">mdpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_MEDIUM = 160,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">tvdpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_TV = 213,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">hdpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_HIGH = 240,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">xhdpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_XHIGH = 320,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">xxhdpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_XXHIGH = 480,
+ /**
+ * Density: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">xxxhdpi</a>
+ * resource qualifier.
+ */
ACONFIGURATION_DENSITY_XXXHIGH = 640,
+ /** Density: any density. */
ACONFIGURATION_DENSITY_ANY = 0xfffe,
+ /** Density: no density specified. */
ACONFIGURATION_DENSITY_NONE = 0xffff,
+ /** Keyboard: not specified. */
ACONFIGURATION_KEYBOARD_ANY = 0x0000,
+ /**
+ * Keyboard: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a>
+ * resource qualifier.
+ */
ACONFIGURATION_KEYBOARD_NOKEYS = 0x0001,
+ /**
+ * Keyboard: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a>
+ * resource qualifier.
+ */
ACONFIGURATION_KEYBOARD_QWERTY = 0x0002,
+ /**
+ * Keyboard: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
+ * resource qualifier.
+ */
ACONFIGURATION_KEYBOARD_12KEY = 0x0003,
+ /** Navigation: not specified. */
ACONFIGURATION_NAVIGATION_ANY = 0x0000,
+ /**
+ * Navigation: value corresponding to the
+ * <a href="@@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a>
+ * resource qualifier.
+ */
ACONFIGURATION_NAVIGATION_NONAV = 0x0001,
+ /**
+ * Navigation: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a>
+ * resource qualifier.
+ */
ACONFIGURATION_NAVIGATION_DPAD = 0x0002,
+ /**
+ * Navigation: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a>
+ * resource qualifier.
+ */
ACONFIGURATION_NAVIGATION_TRACKBALL = 0x0003,
+ /**
+ * Navigation: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
+ * resource qualifier.
+ */
ACONFIGURATION_NAVIGATION_WHEEL = 0x0004,
+ /** Keyboard availability: not specified. */
ACONFIGURATION_KEYSHIDDEN_ANY = 0x0000,
+ /**
+ * Keyboard availability: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a>
+ * resource qualifier.
+ */
ACONFIGURATION_KEYSHIDDEN_NO = 0x0001,
+ /**
+ * Keyboard availability: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a>
+ * resource qualifier.
+ */
ACONFIGURATION_KEYSHIDDEN_YES = 0x0002,
+ /**
+ * Keyboard availability: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyssoft</a>
+ * resource qualifier.
+ */
ACONFIGURATION_KEYSHIDDEN_SOFT = 0x0003,
+ /** Navigation availability: not specified. */
ACONFIGURATION_NAVHIDDEN_ANY = 0x0000,
+ /**
+ * Navigation availability: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a>
+ * resource qualifier.
+ */
ACONFIGURATION_NAVHIDDEN_NO = 0x0001,
+ /**
+ * Navigation availability: value corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
+ * resource qualifier.
+ */
ACONFIGURATION_NAVHIDDEN_YES = 0x0002,
+ /** Screen size: not specified. */
ACONFIGURATION_SCREENSIZE_ANY = 0x00,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 320x426 dp units, corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a>
+ * resource qualifier.
+ */
ACONFIGURATION_SCREENSIZE_SMALL = 0x01,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 320x470 dp units, corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a>
+ * resource qualifier.
+ */
ACONFIGURATION_SCREENSIZE_NORMAL = 0x02,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 480x640 dp units, corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a>
+ * resource qualifier.
+ */
ACONFIGURATION_SCREENSIZE_LARGE = 0x03,
+ /**
+ * Screen size: value indicating the screen is at least
+ * approximately 720x960 dp units, corresponding to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a>
+ * resource qualifier.
+ */
ACONFIGURATION_SCREENSIZE_XLARGE = 0x04,
+ /** Screen layout: not specified. */
ACONFIGURATION_SCREENLONG_ANY = 0x00,
+ /**
+ * Screen layout: value that corresponds to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a>
+ * resource qualifier.
+ */
ACONFIGURATION_SCREENLONG_NO = 0x1,
+ /**
+ * Screen layout: value that corresponds to the
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a>
+ * resource qualifier.
+ */
ACONFIGURATION_SCREENLONG_YES = 0x2,
+ ACONFIGURATION_SCREENROUND_ANY = 0x00,
+ ACONFIGURATION_SCREENROUND_NO = 0x1,
+ ACONFIGURATION_SCREENROUND_YES = 0x2,
+
+ /** UI mode: not specified. */
ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">no
+ * UI mode type</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_TYPE_NORMAL = 0x01,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_TYPE_DESK = 0x02,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">car</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">television</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05,
+ /**
+ * UI mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06,
+ /** UI night mode: not specified.*/
ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00,
+ /**
+ * UI night mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NightQualifier">notnight</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1,
+ /**
+ * UI night mode: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NightQualifier">night</a> resource qualifier specified.
+ */
ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2,
+ /** Screen width DPI: not specified. */
ACONFIGURATION_SCREEN_WIDTH_DP_ANY = 0x0000,
+ /** Screen height DPI: not specified. */
ACONFIGURATION_SCREEN_HEIGHT_DP_ANY = 0x0000,
+ /** Smallest screen width DPI: not specified.*/
ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000,
+ /** Layout direction: not specified. */
ACONFIGURATION_LAYOUTDIR_ANY = 0x00,
+ /**
+ * Layout direction: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">ldltr</a> resource qualifier specified.
+ */
ACONFIGURATION_LAYOUTDIR_LTR = 0x01,
+ /**
+ * Layout direction: value that corresponds to
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">ldrtl</a> resource qualifier specified.
+ */
ACONFIGURATION_LAYOUTDIR_RTL = 0x02,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#MccQualifier">mcc</a>
+ * configuration.
+ */
ACONFIGURATION_MCC = 0x0001,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
+ * configuration.
+ */
ACONFIGURATION_MNC = 0x0002,
+ /**
+ * Bit mask for
+ * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
+ * configuration.
+ */
ACONFIGURATION_LOCALE = 0x0004,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#TouchscreenQualifier">touchscreen</a>
+ * configuration.
+ */
ACONFIGURATION_TOUCHSCREEN = 0x0008,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">keyboard</a>
+ * configuration.
+ */
ACONFIGURATION_KEYBOARD = 0x0010,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyboardHidden</a>
+ * configuration.
+ */
ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">navigation</a>
+ * configuration.
+ */
ACONFIGURATION_NAVIGATION = 0x0040,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#OrientationQualifier">orientation</a>
+ * configuration.
+ */
ACONFIGURATION_ORIENTATION = 0x0080,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
+ * configuration.
+ */
ACONFIGURATION_DENSITY = 0x0100,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">screen size</a>
+ * configuration.
+ */
ACONFIGURATION_SCREEN_SIZE = 0x0200,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#VersionQualifier">platform version</a>
+ * configuration.
+ */
ACONFIGURATION_VERSION = 0x0400,
+ /**
+ * Bit mask for screen layout configuration.
+ */
ACONFIGURATION_SCREEN_LAYOUT = 0x0800,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">ui mode</a>
+ * configuration.
+ */
ACONFIGURATION_UI_MODE = 0x1000,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest screen width</a>
+ * configuration.
+ */
ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000,
+ /**
+ * Bit mask for
+ * <a href="@dacRoot/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">layout direction</a>
+ * configuration.
+ */
ACONFIGURATION_LAYOUTDIR = 0x4000,
-
+ ACONFIGURATION_SCREEN_ROUND = 0x8000,
+ /**
+ * Constant used to to represent MNC (Mobile Network Code) zero.
+ * 0 cannot be used, since it is used to represent an undefined MNC.
+ */
ACONFIGURATION_MNC_ZERO = 0xffff,
};
@@ -132,7 +443,7 @@
/**
* Create and return a new AConfiguration based on the current configuration in
- * use in the given AssetManager.
+ * use in the given {@link AAssetManager}.
*/
void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am);
@@ -288,6 +599,16 @@
void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
/**
+ * Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
+ */
+int32_t AConfiguration_getScreenRound(AConfiguration* config);
+
+/**
+ * Set the current screen round in the configuration.
+ */
+void AConfiguration_setScreenRound(AConfiguration* config, int32_t screenRound);
+
+/**
* Return the current ACONFIGURATION_UI_MODE_TYPE_* set in the configuration.
*/
int32_t AConfiguration_getUiModeType(AConfiguration* config);
@@ -383,3 +704,5 @@
#endif
#endif // ANDROID_CONFIGURATION_H
+
+/** @} */
diff --git a/include/android/input.h b/include/android/input.h
index a660761..5ab4e29 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Input
+ * @{
+ */
+
+/**
+ * @file input.h
+ */
+
#ifndef _ANDROID_INPUT_H
#define _ANDROID_INPUT_H
@@ -49,247 +58,271 @@
extern "C" {
#endif
-/*
+/**
* Key states (may be returned by queries about the current state of a
* particular key code, scan code or switch).
*/
enum {
- /* The key state is unknown or the requested key itself is not supported. */
+ /** The key state is unknown or the requested key itself is not supported. */
AKEY_STATE_UNKNOWN = -1,
- /* The key is up. */
+ /** The key is up. */
AKEY_STATE_UP = 0,
- /* The key is down. */
+ /** The key is down. */
AKEY_STATE_DOWN = 1,
- /* The key is down but is a virtual key press that is being emulated by the system. */
+ /** The key is down but is a virtual key press that is being emulated by the system. */
AKEY_STATE_VIRTUAL = 2
};
-/*
+/**
* Meta key / modifer state.
*/
enum {
- /* No meta keys are pressed. */
+ /** No meta keys are pressed. */
AMETA_NONE = 0,
- /* This mask is used to check whether one of the ALT meta keys is pressed. */
+ /** This mask is used to check whether one of the ALT meta keys is pressed. */
AMETA_ALT_ON = 0x02,
- /* This mask is used to check whether the left ALT meta key is pressed. */
+ /** This mask is used to check whether the left ALT meta key is pressed. */
AMETA_ALT_LEFT_ON = 0x10,
- /* This mask is used to check whether the right ALT meta key is pressed. */
+ /** This mask is used to check whether the right ALT meta key is pressed. */
AMETA_ALT_RIGHT_ON = 0x20,
- /* This mask is used to check whether one of the SHIFT meta keys is pressed. */
+ /** This mask is used to check whether one of the SHIFT meta keys is pressed. */
AMETA_SHIFT_ON = 0x01,
- /* This mask is used to check whether the left SHIFT meta key is pressed. */
+ /** This mask is used to check whether the left SHIFT meta key is pressed. */
AMETA_SHIFT_LEFT_ON = 0x40,
- /* This mask is used to check whether the right SHIFT meta key is pressed. */
+ /** This mask is used to check whether the right SHIFT meta key is pressed. */
AMETA_SHIFT_RIGHT_ON = 0x80,
- /* This mask is used to check whether the SYM meta key is pressed. */
+ /** This mask is used to check whether the SYM meta key is pressed. */
AMETA_SYM_ON = 0x04,
- /* This mask is used to check whether the FUNCTION meta key is pressed. */
+ /** This mask is used to check whether the FUNCTION meta key is pressed. */
AMETA_FUNCTION_ON = 0x08,
- /* This mask is used to check whether one of the CTRL meta keys is pressed. */
+ /** This mask is used to check whether one of the CTRL meta keys is pressed. */
AMETA_CTRL_ON = 0x1000,
- /* This mask is used to check whether the left CTRL meta key is pressed. */
+ /** This mask is used to check whether the left CTRL meta key is pressed. */
AMETA_CTRL_LEFT_ON = 0x2000,
- /* This mask is used to check whether the right CTRL meta key is pressed. */
+ /** This mask is used to check whether the right CTRL meta key is pressed. */
AMETA_CTRL_RIGHT_ON = 0x4000,
- /* This mask is used to check whether one of the META meta keys is pressed. */
+ /** This mask is used to check whether one of the META meta keys is pressed. */
AMETA_META_ON = 0x10000,
- /* This mask is used to check whether the left META meta key is pressed. */
+ /** This mask is used to check whether the left META meta key is pressed. */
AMETA_META_LEFT_ON = 0x20000,
- /* This mask is used to check whether the right META meta key is pressed. */
+ /** This mask is used to check whether the right META meta key is pressed. */
AMETA_META_RIGHT_ON = 0x40000,
- /* This mask is used to check whether the CAPS LOCK meta key is on. */
+ /** This mask is used to check whether the CAPS LOCK meta key is on. */
AMETA_CAPS_LOCK_ON = 0x100000,
- /* This mask is used to check whether the NUM LOCK meta key is on. */
+ /** This mask is used to check whether the NUM LOCK meta key is on. */
AMETA_NUM_LOCK_ON = 0x200000,
- /* This mask is used to check whether the SCROLL LOCK meta key is on. */
+ /** This mask is used to check whether the SCROLL LOCK meta key is on. */
AMETA_SCROLL_LOCK_ON = 0x400000,
};
-/*
+struct AInputEvent;
+/**
* Input events.
*
* Input events are opaque structures. Use the provided accessors functions to
* read their properties.
*/
-struct AInputEvent;
typedef struct AInputEvent AInputEvent;
-/*
+/**
* Input event types.
*/
enum {
- /* Indicates that the input event is a key event. */
+ /** Indicates that the input event is a key event. */
AINPUT_EVENT_TYPE_KEY = 1,
- /* Indicates that the input event is a motion event. */
+ /** Indicates that the input event is a motion event. */
AINPUT_EVENT_TYPE_MOTION = 2
};
-/*
+/**
* Key event actions.
*/
enum {
- /* The key has been pressed down. */
+ /** The key has been pressed down. */
AKEY_EVENT_ACTION_DOWN = 0,
- /* The key has been released. */
+ /** The key has been released. */
AKEY_EVENT_ACTION_UP = 1,
- /* Multiple duplicate key events have occurred in a row, or a complex string is
- * being delivered. The repeat_count property of the key event contains the number
- * of times the given key code should be executed.
+ /**
+ * Multiple duplicate key events have occurred in a row, or a
+ * complex string is being delivered. The repeat_count property
+ * of the key event contains the number of times the given key
+ * code should be executed.
*/
AKEY_EVENT_ACTION_MULTIPLE = 2
};
-/*
+/**
* Key event flags.
*/
enum {
- /* This mask is set if the device woke because of this key event. */
+ /** This mask is set if the device woke because of this key event. */
AKEY_EVENT_FLAG_WOKE_HERE = 0x1,
- /* This mask is set if the key event was generated by a software keyboard. */
+ /** This mask is set if the key event was generated by a software keyboard. */
AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2,
- /* This mask is set if we don't want the key event to cause us to leave touch mode. */
+ /** This mask is set if we don't want the key event to cause us to leave touch mode. */
AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4,
- /* This mask is set if an event was known to come from a trusted part
- * of the system. That is, the event is known to come from the user,
- * and could not have been spoofed by a third party component. */
+ /**
+ * This mask is set if an event was known to come from a trusted
+ * part of the system. That is, the event is known to come from
+ * the user, and could not have been spoofed by a third party
+ * component.
+ */
AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
- /* This mask is used for compatibility, to identify enter keys that are
+ /**
+ * This mask is used for compatibility, to identify enter keys that are
* coming from an IME whose enter key has been auto-labelled "next" or
* "done". This allows TextView to dispatch these as normal enter keys
* for old applications, but still do the appropriate action when
- * receiving them. */
+ * receiving them.
+ */
AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10,
- /* When associated with up key events, this indicates that the key press
+ /**
+ * When associated with up key events, this indicates that the key press
* has been canceled. Typically this is used with virtual touch screen
* keys, where the user can slide from the virtual key area on to the
* display: in that case, the application will receive a canceled up
* event and should not perform the action normally associated with the
* key. Note that for this to work, the application can not perform an
* action for a key until it receives an up or the long press timeout has
- * expired. */
+ * expired.
+ */
AKEY_EVENT_FLAG_CANCELED = 0x20,
- /* This key event was generated by a virtual (on-screen) hard key area.
+ /**
+ * This key event was generated by a virtual (on-screen) hard key area.
* Typically this is an area of the touchscreen, outside of the regular
- * display, dedicated to "hardware" buttons. */
+ * display, dedicated to "hardware" buttons.
+ */
AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40,
- /* This flag is set for the first key repeat that occurs after the
- * long press timeout. */
+ /**
+ * This flag is set for the first key repeat that occurs after the
+ * long press timeout.
+ */
AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
- /* Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
- * press action was executed while it was down. */
+ /**
+ * Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long
+ * press action was executed while it was down.
+ */
AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100,
- /* Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
+ /**
+ * Set for AKEY_EVENT_ACTION_UP when this event's key code is still being
* tracked from its initial down. That is, somebody requested that tracking
* started on the key down and a long press has not caused
- * the tracking to be canceled. */
+ * the tracking to be canceled.
+ */
AKEY_EVENT_FLAG_TRACKING = 0x200,
- /* Set when a key event has been synthesized to implement default behavior
+ /**
+ * Set when a key event has been synthesized to implement default behavior
* for an event that the application did not handle.
* Fallback key events are generated by unhandled trackball motions
* (to emulate a directional keypad) and by certain unhandled key presses
* that are declared in the key map (such as special function numeric keypad
- * keys when numlock is off). */
+ * keys when numlock is off).
+ */
AKEY_EVENT_FLAG_FALLBACK = 0x400,
};
-/*
- * Motion event actions.
- */
-
-/* Bit shift for the action bits holding the pointer index as
+/**
+ * Bit shift for the action bits holding the pointer index as
* defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.
*/
#define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT 8
+/** Motion event actions */
enum {
- /* Bit mask of the parts of the action code that are the action itself.
- */
+ /** Bit mask of the parts of the action code that are the action itself. */
AMOTION_EVENT_ACTION_MASK = 0xff,
- /* Bits in the action code that represent a pointer index, used with
+ /**
+ * Bits in the action code that represent a pointer index, used with
* AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting
* down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer
* index where the data for the pointer going up or down can be found.
*/
AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00,
- /* A pressed gesture has started, the motion contains the initial starting location.
- */
+ /** A pressed gesture has started, the motion contains the initial starting location. */
AMOTION_EVENT_ACTION_DOWN = 0,
- /* A pressed gesture has finished, the motion contains the final release location
+ /**
+ * A pressed gesture has finished, the motion contains the final release location
* as well as any intermediate points since the last down or move event.
*/
AMOTION_EVENT_ACTION_UP = 1,
- /* A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+ /**
+ * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
* AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as
* any intermediate points since the last down or move event.
*/
AMOTION_EVENT_ACTION_MOVE = 2,
- /* The current gesture has been aborted.
+ /**
+ * The current gesture has been aborted.
* You will not receive any more points in it. You should treat this as
* an up event, but not perform any action that you normally would.
*/
AMOTION_EVENT_ACTION_CANCEL = 3,
- /* A movement has happened outside of the normal bounds of the UI element.
+ /**
+ * A movement has happened outside of the normal bounds of the UI element.
* This does not provide a full gesture, but only the initial location of the movement/touch.
*/
AMOTION_EVENT_ACTION_OUTSIDE = 4,
- /* A non-primary pointer has gone down.
+ /**
+ * A non-primary pointer has gone down.
* The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
*/
AMOTION_EVENT_ACTION_POINTER_DOWN = 5,
- /* A non-primary pointer has gone up.
+ /**
+ * A non-primary pointer has gone up.
* The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.
*/
AMOTION_EVENT_ACTION_POINTER_UP = 6,
- /* A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+ /**
+ * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
* The motion contains the most recent point, as well as any intermediate points since
* the last hover move event.
*/
AMOTION_EVENT_ACTION_HOVER_MOVE = 7,
- /* The motion event contains relative vertical and/or horizontal scroll offsets.
+ /**
+ * The motion event contains relative vertical and/or horizontal scroll offsets.
* Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
* and AMOTION_EVENT_AXIS_HSCROLL.
* The pointer may or may not be down when this event is dispatched.
@@ -298,20 +331,25 @@
*/
AMOTION_EVENT_ACTION_SCROLL = 8,
- /* The pointer is not down but has entered the boundaries of a window or view.
- */
+ /** The pointer is not down but has entered the boundaries of a window or view. */
AMOTION_EVENT_ACTION_HOVER_ENTER = 9,
- /* The pointer is not down but has exited the boundaries of a window or view.
- */
+ /** The pointer is not down but has exited the boundaries of a window or view. */
AMOTION_EVENT_ACTION_HOVER_EXIT = 10,
+
+ /* One or more buttons have been pressed. */
+ AMOTION_EVENT_ACTION_BUTTON_PRESS = 11,
+
+ /* One or more buttons have been released. */
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE = 12,
};
-/*
+/**
* Motion event flags.
*/
enum {
- /* This flag indicates that the window that received this motion event is partly
+ /**
+ * This flag indicates that the window that received this motion event is partly
* or wholly obscured by another visible window above it. This flag is set to true
* even if the event did not directly pass through the obscured area.
* A security sensitive application can check this flag to identify situations in which
@@ -323,170 +361,513 @@
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1,
};
-/*
+/**
* Motion event edge touch flags.
*/
enum {
- /* No edges intersected */
+ /** No edges intersected. */
AMOTION_EVENT_EDGE_FLAG_NONE = 0,
- /* Flag indicating the motion event intersected the top edge of the screen. */
+ /** Flag indicating the motion event intersected the top edge of the screen. */
AMOTION_EVENT_EDGE_FLAG_TOP = 0x01,
- /* Flag indicating the motion event intersected the bottom edge of the screen. */
+ /** Flag indicating the motion event intersected the bottom edge of the screen. */
AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02,
- /* Flag indicating the motion event intersected the left edge of the screen. */
+ /** Flag indicating the motion event intersected the left edge of the screen. */
AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04,
- /* Flag indicating the motion event intersected the right edge of the screen. */
+ /** Flag indicating the motion event intersected the right edge of the screen. */
AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08
};
-/*
+/**
* Constants that identify each individual axis of a motion event.
- * Refer to the documentation on the MotionEvent class for descriptions of each axis.
+ * @anchor AMOTION_EVENT_AXIS
*/
enum {
+ /**
+ * Axis constant: X axis of a motion event.
+ *
+ * - For a touch screen, reports the absolute X screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * - For a touch pad, reports the absolute X surface position of the center of the touch
+ * contact area. The units are device-dependent.
+ * - For a mouse, reports the absolute X screen position of the mouse pointer.
+ * The units are display pixels.
+ * - For a trackball, reports the relative horizontal displacement of the trackball.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ * - For a joystick, reports the absolute X position of the joystick.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ */
AMOTION_EVENT_AXIS_X = 0,
+ /**
+ * Axis constant: Y axis of a motion event.
+ *
+ * - For a touch screen, reports the absolute Y screen position of the center of
+ * the touch contact area. The units are display pixels.
+ * - For a touch pad, reports the absolute Y surface position of the center of the touch
+ * contact area. The units are device-dependent.
+ * - For a mouse, reports the absolute Y screen position of the mouse pointer.
+ * The units are display pixels.
+ * - For a trackball, reports the relative vertical displacement of the trackball.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ * - For a joystick, reports the absolute Y position of the joystick.
+ * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+ */
AMOTION_EVENT_AXIS_Y = 1,
+ /**
+ * Axis constant: Pressure axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the approximate pressure applied to the surface
+ * by a finger or other tool. The value is normalized to a range from
+ * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+ * may be generated depending on the calibration of the input device.
+ * - For a trackball, the value is set to 1 if the trackball button is pressed
+ * or 0 otherwise.
+ * - For a mouse, the value is set to 1 if the primary mouse button is pressed
+ * or 0 otherwise.
+ */
AMOTION_EVENT_AXIS_PRESSURE = 2,
+ /**
+ * Axis constant: Size axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the approximate size of the contact area in
+ * relation to the maximum detectable size for the device. The value is normalized
+ * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+ * although it is not a linear scale. This value is of limited use.
+ * To obtain calibrated size information, see
+ * {@link AMOTION_EVENT_AXIS_TOUCH_MAJOR} or {@link AMOTION_EVENT_AXIS_TOOL_MAJOR}.
+ */
AMOTION_EVENT_AXIS_SIZE = 3,
+ /**
+ * Axis constant: TouchMajor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * - For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent.
+ */
AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4,
+ /**
+ * Axis constant: TouchMinor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are display pixels.
+ * - For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the touch area at the point of contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ */
AMOTION_EVENT_AXIS_TOUCH_MINOR = 5,
+ /**
+ * Axis constant: ToolMajor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * - For a touch pad, reports the length of the major axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ *
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ */
AMOTION_EVENT_AXIS_TOOL_MAJOR = 6,
+ /**
+ * Axis constant: ToolMinor axis of a motion event.
+ *
+ * - For a touch screen, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * - For a touch pad, reports the length of the minor axis of an ellipse that
+ * represents the size of the approaching finger or tool used to make contact.
+ * The units are device-dependent.
+ *
+ * When the touch is circular, the major and minor axis lengths will be equal to one another.
+ *
+ * The tool size may be larger than the touch size since the tool may not be fully
+ * in contact with the touch sensor.
+ */
AMOTION_EVENT_AXIS_TOOL_MINOR = 7,
+ /**
+ * Axis constant: Orientation axis of a motion event.
+ *
+ * - For a touch screen or touch pad, reports the orientation of the finger
+ * or tool in radians relative to the vertical plane of the device.
+ * An angle of 0 radians indicates that the major axis of contact is oriented
+ * upwards, is perfectly circular or is of unknown orientation. A positive angle
+ * indicates that the major axis of contact is oriented to the right. A negative angle
+ * indicates that the major axis of contact is oriented to the left.
+ * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+ * (finger pointing fully right).
+ * - For a stylus, the orientation indicates the direction in which the stylus
+ * is pointing in relation to the vertical axis of the current orientation of the screen.
+ * The range is from -PI radians to PI radians, where 0 is pointing up,
+ * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+ * is pointing right. See also {@link AMOTION_EVENT_AXIS_TILT}.
+ */
AMOTION_EVENT_AXIS_ORIENTATION = 8,
+ /**
+ * Axis constant: Vertical Scroll axis of a motion event.
+ *
+ * - For a mouse, reports the relative movement of the vertical scroll wheel.
+ * The value is normalized to a range from -1.0 (down) to 1.0 (up).
+ *
+ * This axis should be used to scroll views vertically.
+ */
AMOTION_EVENT_AXIS_VSCROLL = 9,
+ /**
+ * Axis constant: Horizontal Scroll axis of a motion event.
+ *
+ * - For a mouse, reports the relative movement of the horizontal scroll wheel.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ *
+ * This axis should be used to scroll views horizontally.
+ */
AMOTION_EVENT_AXIS_HSCROLL = 10,
+ /**
+ * Axis constant: Z axis of a motion event.
+ *
+ * - For a joystick, reports the absolute Z position of the joystick.
+ * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+ * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute X position of the second joystick instead.</em>
+ */
AMOTION_EVENT_AXIS_Z = 11,
+ /**
+ * Axis constant: X Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the X axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ */
AMOTION_EVENT_AXIS_RX = 12,
+ /**
+ * Axis constant: Y Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the Y axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ */
AMOTION_EVENT_AXIS_RY = 13,
+ /**
+ * Axis constant: Z Rotation axis of a motion event.
+ *
+ * - For a joystick, reports the absolute rotation angle about the Z axis.
+ * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+ * On game pads with two analog joysticks, this axis is often reinterpreted
+ * to report the absolute Y position of the second joystick instead.
+ */
AMOTION_EVENT_AXIS_RZ = 14,
+ /**
+ * Axis constant: Hat X axis of a motion event.
+ *
+ * - For a joystick, reports the absolute X position of the directional hat control.
+ * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+ */
AMOTION_EVENT_AXIS_HAT_X = 15,
+ /**
+ * Axis constant: Hat Y axis of a motion event.
+ *
+ * - For a joystick, reports the absolute Y position of the directional hat control.
+ * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+ */
AMOTION_EVENT_AXIS_HAT_Y = 16,
+ /**
+ * Axis constant: Left Trigger axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the left trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ */
AMOTION_EVENT_AXIS_LTRIGGER = 17,
+ /**
+ * Axis constant: Right Trigger axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the right trigger control.
+ * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+ */
AMOTION_EVENT_AXIS_RTRIGGER = 18,
+ /**
+ * Axis constant: Throttle axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the throttle control.
+ * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+ */
AMOTION_EVENT_AXIS_THROTTLE = 19,
+ /**
+ * Axis constant: Rudder axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the rudder control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ */
AMOTION_EVENT_AXIS_RUDDER = 20,
+ /**
+ * Axis constant: Wheel axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the steering wheel control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ */
AMOTION_EVENT_AXIS_WHEEL = 21,
+ /**
+ * Axis constant: Gas axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the gas (accelerator) control.
+ * The value is normalized to a range from 0.0 (no acceleration)
+ * to 1.0 (maximum acceleration).
+ */
AMOTION_EVENT_AXIS_GAS = 22,
+ /**
+ * Axis constant: Brake axis of a motion event.
+ *
+ * - For a joystick, reports the absolute position of the brake control.
+ * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+ */
AMOTION_EVENT_AXIS_BRAKE = 23,
+ /**
+ * Axis constant: Distance axis of a motion event.
+ *
+ * - For a stylus, reports the distance of the stylus from the screen.
+ * A value of 0.0 indicates direct contact and larger values indicate increasing
+ * distance from the surface.
+ */
AMOTION_EVENT_AXIS_DISTANCE = 24,
+ /**
+ * Axis constant: Tilt axis of a motion event.
+ *
+ * - For a stylus, reports the tilt angle of the stylus in radians where
+ * 0 radians indicates that the stylus is being held perpendicular to the
+ * surface, and PI/2 radians indicates that the stylus is being held flat
+ * against the surface.
+ */
AMOTION_EVENT_AXIS_TILT = 25,
+ /**
+ * Axis constant: Generic 1 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_1 = 32,
+ /**
+ * Axis constant: Generic 2 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_2 = 33,
+ /**
+ * Axis constant: Generic 3 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_3 = 34,
+ /**
+ * Axis constant: Generic 4 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_4 = 35,
+ /**
+ * Axis constant: Generic 5 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_5 = 36,
+ /**
+ * Axis constant: Generic 6 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_6 = 37,
+ /**
+ * Axis constant: Generic 7 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_7 = 38,
+ /**
+ * Axis constant: Generic 8 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_8 = 39,
+ /**
+ * Axis constant: Generic 9 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_9 = 40,
+ /**
+ * Axis constant: Generic 10 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_10 = 41,
+ /**
+ * Axis constant: Generic 11 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_11 = 42,
+ /**
+ * Axis constant: Generic 12 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_12 = 43,
+ /**
+ * Axis constant: Generic 13 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_13 = 44,
+ /**
+ * Axis constant: Generic 14 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_14 = 45,
+ /**
+ * Axis constant: Generic 15 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_15 = 46,
+ /**
+ * Axis constant: Generic 16 axis of a motion event.
+ * The interpretation of a generic axis is device-specific.
+ */
AMOTION_EVENT_AXIS_GENERIC_16 = 47,
// NOTE: If you add a new axis here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
};
-/*
+/**
* Constants that identify buttons that are associated with motion events.
* Refer to the documentation on the MotionEvent class for descriptions of each button.
*/
enum {
+ /** primary */
AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
+ /** secondary */
AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1,
+ /** tertiary */
AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
+ /** back */
AMOTION_EVENT_BUTTON_BACK = 1 << 3,
+ /** forward */
AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
+ AMOTION_EVENT_BUTTON_STYLUS_PRIMARY = 1 << 5,
+ AMOTION_EVENT_BUTTON_STYLUS_SECONDARY = 1 << 6,
};
-/*
+/**
* Constants that identify tool types.
* Refer to the documentation on the MotionEvent class for descriptions of each tool type.
*/
enum {
+ /** unknown */
AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0,
+ /** finger */
AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
+ /** stylus */
AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
+ /** mouse */
AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
+ /** eraser */
AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
};
-/*
- * Input sources.
+/**
+ * Input source masks.
*
* Refer to the documentation on android.view.InputDevice for more details about input sources
* and their correct interpretation.
*/
enum {
+ /** mask */
AINPUT_SOURCE_CLASS_MASK = 0x000000ff,
+ /** none */
AINPUT_SOURCE_CLASS_NONE = 0x00000000,
+ /** button */
AINPUT_SOURCE_CLASS_BUTTON = 0x00000001,
+ /** pointer */
AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
+ /** navigation */
AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
+ /** position */
AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
+ /** joystick */
AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010,
};
+/**
+ * Input sources.
+ */
enum {
+ /** unknown */
AINPUT_SOURCE_UNKNOWN = 0x00000000,
+ /** keyboard */
AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
+ /** dpad */
AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
+ /** gamepad */
AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
+ /** touchscreen */
AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
+ /** mouse */
AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
+ /** stylus */
AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER,
+ /** bluetooth stylus */
+ AINPUT_SOURCE_BLUETOOTH_STYLUS = 0x00008000 | AINPUT_SOURCE_STYLUS,
+ /** trackball */
AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
+ /** touchpad */
AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
+ /** navigation */
AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
+ /** joystick */
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ /** any */
AINPUT_SOURCE_ANY = 0xffffff00,
};
-/*
+/**
* Keyboard types.
*
* Refer to the documentation on android.view.InputDevice for more details.
*/
enum {
+ /** none */
AINPUT_KEYBOARD_TYPE_NONE = 0,
+ /** non alphabetic */
AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1,
+ /** alphabetic */
AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2,
};
-/*
+/**
* Constants used to retrieve information about the range of motion for a particular
* coordinate of a motion event.
*
* Refer to the documentation on android.view.InputDevice for more details about input sources
* and their correct interpretation.
*
- * DEPRECATION NOTICE: These constants are deprecated. Use AMOTION_EVENT_AXIS_* constants instead.
+ * @deprecated These constants are deprecated. Use {@link AMOTION_EVENT_AXIS AMOTION_EVENT_AXIS_*} constants instead.
*/
enum {
+ /** x */
AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X,
+ /** y */
AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y,
+ /** pressure */
AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE,
+ /** size */
AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE,
+ /** touch major */
AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR,
+ /** touch minor */
AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR,
+ /** tool major */
AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR,
+ /** tool minor */
AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR,
+ /** orientation */
AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION,
-} __attribute__ ((deprecated));
+};
-/*
+/**
* Input event accessors.
*
* Note that most functions can only be used on input events that are of a given type.
@@ -495,10 +876,10 @@
/*** Accessors for all input events. ***/
-/* Get the input event type. */
+/** Get the input event type. */
int32_t AInputEvent_getType(const AInputEvent* event);
-/* Get the id for the device that an input event came from.
+/** Get the id for the device that an input event came from.
*
* Input events can be generated by multiple different input devices.
* Use the input device id to obtain information about the input
@@ -510,272 +891,351 @@
*/
int32_t AInputEvent_getDeviceId(const AInputEvent* event);
-/* Get the input event source. */
+/** Get the input event source. */
int32_t AInputEvent_getSource(const AInputEvent* event);
/*** Accessors for key events only. ***/
-/* Get the key event action. */
+/** Get the key event action. */
int32_t AKeyEvent_getAction(const AInputEvent* key_event);
-/* Get the key event flags. */
+/** Get the key event flags. */
int32_t AKeyEvent_getFlags(const AInputEvent* key_event);
-/* Get the key code of the key event.
- * This is the physical key that was pressed, not the Unicode character. */
+/**
+ * Get the key code of the key event.
+ * This is the physical key that was pressed, not the Unicode character.
+ */
int32_t AKeyEvent_getKeyCode(const AInputEvent* key_event);
-/* Get the hardware key id of this key event.
- * These values are not reliable and vary from device to device. */
+/**
+ * Get the hardware key id of this key event.
+ * These values are not reliable and vary from device to device.
+ */
int32_t AKeyEvent_getScanCode(const AInputEvent* key_event);
-/* Get the meta key state. */
+/** Get the meta key state. */
int32_t AKeyEvent_getMetaState(const AInputEvent* key_event);
-/* Get the repeat count of the event.
+/**
+ * Get the repeat count of the event.
* For both key up an key down events, this is the number of times the key has
* repeated with the first down starting at 0 and counting up from there. For
- * multiple key events, this is the number of down/up pairs that have occurred. */
+ * multiple key events, this is the number of down/up pairs that have occurred.
+ */
int32_t AKeyEvent_getRepeatCount(const AInputEvent* key_event);
-/* Get the time of the most recent key down event, in the
+/**
+ * Get the time of the most recent key down event, in the
* java.lang.System.nanoTime() time base. If this is a down event,
* this will be the same as eventTime.
* Note that when chording keys, this value is the down time of the most recently
- * pressed key, which may not be the same physical key of this event. */
+ * pressed key, which may not be the same physical key of this event.
+ */
int64_t AKeyEvent_getDownTime(const AInputEvent* key_event);
-/* Get the time this event occurred, in the
- * java.lang.System.nanoTime() time base. */
+/**
+ * Get the time this event occurred, in the
+ * java.lang.System.nanoTime() time base.
+ */
int64_t AKeyEvent_getEventTime(const AInputEvent* key_event);
/*** Accessors for motion events only. ***/
-/* Get the combined motion event action code and pointer index. */
+/** Get the combined motion event action code and pointer index. */
int32_t AMotionEvent_getAction(const AInputEvent* motion_event);
-/* Get the motion event flags. */
+/** Get the motion event flags. */
int32_t AMotionEvent_getFlags(const AInputEvent* motion_event);
-/* Get the state of any meta / modifier keys that were in effect when the
- * event was generated. */
+/**
+ * Get the state of any meta / modifier keys that were in effect when the
+ * event was generated.
+ */
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
-/* Get the button state of all buttons that are pressed. */
+/** Get the button state of all buttons that are pressed. */
int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
-/* Get a bitfield indicating which edges, if any, were touched by this motion event.
+/**
+ * Get a bitfield indicating which edges, if any, were touched by this motion event.
* For touch events, clients can use this to determine if the user's finger was
- * touching the edge of the display. */
+ * touching the edge of the display.
+ */
int32_t AMotionEvent_getEdgeFlags(const AInputEvent* motion_event);
-/* Get the time when the user originally pressed down to start a stream of
- * position events, in the java.lang.System.nanoTime() time base. */
+/**
+ * Get the time when the user originally pressed down to start a stream of
+ * position events, in the java.lang.System.nanoTime() time base.
+ */
int64_t AMotionEvent_getDownTime(const AInputEvent* motion_event);
-/* Get the time when this specific event was generated,
- * in the java.lang.System.nanoTime() time base. */
+/**
+ * Get the time when this specific event was generated,
+ * in the java.lang.System.nanoTime() time base.
+ */
int64_t AMotionEvent_getEventTime(const AInputEvent* motion_event);
-/* Get the X coordinate offset.
+/**
+ * Get the X coordinate offset.
* For touch events on the screen, this is the delta that was added to the raw
* screen coordinates to adjust for the absolute position of the containing windows
- * and views. */
+ * and views.
+ */
float AMotionEvent_getXOffset(const AInputEvent* motion_event);
-/* Get the Y coordinate offset.
+/**
+ * Get the Y coordinate offset.
* For touch events on the screen, this is the delta that was added to the raw
* screen coordinates to adjust for the absolute position of the containing windows
- * and views. */
+ * and views.
+ */
float AMotionEvent_getYOffset(const AInputEvent* motion_event);
-/* Get the precision of the X coordinates being reported.
+/**
+ * Get the precision of the X coordinates being reported.
* You can multiply this number with an X coordinate sample to find the
- * actual hardware value of the X coordinate. */
+ * actual hardware value of the X coordinate.
+ */
float AMotionEvent_getXPrecision(const AInputEvent* motion_event);
-/* Get the precision of the Y coordinates being reported.
+/**
+ * Get the precision of the Y coordinates being reported.
* You can multiply this number with a Y coordinate sample to find the
- * actual hardware value of the Y coordinate. */
+ * actual hardware value of the Y coordinate.
+ */
float AMotionEvent_getYPrecision(const AInputEvent* motion_event);
-/* Get the number of pointers of data contained in this event.
- * Always >= 1. */
+/**
+ * Get the number of pointers of data contained in this event.
+ * Always >= 1.
+ */
size_t AMotionEvent_getPointerCount(const AInputEvent* motion_event);
-/* Get the pointer identifier associated with a particular pointer
+/**
+ * Get the pointer identifier associated with a particular pointer
* data index in this event. The identifier tells you the actual pointer
* number associated with the data, accounting for individual pointers
- * going up and down since the start of the current gesture. */
+ * going up and down since the start of the current gesture.
+ */
int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the tool type of a pointer for the given pointer index.
+/**
+ * Get the tool type of a pointer for the given pointer index.
* The tool type indicates the type of tool used to make contact such as a
- * finger or stylus, if known. */
+ * finger or stylus, if known.
+ */
int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the original raw X coordinate of this event.
+/**
+ * Get the original raw X coordinate of this event.
* For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
- * and views. */
+ * and views.
+ */
float AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the original raw X coordinate of this event.
+/**
+ * Get the original raw X coordinate of this event.
* For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
- * and views. */
+ * and views.
+ */
float AMotionEvent_getRawY(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current X coordinate of this event for the given pointer index.
+/**
+ * Get the current X coordinate of this event for the given pointer index.
* Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
+ * that are sub-pixel precise.
+ */
float AMotionEvent_getX(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current Y coordinate of this event for the given pointer index.
+/**
+ * Get the current Y coordinate of this event for the given pointer index.
* Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
+ * that are sub-pixel precise.
+ */
float AMotionEvent_getY(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current pressure of this event for the given pointer index.
+/**
+ * Get the current pressure of this event for the given pointer index.
* The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
* although values higher than 1 may be generated depending on the calibration of
- * the input device. */
+ * the input device.
+ */
float AMotionEvent_getPressure(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current scaled value of the approximate size for the given pointer index.
+/**
+ * Get the current scaled value of the approximate size for the given pointer index.
* This represents some approximation of the area of the screen being
* pressed; the actual value in pixels corresponding to the
* touch is normalized with the device specific range of values
* and scaled to a value between 0 and 1. The value of size can be used to
- * determine fat touch events. */
+ * determine fat touch events.
+ */
float AMotionEvent_getSize(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current length of the major axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index. */
+/**
+ * Get the current length of the major axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index.
+ */
float AMotionEvent_getTouchMajor(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current length of the minor axis of an ellipse that describes the touch area
- * at the point of contact for the given pointer index. */
+/**
+ * Get the current length of the minor axis of an ellipse that describes the touch area
+ * at the point of contact for the given pointer index.
+ */
float AMotionEvent_getTouchMinor(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current length of the major axis of an ellipse that describes the size
+/**
+ * Get the current length of the major axis of an ellipse that describes the size
* of the approaching tool for the given pointer index.
* The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
+ * touching the device independent of its actual touch area at the point of contact.
+ */
float AMotionEvent_getToolMajor(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current length of the minor axis of an ellipse that describes the size
+/**
+ * Get the current length of the minor axis of an ellipse that describes the size
* of the approaching tool for the given pointer index.
* The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
+ * touching the device independent of its actual touch area at the point of contact.
+ */
float AMotionEvent_getToolMinor(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the current orientation of the touch area and tool area in radians clockwise from
+/**
+ * Get the current orientation of the touch area and tool area in radians clockwise from
* vertical for the given pointer index.
* An angle of 0 degrees indicates that the major axis of contact is oriented
* upwards, is perfectly circular or is of unknown orientation. A positive angle
* indicates that the major axis of contact is oriented to the right. A negative angle
* indicates that the major axis of contact is oriented to the left.
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
- * (finger pointing fully right). */
+ * (finger pointing fully right).
+ */
float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
-/* Get the value of the request axis for the given pointer index. */
+/** Get the value of the request axis for the given pointer index. */
float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
int32_t axis, size_t pointer_index);
-/* Get the number of historical points in this event. These are movements that
+/**
+ * Get the number of historical points in this event. These are movements that
* have occurred between this event and the previous event. This only applies
* to AMOTION_EVENT_ACTION_MOVE events -- all other actions will have a size of 0.
- * Historical samples are indexed from oldest to newest. */
+ * Historical samples are indexed from oldest to newest.
+ */
size_t AMotionEvent_getHistorySize(const AInputEvent* motion_event);
-/* Get the time that a historical movement occurred between this event and
- * the previous event, in the java.lang.System.nanoTime() time base. */
+/**
+ * Get the time that a historical movement occurred between this event and
+ * the previous event, in the java.lang.System.nanoTime() time base.
+ */
int64_t AMotionEvent_getHistoricalEventTime(const AInputEvent* motion_event,
size_t history_index);
-/* Get the historical raw X coordinate of this event for the given pointer index that
+/**
+ * Get the historical raw X coordinate of this event for the given pointer index that
* occurred between this event and the previous motion event.
* For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
* and views.
* Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
+ * that are sub-pixel precise.
+ */
float AMotionEvent_getHistoricalRawX(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical raw Y coordinate of this event for the given pointer index that
+/**
+ * Get the historical raw Y coordinate of this event for the given pointer index that
* occurred between this event and the previous motion event.
* For touch events on the screen, this is the original location of the event
* on the screen, before it had been adjusted for the containing window
* and views.
* Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
+ * that are sub-pixel precise.
+ */
float AMotionEvent_getHistoricalRawY(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical X coordinate of this event for the given pointer index that
+/**
+ * Get the historical X coordinate of this event for the given pointer index that
* occurred between this event and the previous motion event.
* Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
+ * that are sub-pixel precise.
+ */
float AMotionEvent_getHistoricalX(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical Y coordinate of this event for the given pointer index that
+/**
+ * Get the historical Y coordinate of this event for the given pointer index that
* occurred between this event and the previous motion event.
* Whole numbers are pixels; the value may have a fraction for input devices
- * that are sub-pixel precise. */
+ * that are sub-pixel precise.
+ */
float AMotionEvent_getHistoricalY(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical pressure of this event for the given pointer index that
+/**
+ * Get the historical pressure of this event for the given pointer index that
* occurred between this event and the previous motion event.
* The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
* although values higher than 1 may be generated depending on the calibration of
- * the input device. */
+ * the input device.
+ */
float AMotionEvent_getHistoricalPressure(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the current scaled value of the approximate size for the given pointer index that
+/**
+ * Get the current scaled value of the approximate size for the given pointer index that
* occurred between this event and the previous motion event.
* This represents some approximation of the area of the screen being
* pressed; the actual value in pixels corresponding to the
* touch is normalized with the device specific range of values
* and scaled to a value between 0 and 1. The value of size can be used to
- * determine fat touch events. */
+ * determine fat touch events.
+ */
float AMotionEvent_getHistoricalSize(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical length of the major axis of an ellipse that describes the touch area
+/**
+ * Get the historical length of the major axis of an ellipse that describes the touch area
* at the point of contact for the given pointer index that
- * occurred between this event and the previous motion event. */
+ * occurred between this event and the previous motion event.
+ */
float AMotionEvent_getHistoricalTouchMajor(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical length of the minor axis of an ellipse that describes the touch area
+/**
+ * Get the historical length of the minor axis of an ellipse that describes the touch area
* at the point of contact for the given pointer index that
- * occurred between this event and the previous motion event. */
+ * occurred between this event and the previous motion event.
+ */
float AMotionEvent_getHistoricalTouchMinor(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical length of the major axis of an ellipse that describes the size
+/**
+ * Get the historical length of the major axis of an ellipse that describes the size
* of the approaching tool for the given pointer index that
* occurred between this event and the previous motion event.
* The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
+ * touching the device independent of its actual touch area at the point of contact.
+ */
float AMotionEvent_getHistoricalToolMajor(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical length of the minor axis of an ellipse that describes the size
+/**
+ * Get the historical length of the minor axis of an ellipse that describes the size
* of the approaching tool for the given pointer index that
* occurred between this event and the previous motion event.
* The tool area represents the estimated size of the finger or pen that is
- * touching the device independent of its actual touch area at the point of contact. */
+ * touching the device independent of its actual touch area at the point of contact.
+ */
float AMotionEvent_getHistoricalToolMinor(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical orientation of the touch area and tool area in radians clockwise from
+/**
+ * Get the historical orientation of the touch area and tool area in radians clockwise from
* vertical for the given pointer index that
* occurred between this event and the previous motion event.
* An angle of 0 degrees indicates that the major axis of contact is oriented
@@ -783,51 +1243,54 @@
* indicates that the major axis of contact is oriented to the right. A negative angle
* indicates that the major axis of contact is oriented to the left.
* The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
- * (finger pointing fully right). */
+ * (finger pointing fully right).
+ */
float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-/* Get the historical value of the request axis for the given pointer index
- * that occurred between this event and the previous motion event. */
+/**
+ * Get the historical value of the request axis for the given pointer index
+ * that occurred between this event and the previous motion event.
+ */
float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
int32_t axis, size_t pointer_index, size_t history_index);
-/*
+struct AInputQueue;
+/**
* Input queue
*
* An input queue is the facility through which you retrieve input
* events.
*/
-struct AInputQueue;
typedef struct AInputQueue AInputQueue;
-/*
+/**
* Add this input queue to a looper for processing. See
* ALooper_addFd() for information on the ident, callback, and data params.
*/
void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
int ident, ALooper_callbackFunc callback, void* data);
-/*
+/**
* Remove the input queue from the looper it is currently attached to.
*/
void AInputQueue_detachLooper(AInputQueue* queue);
-/*
+/**
* Returns true if there are one or more events available in the
* input queue. Returns 1 if the queue has events; 0 if
* it does not have events; and a negative value if there is an error.
*/
int32_t AInputQueue_hasEvents(AInputQueue* queue);
-/*
+/**
* Returns the next available event from the queue. Returns a negative
* value if no events are available or an error has occurred.
*/
int32_t AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent);
-/*
+/**
* Sends the key for standard pre-dispatching -- that is, possibly deliver
* it to the current IME to be consumed before the app. Returns 0 if it
* was not pre-dispatched, meaning you can process it right now. If non-zero
@@ -837,7 +1300,7 @@
*/
int32_t AInputQueue_preDispatchEvent(AInputQueue* queue, AInputEvent* event);
-/*
+/**
* Report that dispatching has finished with the given event.
* This must be called after receiving an event with AInputQueue_get_event().
*/
@@ -848,3 +1311,5 @@
#endif
#endif // _ANDROID_INPUT_H
+
+/** @} */
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 268d092..f671116 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Input
+ * @{
+ */
+
+/**
+ * @file keycodes.h
+ */
+
#ifndef _ANDROID_KEYCODES_H
#define _ANDROID_KEYCODES_H
@@ -39,270 +48,681 @@
extern "C" {
#endif
-/*
+/**
* Key codes.
*/
enum {
+ /** Unknown key code. */
AKEYCODE_UNKNOWN = 0,
+ /** Soft Left key.
+ * Usually situated below the display on phones and used as a multi-function
+ * feature key for selecting a software defined function shown on the bottom left
+ * of the display. */
AKEYCODE_SOFT_LEFT = 1,
+ /** Soft Right key.
+ * Usually situated below the display on phones and used as a multi-function
+ * feature key for selecting a software defined function shown on the bottom right
+ * of the display. */
AKEYCODE_SOFT_RIGHT = 2,
+ /** Home key.
+ * This key is handled by the framework and is never delivered to applications. */
AKEYCODE_HOME = 3,
+ /** Back key. */
AKEYCODE_BACK = 4,
+ /** Call key. */
AKEYCODE_CALL = 5,
+ /** End Call key. */
AKEYCODE_ENDCALL = 6,
+ /** '0' key. */
AKEYCODE_0 = 7,
+ /** '1' key. */
AKEYCODE_1 = 8,
+ /** '2' key. */
AKEYCODE_2 = 9,
+ /** '3' key. */
AKEYCODE_3 = 10,
+ /** '4' key. */
AKEYCODE_4 = 11,
+ /** '5' key. */
AKEYCODE_5 = 12,
+ /** '6' key. */
AKEYCODE_6 = 13,
+ /** '7' key. */
AKEYCODE_7 = 14,
+ /** '8' key. */
AKEYCODE_8 = 15,
+ /** '9' key. */
AKEYCODE_9 = 16,
+ /** '*' key. */
AKEYCODE_STAR = 17,
+ /** '#' key. */
AKEYCODE_POUND = 18,
+ /** Directional Pad Up key.
+ * May also be synthesized from trackball motions. */
AKEYCODE_DPAD_UP = 19,
+ /** Directional Pad Down key.
+ * May also be synthesized from trackball motions. */
AKEYCODE_DPAD_DOWN = 20,
+ /** Directional Pad Left key.
+ * May also be synthesized from trackball motions. */
AKEYCODE_DPAD_LEFT = 21,
+ /** Directional Pad Right key.
+ * May also be synthesized from trackball motions. */
AKEYCODE_DPAD_RIGHT = 22,
+ /** Directional Pad Center key.
+ * May also be synthesized from trackball motions. */
AKEYCODE_DPAD_CENTER = 23,
+ /** Volume Up key.
+ * Adjusts the speaker volume up. */
AKEYCODE_VOLUME_UP = 24,
+ /** Volume Down key.
+ * Adjusts the speaker volume down. */
AKEYCODE_VOLUME_DOWN = 25,
+ /** Power key. */
AKEYCODE_POWER = 26,
+ /** Camera key.
+ * Used to launch a camera application or take pictures. */
AKEYCODE_CAMERA = 27,
+ /** Clear key. */
AKEYCODE_CLEAR = 28,
+ /** 'A' key. */
AKEYCODE_A = 29,
+ /** 'B' key. */
AKEYCODE_B = 30,
+ /** 'C' key. */
AKEYCODE_C = 31,
+ /** 'D' key. */
AKEYCODE_D = 32,
+ /** 'E' key. */
AKEYCODE_E = 33,
+ /** 'F' key. */
AKEYCODE_F = 34,
+ /** 'G' key. */
AKEYCODE_G = 35,
+ /** 'H' key. */
AKEYCODE_H = 36,
+ /** 'I' key. */
AKEYCODE_I = 37,
+ /** 'J' key. */
AKEYCODE_J = 38,
+ /** 'K' key. */
AKEYCODE_K = 39,
+ /** 'L' key. */
AKEYCODE_L = 40,
+ /** 'M' key. */
AKEYCODE_M = 41,
+ /** 'N' key. */
AKEYCODE_N = 42,
+ /** 'O' key. */
AKEYCODE_O = 43,
+ /** 'P' key. */
AKEYCODE_P = 44,
+ /** 'Q' key. */
AKEYCODE_Q = 45,
+ /** 'R' key. */
AKEYCODE_R = 46,
+ /** 'S' key. */
AKEYCODE_S = 47,
+ /** 'T' key. */
AKEYCODE_T = 48,
+ /** 'U' key. */
AKEYCODE_U = 49,
+ /** 'V' key. */
AKEYCODE_V = 50,
+ /** 'W' key. */
AKEYCODE_W = 51,
+ /** 'X' key. */
AKEYCODE_X = 52,
+ /** 'Y' key. */
AKEYCODE_Y = 53,
+ /** 'Z' key. */
AKEYCODE_Z = 54,
+ /** ',' key. */
AKEYCODE_COMMA = 55,
+ /** '.' key. */
AKEYCODE_PERIOD = 56,
+ /** Left Alt modifier key. */
AKEYCODE_ALT_LEFT = 57,
+ /** Right Alt modifier key. */
AKEYCODE_ALT_RIGHT = 58,
+ /** Left Shift modifier key. */
AKEYCODE_SHIFT_LEFT = 59,
+ /** Right Shift modifier key. */
AKEYCODE_SHIFT_RIGHT = 60,
+ /** Tab key. */
AKEYCODE_TAB = 61,
+ /** Space key. */
AKEYCODE_SPACE = 62,
+ /** Symbol modifier key.
+ * Used to enter alternate symbols. */
AKEYCODE_SYM = 63,
+ /** Explorer special function key.
+ * Used to launch a browser application. */
AKEYCODE_EXPLORER = 64,
+ /** Envelope special function key.
+ * Used to launch a mail application. */
AKEYCODE_ENVELOPE = 65,
+ /** Enter key. */
AKEYCODE_ENTER = 66,
+ /** Backspace key.
+ * Deletes characters before the insertion point, unlike {@link AKEYCODE_FORWARD_DEL}. */
AKEYCODE_DEL = 67,
+ /** '`' (backtick) key. */
AKEYCODE_GRAVE = 68,
+ /** '-'. */
AKEYCODE_MINUS = 69,
+ /** '=' key. */
AKEYCODE_EQUALS = 70,
+ /** '[' key. */
AKEYCODE_LEFT_BRACKET = 71,
+ /** ']' key. */
AKEYCODE_RIGHT_BRACKET = 72,
+ /** '\' key. */
AKEYCODE_BACKSLASH = 73,
+ /** ';' key. */
AKEYCODE_SEMICOLON = 74,
+ /** ''' (apostrophe) key. */
AKEYCODE_APOSTROPHE = 75,
+ /** '/' key. */
AKEYCODE_SLASH = 76,
+ /** '@' key. */
AKEYCODE_AT = 77,
+ /** Number modifier key.
+ * Used to enter numeric symbols.
+ * This key is not {@link AKEYCODE_NUM_LOCK}; it is more like {@link AKEYCODE_ALT_LEFT}. */
AKEYCODE_NUM = 78,
+ /** Headset Hook key.
+ * Used to hang up calls and stop media. */
AKEYCODE_HEADSETHOOK = 79,
- AKEYCODE_FOCUS = 80, // *Camera* focus
+ /** Camera Focus key.
+ * Used to focus the camera. */
+ AKEYCODE_FOCUS = 80,
+ /** '+' key. */
AKEYCODE_PLUS = 81,
+ /** Menu key. */
AKEYCODE_MENU = 82,
+ /** Notification key. */
AKEYCODE_NOTIFICATION = 83,
+ /** Search key. */
AKEYCODE_SEARCH = 84,
+ /** Play/Pause media key. */
AKEYCODE_MEDIA_PLAY_PAUSE= 85,
+ /** Stop media key. */
AKEYCODE_MEDIA_STOP = 86,
+ /** Play Next media key. */
AKEYCODE_MEDIA_NEXT = 87,
+ /** Play Previous media key. */
AKEYCODE_MEDIA_PREVIOUS = 88,
+ /** Rewind media key. */
AKEYCODE_MEDIA_REWIND = 89,
+ /** Fast Forward media key. */
AKEYCODE_MEDIA_FAST_FORWARD = 90,
+ /** Mute key.
+ * Mutes the microphone, unlike {@link AKEYCODE_VOLUME_MUTE}. */
AKEYCODE_MUTE = 91,
+ /** Page Up key. */
AKEYCODE_PAGE_UP = 92,
+ /** Page Down key. */
AKEYCODE_PAGE_DOWN = 93,
+ /** Picture Symbols modifier key.
+ * Used to switch symbol sets (Emoji, Kao-moji). */
AKEYCODE_PICTSYMBOLS = 94,
+ /** Switch Charset modifier key.
+ * Used to switch character sets (Kanji, Katakana). */
AKEYCODE_SWITCH_CHARSET = 95,
+ /** A Button key.
+ * On a game controller, the A button should be either the button labeled A
+ * or the first button on the bottom row of controller buttons. */
AKEYCODE_BUTTON_A = 96,
+ /** B Button key.
+ * On a game controller, the B button should be either the button labeled B
+ * or the second button on the bottom row of controller buttons. */
AKEYCODE_BUTTON_B = 97,
+ /** C Button key.
+ * On a game controller, the C button should be either the button labeled C
+ * or the third button on the bottom row of controller buttons. */
AKEYCODE_BUTTON_C = 98,
+ /** X Button key.
+ * On a game controller, the X button should be either the button labeled X
+ * or the first button on the upper row of controller buttons. */
AKEYCODE_BUTTON_X = 99,
+ /** Y Button key.
+ * On a game controller, the Y button should be either the button labeled Y
+ * or the second button on the upper row of controller buttons. */
AKEYCODE_BUTTON_Y = 100,
+ /** Z Button key.
+ * On a game controller, the Z button should be either the button labeled Z
+ * or the third button on the upper row of controller buttons. */
AKEYCODE_BUTTON_Z = 101,
+ /** L1 Button key.
+ * On a game controller, the L1 button should be either the button labeled L1 (or L)
+ * or the top left trigger button. */
AKEYCODE_BUTTON_L1 = 102,
+ /** R1 Button key.
+ * On a game controller, the R1 button should be either the button labeled R1 (or R)
+ * or the top right trigger button. */
AKEYCODE_BUTTON_R1 = 103,
+ /** L2 Button key.
+ * On a game controller, the L2 button should be either the button labeled L2
+ * or the bottom left trigger button. */
AKEYCODE_BUTTON_L2 = 104,
+ /** R2 Button key.
+ * On a game controller, the R2 button should be either the button labeled R2
+ * or the bottom right trigger button. */
AKEYCODE_BUTTON_R2 = 105,
+ /** Left Thumb Button key.
+ * On a game controller, the left thumb button indicates that the left (or only)
+ * joystick is pressed. */
AKEYCODE_BUTTON_THUMBL = 106,
+ /** Right Thumb Button key.
+ * On a game controller, the right thumb button indicates that the right
+ * joystick is pressed. */
AKEYCODE_BUTTON_THUMBR = 107,
+ /** Start Button key.
+ * On a game controller, the button labeled Start. */
AKEYCODE_BUTTON_START = 108,
+ /** Select Button key.
+ * On a game controller, the button labeled Select. */
AKEYCODE_BUTTON_SELECT = 109,
+ /** Mode Button key.
+ * On a game controller, the button labeled Mode. */
AKEYCODE_BUTTON_MODE = 110,
+ /** Escape key. */
AKEYCODE_ESCAPE = 111,
+ /** Forward Delete key.
+ * Deletes characters ahead of the insertion point, unlike {@link AKEYCODE_DEL}. */
AKEYCODE_FORWARD_DEL = 112,
+ /** Left Control modifier key. */
AKEYCODE_CTRL_LEFT = 113,
+ /** Right Control modifier key. */
AKEYCODE_CTRL_RIGHT = 114,
+ /** Caps Lock key. */
AKEYCODE_CAPS_LOCK = 115,
+ /** Scroll Lock key. */
AKEYCODE_SCROLL_LOCK = 116,
+ /** Left Meta modifier key. */
AKEYCODE_META_LEFT = 117,
+ /** Right Meta modifier key. */
AKEYCODE_META_RIGHT = 118,
+ /** Function modifier key. */
AKEYCODE_FUNCTION = 119,
+ /** System Request / Print Screen key. */
AKEYCODE_SYSRQ = 120,
+ /** Break / Pause key. */
AKEYCODE_BREAK = 121,
+ /** Home Movement key.
+ * Used for scrolling or moving the cursor around to the start of a line
+ * or to the top of a list. */
AKEYCODE_MOVE_HOME = 122,
+ /** End Movement key.
+ * Used for scrolling or moving the cursor around to the end of a line
+ * or to the bottom of a list. */
AKEYCODE_MOVE_END = 123,
+ /** Insert key.
+ * Toggles insert / overwrite edit mode. */
AKEYCODE_INSERT = 124,
+ /** Forward key.
+ * Navigates forward in the history stack. Complement of {@link AKEYCODE_BACK}. */
AKEYCODE_FORWARD = 125,
+ /** Play media key. */
AKEYCODE_MEDIA_PLAY = 126,
+ /** Pause media key. */
AKEYCODE_MEDIA_PAUSE = 127,
+ /** Close media key.
+ * May be used to close a CD tray, for example. */
AKEYCODE_MEDIA_CLOSE = 128,
+ /** Eject media key.
+ * May be used to eject a CD tray, for example. */
AKEYCODE_MEDIA_EJECT = 129,
+ /** Record media key. */
AKEYCODE_MEDIA_RECORD = 130,
+ /** F1 key. */
AKEYCODE_F1 = 131,
+ /** F2 key. */
AKEYCODE_F2 = 132,
+ /** F3 key. */
AKEYCODE_F3 = 133,
+ /** F4 key. */
AKEYCODE_F4 = 134,
+ /** F5 key. */
AKEYCODE_F5 = 135,
+ /** F6 key. */
AKEYCODE_F6 = 136,
+ /** F7 key. */
AKEYCODE_F7 = 137,
+ /** F8 key. */
AKEYCODE_F8 = 138,
+ /** F9 key. */
AKEYCODE_F9 = 139,
+ /** F10 key. */
AKEYCODE_F10 = 140,
+ /** F11 key. */
AKEYCODE_F11 = 141,
+ /** F12 key. */
AKEYCODE_F12 = 142,
+ /** Num Lock key.
+ * This is the Num Lock key; it is different from {@link AKEYCODE_NUM}.
+ * This key alters the behavior of other keys on the numeric keypad. */
AKEYCODE_NUM_LOCK = 143,
+ /** Numeric keypad '0' key. */
AKEYCODE_NUMPAD_0 = 144,
+ /** Numeric keypad '1' key. */
AKEYCODE_NUMPAD_1 = 145,
+ /** Numeric keypad '2' key. */
AKEYCODE_NUMPAD_2 = 146,
+ /** Numeric keypad '3' key. */
AKEYCODE_NUMPAD_3 = 147,
+ /** Numeric keypad '4' key. */
AKEYCODE_NUMPAD_4 = 148,
+ /** Numeric keypad '5' key. */
AKEYCODE_NUMPAD_5 = 149,
+ /** Numeric keypad '6' key. */
AKEYCODE_NUMPAD_6 = 150,
+ /** Numeric keypad '7' key. */
AKEYCODE_NUMPAD_7 = 151,
+ /** Numeric keypad '8' key. */
AKEYCODE_NUMPAD_8 = 152,
+ /** Numeric keypad '9' key. */
AKEYCODE_NUMPAD_9 = 153,
+ /** Numeric keypad '/' key (for division). */
AKEYCODE_NUMPAD_DIVIDE = 154,
+ /** Numeric keypad '*' key (for multiplication). */
AKEYCODE_NUMPAD_MULTIPLY = 155,
+ /** Numeric keypad '-' key (for subtraction). */
AKEYCODE_NUMPAD_SUBTRACT = 156,
+ /** Numeric keypad '+' key (for addition). */
AKEYCODE_NUMPAD_ADD = 157,
+ /** Numeric keypad '.' key (for decimals or digit grouping). */
AKEYCODE_NUMPAD_DOT = 158,
+ /** Numeric keypad ',' key (for decimals or digit grouping). */
AKEYCODE_NUMPAD_COMMA = 159,
+ /** Numeric keypad Enter key. */
AKEYCODE_NUMPAD_ENTER = 160,
+ /** Numeric keypad '=' key. */
AKEYCODE_NUMPAD_EQUALS = 161,
+ /** Numeric keypad '(' key. */
AKEYCODE_NUMPAD_LEFT_PAREN = 162,
+ /** Numeric keypad ')' key. */
AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
+ /** Volume Mute key.
+ * Mutes the speaker, unlike {@link AKEYCODE_MUTE}.
+ * This key should normally be implemented as a toggle such that the first press
+ * mutes the speaker and the second press restores the original volume. */
AKEYCODE_VOLUME_MUTE = 164,
+ /** Info key.
+ * Common on TV remotes to show additional information related to what is
+ * currently being viewed. */
AKEYCODE_INFO = 165,
+ /** Channel up key.
+ * On TV remotes, increments the television channel. */
AKEYCODE_CHANNEL_UP = 166,
+ /** Channel down key.
+ * On TV remotes, decrements the television channel. */
AKEYCODE_CHANNEL_DOWN = 167,
+ /** Zoom in key. */
AKEYCODE_ZOOM_IN = 168,
+ /** Zoom out key. */
AKEYCODE_ZOOM_OUT = 169,
+ /** TV key.
+ * On TV remotes, switches to viewing live TV. */
AKEYCODE_TV = 170,
+ /** Window key.
+ * On TV remotes, toggles picture-in-picture mode or other windowing functions. */
AKEYCODE_WINDOW = 171,
+ /** Guide key.
+ * On TV remotes, shows a programming guide. */
AKEYCODE_GUIDE = 172,
+ /** DVR key.
+ * On some TV remotes, switches to a DVR mode for recorded shows. */
AKEYCODE_DVR = 173,
+ /** Bookmark key.
+ * On some TV remotes, bookmarks content or web pages. */
AKEYCODE_BOOKMARK = 174,
+ /** Toggle captions key.
+ * Switches the mode for closed-captioning text, for example during television shows. */
AKEYCODE_CAPTIONS = 175,
+ /** Settings key.
+ * Starts the system settings activity. */
AKEYCODE_SETTINGS = 176,
+ /** TV power key.
+ * On TV remotes, toggles the power on a television screen. */
AKEYCODE_TV_POWER = 177,
+ /** TV input key.
+ * On TV remotes, switches the input on a television screen. */
AKEYCODE_TV_INPUT = 178,
+ /** Set-top-box power key.
+ * On TV remotes, toggles the power on an external Set-top-box. */
AKEYCODE_STB_POWER = 179,
+ /** Set-top-box input key.
+ * On TV remotes, switches the input mode on an external Set-top-box. */
AKEYCODE_STB_INPUT = 180,
+ /** A/V Receiver power key.
+ * On TV remotes, toggles the power on an external A/V Receiver. */
AKEYCODE_AVR_POWER = 181,
+ /** A/V Receiver input key.
+ * On TV remotes, switches the input mode on an external A/V Receiver. */
AKEYCODE_AVR_INPUT = 182,
+ /** Red "programmable" key.
+ * On TV remotes, acts as a contextual/programmable key. */
AKEYCODE_PROG_RED = 183,
+ /** Green "programmable" key.
+ * On TV remotes, actsas a contextual/programmable key. */
AKEYCODE_PROG_GREEN = 184,
+ /** Yellow "programmable" key.
+ * On TV remotes, acts as a contextual/programmable key. */
AKEYCODE_PROG_YELLOW = 185,
+ /** Blue "programmable" key.
+ * On TV remotes, acts as a contextual/programmable key. */
AKEYCODE_PROG_BLUE = 186,
+ /** App switch key.
+ * Should bring up the application switcher dialog. */
AKEYCODE_APP_SWITCH = 187,
+ /** Generic Game Pad Button #1.*/
AKEYCODE_BUTTON_1 = 188,
+ /** Generic Game Pad Button #2.*/
AKEYCODE_BUTTON_2 = 189,
+ /** Generic Game Pad Button #3.*/
AKEYCODE_BUTTON_3 = 190,
+ /** Generic Game Pad Button #4.*/
AKEYCODE_BUTTON_4 = 191,
+ /** Generic Game Pad Button #5.*/
AKEYCODE_BUTTON_5 = 192,
+ /** Generic Game Pad Button #6.*/
AKEYCODE_BUTTON_6 = 193,
+ /** Generic Game Pad Button #7.*/
AKEYCODE_BUTTON_7 = 194,
+ /** Generic Game Pad Button #8.*/
AKEYCODE_BUTTON_8 = 195,
+ /** Generic Game Pad Button #9.*/
AKEYCODE_BUTTON_9 = 196,
+ /** Generic Game Pad Button #10.*/
AKEYCODE_BUTTON_10 = 197,
+ /** Generic Game Pad Button #11.*/
AKEYCODE_BUTTON_11 = 198,
+ /** Generic Game Pad Button #12.*/
AKEYCODE_BUTTON_12 = 199,
+ /** Generic Game Pad Button #13.*/
AKEYCODE_BUTTON_13 = 200,
+ /** Generic Game Pad Button #14.*/
AKEYCODE_BUTTON_14 = 201,
+ /** Generic Game Pad Button #15.*/
AKEYCODE_BUTTON_15 = 202,
+ /** Generic Game Pad Button #16.*/
AKEYCODE_BUTTON_16 = 203,
+ /** Language Switch key.
+ * Toggles the current input language such as switching between English and Japanese on
+ * a QWERTY keyboard. On some devices, the same function may be performed by
+ * pressing Shift+Spacebar. */
AKEYCODE_LANGUAGE_SWITCH = 204,
+ /** Manner Mode key.
+ * Toggles silent or vibrate mode on and off to make the device behave more politely
+ * in certain settings such as on a crowded train. On some devices, the key may only
+ * operate when long-pressed. */
AKEYCODE_MANNER_MODE = 205,
+ /** 3D Mode key.
+ * Toggles the display between 2D and 3D mode. */
AKEYCODE_3D_MODE = 206,
+ /** Contacts special function key.
+ * Used to launch an address book application. */
AKEYCODE_CONTACTS = 207,
+ /** Calendar special function key.
+ * Used to launch a calendar application. */
AKEYCODE_CALENDAR = 208,
+ /** Music special function key.
+ * Used to launch a music player application. */
AKEYCODE_MUSIC = 209,
+ /** Calculator special function key.
+ * Used to launch a calculator application. */
AKEYCODE_CALCULATOR = 210,
+ /** Japanese full-width / half-width key. */
AKEYCODE_ZENKAKU_HANKAKU = 211,
+ /** Japanese alphanumeric key. */
AKEYCODE_EISU = 212,
+ /** Japanese non-conversion key. */
AKEYCODE_MUHENKAN = 213,
+ /** Japanese conversion key. */
AKEYCODE_HENKAN = 214,
+ /** Japanese katakana / hiragana key. */
AKEYCODE_KATAKANA_HIRAGANA = 215,
+ /** Japanese Yen key. */
AKEYCODE_YEN = 216,
+ /** Japanese Ro key. */
AKEYCODE_RO = 217,
+ /** Japanese kana key. */
AKEYCODE_KANA = 218,
+ /** Assist key.
+ * Launches the global assist activity. Not delivered to applications. */
AKEYCODE_ASSIST = 219,
+ /** Brightness Down key.
+ * Adjusts the screen brightness down. */
AKEYCODE_BRIGHTNESS_DOWN = 220,
+ /** Brightness Up key.
+ * Adjusts the screen brightness up. */
AKEYCODE_BRIGHTNESS_UP = 221,
+ /** Audio Track key.
+ * Switches the audio tracks. */
AKEYCODE_MEDIA_AUDIO_TRACK = 222,
+ /** Sleep key.
+ * Puts the device to sleep. Behaves somewhat like {@link AKEYCODE_POWER} but it
+ * has no effect if the device is already asleep. */
AKEYCODE_SLEEP = 223,
+ /** Wakeup key.
+ * Wakes up the device. Behaves somewhat like {@link AKEYCODE_POWER} but it
+ * has no effect if the device is already awake. */
AKEYCODE_WAKEUP = 224,
+ /** Pairing key.
+ * Initiates peripheral pairing mode. Useful for pairing remote control
+ * devices or game controllers, especially if no other input mode is
+ * available. */
AKEYCODE_PAIRING = 225,
+ /** Media Top Menu key.
+ * Goes to the top of media menu. */
AKEYCODE_MEDIA_TOP_MENU = 226,
+ /** '11' key. */
AKEYCODE_11 = 227,
+ /** '12' key. */
AKEYCODE_12 = 228,
+ /** Last Channel key.
+ * Goes to the last viewed channel. */
AKEYCODE_LAST_CHANNEL = 229,
+ /** TV data service key.
+ * Displays data services like weather, sports. */
AKEYCODE_TV_DATA_SERVICE = 230,
+ /** Voice Assist key.
+ * Launches the global voice assist activity. Not delivered to applications. */
AKEYCODE_VOICE_ASSIST = 231,
+ /** Radio key.
+ * Toggles TV service / Radio service. */
AKEYCODE_TV_RADIO_SERVICE = 232,
+ /** Teletext key.
+ * Displays Teletext service. */
AKEYCODE_TV_TELETEXT = 233,
+ /** Number entry key.
+ * Initiates to enter multi-digit channel nubmber when each digit key is assigned
+ * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
+ * User Control Code. */
AKEYCODE_TV_NUMBER_ENTRY = 234,
+ /** Analog Terrestrial key.
+ * Switches to analog terrestrial broadcast service. */
AKEYCODE_TV_TERRESTRIAL_ANALOG = 235,
+ /** Digital Terrestrial key.
+ * Switches to digital terrestrial broadcast service. */
AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236,
+ /** Satellite key.
+ * Switches to digital satellite broadcast service. */
AKEYCODE_TV_SATELLITE = 237,
+ /** BS key.
+ * Switches to BS digital satellite broadcasting service available in Japan. */
AKEYCODE_TV_SATELLITE_BS = 238,
+ /** CS key.
+ * Switches to CS digital satellite broadcasting service available in Japan. */
AKEYCODE_TV_SATELLITE_CS = 239,
+ /** BS/CS key.
+ * Toggles between BS and CS digital satellite services. */
AKEYCODE_TV_SATELLITE_SERVICE = 240,
+ /** Toggle Network key.
+ * Toggles selecting broacast services. */
AKEYCODE_TV_NETWORK = 241,
+ /** Antenna/Cable key.
+ * Toggles broadcast input source between antenna and cable. */
AKEYCODE_TV_ANTENNA_CABLE = 242,
+ /** HDMI #1 key.
+ * Switches to HDMI input #1. */
AKEYCODE_TV_INPUT_HDMI_1 = 243,
+ /** HDMI #2 key.
+ * Switches to HDMI input #2. */
AKEYCODE_TV_INPUT_HDMI_2 = 244,
+ /** HDMI #3 key.
+ * Switches to HDMI input #3. */
AKEYCODE_TV_INPUT_HDMI_3 = 245,
+ /** HDMI #4 key.
+ * Switches to HDMI input #4. */
AKEYCODE_TV_INPUT_HDMI_4 = 246,
+ /** Composite #1 key.
+ * Switches to composite video input #1. */
AKEYCODE_TV_INPUT_COMPOSITE_1 = 247,
+ /** Composite #2 key.
+ * Switches to composite video input #2. */
AKEYCODE_TV_INPUT_COMPOSITE_2 = 248,
+ /** Component #1 key.
+ * Switches to component video input #1. */
AKEYCODE_TV_INPUT_COMPONENT_1 = 249,
+ /** Component #2 key.
+ * Switches to component video input #2. */
AKEYCODE_TV_INPUT_COMPONENT_2 = 250,
+ /** VGA #1 key.
+ * Switches to VGA (analog RGB) input #1. */
AKEYCODE_TV_INPUT_VGA_1 = 251,
+ /** Audio description key.
+ * Toggles audio description off / on. */
AKEYCODE_TV_AUDIO_DESCRIPTION = 252,
+ /** Audio description mixing volume up key.
+ * Louden audio description volume as compared with normal audio volume. */
AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253,
+ /** Audio description mixing volume down key.
+ * Lessen audio description volume as compared with normal audio volume. */
AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254,
+ /** Zoom mode key.
+ * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
AKEYCODE_TV_ZOOM_MODE = 255,
+ /** Contents menu key.
+ * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
+ * Code */
AKEYCODE_TV_CONTENTS_MENU = 256,
+ /** Media context menu key.
+ * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
+ * Menu (0x11) of CEC User Control Code. */
AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257,
+ /** Timer programming key.
+ * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
+ * CEC User Control Code. */
AKEYCODE_TV_TIMER_PROGRAMMING = 258,
+ /** Help key. */
AKEYCODE_HELP = 259,
+ AKEYCODE_NAVIGATE_PREVIOUS = 260,
+ AKEYCODE_NAVIGATE_NEXT = 261,
+ AKEYCODE_NAVIGATE_IN = 262,
+ AKEYCODE_NAVIGATE_OUT = 263,
/** Primary stem key for Wear
* Main power/reset button on watch. */
AKEYCODE_STEM_PRIMARY = 264,
@@ -322,3 +742,5 @@
#endif
#endif // _ANDROID_KEYCODES_H
+
+/** @} */
diff --git a/include/android/looper.h b/include/android/looper.h
index 74c0383..718f703 100644
--- a/include/android/looper.h
+++ b/include/android/looper.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Looper
+ * @{
+ */
+
+/**
+ * @file looper.h
+ */
#ifndef ANDROID_LOOPER_H
#define ANDROID_LOOPER_H
@@ -22,6 +30,7 @@
extern "C" {
#endif
+struct ALooper;
/**
* ALooper
*
@@ -35,7 +44,6 @@
*
* A thread can have only one ALooper associated with it.
*/
-struct ALooper;
typedef struct ALooper ALooper;
/**
@@ -44,13 +52,14 @@
*/
ALooper* ALooper_forThread();
+/** Option for for ALooper_prepare(). */
enum {
/**
- * Option for ALooper_prepare: this looper will accept calls to
- * ALooper_addFd() that do not have a callback (that is provide NULL
- * for the callback). In this case the caller of ALooper_pollOnce()
- * or ALooper_pollAll() MUST check the return from these functions to
- * discover when data is available on such fds and process it.
+ * This looper will accept calls to ALooper_addFd() that do not
+ * have a callback (that is provide NULL for the callback). In
+ * this case the caller of ALooper_pollOnce() or ALooper_pollAll()
+ * MUST check the return from these functions to discover when
+ * data is available on such fds and process it.
*/
ALOOPER_PREPARE_ALLOW_NON_CALLBACKS = 1<<0
};
@@ -64,9 +73,9 @@
*/
ALooper* ALooper_prepare(int opts);
+/** Result from ALooper_pollOnce() and ALooper_pollAll(). */
enum {
/**
- * Result from ALooper_pollOnce() and ALooper_pollAll():
* The poll was awoken using wake() before the timeout expired
* and no callbacks were executed and no other file descriptors were ready.
*/
@@ -176,10 +185,12 @@
*
* Returns ALOOPER_POLL_ERROR if an error occurred.
*
- * Returns a value >= 0 containing an identifier if its file descriptor has data
- * and it has no callback function (requiring the caller here to handle it).
- * In this (and only this) case outFd, outEvents and outData will contain the poll
- * events and data associated with the fd, otherwise they will be set to NULL.
+ * Returns a value >= 0 containing an identifier (the same identifier
+ * `ident` passed to ALooper_addFd()) if its file descriptor has data
+ * and it has no callback function (requiring the caller here to
+ * handle it). In this (and only this) case outFd, outEvents and
+ * outData will contain the poll events and data associated with the
+ * fd, otherwise they will be set to NULL.
*
* This method does not return until it has finished invoking the appropriate callbacks
* for all file descriptors that were signalled.
@@ -254,3 +265,5 @@
#endif
#endif // ANDROID_LOOPER_H
+
+/** @} */
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
new file mode 100644
index 0000000..6c718c9
--- /dev/null
+++ b/include/android/multinetwork.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_MULTINETWORK_H
+#define ANDROID_MULTINETWORK_H
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * The corresponding C type for android.net.Network#getNetworkHandle() return
+ * values. The Java signed long value can be safely cast to a net_handle_t:
+ *
+ * [C] ((net_handle_t) java_long_network_handle)
+ * [C++] static_cast<net_handle_t>(java_long_network_handle)
+ *
+ * as appropriate.
+ */
+typedef uint64_t net_handle_t;
+
+/**
+ * The value NETWORK_UNSPECIFIED indicates no specific network.
+ *
+ * For some functions (documented below), a previous binding may be cleared
+ * by an invocation with NETWORK_UNSPECIFIED.
+ *
+ * Depending on the context it may indicate an error. It is expressly
+ * not used to indicate some notion of the "current default network".
+ */
+#define NETWORK_UNSPECIFIED ((net_handle_t)0)
+
+
+/**
+ * All functions below that return an int return 0 on success or -1
+ * on failure with an appropriate errno value set.
+ */
+
+
+/**
+ * Set the network to be used by the given socket file descriptor.
+ *
+ * To clear a previous socket binding invoke with NETWORK_UNSPECIFIED.
+ *
+ * This is the equivalent of:
+ *
+ * [ android.net.Network#bindSocket() ]
+ * https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket)
+ */
+int android_setsocknetwork(net_handle_t network, int fd);
+
+
+/**
+ * Binds the current process to |network|. All sockets created in the future
+ * (and not explicitly bound via android_setsocknetwork()) will be bound to
+ * |network|. All host name resolutions will be limited to |network| as well.
+ * Note that if the network identified by |network| ever disconnects, all
+ * sockets created in this way will cease to work and all host name
+ * resolutions will fail. This is by design so an application doesn't
+ * accidentally use sockets it thinks are still bound to a particular network.
+ *
+ * To clear a previous process binding invoke with NETWORK_UNSPECIFIED.
+ *
+ * This is the equivalent of:
+ *
+ * [ android.net.ConnectivityManager#setProcessDefaultNetwork() ]
+ * https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network)
+ */
+int android_setprocnetwork(net_handle_t network);
+
+
+/**
+ * Perform hostname resolution via the DNS servers associated with |network|.
+ *
+ * All arguments (apart from |network|) are used identically as those passed
+ * to getaddrinfo(3). Return and error values are identical to those of
+ * getaddrinfo(3), and in particular gai_strerror(3) can be used as expected.
+ * Similar to getaddrinfo(3):
+ * - |hints| may be NULL (in which case man page documented defaults apply)
+ * - either |node| or |service| may be NULL, but not both
+ * - |res| must not be NULL
+ *
+ * This is the equivalent of:
+ *
+ * [ android.net.Network#getAllByName() ]
+ * https://developer.android.com/reference/android/net/Network.html#getAllByName(java.lang.String)
+ */
+int android_getaddrinfofornetwork(net_handle_t network,
+ const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res);
+
+__END_DECLS
+
+#endif // ANDROID_MULTINETWORK_H
diff --git a/include/android/native_activity.h b/include/android/native_activity.h
index bc70f88..d3d99cf 100644
--- a/include/android/native_activity.h
+++ b/include/android/native_activity.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file native_activity.h
+ */
#ifndef ANDROID_NATIVE_ACTIVITY_H
#define ANDROID_NATIVE_ACTIVITY_H
@@ -31,6 +39,9 @@
extern "C" {
#endif
+/**
+ * {@link ANativeActivityCallbacks}
+ */
struct ANativeActivityCallbacks;
/**
@@ -75,17 +86,17 @@
* Path to this application's internal data directory.
*/
const char* internalDataPath;
-
+
/**
* Path to this application's external (removable/mountable) data directory.
*/
const char* externalDataPath;
-
+
/**
* The platform's SDK version code.
*/
int32_t sdkVersion;
-
+
/**
* This is the native instance of the application. It is not used by
* the framework, but can be set by the application to its own instance
@@ -119,13 +130,13 @@
* for more information.
*/
void (*onStart)(ANativeActivity* activity);
-
+
/**
* NativeActivity has resumed. See Java documentation for Activity.onResume()
* for more information.
*/
void (*onResume)(ANativeActivity* activity);
-
+
/**
* Framework is asking NativeActivity to save its current instance state.
* See Java documentation for Activity.onSaveInstanceState() for more
@@ -136,19 +147,19 @@
* entities (pointers to memory, file descriptors, etc).
*/
void* (*onSaveInstanceState)(ANativeActivity* activity, size_t* outSize);
-
+
/**
* NativeActivity has paused. See Java documentation for Activity.onPause()
* for more information.
*/
void (*onPause)(ANativeActivity* activity);
-
+
/**
* NativeActivity has stopped. See Java documentation for Activity.onStop()
* for more information.
*/
void (*onStop)(ANativeActivity* activity);
-
+
/**
* NativeActivity is being destroyed. See Java documentation for Activity.onDestroy()
* for more information.
@@ -160,7 +171,7 @@
* for example, to pause a game when it loses input focus.
*/
void (*onWindowFocusChanged)(ANativeActivity* activity, int hasFocus);
-
+
/**
* The drawing window for this native activity has been created. You
* can use the given native window object to start drawing.
@@ -191,13 +202,13 @@
* returning from here.
*/
void (*onNativeWindowDestroyed)(ANativeActivity* activity, ANativeWindow* window);
-
+
/**
* The input queue for this native activity's window has been created.
* You can use the given input queue to start retrieving input events.
*/
void (*onInputQueueCreated)(ANativeActivity* activity, AInputQueue* queue);
-
+
/**
* The input queue for this native activity's window is being destroyed.
* You should no longer try to reference this object upon returning from this
@@ -273,7 +284,17 @@
* API for documentation.
*/
enum {
+ /**
+ * Implicit request to show the input window, not as the result
+ * of a direct request by the user.
+ */
ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT = 0x0001,
+
+ /**
+ * The user has forced the input method open (such as by
+ * long-pressing menu) so it should not be closed until they
+ * explicitly do so.
+ */
ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002,
};
@@ -290,7 +311,15 @@
* API for documentation.
*/
enum {
+ /**
+ * The soft input window should only be hidden if it was not
+ * explicitly shown by the user.
+ */
ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY = 0x0001,
+ /**
+ * The soft input window should normally be hidden, unless it was
+ * originally shown with {@link ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED}.
+ */
ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002,
};
@@ -308,3 +337,4 @@
#endif // ANDROID_NATIVE_ACTIVITY_H
+/** @} */
diff --git a/include/android/native_window.h b/include/android/native_window.h
index 2f4f2d3..cf07f1a 100644
--- a/include/android/native_window.h
+++ b/include/android/native_window.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file native_window.h
+ */
+
#ifndef ANDROID_NATIVE_WINDOW_H
#define ANDROID_NATIVE_WINDOW_H
@@ -23,18 +32,31 @@
extern "C" {
#endif
-/*
+/**
* Pixel formats that a window can use.
*/
enum {
+ /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
WINDOW_FORMAT_RGBA_8888 = 1,
+ /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Unused: 8 bits. **/
WINDOW_FORMAT_RGBX_8888 = 2,
+ /** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
WINDOW_FORMAT_RGB_565 = 4,
};
struct ANativeWindow;
+/**
+ * {@link ANativeWindow} is opaque type that provides access to a native window.
+ *
+ * A pointer can be obtained using ANativeWindow_fromSurface().
+ */
typedef struct ANativeWindow ANativeWindow;
+/**
+ * {@link ANativeWindow} is a struct that represents a windows buffer.
+ *
+ * A pointer can be obtained using ANativeWindow_lock().
+ */
typedef struct ANativeWindow_Buffer {
// The number of pixels that are show horizontally.
int32_t width;
@@ -51,7 +73,7 @@
// The actual bits.
void* bits;
-
+
// Do not touch.
uint32_t reserved[6];
} ANativeWindow_Buffer;
@@ -67,25 +89,25 @@
*/
void ANativeWindow_release(ANativeWindow* window);
-/*
+/**
* Return the current width in pixels of the window surface. Returns a
* negative value on error.
*/
int32_t ANativeWindow_getWidth(ANativeWindow* window);
-/*
+/**
* Return the current height in pixels of the window surface. Returns a
* negative value on error.
*/
int32_t ANativeWindow_getHeight(ANativeWindow* window);
-/*
+/**
* Return the current pixel format of the window surface. Returns a
* negative value on error.
*/
int32_t ANativeWindow_getFormat(ANativeWindow* window);
-/*
+/**
* Change the format and size of the window buffers.
*
* The width and height control the number of pixels in the buffers, not the
@@ -124,3 +146,5 @@
#endif
#endif // ANDROID_NATIVE_WINDOW_H
+
+/** @} */
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index b9e72ef..60a36c3 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file native_window_jni.h
+ */
+
#ifndef ANDROID_NATIVE_WINDOW_JNI_H
#define ANDROID_NATIVE_WINDOW_JNI_H
@@ -38,3 +47,5 @@
#endif
#endif // ANDROID_NATIVE_WINDOW_H
+
+/** @} */
diff --git a/include/android/obb.h b/include/android/obb.h
index 65e9b2a..4c6d9d7 100644
--- a/include/android/obb.h
+++ b/include/android/obb.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Storage
+ * @{
+ */
+
+/**
+ * @file obb.h
+ */
#ifndef ANDROID_OBB_H
#define ANDROID_OBB_H
@@ -25,9 +33,12 @@
#endif
struct AObbInfo;
+/** {@link AObbInfo} is an opaque type representing information for obb storage. */
typedef struct AObbInfo AObbInfo;
+/** Flag for an obb file, returned by AObbInfo_getFlags(). */
enum {
+ /** overlay */
AOBBINFO_OVERLAY = 0x0001,
};
@@ -61,3 +72,5 @@
#endif
#endif // ANDROID_OBB_H
+
+/** @} */
diff --git a/include/android/rect.h b/include/android/rect.h
index bcd42a9..80741c0 100644
--- a/include/android/rect.h
+++ b/include/android/rect.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file rect.h
+ */
#ifndef ANDROID_RECT_H
#define ANDROID_RECT_H
@@ -24,13 +32,24 @@
extern "C" {
#endif
+/**
+ * {@link ARect} is a struct that represents a rectangular window area.
+ *
+ * It is used with {@link
+ * ANativeActivityCallbacks::onContentRectChanged} event callback and
+ * ANativeWindow_lock() function.
+ */
typedef struct ARect {
#ifdef __cplusplus
typedef int32_t value_type;
#endif
+ /** left position */
int32_t left;
+ /** top position */
int32_t top;
+ /** left position */
int32_t right;
+ /** bottom position */
int32_t bottom;
} ARect;
@@ -39,3 +58,5 @@
#endif
#endif // ANDROID_RECT_H
+
+/** @} */
diff --git a/include/android/sensor.h b/include/android/sensor.h
index d58c460..73928ea 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Sensor
+ * @{
+ */
+
+/**
+ * @file sensor.h
+ */
#ifndef ANDROID_SENSOR_H
#define ANDROID_SENSOR_H
@@ -34,7 +42,7 @@
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
*/
-/*
+/**
* Structures and functions to receive and process sensor events in
* native code.
*
@@ -49,37 +57,82 @@
#endif
-/*
- * Sensor types
+/**
+ * Sensor types.
* (keep in sync with hardware/sensor.h)
*/
-
enum {
+ /**
+ * {@link ASENSOR_TYPE_ACCELEROMETER}
+ * reporting-mode: continuous
+ *
+ * All values are in SI units (m/s^2) and measure the acceleration of the
+ * device minus the force of gravity.
+ */
ASENSOR_TYPE_ACCELEROMETER = 1,
+ /**
+ * {@link ASENSOR_TYPE_MAGNETIC_FIELD}
+ * reporting-mode: continuous
+ *
+ * All values are in micro-Tesla (uT) and measure the geomagnetic
+ * field in the X, Y and Z axis.
+ */
ASENSOR_TYPE_MAGNETIC_FIELD = 2,
+ /**
+ * {@link ASENSOR_TYPE_GYROSCOPE}
+ * reporting-mode: continuous
+ *
+ * All values are in radians/second and measure the rate of rotation
+ * around the X, Y and Z axis.
+ */
ASENSOR_TYPE_GYROSCOPE = 4,
+ /**
+ * {@link ASENSOR_TYPE_LIGHT}
+ * reporting-mode: on-change
+ *
+ * The light sensor value is returned in SI lux units.
+ */
ASENSOR_TYPE_LIGHT = 5,
+ /**
+ * {@link ASENSOR_TYPE_PROXIMITY}
+ * reporting-mode: on-change
+ *
+ * The proximity sensor which turns the screen off and back on during calls is the
+ * wake-up proximity sensor. Implement wake-up proximity sensor before implementing
+ * a non wake-up proximity sensor. For the wake-up proximity sensor set the flag
+ * SENSOR_FLAG_WAKE_UP.
+ * The value corresponds to the distance to the nearest object in centimeters.
+ */
ASENSOR_TYPE_PROXIMITY = 8
};
-/*
- * Sensor accuracy measure
+/**
+ * Sensor accuracy measure.
*/
enum {
+ /** no contact */
ASENSOR_STATUS_NO_CONTACT = -1,
+ /** unreliable */
ASENSOR_STATUS_UNRELIABLE = 0,
+ /** low accuracy */
ASENSOR_STATUS_ACCURACY_LOW = 1,
+ /** medium accuracy */
ASENSOR_STATUS_ACCURACY_MEDIUM = 2,
+ /** high accuracy */
ASENSOR_STATUS_ACCURACY_HIGH = 3
};
-/*
+/**
* Sensor Reporting Modes.
*/
enum {
+ /** continuous reporting */
AREPORTING_MODE_CONTINUOUS = 0,
+ /** reporting on change */
AREPORTING_MODE_ON_CHANGE = 1,
+ /** on shot reporting */
AREPORTING_MODE_ONE_SHOT = 2,
+ /** special trigger reporting */
AREPORTING_MODE_SPECIAL_TRIGGER = 3
};
@@ -87,14 +140,14 @@
* A few useful constants
*/
-/* Earth's gravity in m/s^2 */
+/** Earth's gravity in m/s^2 */
#define ASENSOR_STANDARD_GRAVITY (9.80665f)
-/* Maximum magnetic field on Earth's surface in uT */
+/** Maximum magnetic field on Earth's surface in uT */
#define ASENSOR_MAGNETIC_FIELD_EARTH_MAX (60.0f)
-/* Minimum magnetic field on Earth's surface in uT*/
+/** Minimum magnetic field on Earth's surface in uT*/
#define ASENSOR_MAGNETIC_FIELD_EARTH_MIN (30.0f)
-/*
+/**
* A sensor event.
*/
@@ -180,54 +233,134 @@
} ASensorEvent;
struct ASensorManager;
+/**
+ * {@link ASensorManager} is an opaque type to manage sensors and
+ * events queues.
+ *
+ * {@link ASensorManager} is a singleton that can be obtained using
+ * ASensorManager_getInstance().
+ *
+ * This file provides a set of functions that uses {@link
+ * ASensorManager} to access and list hardware sensors, and
+ * create and destroy event queues:
+ * - ASensorManager_getSensorList()
+ * - ASensorManager_getDefaultSensor()
+ * - ASensorManager_getDefaultSensorEx()
+ * - ASensorManager_createEventQueue()
+ * - ASensorManager_destroyEventQueue()
+ */
typedef struct ASensorManager ASensorManager;
+
struct ASensorEventQueue;
+/**
+ * {@link ASensorEventQueue} is an opaque type that provides access to
+ * {@link ASensorEvent} from hardware sensors.
+ *
+ * A new {@link ASensorEventQueue} can be obtained using ASensorManager_createEventQueue().
+ *
+ * This file provides a set of functions to enable and disable
+ * sensors, check and get events, and set event rates on a {@link
+ * ASensorEventQueue}.
+ * - ASensorEventQueue_enableSensor()
+ * - ASensorEventQueue_disableSensor()
+ * - ASensorEventQueue_hasEvents()
+ * - ASensorEventQueue_getEvents()
+ * - ASensorEventQueue_setEventRate()
+ */
typedef struct ASensorEventQueue ASensorEventQueue;
struct ASensor;
+/**
+ * {@link ASensor} is an opaque type that provides information about
+ * an hardware sensors.
+ *
+ * A {@link ASensor} pointer can be obtained using
+ * ASensorManager_getDefaultSensor(),
+ * ASensorManager_getDefaultSensorEx() or from a {@link ASensorList}.
+ *
+ * This file provides a set of functions to access properties of a
+ * {@link ASensor}:
+ * - ASensor_getName()
+ * - ASensor_getVendor()
+ * - ASensor_getType()
+ * - ASensor_getResolution()
+ * - ASensor_getMinDelay()
+ * - ASensor_getFifoMaxEventCount()
+ * - ASensor_getFifoReservedEventCount()
+ * - ASensor_getStringType()
+ * - ASensor_getReportingMode()
+ * - ASensor_isWakeUpSensor()
+ */
typedef struct ASensor ASensor;
+/**
+ * {@link ASensorRef} is a type for constant pointers to {@link ASensor}.
+ *
+ * This is used to define entry in {@link ASensorList} arrays.
+ */
typedef ASensor const* ASensorRef;
+/**
+ * {@link ASensorList} is an array of reference to {@link ASensor}.
+ *
+ * A {@link ASensorList} can be initialized using ASensorManager_getSensorList().
+ */
typedef ASensorRef const* ASensorList;
/*****************************************************************************/
-/*
- * Get a reference to the sensor manager. ASensorManager is a singleton.
+/**
+ * Get a reference to the sensor manager. ASensorManager is a singleton
+ * per package as different packages may have access to different sensors.
+ *
+ * Deprecated: Use ASensorManager_getInstanceForPackage(const char*) instead.
*
* Example:
*
* ASensorManager* sensorManager = ASensorManager_getInstance();
*
*/
-ASensorManager* ASensorManager_getInstance();
-
+__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
/*
+ * Get a reference to the sensor manager. ASensorManager is a singleton
+ * per package as different packages may have access to different sensors.
+ *
+ * Example:
+ *
+ * ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
+ *
+ */
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName);
+
+/**
* Returns the list of available sensors.
*/
int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list);
-/*
+/**
* Returns the default sensor for the given type, or NULL if no sensor
* of that type exists.
*/
ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
-/*
+/**
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
*/
ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type,
bool wakeUp);
-/*
+/**
* Creates a new sensor event queue and associate it with a looper.
+ *
+ * "ident" is a identifier for the events that will be returned when
+ * calling ALooper_pollOnce(). The identifier must be >= 0, or
+ * ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
*/
ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
ALooper* looper, int ident, ALooper_callbackFunc callback, void* data);
-/*
+/**
* Destroys the event queue and free all resources associated to it.
*/
int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
@@ -235,17 +368,17 @@
/*****************************************************************************/
-/*
+/**
* Enable the selected sensor. Returns a negative error code on failure.
*/
int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor);
-/*
+/**
* Disable the selected sensor. Returns a negative error code on failure.
*/
int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor const* sensor);
-/*
+/**
* Sets the delivery rate of events in microseconds for the given sensor.
* Note that this is a hint only, generally event will arrive at a higher
* rate. It is an error to set a rate inferior to the value returned by
@@ -254,14 +387,14 @@
*/
int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor const* sensor, int32_t usec);
-/*
+/**
* Returns true if there are one or more events available in the
* sensor queue. Returns 1 if the queue has events; 0 if
* it does not have events; and a negative value if there is an error.
*/
int ASensorEventQueue_hasEvents(ASensorEventQueue* queue);
-/*
+/**
* Returns the next available events from the queue. Returns a negative
* value if no events are available or an error has occurred, otherwise
* the number of events returned.
@@ -280,55 +413,55 @@
/*****************************************************************************/
-/*
+/**
* Returns this sensor's name (non localized)
*/
const char* ASensor_getName(ASensor const* sensor);
-/*
+/**
* Returns this sensor's vendor's name (non localized)
*/
const char* ASensor_getVendor(ASensor const* sensor);
-/*
+/**
* Return this sensor's type
*/
int ASensor_getType(ASensor const* sensor);
-/*
+/**
* Returns this sensors's resolution
*/
float ASensor_getResolution(ASensor const* sensor);
-/*
+/**
* Returns the minimum delay allowed between events in microseconds.
* A value of zero means that this sensor doesn't report events at a
* constant rate, but rather only when a new data is available.
*/
int ASensor_getMinDelay(ASensor const* sensor);
-/*
+/**
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
*/
int ASensor_getFifoMaxEventCount(ASensor const* sensor);
-/*
+/**
* Returns the hardware batch fifo size reserved to this sensor.
*/
int ASensor_getFifoReservedEventCount(ASensor const* sensor);
-/*
+/**
* Returns this sensor's string type.
*/
const char* ASensor_getStringType(ASensor const* sensor);
-/*
+/**
* Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
*/
int ASensor_getReportingMode(ASensor const* sensor);
-/*
+/**
* Returns true if this is a wake up sensor, false otherwise.
*/
bool ASensor_isWakeUpSensor(ASensor const* sensor);
@@ -338,3 +471,5 @@
#endif
#endif // ANDROID_SENSOR_H
+
+/** @} */
diff --git a/include/android/storage_manager.h b/include/android/storage_manager.h
index bad2491..7f2ee08 100644
--- a/include/android/storage_manager.h
+++ b/include/android/storage_manager.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup Storage
+ * @{
+ */
+
+/**
+ * @file storage_manager.h
+ */
#ifndef ANDROID_STORAGE_MANAGER_H
#define ANDROID_STORAGE_MANAGER_H
@@ -25,55 +33,62 @@
#endif
struct AStorageManager;
+/**
+ * {@link AStorageManager} manages application OBB storage, a pointer
+ * can be obtained with AStorageManager_new().
+ */
typedef struct AStorageManager AStorageManager;
+/**
+ * The different states of a OBB storage passed to AStorageManager_obbCallbackFunc().
+ */
enum {
- /*
+ /**
* The OBB container is now mounted and ready for use. Can be returned
* as the status for callbacks made during asynchronous OBB actions.
*/
AOBB_STATE_MOUNTED = 1,
- /*
+ /**
* The OBB container is now unmounted and not usable. Can be returned
* as the status for callbacks made during asynchronous OBB actions.
*/
AOBB_STATE_UNMOUNTED = 2,
- /*
+ /**
* There was an internal system error encountered while trying to
* mount the OBB. Can be returned as the status for callbacks made
* during asynchronous OBB actions.
*/
AOBB_STATE_ERROR_INTERNAL = 20,
- /*
+ /**
* The OBB could not be mounted by the system. Can be returned as the
* status for callbacks made during asynchronous OBB actions.
*/
AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21,
- /*
+ /**
* The OBB could not be unmounted. This most likely indicates that a
* file is in use on the OBB. Can be returned as the status for
* callbacks made during asynchronous OBB actions.
*/
AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22,
- /*
+ /**
* A call was made to unmount the OBB when it was not mounted. Can be
* returned as the status for callbacks made during asynchronous OBB
* actions.
*/
AOBB_STATE_ERROR_NOT_MOUNTED = 23,
- /*
+ /**
* The OBB has already been mounted. Can be returned as the status for
* callbacks made during asynchronous OBB actions.
*/
AOBB_STATE_ERROR_ALREADY_MOUNTED = 24,
- /*
+ /**
* The current application does not have permission to use this OBB.
* This could be because the OBB indicates it's owned by a different
* package. Can be returned as the status for callbacks made during
@@ -94,6 +109,16 @@
/**
* Callback function for asynchronous calls made on OBB files.
+ *
+ * "state" is one of the following constants:
+ * - {@link AOBB_STATE_MOUNTED}
+ * - {@link AOBB_STATE_UNMOUNTED}
+ * - {@link AOBB_STATE_ERROR_INTERNAL}
+ * - {@link AOBB_STATE_ERROR_COULD_NOT_MOUNT}
+ * - {@link AOBB_STATE_ERROR_COULD_NOT_UNMOUNT}
+ * - {@link AOBB_STATE_ERROR_NOT_MOUNTED}
+ * - {@link AOBB_STATE_ERROR_ALREADY_MOUNTED}
+ * - {@link AOBB_STATE_ERROR_PERMISSION_DENIED}
*/
typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const int32_t state, void* data);
@@ -125,3 +150,5 @@
#endif
#endif // ANDROID_STORAGE_MANAGER_H
+
+/** @} */
diff --git a/include/android/trace.h b/include/android/trace.h
new file mode 100644
index 0000000..e42e334
--- /dev/null
+++ b/include/android/trace.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+#ifndef ANDROID_NATIVE_TRACE_H
+#define ANDROID_NATIVE_TRACE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns true if tracing is enabled. Use this signal to avoid expensive computation only necessary
+ * when tracing is enabled.
+ */
+bool ATrace_isEnabled();
+
+/**
+ * Writes a tracing message to indicate that the given section of code has begun. This call must be
+ * followed by a corresponding call to endSection() on the same thread.
+ *
+ * Note: At this time the vertical bar character '|' and newline character '\n' are used internally
+ * by the tracing mechanism. If sectionName contains these characters they will be replaced with a
+ * space character in the trace.
+ */
+void ATrace_beginSection(const char* sectionName);
+
+/**
+ * Writes a tracing message to indicate that a given section of code has ended. This call must be
+ * preceeded by a corresponding call to beginSection(char*) on the same thread. Calling this method
+ * will mark the end of the most recently begun section of code, so care must be taken to ensure
+ * that beginSection / endSection pairs are properly nested and called from the same thread.
+ */
+void ATrace_endSection();
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_NATIVE_TRACE_H
diff --git a/include/android/window.h b/include/android/window.h
index 2ab192b..436bf3a 100644
--- a/include/android/window.h
+++ b/include/android/window.h
@@ -14,6 +14,14 @@
* limitations under the License.
*/
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file window.h
+ */
#ifndef ANDROID_WINDOW_H
#define ANDROID_WINDOW_H
@@ -26,28 +34,184 @@
* Window flags, as per the Java API at android.view.WindowManager.LayoutParams.
*/
enum {
+ /**
+ * As long as this window is visible to the user, allow the lock
+ * screen to activate while the screen is on. This can be used
+ * independently, or in combination with {@link
+ * AWINDOW_FLAG_KEEP_SCREEN_ON} and/or {@link
+ * AWINDOW_FLAG_SHOW_WHEN_LOCKED}
+ */
AWINDOW_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
+ /** Everything behind this window will be dimmed. */
AWINDOW_FLAG_DIM_BEHIND = 0x00000002,
+ /**
+ * Blur everything behind this window.
+ * @deprecated Blurring is no longer supported.
+ */
AWINDOW_FLAG_BLUR_BEHIND = 0x00000004,
+ /**
+ * This window won't ever get key input focus, so the
+ * user can not send key or other button events to it. Those will
+ * instead go to whatever focusable window is behind it. This flag
+ * will also enable {@link AWINDOW_FLAG_NOT_TOUCH_MODAL} whether or not that
+ * is explicitly set.
+ *
+ * Setting this flag also implies that the window will not need to
+ * interact with
+ * a soft input method, so it will be Z-ordered and positioned
+ * independently of any active input method (typically this means it
+ * gets Z-ordered on top of the input method, so it can use the full
+ * screen for its content and cover the input method if needed. You
+ * can use {@link AWINDOW_FLAG_ALT_FOCUSABLE_IM} to modify this behavior.
+ */
AWINDOW_FLAG_NOT_FOCUSABLE = 0x00000008,
+ /** this window can never receive touch events. */
AWINDOW_FLAG_NOT_TOUCHABLE = 0x00000010,
+ /**
+ * Even when this window is focusable (its
+ * {@link AWINDOW_FLAG_NOT_FOCUSABLE} is not set), allow any pointer events
+ * outside of the window to be sent to the windows behind it. Otherwise
+ * it will consume all pointer events itself, regardless of whether they
+ * are inside of the window.
+ */
AWINDOW_FLAG_NOT_TOUCH_MODAL = 0x00000020,
+ /**
+ * When set, if the device is asleep when the touch
+ * screen is pressed, you will receive this first touch event. Usually
+ * the first touch event is consumed by the system since the user can
+ * not see what they are pressing on.
+ *
+ * @deprecated This flag has no effect.
+ */
AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
+ /**
+ * As long as this window is visible to the user, keep
+ * the device's screen turned on and bright.
+ */
AWINDOW_FLAG_KEEP_SCREEN_ON = 0x00000080,
+ /**
+ * Place the window within the entire screen, ignoring
+ * decorations around the border (such as the status bar). The
+ * window must correctly position its contents to take the screen
+ * decoration into account.
+ */
AWINDOW_FLAG_LAYOUT_IN_SCREEN = 0x00000100,
+ /** allow window to extend outside of the screen. */
AWINDOW_FLAG_LAYOUT_NO_LIMITS = 0x00000200,
+ /**
+ * Hide all screen decorations (such as the status
+ * bar) while this window is displayed. This allows the window to
+ * use the entire display space for itself -- the status bar will
+ * be hidden when an app window with this flag set is on the top
+ * layer. A fullscreen window will ignore a value of {@link
+ * AWINDOW_SOFT_INPUT_ADJUST_RESIZE}; the window will stay
+ * fullscreen and will not resize.
+ */
AWINDOW_FLAG_FULLSCREEN = 0x00000400,
+ /**
+ * Override {@link AWINDOW_FLAG_FULLSCREEN} and force the
+ * screen decorations (such as the status bar) to be shown.
+ */
AWINDOW_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
+ /**
+ * Turn on dithering when compositing this window to
+ * the screen.
+ * @deprecated This flag is no longer used.
+ */
AWINDOW_FLAG_DITHER = 0x00001000,
+ /**
+ * Treat the content of the window as secure, preventing
+ * it from appearing in screenshots or from being viewed on non-secure
+ * displays.
+ */
AWINDOW_FLAG_SECURE = 0x00002000,
+ /**
+ * A special mode where the layout parameters are used
+ * to perform scaling of the surface when it is composited to the
+ * screen.
+ */
AWINDOW_FLAG_SCALED = 0x00004000,
+ /**
+ * Intended for windows that will often be used when the user is
+ * holding the screen against their face, it will aggressively
+ * filter the event stream to prevent unintended presses in this
+ * situation that may not be desired for a particular window, when
+ * such an event stream is detected, the application will receive
+ * a {@link AMOTION_EVENT_ACTION_CANCEL} to indicate this so
+ * applications can handle this accordingly by taking no action on
+ * the event until the finger is released.
+ */
AWINDOW_FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
+ /**
+ * A special option only for use in combination with
+ * {@link AWINDOW_FLAG_LAYOUT_IN_SCREEN}. When requesting layout in the
+ * screen your window may appear on top of or behind screen decorations
+ * such as the status bar. By also including this flag, the window
+ * manager will report the inset rectangle needed to ensure your
+ * content is not covered by screen decorations.
+ */
AWINDOW_FLAG_LAYOUT_INSET_DECOR = 0x00010000,
+ /**
+ * Invert the state of {@link AWINDOW_FLAG_NOT_FOCUSABLE} with
+ * respect to how this window interacts with the current method.
+ * That is, if FLAG_NOT_FOCUSABLE is set and this flag is set,
+ * then the window will behave as if it needs to interact with the
+ * input method and thus be placed behind/away from it; if {@link
+ * AWINDOW_FLAG_NOT_FOCUSABLE} is not set and this flag is set,
+ * then the window will behave as if it doesn't need to interact
+ * with the input method and can be placed to use more space and
+ * cover the input method.
+ */
AWINDOW_FLAG_ALT_FOCUSABLE_IM = 0x00020000,
+ /**
+ * If you have set {@link AWINDOW_FLAG_NOT_TOUCH_MODAL}, you
+ * can set this flag to receive a single special MotionEvent with
+ * the action
+ * {@link AMOTION_EVENT_ACTION_OUTSIDE} for
+ * touches that occur outside of your window. Note that you will not
+ * receive the full down/move/up gesture, only the location of the
+ * first down as an {@link AMOTION_EVENT_ACTION_OUTSIDE}.
+ */
AWINDOW_FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
+ /**
+ * Special flag to let windows be shown when the screen
+ * is locked. This will let application windows take precedence over
+ * key guard or any other lock screens. Can be used with
+ * {@link AWINDOW_FLAG_KEEP_SCREEN_ON} to turn screen on and display windows
+ * directly before showing the key guard window. Can be used with
+ * {@link AWINDOW_FLAG_DISMISS_KEYGUARD} to automatically fully dismisss
+ * non-secure keyguards. This flag only applies to the top-most
+ * full-screen window.
+ */
AWINDOW_FLAG_SHOW_WHEN_LOCKED = 0x00080000,
+ /**
+ * Ask that the system wallpaper be shown behind
+ * your window. The window surface must be translucent to be able
+ * to actually see the wallpaper behind it; this flag just ensures
+ * that the wallpaper surface will be there if this window actually
+ * has translucent regions.
+ */
AWINDOW_FLAG_SHOW_WALLPAPER = 0x00100000,
+ /**
+ * When set as a window is being added or made
+ * visible, once the window has been shown then the system will
+ * poke the power manager's user activity (as if the user had woken
+ * up the device) to turn the screen on.
+ */
AWINDOW_FLAG_TURN_SCREEN_ON = 0x00200000,
+ /**
+ * When set the window will cause the keyguard to
+ * be dismissed, only if it is not a secure lock keyguard. Because such
+ * a keyguard is not needed for security, it will never re-appear if
+ * the user navigates to another window (in contrast to
+ * {@link AWINDOW_FLAG_SHOW_WHEN_LOCKED}, which will only temporarily
+ * hide both secure and non-secure keyguards but ensure they reappear
+ * when the user moves to another UI that doesn't hide them).
+ * If the keyguard is currently active and is secure (requires an
+ * unlock pattern) than the user will still need to confirm it before
+ * seeing this window, unless {@link AWINDOW_FLAG_SHOW_WHEN_LOCKED} has
+ * also been set.
+ */
AWINDOW_FLAG_DISMISS_KEYGUARD = 0x00400000,
};
@@ -56,3 +220,5 @@
#endif
#endif // ANDROID_WINDOW_H
+
+/** @} */
diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h
index 6211cf4..f0a2790 100644
--- a/include/batteryservice/BatteryService.h
+++ b/include/batteryservice/BatteryService.h
@@ -57,6 +57,7 @@
bool chargerAcOnline;
bool chargerUsbOnline;
bool chargerWirelessOnline;
+ int maxChargingCurrent;
int batteryStatus;
int batteryHealth;
bool batteryPresent;
diff --git a/include/binder/AppOpsManager.h b/include/binder/AppOpsManager.h
index 256cb94..042927c 100644
--- a/include/binder/AppOpsManager.h
+++ b/include/binder/AppOpsManager.h
@@ -63,7 +63,35 @@
OP_ACCESS_NOTIFICATIONS = 25,
OP_CAMERA = 26,
OP_RECORD_AUDIO = 27,
- OP_PLAY_AUDIO = 28
+ OP_PLAY_AUDIO = 28,
+ OP_READ_CLIPBOARD = 29,
+ OP_WRITE_CLIPBOARD = 30,
+ OP_TAKE_MEDIA_BUTTONS = 31,
+ OP_TAKE_AUDIO_FOCUS = 32,
+ OP_AUDIO_MASTER_VOLUME = 33,
+ OP_AUDIO_VOICE_VOLUME = 34,
+ OP_AUDIO_RING_VOLUME = 35,
+ OP_AUDIO_MEDIA_VOLUME = 36,
+ OP_AUDIO_ALARM_VOLUME = 37,
+ OP_AUDIO_NOTIFICATION_VOLUME = 38,
+ OP_AUDIO_BLUETOOTH_VOLUME = 39,
+ OP_WAKE_LOCK = 40,
+ OP_MONITOR_LOCATION = 41,
+ OP_MONITOR_HIGH_POWER_LOCATION = 42,
+ OP_GET_USAGE_STATS = 43,
+ OP_MUTE_MICROPHONE = 44,
+ OP_TOAST_WINDOW = 45,
+ OP_PROJECT_MEDIA = 46,
+ OP_ACTIVATE_VPN = 47,
+ OP_WRITE_WALLPAPER = 48,
+ OP_ASSIST_STRUCTURE = 49,
+ OP_ASSIST_SCREENSHOT = 50,
+ OP_READ_PHONE_STATE = 51,
+ OP_ADD_VOICEMAIL = 52,
+ OP_USE_SIP = 53,
+ OP_PROCESS_OUTGOING_CALLS = 54,
+ OP_USE_FINGERPRINT = 55,
+ OP_BODY_SENSORS = 56
};
AppOpsManager();
@@ -75,6 +103,7 @@
void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback);
void stopWatchingMode(const sp<IAppOpsCallback>& callback);
+ int32_t permissionToOpCode(const String16& permission);
private:
Mutex mLock;
diff --git a/include/binder/IAppOpsService.h b/include/binder/IAppOpsService.h
index 193e9cc..cd81efa 100644
--- a/include/binder/IAppOpsService.h
+++ b/include/binder/IAppOpsService.h
@@ -40,6 +40,7 @@
const sp<IAppOpsCallback>& callback) = 0;
virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
virtual sp<IBinder> getToken(const sp<IBinder>& clientToken) = 0;
+ virtual int32_t permissionToOpCode(const String16& permission) = 0;
enum {
CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -49,6 +50,7 @@
START_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+4,
STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
+ PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
};
enum {
diff --git a/include/binder/IBatteryStats.h b/include/binder/IBatteryStats.h
index 7ddac57..5f38186 100644
--- a/include/binder/IBatteryStats.h
+++ b/include/binder/IBatteryStats.h
@@ -36,6 +36,12 @@
virtual void noteStopAudio(int uid) = 0;
virtual void noteResetVideo() = 0;
virtual void noteResetAudio() = 0;
+ virtual void noteFlashlightOn(int uid) = 0;
+ virtual void noteFlashlightOff(int uid) = 0;
+ virtual void noteStartCamera(int uid) = 0;
+ virtual void noteStopCamera(int uid) = 0;
+ virtual void noteResetCamera() = 0;
+ virtual void noteResetFlashlight() = 0;
enum {
NOTE_START_SENSOR_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -46,6 +52,12 @@
NOTE_STOP_AUDIO_TRANSACTION,
NOTE_RESET_VIDEO_TRANSACTION,
NOTE_RESET_AUDIO_TRANSACTION,
+ NOTE_FLASHLIGHT_ON_TRANSACTION,
+ NOTE_FLASHLIGHT_OFF_TRANSACTION,
+ NOTE_START_CAMERA_TRANSACTION,
+ NOTE_STOP_CAMERA_TRANSACTION,
+ NOTE_RESET_CAMERA_TRANSACTION,
+ NOTE_RESET_FLASHLIGHT_TRANSACTION
};
};
diff --git a/include/binder/IInterface.h b/include/binder/IInterface.h
index 5f9f69c..4ce3613 100644
--- a/include/binder/IInterface.h
+++ b/include/binder/IInterface.h
@@ -28,9 +28,9 @@
{
public:
IInterface();
- sp<IBinder> asBinder();
- sp<const IBinder> asBinder() const;
-
+ static sp<IBinder> asBinder(const IInterface*);
+ static sp<IBinder> asBinder(const sp<IInterface>&);
+
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
index 6e0c01b..1853cff 100644
--- a/include/binder/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -22,7 +22,7 @@
#include <binder/ProcessState.h>
#include <utils/Vector.h>
-#ifdef HAVE_WIN32_PROC
+#if defined(_WIN32)
typedef int uid_t;
#endif
@@ -39,8 +39,8 @@
status_t clearLastError();
- int getCallingPid() const;
- int getCallingUid() const;
+ pid_t getCallingPid() const;
+ uid_t getCallingUid() const;
void setStrictModePolicy(int32_t policy);
int32_t getStrictModePolicy() const;
@@ -76,14 +76,18 @@
BpBinder* proxy);
static void shutdown();
-
+
// Call this to disable switching threads to background scheduling when
// receiving incoming IPC calls. This is specifically here for the
// Android system process, since it expects to have background apps calling
// in to it but doesn't want to acquire locks in its services while in
// the background.
static void disableBackgroundScheduling(bool disable);
-
+
+ // Call blocks until the number of executing binder threads is less than
+ // the maximum number of binder threads threads allowed for this process.
+ void blockUntilThreadAvailable();
+
private:
IPCThreadState();
~IPCThreadState();
@@ -101,9 +105,9 @@
status_t getAndExecuteCommand();
status_t executeCommand(int32_t command);
void processPendingDerefs();
-
+
void clearCaller();
-
+
static void threadDestructor(void *st);
static void freeBuffer(Parcel* parcel,
const uint8_t* data, size_t dataSize,
@@ -114,7 +118,7 @@
const pid_t mMyThreadId;
Vector<BBinder*> mPendingStrongDerefs;
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
-
+
Parcel mIn;
Parcel mOut;
status_t mLastError;
diff --git a/include/binder/IPermissionController.h b/include/binder/IPermissionController.h
index f9d371b..4e5fb34 100644
--- a/include/binder/IPermissionController.h
+++ b/include/binder/IPermissionController.h
@@ -19,6 +19,7 @@
#define ANDROID_IPERMISSION_CONTROLLER_H
#include <binder/IInterface.h>
+#include <stdlib.h>
namespace android {
@@ -29,11 +30,16 @@
public:
DECLARE_META_INTERFACE(PermissionController);
- virtual bool checkPermission(const String16& permission,
- int32_t pid, int32_t uid) = 0;
-
+ virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) = 0;
+
+ virtual void getPackagesForUid(const uid_t uid, Vector<String16> &packages) = 0;
+
+ virtual bool isRuntimePermission(const String16& permission) = 0;
+
enum {
- CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
+ CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
+ IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2
};
};
diff --git a/include/binder/IProcessInfoService.h b/include/binder/IProcessInfoService.h
new file mode 100644
index 0000000..dc62f45
--- /dev/null
+++ b/include/binder/IProcessInfoService.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#ifndef ANDROID_I_PROCESS_INFO_SERVICE_H
+#define ANDROID_I_PROCESS_INFO_SERVICE_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IProcessInfoService : public IInterface {
+public:
+ DECLARE_META_INTERFACE(ProcessInfoService);
+
+ virtual status_t getProcessStatesFromPids( size_t length,
+ /*in*/ int32_t* pids,
+ /*out*/ int32_t* states) = 0;
+
+ enum {
+ GET_PROCESS_STATES_FROM_PIDS = IBinder::FIRST_CALL_TRANSACTION,
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnProcessInfoService : public BnInterface<IProcessInfoService> {
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_I_PROCESS_INFO_SERVICE_H
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 6a69761..3ada1e9 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -60,6 +60,7 @@
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
+ bool allowFds() const;
bool pushAllowFds(bool allowFds);
void restoreAllowFds(bool lastValue);
@@ -94,7 +95,9 @@
void* writeInplace(size_t len);
status_t writeUnpadded(const void* data, size_t len);
status_t writeInt32(int32_t val);
+ status_t writeUint32(uint32_t val);
status_t writeInt64(int64_t val);
+ status_t writeUint64(uint64_t val);
status_t writeFloat(float val);
status_t writeDouble(double val);
status_t writeCString(const char* str);
@@ -128,16 +131,18 @@
// will be closed once the parcel is destroyed.
status_t writeDupFileDescriptor(int fd);
- // Writes a raw fd and optional comm channel fd to the parcel as a ParcelFileDescriptor.
- // A dup's of the fds are made, which will be closed once the parcel is destroyed.
- // Null values are passed as -1.
- status_t writeParcelFileDescriptor(int fd, int commChannel = -1);
-
// Writes a blob to the parcel.
// If the blob is small, then it is stored in-place, otherwise it is
- // transferred by way of an anonymous shared memory region.
+ // transferred by way of an anonymous shared memory region. Prefer sending
+ // immutable blobs if possible since they may be subsequently transferred between
+ // processes without further copying whereas mutable blobs always need to be copied.
// The caller should call release() on the blob after writing its contents.
- status_t writeBlob(size_t len, WritableBlob* outBlob);
+ status_t writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob);
+
+ // Write an existing immutable blob file descriptor to the parcel.
+ // This allows the client to send the same blob to multiple processes
+ // as long as it keeps a dup of the blob file descriptor handy for later.
+ status_t writeDupImmutableBlobFileDescriptor(int fd);
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
@@ -152,8 +157,12 @@
const void* readInplace(size_t len) const;
int32_t readInt32() const;
status_t readInt32(int32_t *pArg) const;
+ uint32_t readUint32() const;
+ status_t readUint32(uint32_t *pArg) const;
int64_t readInt64() const;
status_t readInt64(int64_t *pArg) const;
+ uint64_t readUint64() const;
+ status_t readUint64(uint64_t *pArg) const;
float readFloat() const;
status_t readFloat(float *pArg) const;
double readDouble() const;
@@ -192,11 +201,6 @@
// in the parcel, which you do not own -- use dup() to get your own copy.
int readFileDescriptor() const;
- // Reads a ParcelFileDescriptor from the parcel. Returns the raw fd as
- // the result, and the optional comm channel fd in outCommChannel.
- // Null values are returned as -1.
- int readParcelFileDescriptor(int& outCommChannel) const;
-
// Reads a blob from the parcel.
// The caller should call release() on the blob after reading its contents.
status_t readBlob(size_t len, ReadableBlob* outBlob) const;
@@ -274,16 +278,19 @@
Blob();
~Blob();
+ void clear();
void release();
inline size_t size() const { return mSize; }
+ inline int fd() const { return mFd; };
+ inline bool isMutable() const { return mMutable; }
protected:
- void init(bool mapped, void* data, size_t size);
- void clear();
+ void init(int fd, void* data, size_t size, bool isMutable);
- bool mMapped;
+ int mFd; // owned by parcel so not closed when released
void* mData;
size_t mSize;
+ bool mMutable;
};
class FlattenableHelperInterface {
@@ -324,6 +331,7 @@
friend class Parcel;
public:
inline const void* data() const { return mData; }
+ inline void* mutableData() { return isMutable() ? mData : NULL; }
};
class WritableBlob : public Blob {
@@ -331,6 +339,12 @@
public:
inline void* data() { return mData; }
};
+
+private:
+ size_t mBlobAshmemSize;
+
+public:
+ size_t getBlobAshmemSize() const;
};
// ---------------------------------------------------------------------------
diff --git a/include/binder/ProcessInfoService.h b/include/binder/ProcessInfoService.h
new file mode 100644
index 0000000..c5ead20
--- /dev/null
+++ b/include/binder/ProcessInfoService.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#ifndef ANDROID_PROCESS_INFO_SERVICE_H
+#define ANDROID_PROCESS_INFO_SERVICE_H
+
+#include <binder/IProcessInfoService.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+#include <sys/types.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class ProcessInfoService : public Singleton<ProcessInfoService> {
+
+ friend class Singleton<ProcessInfoService>;
+ sp<IProcessInfoService> mProcessInfoService;
+ Mutex mProcessInfoLock;
+
+ ProcessInfoService();
+
+ status_t getProcessStatesImpl(size_t length, /*in*/ int32_t* pids, /*out*/ int32_t* states);
+ void updateBinderLocked();
+
+ static const int BINDER_ATTEMPT_LIMIT = 5;
+
+public:
+
+ /**
+ * For each PID in the given "pids" input array, write the current process state
+ * for that process into the "states" output array, or
+ * ActivityManager.PROCESS_STATE_NONEXISTENT * to indicate that no process with the given PID
+ * exists.
+ *
+ * Returns NO_ERROR if this operation was successful, or a negative error code otherwise.
+ */
+ static status_t getProcessStatesFromPids(size_t length, /*in*/ int32_t* pids,
+ /*out*/ int32_t* states) {
+ return ProcessInfoService::getInstance().getProcessStatesImpl(length, /*in*/ pids,
+ /*out*/ states);
+ }
+
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_PROCESS_INFO_SERVICE_H
+
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index 3bc978d..f9edc2a 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -24,6 +24,8 @@
#include <utils/threads.h>
+#include <pthread.h>
+
// ---------------------------------------------------------------------------
namespace android {
@@ -71,25 +73,33 @@
ProcessState(const ProcessState& o);
ProcessState& operator=(const ProcessState& o);
String8 makeBinderThreadName();
-
+
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
-
+
handle_entry* lookupHandleLocked(int32_t handle);
int mDriverFD;
void* mVMStart;
-
+
+ // Protects thread count variable below.
+ pthread_mutex_t mThreadCountLock;
+ pthread_cond_t mThreadCountDecrement;
+ // Number of binder threads current executing a command.
+ size_t mExecutingThreadsCount;
+ // Maximum number for binder threads allowed for this process.
+ size_t mMaxThreads;
+
mutable Mutex mLock; // protects everything below.
-
+
Vector<handle_entry>mHandleToObject;
bool mManagesContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
-
+
KeyedVector<String16, sp<IBinder> >
mContexts;
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 01b6ff4..145efe6 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -20,9 +20,10 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <gui/IGraphicBufferConsumer.h>
-
#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <system/graphics.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
@@ -45,7 +46,6 @@
enum { INVALID_BUFFER_SLOT = -1 };
BufferItem();
~BufferItem();
- operator IGraphicBufferConsumer::BufferItem() const;
static const char* scalingModeName(uint32_t scalingMode);
@@ -72,17 +72,39 @@
// to set by queueBuffer each time this slot is queued. This value
// is guaranteed to be monotonically increasing for each newly
// acquired buffer.
- int64_t mTimestamp;
+ union {
+ int64_t mTimestamp;
+ struct {
+ uint32_t mTimestampLo;
+ uint32_t mTimestampHi;
+ };
+ };
// mIsAutoTimestamp indicates whether mTimestamp was generated
// automatically when the buffer was queued.
bool mIsAutoTimestamp;
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
+ // mDataSpace is the current dataSpace value for this buffer slot. This gets
+ // set by queueBuffer each time this slot is queued. The meaning of the
+ // dataSpace is format-dependent.
+ android_dataspace mDataSpace;
- // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
- int mSlot;
+ // mFrameNumber is the number of the queued frame for this slot.
+ union {
+ uint64_t mFrameNumber;
+ struct {
+ uint32_t mFrameNumberLo;
+ uint32_t mFrameNumberHi;
+ };
+ };
+
+ union {
+ // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
+ int mSlot;
+
+ // mBuf is the former name for mSlot
+ int mBuf;
+ };
// mIsDroppable whether this buffer was queued with the
// property that it can be replaced by a new buffer for the purpose of
@@ -97,6 +119,10 @@
// Indicates this buffer must be transformed by the inverse transform of the screen
// it is displayed onto. This is applied after mTransform.
bool mTransformToDisplayInverse;
+
+ // Describes the portion of the surface that has been modified since the
+ // previous frame
+ Region mSurfaceDamage;
};
} // namespace android
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index 5494ff1..56c7a3f 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -42,8 +42,6 @@
public:
typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
- typedef BufferQueue::BufferItem BufferItem;
-
enum { DEFAULT_MAX_BUFFERS = -1 };
enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
@@ -76,8 +74,8 @@
//
// If waitForFence is true, and the acquired BufferItem has a valid fence object,
// acquireBuffer will wait on the fence with no timeout before returning.
- status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen,
- bool waitForFence = true);
+ status_t acquireBuffer(BufferItem* item, nsecs_t presentWhen,
+ bool waitForFence = true);
// Returns an acquired buffer to the queue, allowing it to be reused. Since
// only a fixed number of buffers may be acquired at a time, old buffers
@@ -88,14 +86,6 @@
status_t releaseBuffer(const BufferItem &item,
const sp<Fence>& releaseFence = Fence::NO_FENCE);
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
};
} // namespace android
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 1188837..09300a2 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUE_H
#define ANDROID_GUI_BUFFERQUEUE_H
+#include <gui/BufferItem.h>
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
@@ -34,7 +35,7 @@
// Attempts at runtime to increase the number of buffers past this will fail.
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
// Used as a placeholder slot# when the value isn't pointing to an existing buffer.
- enum { INVALID_BUFFER_SLOT = IGraphicBufferConsumer::BufferItem::INVALID_BUFFER_SLOT };
+ enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };
// Alias to <IGraphicBufferConsumer.h> -- please scope from there in future code!
enum {
NO_BUFFER_AVAILABLE = IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
@@ -47,7 +48,6 @@
// for backward source compatibility
typedef ::android::ConsumerListener ConsumerListener;
- typedef IGraphicBufferConsumer::BufferItem BufferItem;
// ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
// reference to the actual consumer object. It forwards all calls to that
@@ -62,9 +62,10 @@
public:
ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
virtual ~ProxyConsumerListener();
- virtual void onFrameAvailable(const android::BufferItem& item);
- virtual void onBuffersReleased();
- virtual void onSidebandStreamChanged();
+ virtual void onFrameAvailable(const BufferItem& item) override;
+ virtual void onFrameReplaced(const BufferItem& item) override;
+ virtual void onBuffersReleased() override;
+ virtual void onSidebandStreamChanged() override;
private:
// mConsumerListener is a weak reference to the IConsumerListener. This is
// the raison d'etre of ProxyConsumerListener.
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index 1912ed0..cde302f 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -47,7 +47,7 @@
// returned. The presentation time is in nanoseconds, and the time base
// is CLOCK_MONOTONIC.
virtual status_t acquireBuffer(BufferItem* outBuffer,
- nsecs_t expectedPresent);
+ nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;
// See IGraphicBufferConsumer::detachBuffer
virtual status_t detachBuffer(int slot);
@@ -125,9 +125,15 @@
// setDefaultBufferFormat allows the BufferQueue to create
// GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat);
+ // in dequeueBuffer. The initial default is HAL_PIXEL_FORMAT_RGBA_8888.
+ virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat);
+
+ // setDefaultBufferDataSpace allows the BufferQueue to create
+ // GraphicBuffers of a defaultDataSpace if no data space is specified
+ // in queueBuffer.
+ // The initial default is HAL_DATASPACE_UNKNOWN
+ virtual status_t setDefaultBufferDataSpace(
+ android_dataspace defaultDataSpace);
// setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
// These are merged with the bits passed to dequeueBuffer. The values are
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 1050e3b..99134ea 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUECORE_H
#define ANDROID_GUI_BUFFERQUEUECORE_H
+#include <gui/BufferItem.h>
#include <gui/BufferQueueDefs.h>
#include <gui/BufferSlot.h>
@@ -29,11 +30,14 @@
#include <utils/Trace.h>
#include <utils/Vector.h>
-#define BQ_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define BQ_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define BQ_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define BQ_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define BQ_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
+#include <list>
+#include <set>
+
+#define BQ_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
+#define BQ_LOGD(x, ...) ALOGD("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
+#define BQ_LOGI(x, ...) ALOGI("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
+#define BQ_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
+#define BQ_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
#define ATRACE_BUFFER_INDEX(index) \
if (ATRACE_ENABLED()) { \
@@ -45,7 +49,6 @@
namespace android {
-class BufferItem;
class IConsumerListener;
class IGraphicBufferAlloc;
class IProducerListener;
@@ -58,7 +61,7 @@
public:
// Used as a placeholder slot number when the value isn't pointing to an
// existing buffer.
- enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem
+ enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };
// We reserve two slots in order to guarantee that the producer and
// consumer can run asynchronously.
@@ -123,6 +126,10 @@
// waitWhileAllocatingLocked blocks until mIsAllocating is false.
void waitWhileAllocatingLocked() const;
+ // validateConsistencyLocked ensures that the free lists are in sync with
+ // the information stored in mSlots
+ void validateConsistencyLocked() const;
+
// mAllocator is the connection to SurfaceFlinger that is used to allocate
// new GraphicBuffer objects.
sp<IGraphicBufferAlloc> mAllocator;
@@ -177,6 +184,14 @@
// mQueue is a FIFO of queued buffers used in synchronous mode.
Fifo mQueue;
+ // mFreeSlots contains all of the slots which are FREE and do not currently
+ // have a buffer attached
+ std::set<int> mFreeSlots;
+
+ // mFreeBuffers contains all of the slots which are FREE and currently have
+ // a buffer attached
+ std::list<int> mFreeBuffers;
+
// mOverrideMaxBufferCount is the limit on the number of buffers that will
// be allocated at one time. This value is set by the producer by calling
// setBufferCount. The default is 0, which means that the producer doesn't
@@ -199,15 +214,20 @@
// mDefaultBufferFormat can be set so it will override the buffer format
// when it isn't specified in dequeueBuffer.
- uint32_t mDefaultBufferFormat;
+ PixelFormat mDefaultBufferFormat;
// mDefaultWidth holds the default width of allocated buffers. It is used
// in dequeueBuffer if a width and height of 0 are specified.
- int mDefaultWidth;
+ uint32_t mDefaultWidth;
// mDefaultHeight holds the default height of allocated buffers. It is used
// in dequeueBuffer if a width and height of 0 are specified.
- int mDefaultHeight;
+ uint32_t mDefaultHeight;
+
+ // mDefaultBufferDataSpace holds the default dataSpace of queued buffers.
+ // It is used in queueBuffer if a dataspace of 0 (HAL_DATASPACE_UNKNOWN)
+ // is specified.
+ android_dataspace mDefaultBufferDataSpace;
// mDefaultMaxBufferCount is the default limit on the number of buffers that
// will be allocated at one time. This default limit is set by the consumer.
@@ -246,6 +266,20 @@
// mIsAllocatingCondition is a condition variable used by producers to wait until mIsAllocating
// becomes false.
mutable Condition mIsAllocatingCondition;
+
+ // mAllowAllocation determines whether dequeueBuffer is allowed to allocate
+ // new buffers
+ bool mAllowAllocation;
+
+ // mBufferAge tracks the age of the contents of the most recently dequeued
+ // buffer as the number of frames that have elapsed since it was last queued
+ uint64_t mBufferAge;
+
+ // mGenerationNumber stores the current generation number of the attached
+ // producer. Any attempt to attach a buffer with a different generation
+ // number will fail.
+ uint32_t mGenerationNumber;
+
}; // class BufferQueueCore
} // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index ed1056a..9754a89 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -73,9 +73,7 @@
// updateTexImage() is called. If width and height are both zero, the
// default values specified by setDefaultBufferSize() are used instead.
//
- // The pixel formats are enumerated in graphics.h, e.g.
- // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format
- // will be used.
+ // If the format is 0, the default format will be used.
//
// The usage argument specifies gralloc buffer usage flags. The values
// are enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER. These
@@ -93,8 +91,9 @@
//
// In both cases, the producer will need to call requestBuffer to get a
// GraphicBuffer handle for the returned slot.
- virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence, bool async,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+ virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
+ bool async, uint32_t width, uint32_t height, PixelFormat format,
+ uint32_t usage);
// See IGraphicBufferProducer::detachBuffer
virtual status_t detachBuffer(int slot);
@@ -171,7 +170,16 @@
// See IGraphicBufferProducer::allocateBuffers
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
+ PixelFormat format, uint32_t usage);
+
+ // See IGraphicBufferProducer::allowAllocation
+ virtual status_t allowAllocation(bool allow);
+
+ // See IGraphicBufferProducer::setGenerationNumber
+ virtual status_t setGenerationNumber(uint32_t generationNumber);
+
+ // See IGraphicBufferProducer::getConsumerName
+ virtual String8 getConsumerName() const override;
private:
// This is required by the IBinder::DeathRecipient interface
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index f7ab5ac..9307a26 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -38,15 +38,9 @@
protected ConsumerListener {
public:
struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. This means that frames that are queued
- // while in asynchronous mode only trigger the callback if no previous
- // frames are pending. Frames queued while in synchronous mode always
- // trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
+ // See IConsumerListener::onFrame{Available,Replaced}
virtual void onFrameAvailable(const BufferItem& item) = 0;
+ virtual void onFrameReplaced(const BufferItem& /* item */) {}
};
virtual ~ConsumerBase();
@@ -62,6 +56,9 @@
// or by OpenGL ES as a texture) then those buffer will remain allocated.
void abandon();
+ // Returns true if the ConsumerBase is in the 'abandoned' state
+ bool isAbandoned();
+
// set the name of the ConsumerBase that will be used to identify it in
// log messages.
void setName(const String8& name);
@@ -76,6 +73,18 @@
// when a new frame becomes available.
void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
+ // See IGraphicBufferConsumer::detachBuffer
+ status_t detachBuffer(int slot);
+
+ // See IGraphicBufferConsumer::setDefaultBufferSize
+ status_t setDefaultBufferSize(uint32_t width, uint32_t height);
+
+ // See IGraphicBufferConsumer::setDefaultBufferFormat
+ status_t setDefaultBufferFormat(PixelFormat defaultFormat);
+
+ // See IGraphicBufferConsumer::setDefaultBufferDataSpace
+ status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
+
private:
ConsumerBase(const ConsumerBase&);
void operator=(const ConsumerBase&);
@@ -101,14 +110,16 @@
// Implementation of the IConsumerListener interface. These
// calls are used to notify the ConsumerBase of asynchronous events in the
- // BufferQueue. The onFrameAvailable and onBuffersReleased methods should
- // not need to be overridden by derived classes, but if they are overridden
- // the ConsumerBase implementation must be called from the derived class.
- // The ConsumerBase version of onSidebandStreamChanged does nothing and can
- // be overriden by derived classes if they want the notification.
- virtual void onFrameAvailable(const BufferItem& item);
- virtual void onBuffersReleased();
- virtual void onSidebandStreamChanged();
+ // BufferQueue. The onFrameAvailable, onFrameReplaced, and
+ // onBuffersReleased methods should not need to be overridden by derived
+ // classes, but if they are overridden the ConsumerBase implementation must
+ // be called from the derived class. The ConsumerBase version of
+ // onSidebandStreamChanged does nothing and can be overriden by derived
+ // classes if they want the notification.
+ virtual void onFrameAvailable(const BufferItem& item) override;
+ virtual void onFrameReplaced(const BufferItem& item) override;
+ virtual void onBuffersReleased() override;
+ virtual void onSidebandStreamChanged() override;
// freeBufferLocked frees up the given buffer slot. If the slot has been
// initialized this will release the reference to the GraphicBuffer in that
@@ -153,8 +164,8 @@
// initialization that must take place the first time a buffer is assigned
// to a slot. If it is overridden the derived class's implementation must
// call ConsumerBase::acquireBufferLocked.
- virtual status_t acquireBufferLocked(IGraphicBufferConsumer::BufferItem *item,
- nsecs_t presentWhen);
+ virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0);
// releaseBufferLocked relinquishes control over a buffer, returning that
// control to the BufferQueue.
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index 4c6822a..3b07a31 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -53,6 +53,7 @@
uint32_t transform;
uint32_t scalingMode;
int64_t timestamp;
+ android_dataspace dataSpace;
uint64_t frameNumber;
// this is the same as format, except for formats that are compatible with
// a flexible format (e.g. HAL_PIXEL_FORMAT_YCbCr_420_888). In the latter
@@ -71,7 +72,7 @@
// Create a new CPU consumer. The maxLockedBuffers parameter specifies
// how many buffers can be locked for user access at the same time.
CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
- uint32_t maxLockedBuffers, bool controlledByApp = false);
+ size_t maxLockedBuffers, bool controlledByApp = false);
virtual ~CpuConsumer();
@@ -79,18 +80,6 @@
// log messages.
void setName(const String8& name);
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a width and height of zero is requested.
- // A call to setDefaultBufferSize() may trigger requestBuffers() to
- // be called from the client. Default size is 1x1.
- status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // setDefaultBufferFormat allows CpuConsumer's BufferQueue to create buffers
- // of a defaultFormat if no format is specified by producer. Formats are
- // enumerated in graphics.h; the initial default is
- // HAL_PIXEL_FORMAT_RGBA_8888.
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
// Gets the next graphics buffer from the producer and locks it for CPU use,
// filling out the passed-in locked buffer structure with the native pointer
// and metadata. Returns BAD_VALUE if no new buffer is available, and
@@ -110,9 +99,9 @@
private:
// Maximum number of buffers that can be locked at a time
- uint32_t mMaxLockedBuffers;
+ size_t mMaxLockedBuffers;
- status_t releaseAcquiredBufferLocked(int lockedIdx);
+ status_t releaseAcquiredBufferLocked(size_t lockedIdx);
virtual void freeBufferLocked(int slotIndex);
@@ -133,7 +122,7 @@
Vector<AcquiredBuffer> mAcquiredBuffers;
// Count of currently locked buffers
- uint32_t mCurrentLockedBuffers;
+ size_t mCurrentLockedBuffers;
};
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index f91fe46..c35c7be 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -150,7 +150,7 @@
//
// The frame number is an incrementing counter set to 0 at the creation of
// the BufferQueue associated with this consumer.
- int64_t getFrameNumber();
+ uint64_t getFrameNumber();
// setDefaultBufferSize is used to set the size of buffers returned by
// requestBuffers when a with and height of zero is requested.
@@ -197,7 +197,8 @@
// These functions call the corresponding BufferQueue implementation
// so the refactoring can proceed smoothly
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
+ status_t setDefaultBufferFormat(PixelFormat defaultFormat);
+ status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
status_t setConsumerUsageBits(uint32_t usage);
status_t setTransformHint(uint32_t hint);
@@ -240,8 +241,8 @@
// acquireBufferLocked overrides the ConsumerBase method to update the
// mEglSlots array in addition to the ConsumerBase behavior.
- virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item,
- nsecs_t presentWhen);
+ virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) override;
// releaseBufferLocked overrides the ConsumerBase method to update the
// mEglSlots array in addition to the ConsumerBase.
@@ -254,12 +255,12 @@
return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
}
- static bool isExternalFormat(uint32_t format);
+ static bool isExternalFormat(PixelFormat format);
// This releases the buffer in the slot referenced by mCurrentTexture,
// then updates state to refer to the BufferItem, which must be a
// newly-acquired buffer.
- status_t updateAndReleaseLocked(const BufferQueue::BufferItem& item);
+ status_t updateAndReleaseLocked(const BufferItem& item);
// Binds mTexName and the current buffer to mTexTarget. Uses
// mCurrentTexture if it's set, mCurrentTextureImage if not. If the
@@ -391,7 +392,7 @@
// mCurrentFrameNumber is the frame counter for the current texture.
// It gets set each time updateTexImage is called.
- int64_t mCurrentFrameNumber;
+ uint64_t mCurrentFrameNumber;
uint32_t mDefaultWidth, mDefaultHeight;
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h
index b08750c..69fe51e 100644
--- a/include/gui/GraphicBufferAlloc.h
+++ b/include/gui/GraphicBufferAlloc.h
@@ -33,8 +33,9 @@
public:
GraphicBufferAlloc();
virtual ~GraphicBufferAlloc();
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error);
+ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t usage,
+ status_t* error);
};
diff --git a/include/gui/IGraphicBufferAlloc.h b/include/gui/IGraphicBufferAlloc.h
index cee41d9..f3c46ec 100644
--- a/include/gui/IGraphicBufferAlloc.h
+++ b/include/gui/IGraphicBufferAlloc.h
@@ -45,10 +45,10 @@
class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
{
public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 15f51fe..60ec9cc 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -25,6 +25,7 @@
#include <utils/Timers.h>
#include <binder/IInterface.h>
+#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <EGL/egl.h>
@@ -33,6 +34,7 @@
namespace android {
// ----------------------------------------------------------------------------
+class BufferItem;
class Fence;
class GraphicBuffer;
class IConsumerListener;
@@ -41,71 +43,6 @@
class IGraphicBufferConsumer : public IInterface {
public:
-
- // public facing structure for BufferSlot
- class BufferItem : public Flattenable<BufferItem> {
- friend class Flattenable<BufferItem>;
- size_t getPodSize() const;
- size_t getFlattenedSize() const;
- size_t getFdCount() const;
- status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
- status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
-
- public:
- // The default value of mBuf, used to indicate this doesn't correspond to a slot.
- enum { INVALID_BUFFER_SLOT = -1 };
- BufferItem();
-
- // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
- // if the buffer in this slot has been acquired in the past (see
- // BufferSlot.mAcquireCalled).
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mFence is a fence that will signal when the buffer is idle.
- sp<Fence> mFence;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- // refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- // refer to NATIVE_WINDOW_SCALING_* in <window.h>
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued. This value
- // is guaranteed to be monotonically increasing for each newly
- // acquired buffer.
- int64_t mTimestamp;
-
- // mIsAutoTimestamp indicates whether mTimestamp was generated
- // automatically when the buffer was queued.
- bool mIsAutoTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mBuf is the slot index of this buffer (default INVALID_BUFFER_SLOT).
- int mBuf;
-
- // mIsDroppable whether this buffer was queued with the
- // property that it can be replaced by a new buffer for the purpose of
- // making sure dequeueBuffer() won't block.
- // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
- // was queued.
- bool mIsDroppable;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates this buffer must be transformed by the inverse transform of the screen
- // it is displayed onto. This is applied after mTransform.
- bool mTransformToDisplayInverse;
- };
-
enum {
// Returned by releaseBuffer, after which the consumer must
// free any references to the just-released buffer that it might have.
@@ -132,6 +69,12 @@
// returned. The presentation time is in nanoseconds, and the time base
// is CLOCK_MONOTONIC.
//
+ // If maxFrameNumber is non-zero, it indicates that acquireBuffer should
+ // only return a buffer with a frame number less than or equal to
+ // maxFrameNumber. If no such frame is available (such as when a buffer has
+ // been replaced but the consumer has not received the onFrameReplaced
+ // callback), then PRESENT_LATER will be returned.
+ //
// Return of NO_ERROR means the operation completed as normal.
//
// Return of a positive value means the operation could not be completed
@@ -141,7 +84,8 @@
//
// Return of a negative value means an error has occurred:
// * INVALID_OPERATION - too many buffers have been acquired
- virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0;
+ virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) = 0;
// detachBuffer attempts to remove all ownership of the buffer in the given
// slot from the buffer queue. If this call succeeds, the slot will be
@@ -166,7 +110,8 @@
// will be deallocated as stale.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - outSlot or buffer were NULL
+ // * BAD_VALUE - outSlot or buffer were NULL, or the generation number of
+ // the buffer did not match the buffer queue.
// * INVALID_OPERATION - cannot attach the buffer because it would cause too
// many buffers to be acquired.
// * NO_MEMORY - no free slots available
@@ -280,11 +225,19 @@
// setDefaultBufferFormat allows the BufferQueue to create
// GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer. Formats are enumerated in graphics.h; the
- // initial default is HAL_PIXEL_FORMAT_RGBA_8888.
+ // in dequeueBuffer.
+ // The initial default is PIXEL_FORMAT_RGBA_8888.
//
// Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) = 0;
+ virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) = 0;
+
+ // setDefaultBufferDataSpace is a request to the producer to provide buffers
+ // of the indicated dataSpace. The producer may ignore this request.
+ // The initial default is HAL_DATASPACE_UNKNOWN.
+ //
+ // Return of a value other than NO_ERROR means an unknown error has occurred.
+ virtual status_t setDefaultBufferDataSpace(
+ android_dataspace defaultDataSpace) = 0;
// setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
// These are merged with the bits passed to dequeueBuffer. The values are
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 4e9e810..9530de1 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -28,6 +28,7 @@
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
+#include <ui/Region.h>
namespace android {
// ----------------------------------------------------------------------------
@@ -134,9 +135,7 @@
// updateTexImage() is called. If width and height are both zero, the
// default values specified by setDefaultBufferSize() are used instead.
//
- // The pixel formats are enumerated in <graphics.h>, e.g.
- // HAL_PIXEL_FORMAT_RGBA_8888. If the format is 0, the default format
- // will be used.
+ // If the format is 0, the default format will be used.
//
// The usage argument specifies gralloc buffer usage flags. The values
// are enumerated in <gralloc.h>, e.g. GRALLOC_USAGE_HW_RENDER. These
@@ -167,7 +166,7 @@
// All other negative values are an unknown error returned downstream
// from the graphics allocator (typically errno).
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) = 0;
// detachBuffer attempts to remove all ownership of the buffer in the given
// slot from the buffer queue. If this call succeeds, the slot will be
@@ -219,8 +218,9 @@
//
// Return of a negative value means an error has occurred:
// * NO_INIT - the buffer queue has been abandoned.
- // * BAD_VALUE - outSlot or buffer were NULL or invalid combination of
- // async mode and buffer count override.
+ // * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
+ // async mode and buffer count override, or the generation
+ // number of the buffer did not match the buffer queue.
// * INVALID_OPERATION - cannot attach the buffer because it would cause
// too many buffers to be dequeued, either because
// the producer already has a single buffer dequeued
@@ -267,6 +267,7 @@
inline QueueBufferInput(const Parcel& parcel);
// timestamp - a monotonically increasing value in nanoseconds
// isAutoTimestamp - if the timestamp was synthesized at queue time
+ // dataSpace - description of the contents, interpretation depends on format
// crop - a crop rectangle that's used as a hint to the consumer
// scalingMode - a set of flags from NATIVE_WINDOW_SCALING_* in <window.h>
// transform - a set of flags from NATIVE_WINDOW_TRANSFORM_* in <window.h>
@@ -276,17 +277,21 @@
// sticky - the sticky transform set in Surface (only used by the LEGACY
// camera mode).
inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
- const Rect& crop, int scalingMode, uint32_t transform, bool async,
- const sp<Fence>& fence, uint32_t sticky = 0)
- : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
- scalingMode(scalingMode), transform(transform), stickyTransform(sticky),
- async(async), fence(fence) { }
+ android_dataspace dataSpace, const Rect& crop, int scalingMode,
+ uint32_t transform, bool async, const sp<Fence>& fence,
+ uint32_t sticky = 0)
+ : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp),
+ dataSpace(dataSpace), crop(crop), scalingMode(scalingMode),
+ transform(transform), stickyTransform(sticky),
+ async(async), fence(fence), surfaceDamage() { }
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
- Rect* outCrop, int* outScalingMode, uint32_t* outTransform,
- bool* outAsync, sp<Fence>* outFence,
+ android_dataspace* outDataSpace,
+ Rect* outCrop, int* outScalingMode,
+ uint32_t* outTransform, bool* outAsync, sp<Fence>* outFence,
uint32_t* outStickyTransform = NULL) const {
*outTimestamp = timestamp;
*outIsAutoTimestamp = bool(isAutoTimestamp);
+ *outDataSpace = dataSpace;
*outCrop = crop;
*outScalingMode = scalingMode;
*outTransform = transform;
@@ -303,15 +308,20 @@
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
+ const Region& getSurfaceDamage() const { return surfaceDamage; }
+ void setSurfaceDamage(const Region& damage) { surfaceDamage = damage; }
+
private:
int64_t timestamp;
int isAutoTimestamp;
+ android_dataspace dataSpace;
Rect crop;
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
int async;
sp<Fence> fence;
+ Region surfaceDamage;
};
// QueueBufferOutput must be a POD structure
@@ -448,7 +458,31 @@
// dequeueBuffer. If there are already the maximum number of buffers
// allocated, this function has no effect.
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage) = 0;
+ PixelFormat format, uint32_t usage) = 0;
+
+ // Sets whether dequeueBuffer is allowed to allocate new buffers.
+ //
+ // Normally dequeueBuffer does not discriminate between free slots which
+ // already have an allocated buffer and those which do not, and will
+ // allocate a new buffer if the slot doesn't have a buffer or if the slot's
+ // buffer doesn't match the requested size, format, or usage. This method
+ // allows the producer to restrict the eligible slots to those which already
+ // have an allocated buffer of the correct size, format, and usage. If no
+ // eligible slot is available, dequeueBuffer will block or return an error
+ // as usual.
+ virtual status_t allowAllocation(bool allow) = 0;
+
+ // Sets the current generation number of the BufferQueue.
+ //
+ // This generation number will be inserted into any buffers allocated by the
+ // BufferQueue, and any attempts to attach a buffer with a different
+ // generation number will fail. Buffers already in the queue are not
+ // affected and will retain their current generation number. The generation
+ // number defaults to 0.
+ virtual status_t setGenerationNumber(uint32_t generationNumber) = 0;
+
+ // Returns the name of the connected consumer.
+ virtual String8 getConsumerName() const = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
index 9c8afc5..3dca2a3 100644
--- a/include/gui/ISensorServer.h
+++ b/include/gui/ISensorServer.h
@@ -30,14 +30,17 @@
class Sensor;
class ISensorEventConnection;
+class String8;
class ISensorServer : public IInterface
{
public:
DECLARE_META_INTERFACE(SensorServer);
- virtual Vector<Sensor> getSensorList() = 0;
- virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
+ virtual Vector<Sensor> getSensorList(const String16& opPackageName) = 0;
+ virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
+ int mode, const String16& opPackageName) = 0;
+ virtual int32_t isDataInjectionEnabled() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 51717a4..8c3d49e 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -28,7 +28,6 @@
#include <binder/IInterface.h>
#include <ui/FrameStats.h>
-#include <ui/PixelFormat.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposerClient.h>
@@ -39,7 +38,7 @@
class ComposerState;
class DisplayState;
struct DisplayInfo;
-class DisplayStatInfo;
+struct DisplayStatInfo;
class IDisplayEventConnection;
class IMemoryHeap;
class Rect;
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 28a08e2..8142be6 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -67,12 +67,14 @@
int32_t getMinDelay() const;
nsecs_t getMinDelayNs() const;
int32_t getVersion() const;
- int32_t getFifoReservedEventCount() const;
- int32_t getFifoMaxEventCount() const;
+ uint32_t getFifoReservedEventCount() const;
+ uint32_t getFifoMaxEventCount() const;
const String8& getStringType() const;
const String8& getRequiredPermission() const;
+ bool isRequiredPermissionRuntime() const;
+ int32_t getRequiredAppOp() const;
int32_t getMaxDelay() const;
- int32_t getFlags() const;
+ uint32_t getFlags() const;
bool isWakeUpSensor() const;
int32_t getReportingMode() const;
@@ -93,12 +95,14 @@
float mPower;
int32_t mMinDelay;
int32_t mVersion;
- int32_t mFifoReservedEventCount;
- int32_t mFifoMaxEventCount;
+ uint32_t mFifoReservedEventCount;
+ uint32_t mFifoMaxEventCount;
String8 mStringType;
String8 mRequiredPermission;
+ bool mRequiredPermissionRuntime = false;
+ int32_t mRequiredAppOp;
int32_t mMaxDelay;
- int32_t mFlags;
+ uint32_t mFlags;
static void flattenString8(void*& buffer, size_t& size, const String8& string8);
static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8);
};
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index 02b3d38..e5b9fc5 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -23,6 +23,7 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
+#include <utils/String16.h>
#include <gui/BitTube.h>
@@ -52,7 +53,7 @@
enum { MAX_RECEIVE_BUFFER_EVENT_COUNT = 256 };
- SensorEventQueue(const sp<ISensorEventConnection>& connection);
+ SensorEventQueue(const sp<ISensorEventConnection>& connection);
virtual ~SensorEventQueue();
virtual void onFirstRef();
@@ -77,6 +78,8 @@
status_t flush() const;
// Send an ack for every wake_up sensor event that is set to WAKE_UP_SENSOR_EVENT_NEEDS_ACK.
void sendAck(const ASensorEvent* events, int count);
+
+ status_t injectSensorEvent(const ASensorEvent& event);
private:
sp<Looper> getLooper() const;
sp<ISensorEventConnection> mSensorEventConnection;
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 3176462..3796067 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -17,15 +17,20 @@
#ifndef ANDROID_GUI_SENSOR_MANAGER_H
#define ANDROID_GUI_SENSOR_MANAGER_H
+#include <map>
+
#include <stdint.h>
#include <sys/types.h>
#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>
#include <utils/Vector.h>
+#include <utils/String8.h>
#include <gui/SensorEventQueue.h>
@@ -40,20 +45,69 @@
class ISensorServer;
class Sensor;
class SensorEventQueue;
-
// ----------------------------------------------------------------------------
class SensorManager :
- public ASensorManager,
- public Singleton<SensorManager>
+ public ASensorManager
{
public:
- SensorManager();
+ static SensorManager& getInstanceForPackage(const String16& packageName) {
+ Mutex::Autolock _l(sLock);
+
+ SensorManager* sensorManager;
+ std::map<String16, SensorManager*>::iterator iterator =
+ sPackageInstances.find(packageName);
+
+ if (iterator != sPackageInstances.end()) {
+ sensorManager = iterator->second;
+ } else {
+ String16 opPackageName = packageName;
+
+ // It is possible that the calling code has no access to the package name.
+ // In this case we will get the packages for the calling UID and pick the
+ // first one for attributing the app op. This will work correctly for
+ // runtime permissions as for legacy apps we will toggle the app op for
+ // all packages in the UID. The caveat is that the operation may be attributed
+ // to the wrong package and stats based on app ops may be slightly off.
+ if (opPackageName.size() <= 0) {
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+ if (binder != 0) {
+ const uid_t uid = IPCThreadState::self()->getCallingUid();
+ Vector<String16> packages;
+ interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages);
+ if (!packages.isEmpty()) {
+ opPackageName = packages[0];
+ } else {
+ ALOGE("No packages for calling UID");
+ }
+ } else {
+ ALOGE("Cannot get permission service");
+ }
+ }
+
+ sensorManager = new SensorManager(opPackageName);
+
+ // If we had no package name, we looked it up from the UID and the sensor
+ // manager instance we created should also be mapped to the empty package
+ // name, to avoid looking up the packages for a UID and get the same result.
+ if (packageName.size() <= 0) {
+ sPackageInstances.insert(std::make_pair(String16(), sensorManager));
+ }
+
+ // Stash the per package sensor manager.
+ sPackageInstances.insert(std::make_pair(opPackageName, sensorManager));
+ }
+
+ return *sensorManager;
+ }
+
+ SensorManager(const String16& opPackageName);
~SensorManager();
ssize_t getSensorList(Sensor const* const** list) const;
Sensor const* getDefaultSensor(int type);
- sp<SensorEventQueue> createEventQueue();
+ sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
+ bool isDataInjectionEnabled();
private:
// DeathRecipient interface
@@ -62,11 +116,15 @@
status_t assertStateLocked() const;
private:
+ static Mutex sLock;
+ static std::map<String16, SensorManager*> sPackageInstances;
+
mutable Mutex mLock;
mutable sp<ISensorServer> mSensorServer;
mutable Sensor const** mSensorList;
mutable Vector<Sensor> mSensors;
mutable sp<IBinder::DeathRecipient> mDeathObserver;
+ const String16 mOpPackageName;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index f2cf018..72f1067 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -101,6 +101,14 @@
*/
void allocateBuffers();
+ /* Sets the generation number on the IGraphicBufferProducer and updates the
+ * generation number on any buffers attached to the Surface after this call.
+ * See IGBP::setGenerationNumber for more information. */
+ status_t setGenerationNumber(uint32_t generationNumber);
+
+ // See IGraphicBufferProducer::getConsumerName
+ String8 getConsumerName() const;
+
protected:
virtual ~Surface();
@@ -146,6 +154,8 @@
int dispatchLock(va_list args);
int dispatchUnlockAndPost(va_list args);
int dispatchSetSidebandStream(va_list args);
+ int dispatchSetBuffersDataSpace(va_list args);
+ int dispatchSetSurfaceDamage(va_list args);
protected:
virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
@@ -160,20 +170,27 @@
virtual int connect(int api);
virtual int disconnect(int api);
virtual int setBufferCount(int bufferCount);
- virtual int setBuffersDimensions(int w, int h);
- virtual int setBuffersUserDimensions(int w, int h);
- virtual int setBuffersFormat(int format);
+ virtual int setBuffersDimensions(uint32_t width, uint32_t height);
+ virtual int setBuffersUserDimensions(uint32_t width, uint32_t height);
+ virtual int setBuffersFormat(PixelFormat format);
virtual int setScalingMode(int mode);
- virtual int setBuffersTransform(int transform);
- virtual int setBuffersStickyTransform(int transform);
+ virtual int setBuffersTransform(uint32_t transform);
+ virtual int setBuffersStickyTransform(uint32_t transform);
virtual int setBuffersTimestamp(int64_t timestamp);
+ virtual int setBuffersDataSpace(android_dataspace dataSpace);
virtual int setCrop(Rect const* rect);
virtual int setUsage(uint32_t reqUsage);
+ virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
public:
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
virtual int unlockAndPost();
+ virtual int connect(int api, const sp<IProducerListener>& listener);
+ virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence);
+ virtual int attachBuffer(ANativeWindowBuffer*);
+
protected:
enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
@@ -211,7 +228,7 @@
// mReqFormat is the buffer pixel format that will be requested at the next
// deuque operation. It is initialized to PIXEL_FORMAT_RGBA_8888.
- uint32_t mReqFormat;
+ PixelFormat mReqFormat;
// mReqUsage is the set of buffer usage flags that will be requested
// at the next deuque operation. It is initialized to 0.
@@ -222,6 +239,11 @@
// a timestamp is auto-generated when queueBuffer is called.
int64_t mTimestamp;
+ // mDataSpace is the buffer dataSpace that will be used for the next buffer
+ // queue operation. It defaults to HAL_DATASPACE_UNKNOWN, which
+ // means that the buffer contains some type of color data.
+ android_dataspace mDataSpace;
+
// mCrop is the crop rectangle that will be used for the next buffer
// that gets queued. It is set by calling setCrop.
Rect mCrop;
@@ -240,23 +262,23 @@
// from being set by the compositor.
uint32_t mStickyTransform;
- // mDefaultWidth is default width of the buffers, regardless of the
- // native_window_set_buffers_dimensions call.
- uint32_t mDefaultWidth;
+ // mDefaultWidth is default width of the buffers, regardless of the
+ // native_window_set_buffers_dimensions call.
+ uint32_t mDefaultWidth;
- // mDefaultHeight is default height of the buffers, regardless of the
- // native_window_set_buffers_dimensions call.
- uint32_t mDefaultHeight;
+ // mDefaultHeight is default height of the buffers, regardless of the
+ // native_window_set_buffers_dimensions call.
+ uint32_t mDefaultHeight;
- // mUserWidth, if non-zero, is an application-specified override
- // of mDefaultWidth. This is lower priority than the width set by
- // native_window_set_buffers_dimensions.
- uint32_t mUserWidth;
+ // mUserWidth, if non-zero, is an application-specified override
+ // of mDefaultWidth. This is lower priority than the width set by
+ // native_window_set_buffers_dimensions.
+ uint32_t mUserWidth;
- // mUserHeight, if non-zero, is an application-specified override
- // of mDefaultHeight. This is lower priority than the height set
- // by native_window_set_buffers_dimensions.
- uint32_t mUserHeight;
+ // mUserHeight, if non-zero, is an application-specified override
+ // of mDefaultHeight. This is lower priority than the height set
+ // by native_window_set_buffers_dimensions.
+ uint32_t mUserHeight;
// mTransformHint is the transform probably applied to buffers of this
// window. this is only a hint, actual transform may differ.
@@ -284,8 +306,17 @@
sp<GraphicBuffer> mPostedBuffer;
bool mConnectedToCpu;
- // must be accessed from lock/unlock thread only
+ // When a CPU producer is attached, this reflects the region that the
+ // producer wished to update as well as whether the Surface was able to copy
+ // the previous buffer back to allow a partial update.
+ //
+ // When a non-CPU producer is attached, this reflects the surface damage
+ // (the change since the previous frame) passed in by the producer.
Region mDirtyRegion;
+
+ // Stores the current generation number. See setGenerationNumber and
+ // IGraphicBufferProducer::setGenerationNumber for more information.
+ uint32_t mGenerationNumber;
};
}; // namespace android
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 4cbfc09..37d953e 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -127,7 +127,7 @@
status_t show(const sp<IBinder>& id);
status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
- status_t setLayer(const sp<IBinder>& id, int32_t layer);
+ status_t setLayer(const sp<IBinder>& id, uint32_t layer);
status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f);
status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dsdy, float dtdy);
status_t setPosition(const sp<IBinder>& id, float x, float y);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 84fb9f9..9f62f7c 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -57,8 +57,8 @@
// release surface data from java
void clear();
- status_t setLayerStack(int32_t layerStack);
- status_t setLayer(int32_t layer);
+ status_t setLayerStack(uint32_t layerStack);
+ status_t setLayer(uint32_t layer);
status_t setPosition(float x, float y);
status_t setSize(uint32_t w, uint32_t h);
status_t hide();
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
new file mode 100644
index 0000000..629310f
--- /dev/null
+++ b/include/input/IInputFlinger.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _LIBINPUT_IINPUT_FLINGER_H
+#define _LIBINPUT_IINPUT_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+/*
+ * This class defines the Binder IPC interface for accessing various
+ * InputFlinger features.
+ */
+class IInputFlinger : public IInterface {
+public:
+ DECLARE_META_INTERFACE(InputFlinger);
+};
+
+
+/**
+ * Binder implementation.
+ */
+class BnInputFlinger : public BnInterface<IInputFlinger> {
+public:
+ enum {
+ DO_SOMETHING_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ };
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // _LIBINPUT_IINPUT_FLINGER_H
diff --git a/include/input/Input.h b/include/input/Input.h
index c360f63..4a67f47 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -379,6 +379,12 @@
inline int32_t getButtonState() const { return mButtonState; }
+ inline int32_t setButtonState(int32_t buttonState) { mButtonState = buttonState; }
+
+ inline int32_t getActionButton() const { return mActionButton; }
+
+ inline void setActionButton(int32_t button) { mActionButton = button; }
+
inline float getXOffset() const { return mXOffset; }
inline float getYOffset() const { return mYOffset; }
@@ -532,6 +538,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t actionButton,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
@@ -584,6 +591,7 @@
protected:
int32_t mAction;
+ int32_t mActionButton;
int32_t mFlags;
int32_t mEdgeFlags;
int32_t mMetaState;
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index adf9fb9..1ea69d3 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -73,7 +73,8 @@
};
void initialize(int32_t id, int32_t generation, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal);
+ const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
+ bool hasMic);
inline int32_t getId() const { return mId; }
inline int32_t getControllerNumber() const { return mControllerNumber; }
@@ -84,6 +85,7 @@
return mAlias.isEmpty() ? mIdentifier.name : mAlias;
}
inline bool isExternal() const { return mIsExternal; }
+ inline bool hasMic() const { return mHasMic; }
inline uint32_t getSources() const { return mSources; }
const MotionRange* getMotionRange(int32_t axis, uint32_t source) const;
@@ -121,6 +123,7 @@
InputDeviceIdentifier mIdentifier;
String8 mAlias;
bool mIsExternal;
+ bool mHasMic;
uint32_t mSources;
int32_t mKeyboardType;
sp<KeyCharacterMap> mKeyCharacterMap;
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index 8a339f7..a38de00 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -299,6 +299,10 @@
DEFINE_KEYCODE(TV_MEDIA_CONTEXT_MENU),
DEFINE_KEYCODE(TV_TIMER_PROGRAMMING),
DEFINE_KEYCODE(HELP),
+ DEFINE_KEYCODE(NAVIGATE_PREVIOUS),
+ DEFINE_KEYCODE(NAVIGATE_NEXT),
+ DEFINE_KEYCODE(NAVIGATE_IN),
+ DEFINE_KEYCODE(NAVIGATE_OUT),
DEFINE_KEYCODE(STEM_PRIMARY),
DEFINE_KEYCODE(STEM_1),
DEFINE_KEYCODE(STEM_2),
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index e7e383b..f31bcea 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -84,6 +84,7 @@
int32_t deviceId;
int32_t source;
int32_t action;
+ int32_t actionButton;
int32_t flags;
int32_t metaState;
int32_t buttonState;
@@ -95,7 +96,7 @@
float yPrecision;
uint32_t pointerCount;
// Note that PointerCoords requires 8 byte alignment.
- struct Pointer{
+ struct Pointer {
PointerProperties properties;
PointerCoords coords;
} pointers[MAX_POINTERS];
@@ -232,6 +233,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t actionButton,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 49939fd..272881b 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -80,7 +80,10 @@
kDrmPluginEventProvisionRequired = 1,
kDrmPluginEventKeyNeeded,
kDrmPluginEventKeyExpired,
- kDrmPluginEventVendorDefined
+ kDrmPluginEventVendorDefined,
+ kDrmPluginEventSessionReclaimed,
+ kDrmPluginEventExpirationUpdate,
+ kDrmPluginEventKeysChange,
};
// Drm keys can be for offline content or for online streaming.
@@ -93,6 +96,33 @@
kKeyType_Release
};
+ // Enumerate KeyRequestTypes to allow an app to determine the
+ // type of a key request returned from getKeyRequest.
+ enum KeyRequestType {
+ kKeyRequestType_Unknown,
+ kKeyRequestType_Initial,
+ kKeyRequestType_Renewal,
+ kKeyRequestType_Release
+ };
+
+ // Enumerate KeyStatusTypes which indicate the state of a key
+ enum KeyStatusType
+ {
+ kKeyStatusType_Usable,
+ kKeyStatusType_Expired,
+ kKeyStatusType_OutputNotAllowed,
+ kKeyStatusType_StatusPending,
+ kKeyStatusType_InternalError
+ };
+
+ // Used by sendKeysChange to report the usability status of each
+ // key to the app.
+ struct KeyStatus
+ {
+ Vector<uint8_t> mKeyId;
+ KeyStatusType mType;
+ };
+
DrmPlugin() {}
virtual ~DrmPlugin() {}
@@ -135,7 +165,8 @@
Vector<uint8_t> const &initData,
String8 const &mimeType, KeyType keyType,
KeyedVector<String8, String8> const &optionalParameters,
- Vector<uint8_t> &request, String8 &defaultUrl) = 0;
+ Vector<uint8_t> &request, String8 &defaultUrl,
+ KeyRequestType *keyRequestType) = 0;
//
// After a key response is received by the app, it is provided to the
@@ -315,11 +346,18 @@
}
protected:
- // Plugins call sendEvent to deliver events to the java app
+ // Plugins call these methods to deliver events to the java app
void sendEvent(EventType eventType, int extra,
Vector<uint8_t> const *sessionId,
Vector<uint8_t> const *data);
+ void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+ int64_t expiryTimeInMS);
+
+ void sendKeysChange(Vector<uint8_t> const *sessionId,
+ Vector<DrmPlugin::KeyStatus> const *keyStatusList,
+ bool hasNewUsableKey);
+
private:
Mutex mEventLock;
sp<DrmPluginListener> mListener;
@@ -331,14 +369,20 @@
{
public:
virtual void sendEvent(DrmPlugin::EventType eventType, int extra,
- Vector<uint8_t> const *sesionId,
+ Vector<uint8_t> const *sessionId,
Vector<uint8_t> const *data) = 0;
+
+ virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+ int64_t expiryTimeInMS) = 0;
+
+ virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
+ Vector<DrmPlugin::KeyStatus> const *keyStatusList,
+ bool hasNewUsableKey) = 0;
};
inline void DrmPlugin::sendEvent(EventType eventType, int extra,
Vector<uint8_t> const *sessionId,
Vector<uint8_t> const *data) {
-
mEventLock.lock();
sp<DrmPluginListener> listener = mListener;
mEventLock.unlock();
@@ -348,6 +392,28 @@
}
}
+ inline void DrmPlugin::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+ int64_t expiryTimeInMS) {
+ mEventLock.lock();
+ sp<DrmPluginListener> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+ }
+ }
+
+ inline void DrmPlugin::sendKeysChange(Vector<uint8_t> const *sessionId,
+ Vector<DrmPlugin::KeyStatus> const *keyStatusList,
+ bool hasNewUsableKey) {
+ mEventLock.lock();
+ sp<DrmPluginListener> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+ }
+ }
} // namespace android
#endif // DRM_API_H_
diff --git a/include/media/hardware/CryptoAPI.h b/include/media/hardware/CryptoAPI.h
index c800825..3e3257f 100644
--- a/include/media/hardware/CryptoAPI.h
+++ b/include/media/hardware/CryptoAPI.h
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+#include <media/stagefright/MediaErrors.h>
#include <utils/Errors.h>
+#include <utils/Vector.h>
#ifndef CRYPTO_API_H_
@@ -68,7 +70,18 @@
// the resolution of the video being decrypted. The media player should
// call this method when the resolution is determined and any time it
// is subsequently changed.
- virtual void notifyResolution(uint32_t width, uint32_t height) {}
+
+ virtual void notifyResolution(uint32_t /* width */, uint32_t /* height */) {}
+
+ // A MediaDrm session may be associated with a MediaCrypto session. The
+ // associated MediaDrm session is used to load decryption keys
+ // into the crypto/drm plugin. The keys are then referenced by key-id
+ // in the 'key' parameter to the decrypt() method.
+ // Should return NO_ERROR on success, ERROR_DRM_SESSION_NOT_OPENED if
+ // the session is not opened and a code from MediaErrors.h otherwise.
+ virtual status_t setMediaDrmSession(const Vector<uint8_t> & /*sessionId */) {
+ return ERROR_UNSUPPORTED;
+ }
// If the error returned falls into the range
// ERROR_DRM_VENDOR_MIN..ERROR_DRM_VENDOR_MAX, errorDetailMsg should be
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index d5f42be..1008c22 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -52,9 +52,9 @@
OMX_BOOL enable;
};
-// A pointer to this struct is passed to OMX_SetParameter() when the extension
-// index "OMX.google.android.index.storeMetaDataInBuffers"
-// is given.
+// A pointer to this struct is passed to OMX_SetParameter() when the extension index
+// "OMX.google.android.index.storeMetaDataInBuffers" or
+// "OMX.google.android.index.storeANWBufferInMetadata" is given.
//
// When meta data is stored in the video buffers passed between OMX clients
// and OMX components, interpretation of the buffer data is up to the
@@ -62,19 +62,33 @@
// some information helpful for the receiver to locate the actual data.
// The buffer receiver thus needs to know how to interpret what is stored
// in these buffers, with mechanisms pre-determined externally. How to
-// interpret the meta data is outside of the scope of this method.
+// interpret the meta data is outside of the scope of this parameter.
//
-// Currently, this is specifically used to pass meta data from video source
-// (camera component, for instance) to video encoder to avoid memcpying of
-// input video frame data. To do this, bStoreMetaData is set to OMX_TRUE.
-// If bStoreMetaData is set to false, real YUV frame data will be stored
-// in the buffers. In addition, if no OMX_SetParameter() call is made
-// with the corresponding extension index, real YUV data is stored
-// in the buffers.
+// Currently, this is used to pass meta data from video source (camera component, for instance) to
+// video encoder to avoid memcpying of input video frame data, as well as to pass dynamic output
+// buffer to video decoder. To do this, bStoreMetaData is set to OMX_TRUE.
//
-// For video decoder output port, the metadata buffer layout is defined below.
+// If bStoreMetaData is set to false, real YUV frame data will be stored in input buffers, and
+// the output buffers contain either real YUV frame data, or are themselves native handles as
+// directed by enable/use-android-native-buffer parameter settings.
+// In addition, if no OMX_SetParameter() call is made on a port with the corresponding extension
+// index, the component should not assume that the client is not using metadata mode for the port.
//
-// Metadata buffers are registered with the component using UseBuffer calls.
+// If the component supports this using the "OMX.google.android.index.storeANWBufferInMetadata"
+// extension and bStoreMetaData is set to OMX_TRUE, data is passed using the VideoNativeMetadata
+// layout as defined below. Each buffer will be accompanied by a fence. The fence must signal
+// before the buffer can be used (e.g. read from or written into). When returning such buffer to
+// the client, component must provide a new fence that must signal before the returned buffer can
+// be used (e.g. read from or written into). The component owns the incoming fenceFd, and must close
+// it when fence has signaled. The client will own and close the returned fence file descriptor.
+//
+// If the component supports this using the "OMX.google.android.index.storeMetaDataInBuffers"
+// extension and bStoreMetaData is set to OMX_TRUE, data is passed using VideoGrallocMetadata
+// (the layout of which is the VideoGrallocMetadata defined below). Camera input can be also passed
+// as "CameraSource", the layout of which is vendor dependent.
+//
+// Metadata buffers are registered with the component using UseBuffer calls, or can be allocated
+// by the component for encoder-metadata-output buffers.
struct StoreMetaDataInBuffersParams {
OMX_U32 nSize;
OMX_VERSIONTYPE nVersion;
@@ -84,9 +98,26 @@
// Meta data buffer layout used to transport output frames to the decoder for
// dynamic buffer handling.
-struct VideoDecoderOutputMetaData {
- MetadataBufferType eType;
- buffer_handle_t pHandle;
+struct VideoGrallocMetadata {
+ MetadataBufferType eType; // must be kMetadataBufferTypeGrallocSource
+#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+ OMX_PTR pHandle;
+#else
+ buffer_handle_t pHandle;
+#endif
+};
+
+// Legacy name for VideoGrallocMetadata struct.
+struct VideoDecoderOutputMetaData : public VideoGrallocMetadata {};
+
+struct VideoNativeMetadata {
+ MetadataBufferType eType; // must be kMetadataBufferTypeANWBuffer
+#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+ OMX_PTR pBuffer;
+#else
+ struct ANativeWindowBuffer* pBuffer;
+#endif
+ int nFenceFd; // -1 if unused
};
// A pointer to this struct is passed to OMX_SetParameter() when the extension
@@ -173,17 +204,17 @@
};
Type mType;
- size_t mNumPlanes; // number of planes
- size_t mWidth; // width of largest plane (unpadded, as in nFrameWidth)
- size_t mHeight; // height of largest plane (unpadded, as in nFrameHeight)
- size_t mBitDepth; // useable bit depth
+ uint32_t mNumPlanes; // number of planes
+ uint32_t mWidth; // width of largest plane (unpadded, as in nFrameWidth)
+ uint32_t mHeight; // height of largest plane (unpadded, as in nFrameHeight)
+ uint32_t mBitDepth; // useable bit depth
struct PlaneInfo {
- size_t mOffset; // offset of first pixel of the plane in bytes
- // from buffer offset
- size_t mColInc; // column increment in bytes
- size_t mRowInc; // row increment in bytes
- size_t mHorizSubsampling; // subsampling compared to the largest plane
- size_t mVertSubsampling; // subsampling compared to the largest plane
+ uint32_t mOffset; // offset of first pixel of the plane in bytes
+ // from buffer offset
+ uint32_t mColInc; // column increment in bytes
+ uint32_t mRowInc; // row increment in bytes
+ uint32_t mHorizSubsampling; // subsampling compared to the largest plane
+ uint32_t mVertSubsampling; // subsampling compared to the largest plane
};
PlaneInfo mPlane[MAX_NUM_PLANES];
};
diff --git a/include/media/hardware/MetadataBufferType.h b/include/media/hardware/MetadataBufferType.h
index 5876c40..b765203 100644
--- a/include/media/hardware/MetadataBufferType.h
+++ b/include/media/hardware/MetadataBufferType.h
@@ -77,28 +77,43 @@
* GRalloc buffer. The encoder needs to interpret this GRalloc handle
* and encode the frames.
* --------------------------------------------------------------
- * | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+ * | kMetadataBufferTypeGrallocSource | buffer_handle_t buffer |
* --------------------------------------------------------------
+ *
+ * See the VideoGrallocMetadata structure.
*/
kMetadataBufferTypeGrallocSource = 1,
/*
* kMetadataBufferTypeGraphicBuffer is used to indicate that
* the payload of the metadata buffers can be interpreted as
- * a GraphicBuffer. It is only to be used by software encoders.
- * In this case, the metadata that the encoder receives
- * will have a byte stream that consists of two parts:
+ * an ANativeWindowBuffer, and that a fence is provided.
+ *
+ * In this case, the metadata will have a byte stream that consists of three parts:
* 1. First, there is an integer indicating that the metadata
- * contains a GraphicBuffer (kMetadataBufferTypeGraphicBuffer)
- * 2. This is followed by the pointer to the GraphicBuffer that
- * is to be encoded. Encoder must not create a sp<> from this
- * graphic buffer, or free it, as it does not actually own this
- * buffer.
- * --------------------------------------------------------------
- * | kMetadataBufferTypeGraphicBuffer | sizeof(GraphicBuffer *) |
- * --------------------------------------------------------------
+ * contains an ANativeWindowBuffer (kMetadataBufferTypeANWBuffer)
+ * 2. This is followed by the pointer to the ANativeWindowBuffer.
+ * Codec must not free this buffer as it does not actually own this buffer.
+ * 3. Finally, there is an integer containing a fence file descriptor.
+ * The codec must wait on the fence before encoding or decoding into this
+ * buffer. When the buffer is returned, codec must replace this file descriptor
+ * with a new fence, that will be waited on before the buffer is replaced
+ * (encoder) or read (decoder).
+ * ---------------------------------
+ * | kMetadataBufferTypeANWBuffer |
+ * ---------------------------------
+ * | ANativeWindowBuffer *buffer |
+ * ---------------------------------
+ * | int fenceFd |
+ * ---------------------------------
+ *
+ * See the VideoNativeMetadata structure.
*/
- kMetadataBufferTypeGraphicBuffer = 2,
+ kMetadataBufferTypeANWBuffer = 2,
+
+ /* This value is used by framework, but is never used inside a metadata buffer */
+ kMetadataBufferTypeInvalid = -1,
+
// Add more here...
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index 0f177a1..ae8430d 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -287,6 +287,7 @@
// case OMX_EventComponentResumed: return "ComponentResumed";
// case OMX_EventDynamicResourcesAvailable: return "DynamicResourcesAvailable";
// case OMX_EventPortFormatDetected: return "PortFormatDetected";
+ case OMX_EventOutputRendered: return "OutputRendered";
default: return def;
}
}
@@ -521,6 +522,9 @@
case OMX_IndexParamVideoHevc: return "ParamVideoHevc";
// case OMX_IndexParamSliceSegments: return "ParamSliceSegments";
case OMX_IndexConfigAutoFramerateConversion: return "ConfigAutoFramerateConversion";
+ case OMX_IndexConfigPriority: return "ConfigPriority";
+ case OMX_IndexConfigOperatingRate: return "ConfigOperatingRate";
+ case OMX_IndexParamConsumerUsageBits: return "ParamConsumerUsageBits";
default: return asString((OMX_INDEXTYPE)i, def);
}
}
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index 12f2b3b..521c223 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -503,12 +503,24 @@
OMX_EventResourcesAcquired, /**< component has been granted resources and is
automatically starting the state change from
OMX_StateWaitForResources to OMX_StateIdle. */
- OMX_EventComponentResumed, /**< Component resumed due to reacquisition of resources */
- OMX_EventDynamicResourcesAvailable, /**< Component has acquired previously unavailable dynamic resources */
- OMX_EventPortFormatDetected, /**< Component has detected a supported format. */
- OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
- OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
- OMX_EventMax = 0x7FFFFFFF
+ OMX_EventComponentResumed, /**< Component resumed due to reacquisition of resources */
+ OMX_EventDynamicResourcesAvailable, /**< Component has acquired previously unavailable dynamic resources */
+ OMX_EventPortFormatDetected, /**< Component has detected a supported format. */
+ 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
+ * 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,
+ * but must signal the event no more than 40ms after the first frame in the batch. The frames
+ * must be ordered by system timestamp inside and across batches.
+ *
+ * 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.
+ */
+ OMX_EventOutputRendered = 0x7F000001,
+ OMX_EventMax = 0x7FFFFFFF
} OMX_EVENTTYPE;
typedef struct OMX_CALLBACKTYPE
diff --git a/include/media/openmax/OMX_IVCommon.h b/include/media/openmax/OMX_IVCommon.h
index a5b9d18..f9b6f4b 100644
--- a/include/media/openmax/OMX_IVCommon.h
+++ b/include/media/openmax/OMX_IVCommon.h
@@ -157,6 +157,7 @@
* an acceptable range once that is done.
* */
OMX_COLOR_FormatAndroidOpaque = 0x7F000789,
+ OMX_COLOR_Format32BitRGBA8888 = 0x7F00A000,
/** Flexible 8-bit YUV format. Codec should report this format
* as being supported if it supports any YUV420 packed planar
* or semiplanar formats. When port is set to use this format,
diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h
index ea3d0da..25bea1f 100644
--- a/include/media/openmax/OMX_IndexExt.h
+++ b/include/media/openmax/OMX_IndexExt.h
@@ -83,6 +83,9 @@
/* Other configurations */
OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000,
OMX_IndexConfigAutoFramerateConversion, /**< reference: OMX_CONFIG_BOOLEANTYPE */
+ OMX_IndexConfigPriority, /**< reference: OMX_PARAM_U32TYPE */
+ OMX_IndexConfigOperatingRate, /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */
+ OMX_IndexParamConsumerUsageBits, /**< reference: OMX_PARAM_U32TYPE */
/* Time configurations */
OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000,
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 3c97e14..34c0405 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -203,6 +203,12 @@
OMX_BOOL bEnableLoopFilterAcrossSlices;
} OMX_VIDEO_SLICESEGMENTSTYPE;
+/** Structure to return timestamps of rendered output frames 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
+} OMX_VIDEO_RENDEREVENTTYPE;
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 2fa6ff9..cbe8733 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -39,6 +39,7 @@
enum {
eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java
eLayerOpaque = 0x02, // SURFACE_OPAQUE
+ eLayerSecure = 0x80, // SECURE
};
enum {
@@ -48,10 +49,9 @@
eAlphaChanged = 0x00000008,
eMatrixChanged = 0x00000010,
eTransparentRegionChanged = 0x00000020,
- eVisibilityChanged = 0x00000040,
+ eFlagsChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
- eOpacityChanged = 0x00000200,
};
layer_state_t()
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index 20466b6..b431bd5 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -65,7 +65,7 @@
// before the fence signals then -ETIME is returned. A timeout of
// TIMEOUT_NEVER may be used to indicate that the call should wait
// indefinitely for the fence to signal.
- status_t wait(unsigned int timeout);
+ status_t wait(int timeout);
// waitForever is a convenience function for waiting forever for a fence to
// signal (just like wait(TIMEOUT_NEVER)), but issuing an error to the
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index 5cd8101..6b66d5f 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -14,11 +14,13 @@
* limitations under the License.
*/
+#ifndef INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
+#warning "FramebufferNativeWindow is deprecated"
+#endif
+
#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
-#warning "FramebufferNativeWindow is deprecated"
-
#include <stdint.h>
#include <sys/types.h>
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 7630faa..3da720f 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -49,7 +49,7 @@
USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY,
USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN,
USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK,
-
+
USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER,
USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY,
USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -72,11 +72,13 @@
GraphicBuffer();
// creates w * h buffer
- GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+ GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inUsage);
// create a buffer from an existing handle
- GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
- uint32_t stride, native_handle_t* handle, bool keepOwnership);
+ GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inUsage, uint32_t inStride, native_handle_t* inHandle,
+ bool keepOwnership);
// create a buffer from an existing ANativeWindowBuffer
GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership);
@@ -84,26 +86,39 @@
// return status
status_t initCheck() const;
- uint32_t getWidth() const { return width; }
- uint32_t getHeight() const { return height; }
- uint32_t getStride() const { return stride; }
- uint32_t getUsage() const { return usage; }
+ uint32_t getWidth() const { return static_cast<uint32_t>(width); }
+ uint32_t getHeight() const { return static_cast<uint32_t>(height); }
+ uint32_t getStride() const { return static_cast<uint32_t>(stride); }
+ uint32_t getUsage() const { return static_cast<uint32_t>(usage); }
PixelFormat getPixelFormat() const { return format; }
Rect getBounds() const { return Rect(width, height); }
uint64_t getId() const { return mId; }
- status_t reallocate(uint32_t w, uint32_t h, PixelFormat f, uint32_t usage);
+ uint32_t getGenerationNumber() const { return mGenerationNumber; }
+ void setGenerationNumber(uint32_t generation) {
+ mGenerationNumber = generation;
+ }
- status_t lock(uint32_t usage, void** vaddr);
- status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
+ status_t reallocate(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage);
+
+ bool needsReallocation(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage);
+
+ status_t lock(uint32_t inUsage, void** vaddr);
+ status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr);
// For HAL_PIXEL_FORMAT_YCbCr_420_888
- status_t lockYCbCr(uint32_t usage, android_ycbcr *ycbcr);
- status_t lockYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr);
+ status_t lockYCbCr(uint32_t inUsage, android_ycbcr *ycbcr);
+ status_t lockYCbCr(uint32_t inUsage, const Rect& rect,
+ android_ycbcr *ycbcr);
status_t unlock();
- status_t lockAsync(uint32_t usage, void** vaddr, int fenceFd);
- status_t lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd);
- status_t lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd);
- status_t lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd);
+ status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd);
+ status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr,
+ int fenceFd);
+ status_t lockAsyncYCbCr(uint32_t inUsage, android_ycbcr *ycbcr,
+ int fenceFd);
+ status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
+ android_ycbcr *ycbcr, int fenceFd);
status_t unlockAsync(int *fenceFd);
ANativeWindowBuffer* getNativeBuffer() const;
@@ -143,8 +158,8 @@
GraphicBuffer& operator = (const GraphicBuffer& rhs);
const GraphicBuffer& operator = (const GraphicBuffer& rhs) const;
- status_t initSize(uint32_t w, uint32_t h, PixelFormat format,
- uint32_t usage);
+ status_t initSize(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inUsage);
void free_handle();
@@ -156,6 +171,11 @@
sp<ANativeWindowBuffer> mWrappedBuffer;
uint64_t mId;
+
+ // Stores the generation number of this buffer. If this number does not
+ // match the BufferQueue's internal generation number (set through
+ // IGBP::setGenerationNumber), attempts to attach the buffer will fail.
+ uint32_t mGenerationNumber;
};
}; // namespace android
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index dffa788..5443f09 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -1,17 +1,17 @@
-/*
+/*
**
** Copyright 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
+** 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
+** 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
+** 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.
*/
@@ -45,14 +45,14 @@
USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY,
USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN,
USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK,
-
+
USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER,
USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY,
USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN,
USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK,
-
+
USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,
-
+
USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE,
USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER,
USAGE_HW_2D = GRALLOC_USAGE_HW_2D,
@@ -60,10 +60,9 @@
};
static inline GraphicBufferAllocator& get() { return getInstance(); }
-
- status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage,
- buffer_handle_t* handle, int32_t* stride);
+ status_t alloc(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ buffer_handle_t* handle, uint32_t* stride);
status_t free(buffer_handle_t handle);
@@ -72,21 +71,21 @@
private:
struct alloc_rec_t {
- uint32_t w;
- uint32_t h;
- uint32_t s;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
PixelFormat format;
uint32_t usage;
size_t size;
};
-
+
static Mutex sLock;
static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
-
+
friend class Singleton<GraphicBufferAllocator>;
GraphicBufferAllocator();
~GraphicBufferAllocator();
-
+
alloc_device_t *mAllocDev;
};
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index 98fff0e..6099548 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -41,23 +41,24 @@
status_t registerBuffer(buffer_handle_t handle);
status_t unregisterBuffer(buffer_handle_t handle);
-
+
status_t lock(buffer_handle_t handle,
- int usage, const Rect& bounds, void** vaddr);
+ uint32_t usage, const Rect& bounds, void** vaddr);
status_t lockYCbCr(buffer_handle_t handle,
- int usage, const Rect& bounds, android_ycbcr *ycbcr);
+ uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr);
status_t unlock(buffer_handle_t handle);
status_t lockAsync(buffer_handle_t handle,
- int usage, const Rect& bounds, void** vaddr, int fenceFd);
+ uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd);
status_t lockAsyncYCbCr(buffer_handle_t handle,
- int usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd);
+ uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr,
+ int fenceFd);
status_t unlockAsync(buffer_handle_t handle, int *fenceFd);
-
+
// dumps information about the mapping of this handle
void dump(buffer_handle_t handle);
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index 7e46945..f26fecb 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -25,9 +25,6 @@
#ifndef UI_PIXELFORMAT_H
#define UI_PIXELFORMAT_H
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/Errors.h>
#include <hardware/hardware.h>
namespace android {
@@ -63,14 +60,12 @@
PIXEL_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, // 4x8-bit BGRA
PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit ARGB
PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit ARGB
- PIXEL_FORMAT_sRGB_A_8888 = HAL_PIXEL_FORMAT_sRGB_A_8888, // 4x8-bit sRGB + A
- PIXEL_FORMAT_sRGB_X_8888 = HAL_PIXEL_FORMAT_sRGB_X_8888, // 4x8-bit sRGB, no A
};
typedef int32_t PixelFormat;
-ssize_t bytesPerPixel(PixelFormat format);
-ssize_t bitsPerPixel(PixelFormat format);
+uint32_t bytesPerPixel(PixelFormat format);
+uint32_t bitsPerPixel(PixelFormat format);
}; // namespace android
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index 31e28d2..3886f93 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -18,6 +18,7 @@
#define ANDROID_UI_RECT
#include <utils/Flattenable.h>
+#include <utils/Log.h>
#include <utils/TypeHelpers.h>
#include <ui/Point.h>
@@ -30,6 +31,8 @@
public:
typedef ARect::value_type value_type;
+ static const Rect INVALID_RECT;
+
// we don't provide copy-ctor and operator= on purpose
// because we want the compiler generated versions
@@ -43,6 +46,22 @@
bottom = h;
}
+ inline Rect(uint32_t w, uint32_t h) {
+ if (w > INT32_MAX) {
+ ALOG(LOG_WARN, "Rect",
+ "Width %u too large for Rect class, clamping", w);
+ w = INT32_MAX;
+ }
+ if (h > INT32_MAX) {
+ ALOG(LOG_WARN, "Rect",
+ "Height %u too large for Rect class, clamping", h);
+ h = INT32_MAX;
+ }
+ left = top = 0;
+ right = w;
+ bottom = h;
+ }
+
inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) {
left = l;
top = t;
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 0d1c68c..2a14918 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -35,6 +35,8 @@
class Region : public LightFlattenable<Region>
{
public:
+ static const Region INVALID_REGION;
+
Region();
Region(const Region& rhs);
explicit Region(const Rect& rhs);
@@ -55,11 +57,12 @@
// the region becomes its bounds
Region& makeBoundsSelf();
-
+
void clear();
void set(const Rect& r);
+ void set(int32_t w, int32_t h);
void set(uint32_t w, uint32_t h);
-
+
Region& orSelf(const Rect& rhs);
Region& xorSelf(const Rect& rhs);
Region& andSelf(const Rect& rhs);
@@ -110,14 +113,14 @@
inline Region& operator -= (const Region& rhs);
inline Region& operator += (const Point& pt);
-
+
// returns true if the regions share the same underlying storage
bool isTriviallyEqual(const Region& region) const;
/* various ways to access the rectangle list */
-
+
// STL-like iterators
typedef Rect const* const_iterator;
const_iterator begin() const;
@@ -133,7 +136,7 @@
SharedBuffer const* getSharedBuffer(size_t* count) const;
/* no user serviceable parts here... */
-
+
// add a rectangle to the internal list. This rectangle must
// be sorted in Y and X and must not make the region invalid.
void addRectUnchecked(int l, int t, int r, int b);
@@ -149,7 +152,7 @@
private:
class rasterizer;
friend class rasterizer;
-
+
Region& operationSelf(const Rect& r, int op);
Region& operationSelf(const Region& r, int op);
Region& operationSelf(const Region& r, int dx, int dy, int op);
@@ -172,7 +175,7 @@
static bool validate(const Region& reg,
const char* name, bool silent = false);
-
+
// mStorage is a (manually) sorted array of Rects describing the region
// with an extra Rect as the last element which is set to the
// bounds of the region. However, if the region is
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index 79decfe..d5860ef 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -26,6 +26,8 @@
IMemory.cpp \
IPCThreadState.cpp \
IPermissionController.cpp \
+ IProcessInfoService.cpp \
+ ProcessInfoService.cpp \
IServiceManager.cpp \
MemoryDealer.cpp \
MemoryBase.cpp \
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 61b4f7d..e4d8201 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -44,7 +44,7 @@
int64_t startTime = 0;
mLock.lock();
sp<IAppOpsService> service = mService;
- while (service == NULL || !service->asBinder()->isBinderAlive()) {
+ while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
if (binder == NULL) {
// Wait for the app ops service to come back...
@@ -104,4 +104,13 @@
}
}
+int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
+ sp<IAppOpsService> service = getService();
+ if (service != NULL) {
+ return service->permissionToOpCode(permission);
+ }
+ return -1;
+}
+
+
}; // namespace android
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 2554351..9d200fb 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -72,7 +72,7 @@
BBinder::BBinder()
{
- atomic_init(&mExtras, 0);
+ atomic_init(&mExtras, static_cast<uintptr_t>(0));
}
bool BBinder::isBinderAlive() const
@@ -160,10 +160,18 @@
e->mObjects.attach(objectID, object, cleanupCookie, func);
}
+// The C11 standard doesn't allow atomic loads from const fields,
+// though C++11 does. Fudge it until standards get straightened out.
+static inline uintptr_t load_const_atomic(const atomic_uintptr_t* p,
+ memory_order mo) {
+ atomic_uintptr_t* non_const_p = const_cast<atomic_uintptr_t*>(p);
+ return atomic_load_explicit(non_const_p, mo);
+}
+
void* BBinder::findObject(const void* objectID) const
{
Extras* e = reinterpret_cast<Extras*>(
- atomic_load_explicit(&mExtras, memory_order_acquire));
+ load_const_atomic(&mExtras, memory_order_acquire));
if (!e) return NULL;
AutoMutex _l(e->mLock);
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 101de7e..345ba20 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -220,7 +220,6 @@
if ((obit.recipient == recipient
|| (recipient == NULL && obit.cookie == cookie))
&& obit.flags == flags) {
- const uint32_t allFlags = obit.flags|flags;
if (outRecipient != NULL) {
*outRecipient = mObituaries->itemAt(i).recipient;
}
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 2d493c1..1339a67 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -49,9 +49,12 @@
status_t append(const char* txt, size_t len) {
if ((len+bufferPos) > bufferSize) {
- void* b = realloc(buffer, ((len+bufferPos)*3)/2);
+ size_t newSize = ((len+bufferPos)*3)/2;
+ if (newSize < (len+bufferPos)) return NO_MEMORY; // overflow
+ void* b = realloc(buffer, newSize);
if (!b) return NO_MEMORY;
buffer = (char*)b;
+ bufferSize = newSize;
}
memcpy(buffer+bufferPos, txt, len);
bufferPos += len;
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 0ffafbb..bdb7182 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -220,13 +220,8 @@
for (word = 0; word < bytesPerLine; ) {
-#ifdef HAVE_LITTLE_ENDIAN
const size_t startIndex = word+(alignment-(alignment?1:0));
const ssize_t dir = -1;
-#else
- const size_t startIndex = word;
- const ssize_t dir = 1;
-#endif
for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index f58a352..9558376 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -91,14 +91,14 @@
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(op);
data.writeString16(packageName);
- data.writeStrongBinder(callback->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(callback));
remote()->transact(START_WATCHING_MODE_TRANSACTION, data, &reply);
}
virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
- data.writeStrongBinder(callback->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(callback));
remote()->transact(STOP_WATCHING_MODE_TRANSACTION, data, &reply);
}
@@ -111,6 +111,17 @@
if (reply.readExceptionCode() != 0) return NULL;
return reply.readStrongBinder();
}
+
+
+ virtual int32_t permissionToOpCode(const String16& permission) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+ data.writeString16(permission);
+ remote()->transact(PERMISSION_TO_OP_CODE_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) return -1;
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
@@ -187,6 +198,14 @@
reply->writeStrongBinder(token);
return NO_ERROR;
} break;
+ case PERMISSION_TO_OP_CODE_TRANSACTION: {
+ CHECK_INTERFACE(IAppOpsService, data, reply);
+ String16 permission = data.readString16();
+ const int32_t opCode = permissionToOpCode(permission);
+ reply->writeNoException();
+ reply->writeInt32(opCode);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index 8f3b7b4..e32c628 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -89,6 +89,47 @@
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
remote()->transact(NOTE_RESET_AUDIO_TRANSACTION, data, &reply);
}
+
+ virtual void noteFlashlightOn(int uid) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ remote()->transact(NOTE_FLASHLIGHT_ON_TRANSACTION, data, &reply);
+ }
+
+ virtual void noteFlashlightOff(int uid) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ remote()->transact(NOTE_FLASHLIGHT_OFF_TRANSACTION, data, &reply);
+ }
+
+ virtual void noteStartCamera(int uid) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ remote()->transact(NOTE_START_CAMERA_TRANSACTION, data, &reply);
+ }
+
+ virtual void noteStopCamera(int uid) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ remote()->transact(NOTE_STOP_CAMERA_TRANSACTION, data, &reply);
+ }
+
+ virtual void noteResetCamera() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ remote()->transact(NOTE_RESET_CAMERA_TRANSACTION, data, &reply);
+ }
+
+ virtual void noteResetFlashlight() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+ remote()->transact(NOTE_RESET_FLASHLIGHT_TRANSACTION, data, &reply);
+ }
+
};
IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats");
@@ -155,6 +196,46 @@
reply->writeNoException();
return NO_ERROR;
} break;
+ case NOTE_FLASHLIGHT_ON_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ int uid = data.readInt32();
+ noteFlashlightOn(uid);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case NOTE_FLASHLIGHT_OFF_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ int uid = data.readInt32();
+ noteFlashlightOff(uid);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case NOTE_START_CAMERA_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ int uid = data.readInt32();
+ noteStartCamera(uid);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case NOTE_STOP_CAMERA_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ int uid = data.readInt32();
+ noteStopCamera(uid);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case NOTE_RESET_CAMERA_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ noteResetCamera();
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ case NOTE_RESET_FLASHLIGHT_TRANSACTION: {
+ CHECK_INTERFACE(IBatteryStats, data, reply);
+ noteResetFlashlight();
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index 29acf5d..2fcd3d9 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "IInterface"
+#include <utils/Log.h>
#include <binder/IInterface.h>
namespace android {
@@ -27,16 +29,39 @@
IInterface::~IInterface() {
}
-sp<IBinder> IInterface::asBinder()
+// static
+sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
- return this ? onAsBinder() : NULL;
+ if (iface == NULL) return NULL;
+ return const_cast<IInterface*>(iface)->onAsBinder();
}
-sp<const IBinder> IInterface::asBinder() const
+// static
+sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
- return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
+ if (iface == NULL) return NULL;
+ return iface->onAsBinder();
}
+
// ---------------------------------------------------------------------------
}; // namespace android
+
+extern "C" {
+
+void _ZN7android10IInterface8asBinderEv(void *retval, void* self) {
+ ALOGW("deprecated asBinder call, please update your code");
+ //ALOGI("self: %p, retval: %p", self, retval);
+ android::sp<android::IBinder> *ret = new(retval) android::sp<android::IBinder>;
+ *ret = android::IInterface::asBinder((android::IInterface*)self);
+}
+
+void _ZNK7android10IInterface8asBinderEv(void *retval, void *self) {
+ ALOGW("deprecated asBinder call, please update your code");
+ //ALOGI("self: %p, retval: %p", self, retval);
+ android::sp<android::IBinder> *ret = new(retval) android::sp<android::IBinder>;
+ *ret = android::IInterface::asBinder((android::IInterface*)self);
+}
+
+} // extern "C"
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index d8ed995..e9891a8 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -216,7 +216,7 @@
CHECK_INTERFACE(IMemory, data, reply);
ssize_t offset;
size_t size;
- reply->writeStrongBinder( getMemory(&offset, &size)->asBinder() );
+ reply->writeStrongBinder( IInterface::asBinder(getMemory(&offset, &size)) );
reply->writeInt32(offset);
reply->writeInt32(size);
return NO_ERROR;
@@ -241,7 +241,7 @@
if (mRealHeap) {
// by construction we're the last one
if (mBase != MAP_FAILED) {
- sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
+ sp<IBinder> binder = IInterface::asBinder(this);
if (VERBOSE) {
ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
@@ -253,7 +253,7 @@
}
} else {
// remove from list only if it was mapped before
- sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
+ sp<IBinder> binder = IInterface::asBinder(this);
free_heap(binder);
}
}
@@ -262,7 +262,7 @@
void BpMemoryHeap::assertMapped() const
{
if (mHeapId == -1) {
- sp<IBinder> binder(const_cast<BpMemoryHeap*>(this)->asBinder());
+ sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
heap->assertReallyMapped();
if (heap->mBase != MAP_FAILED) {
@@ -297,7 +297,8 @@
uint32_t offset = reply.readInt32();
ALOGE_IF(err, "binder=%p transaction failed fd=%d, size=%zd, err=%d (%s)",
- asBinder().get(), parcel_fd, size, err, strerror(-err));
+ IInterface::asBinder(this).get(),
+ parcel_fd, size, err, strerror(-err));
int fd = dup( parcel_fd );
ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
@@ -314,7 +315,7 @@
mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)",
- asBinder().get(), size, fd, strerror(errno));
+ IInterface::asBinder(this).get(), size, fd, strerror(errno));
close(fd);
} else {
mSize = size;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index dd04dcf..ef88181 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -29,21 +29,14 @@
#include <private/binder/binder_module.h>
#include <private/binder/Static.h>
-#include <sys/ioctl.h>
-#include <signal.h>
#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#ifdef HAVE_PTHREADS
#include <pthread.h>
#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
#include <sys/resource.h>
-#endif
-#ifdef HAVE_WIN32_THREADS
-#include <windows.h>
-#endif
-
+#include <unistd.h>
#if LOG_NDEBUG
@@ -70,13 +63,11 @@
namespace android {
static const char* getReturnString(size_t idx);
-static const char* getCommandString(size_t idx);
static const void* printReturnCommand(TextOutput& out, const void* _cmd);
static const void* printCommand(TextOutput& out, const void* _cmd);
-// This will result in a missing symbol failure if the IF_LOG_COMMANDS()
-// conditionals don't get stripped... but that is probably what we want.
-#if !LOG_NDEBUG
+// Static const and functions will be optimized out if not used,
+// when LOG_NDEBUG and references in IF_LOG_COMMANDS() are optimized out.
static const char *kReturnStrings[] = {
"BR_ERROR",
"BR_OK",
@@ -126,14 +117,6 @@
return "unknown";
}
-static const char* getCommandString(size_t idx)
-{
- if (idx < sizeof(kCommandStrings) / sizeof(kCommandStrings[0]))
- return kCommandStrings[idx];
- else
- return "unknown";
-}
-
static const void* printBinderTransactionData(TextOutput& out, const void* data)
{
const binder_transaction_data* btd =
@@ -145,7 +128,7 @@
out << "target.ptr=" << btd->target.ptr;
}
out << " (cookie " << btd->cookie << ")" << endl
- << "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl
+ << "code=" << TypeCode(btd->code) << ", flags=" << (void*)(long)btd->flags << endl
<< "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
<< " bytes)" << endl
<< "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
@@ -157,10 +140,10 @@
{
static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
- int32_t code = *cmd++;
+ uint32_t code = (uint32_t)*cmd++;
size_t cmdIndex = code & 0xff;
- if (code == (int32_t) BR_ERROR) {
- out << "BR_ERROR: " << (void*)(*cmd++) << endl;
+ if (code == BR_ERROR) {
+ out << "BR_ERROR: " << (void*)(long)(*cmd++) << endl;
return cmd;
} else if (cmdIndex >= N) {
out << "Unknown reply: " << code << endl;
@@ -187,21 +170,21 @@
case BR_DECREFS: {
const int32_t b = *cmd++;
const int32_t c = *cmd++;
- out << ": target=" << (void*)b << " (cookie " << (void*)c << ")";
+ out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")";
} break;
case BR_ATTEMPT_ACQUIRE: {
const int32_t p = *cmd++;
const int32_t b = *cmd++;
const int32_t c = *cmd++;
- out << ": target=" << (void*)b << " (cookie " << (void*)c
+ out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c
<< "), pri=" << p;
} break;
case BR_DEAD_BINDER:
case BR_CLEAR_DEATH_NOTIFICATION_DONE: {
const int32_t c = *cmd++;
- out << ": death cookie " << (void*)c;
+ out << ": death cookie " << (void*)(long)c;
} break;
default:
@@ -218,7 +201,7 @@
{
static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
const int32_t* cmd = (const int32_t*)_cmd;
- int32_t code = *cmd++;
+ uint32_t code = (uint32_t)*cmd++;
size_t cmdIndex = code & 0xff;
if (cmdIndex >= N) {
@@ -242,7 +225,7 @@
case BC_FREE_BUFFER: {
const int32_t buf = *cmd++;
- out << ": buffer=" << (void*)buf;
+ out << ": buffer=" << (void*)(long)buf;
} break;
case BC_INCREFS:
@@ -257,7 +240,7 @@
case BC_ACQUIRE_DONE: {
const int32_t b = *cmd++;
const int32_t c = *cmd++;
- out << ": target=" << (void*)b << " (cookie " << (void*)c << ")";
+ out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")";
} break;
case BC_ATTEMPT_ACQUIRE: {
@@ -270,12 +253,12 @@
case BC_CLEAR_DEATH_NOTIFICATION: {
const int32_t h = *cmd++;
const int32_t c = *cmd++;
- out << ": handle=" << h << " (death cookie " << (void*)c << ")";
+ out << ": handle=" << h << " (death cookie " << (void*)(long)c << ")";
} break;
case BC_DEAD_BINDER_DONE: {
const int32_t c = *cmd++;
- out << ": death cookie " << (void*)c;
+ out << ": death cookie " << (void*)(long)c;
} break;
default:
@@ -287,7 +270,6 @@
out << endl;
return cmd;
}
-#endif
static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gHaveTLS = false;
@@ -361,12 +343,12 @@
return err;
}
-int IPCThreadState::getCallingPid() const
+pid_t IPCThreadState::getCallingPid() const
{
return mCallingPid;
}
-int IPCThreadState::getCallingUid() const
+uid_t IPCThreadState::getCallingUid() const
{
return mCallingUid;
}
@@ -417,6 +399,18 @@
talkWithDriver(false);
}
+void IPCThreadState::blockUntilThreadAvailable()
+{
+ pthread_mutex_lock(&mProcess->mThreadCountLock);
+ while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) {
+ ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n",
+ static_cast<unsigned long>(mProcess->mExecutingThreadsCount),
+ static_cast<unsigned long>(mProcess->mMaxThreads));
+ pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock);
+ }
+ pthread_mutex_unlock(&mProcess->mThreadCountLock);
+}
+
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
@@ -432,8 +426,17 @@
<< getReturnString(cmd) << endl;
}
+ pthread_mutex_lock(&mProcess->mThreadCountLock);
+ mProcess->mExecutingThreadsCount++;
+ pthread_mutex_unlock(&mProcess->mThreadCountLock);
+
result = executeCommand(cmd);
+ pthread_mutex_lock(&mProcess->mThreadCountLock);
+ mProcess->mExecutingThreadsCount--;
+ pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
+ pthread_mutex_unlock(&mProcess->mThreadCountLock);
+
// After executing the command, ensure that the thread is returned to the
// foreground cgroup before rejoining the pool. The driver takes care of
// restoring the priority, but doesn't do anything with cgroups so we
@@ -682,7 +685,7 @@
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
- mMyThreadId(androidGetTid()),
+ mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
@@ -708,7 +711,7 @@
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
- int32_t cmd;
+ uint32_t cmd;
int32_t err;
while (1) {
@@ -717,7 +720,7 @@
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
- cmd = mIn.readInt32();
+ cmd = (uint32_t)mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing waitForResponse Command: "
@@ -947,7 +950,7 @@
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
- switch (cmd) {
+ switch ((uint32_t)cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index 437113d..6bba996 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -48,6 +48,36 @@
if (reply.readExceptionCode() != 0) return 0;
return reply.readInt32() != 0;
}
+
+ virtual void getPackagesForUid(const uid_t uid, Vector<String16>& packages)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+ data.writeInt32(uid);
+ remote()->transact(GET_PACKAGES_FOR_UID_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) {
+ return;
+ }
+ const int32_t size = reply.readInt32();
+ if (size <= 0) {
+ return;
+ }
+ for (int i = 0; i < size; i++) {
+ packages.push(reply.readString16());
+ }
+ }
+
+ virtual bool isRuntimePermission(const String16& permission)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+ data.writeString16(permission);
+ remote()->transact(IS_RUNTIME_PERMISSION_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) return false;
+ return reply.readInt32() != 0;
+ }
};
IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
@@ -57,7 +87,6 @@
status_t BnPermissionController::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
- //printf("PermissionController received: "); data.print();
switch(code) {
case CHECK_PERMISSION_TRANSACTION: {
CHECK_INTERFACE(IPermissionController, data, reply);
@@ -69,6 +98,30 @@
reply->writeInt32(res ? 1 : 0);
return NO_ERROR;
} break;
+
+ case GET_PACKAGES_FOR_UID_TRANSACTION: {
+ CHECK_INTERFACE(IPermissionController, data, reply);
+ int32_t uid = data.readInt32();
+ Vector<String16> packages;
+ getPackagesForUid(uid, packages);
+ reply->writeNoException();
+ size_t size = packages.size();
+ reply->writeInt32(size);
+ for (size_t i = 0; i < size; i++) {
+ reply->writeString16(packages[i]);
+ }
+ return NO_ERROR;
+ } break;
+
+ case IS_RUNTIME_PERMISSION_TRANSACTION: {
+ CHECK_INTERFACE(IPermissionController, data, reply);
+ String16 permission = data.readString16();
+ const bool res = isRuntimePermission(permission);
+ reply->writeNoException();
+ reply->writeInt32(res ? 1 : 0);
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
new file mode 100644
index 0000000..d86eb27
--- /dev/null
+++ b/libs/binder/IProcessInfoService.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 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 <binder/IProcessInfoService.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <sys/types.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpProcessInfoService : public BpInterface<IProcessInfoService> {
+public:
+ BpProcessInfoService(const sp<IBinder>& impl)
+ : BpInterface<IProcessInfoService>(impl) {}
+
+ virtual status_t getProcessStatesFromPids(size_t length, /*in*/ int32_t* pids,
+ /*out*/ int32_t* states)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IProcessInfoService::getInterfaceDescriptor());
+ data.writeInt32Array(length, pids);
+ data.writeInt32(length); // write length of output array, used by java AIDL stubs
+ status_t err = remote()->transact(GET_PROCESS_STATES_FROM_PIDS, data, &reply);
+ if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+ return err;
+ }
+ int32_t replyLen = reply.readInt32();
+ if (static_cast<size_t>(replyLen) != length) {
+ return NOT_ENOUGH_DATA;
+ }
+ if (replyLen > 0 && (err = reply.read(states, length * sizeof(*states))) != NO_ERROR) {
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
+
+// ----------------------------------------------------------------------
+
+status_t BnProcessInfoService::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ switch(code) {
+ case GET_PROCESS_STATES_FROM_PIDS: {
+ CHECK_INTERFACE(IProcessInfoService, data, reply);
+ int32_t arrayLen = data.readInt32();
+ if (arrayLen <= 0) {
+ reply->writeNoException();
+ reply->writeInt32(0);
+ reply->writeInt32(NOT_ENOUGH_DATA);
+ return NO_ERROR;
+ }
+
+ size_t len = static_cast<size_t>(arrayLen);
+ int32_t pids[len];
+ status_t res = data.read(pids, len * sizeof(*pids));
+
+ // Ignore output array length returned in the parcel here, as the states array must
+ // always be the same length as the input PIDs array.
+ int32_t states[len];
+ for (size_t i = 0; i < len; i++) states[i] = -1;
+ if (res == NO_ERROR) {
+ res = getProcessStatesFromPids(len, /*in*/ pids, /*out*/ states);
+ }
+ reply->writeNoException();
+ reply->writeInt32Array(len, states);
+ reply->writeInt32(res);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 7b1b0e7..3c716df 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -87,7 +87,7 @@
}
// Is this a permission failure, or did the controller go away?
- if (pc->asBinder()->isBinderAlive()) {
+ if (IInterface::asBinder(pc)->isBinderAlive()) {
ALOGW("Permission failure: %s from uid=%d pid=%d",
String8(permission).string(), uid, pid);
return false;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 87ce5d0..7a4ddc4 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -54,17 +54,24 @@
// ---------------------------------------------------------------------------
-#define PAD_SIZE(s) (((s)+3)&~3)
+// This macro should never be used at runtime, as a too large value
+// of s could cause an integer overflow. Instead, you should always
+// use the wrapper function pad_size()
+#define PAD_SIZE_UNSAFE(s) (((s)+3)&~3)
+
+static size_t pad_size(size_t s) {
+ if (s > (SIZE_T_MAX - 3)) {
+ abort();
+ }
+ return PAD_SIZE_UNSAFE(s);
+}
// Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
-#define STRICT_MODE_PENALTY_GATHER 0x100
+#define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
#define EX_HAS_REPLY_HEADER -128
-// Maximum size of a blob to transfer in-place.
-static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
-
// XXX This can be made public if we want to provide
// support for typed data.
struct small_flat_data
@@ -79,6 +86,15 @@
static size_t gParcelGlobalAllocSize = 0;
static size_t gParcelGlobalAllocCount = 0;
+// Maximum size of a blob to transfer in-place.
+static const size_t BLOB_INPLACE_LIMIT = 16 * 1024;
+
+enum {
+ BLOB_INPLACE = 0,
+ BLOB_ASHMEM_IMMUTABLE = 1,
+ BLOB_ASHMEM_MUTABLE = 2,
+};
+
void acquire_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who)
{
@@ -355,6 +371,12 @@
status_t Parcel::setDataSize(size_t size)
{
+ if (size > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
status_t err;
err = continueWrite(size);
if (err == NO_ERROR) {
@@ -366,18 +388,36 @@
void Parcel::setDataPosition(size_t pos) const
{
+ if (pos > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ abort();
+ }
+
mDataPos = pos;
mNextObjectHint = 0;
}
status_t Parcel::setDataCapacity(size_t size)
{
+ if (size > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
if (size > mDataCapacity) return continueWrite(size);
return NO_ERROR;
}
status_t Parcel::setData(const uint8_t* buffer, size_t len)
{
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
status_t err = restartWrite(len);
if (err == NO_ERROR) {
memcpy(const_cast<uint8_t*>(data()), buffer, len);
@@ -401,6 +441,12 @@
return NO_ERROR;
}
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
// range checks against the source parcel size
if ((offset > parcel->mDataSize)
|| (len > parcel->mDataSize)
@@ -438,7 +484,8 @@
if (numObjects > 0) {
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
- int newSize = ((mObjectsSize + numObjects)*3)/2;
+ size_t newSize = ((mObjectsSize + numObjects)*3)/2;
+ if (newSize < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t *objects =
(binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
if (objects == (binder_size_t*)0) {
@@ -476,6 +523,11 @@
return err;
}
+bool Parcel::allowFds() const
+{
+ return mAllowFds;
+}
+
bool Parcel::pushAllowFds(bool allowFds)
{
const bool origValue = mAllowFds;
@@ -561,6 +613,12 @@
status_t Parcel::finishWrite(size_t len)
{
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
//printf("Finish write of %d\n", len);
mDataPos += len;
ALOGV("finishWrite Setting data pos of %p to %zu", this, mDataPos);
@@ -574,6 +632,12 @@
status_t Parcel::writeUnpadded(const void* data, size_t len)
{
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
size_t end = mDataPos + len;
if (end < mDataPos) {
// integer overflow
@@ -593,6 +657,12 @@
status_t Parcel::write(const void* data, size_t len)
{
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
void* const d = writeInplace(len);
if (d) {
memcpy(d, data, len);
@@ -603,7 +673,13 @@
void* Parcel::writeInplace(size_t len)
{
- const size_t padded = PAD_SIZE(len);
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return NULL;
+ }
+
+ const size_t padded = pad_size(len);
// sanity check for integer overflow
if (mDataPos+padded < mDataPos) {
@@ -645,21 +721,39 @@
{
return writeAligned(val);
}
+
+status_t Parcel::writeUint32(uint32_t val)
+{
+ return writeAligned(val);
+}
+
status_t Parcel::writeInt32Array(size_t len, const int32_t *val) {
- if (!val) {
- return writeAligned(-1);
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
}
- status_t ret = writeAligned(len);
+
+ if (!val) {
+ return writeInt32(-1);
+ }
+ status_t ret = writeInt32(static_cast<uint32_t>(len));
if (ret == NO_ERROR) {
ret = write(val, len * sizeof(*val));
}
return ret;
}
status_t Parcel::writeByteArray(size_t len, const uint8_t *val) {
- if (!val) {
- return writeAligned(-1);
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
}
- status_t ret = writeAligned(len);
+
+ if (!val) {
+ return writeInt32(-1);
+ }
+ status_t ret = writeInt32(static_cast<uint32_t>(len));
if (ret == NO_ERROR) {
ret = write(val, len * sizeof(*val));
}
@@ -671,6 +765,11 @@
return writeAligned(val);
}
+status_t Parcel::writeUint64(uint64_t val)
+{
+ return writeAligned(val);
+}
+
status_t Parcel::writePointer(uintptr_t val)
{
return writeAligned<binder_uintptr_t>(val);
@@ -799,45 +898,24 @@
return err;
}
-// WARNING: This method must stay in sync with
-// Parcelable.Creator<ParcelFileDescriptor> CREATOR
-// in frameworks/base/core/java/android/os/ParcelFileDescriptor.java
-status_t Parcel::writeParcelFileDescriptor(int fd, int commChannel) {
- status_t status;
-
- if (fd < 0) {
- status = writeInt32(0); // ParcelFileDescriptor is null
- if (status) return status;
- } else {
- status = writeInt32(1); // ParcelFileDescriptor is not null
- if (status) return status;
- status = writeDupFileDescriptor(fd);
- if (status) return status;
- if (commChannel < 0) {
- status = writeInt32(0); // commChannel is null
- if (status) return status;
- } else {
- status = writeInt32(1); // commChannel is not null
- if (status) return status;
- status = writeDupFileDescriptor(commChannel);
- }
- }
- return status;
-}
-
-status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
+status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
{
- status_t status;
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
- if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) {
+ status_t status;
+ if (!mAllowFds || len <= BLOB_INPLACE_LIMIT) {
ALOGV("writeBlob: write in place");
- status = writeInt32(0);
+ status = writeInt32(BLOB_INPLACE);
if (status) return status;
void* ptr = writeInplace(len);
if (!ptr) return NO_MEMORY;
- outBlob->init(false /*mapped*/, ptr, len);
+ outBlob->init(-1, ptr, len, false);
return NO_ERROR;
}
@@ -845,6 +923,8 @@
int fd = ashmem_create_region("Parcel Blob", len);
if (fd < 0) return NO_MEMORY;
+ mBlobAshmemSize += len;
+
int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
if (result < 0) {
status = result;
@@ -853,15 +933,17 @@
if (ptr == MAP_FAILED) {
status = -errno;
} else {
- result = ashmem_set_prot_region(fd, PROT_READ);
+ if (!mutableCopy) {
+ result = ashmem_set_prot_region(fd, PROT_READ);
+ }
if (result < 0) {
status = result;
} else {
- status = writeInt32(1);
+ status = writeInt32(mutableCopy ? BLOB_ASHMEM_MUTABLE : BLOB_ASHMEM_IMMUTABLE);
if (!status) {
status = writeFileDescriptor(fd, true /*takeOwnership*/);
if (!status) {
- outBlob->init(true /*mapped*/, ptr, len);
+ outBlob->init(fd, ptr, len, mutableCopy);
return NO_ERROR;
}
}
@@ -873,6 +955,15 @@
return status;
}
+status_t Parcel::writeDupImmutableBlobFileDescriptor(int fd)
+{
+ // Must match up with what's done in writeBlob.
+ if (!mAllowFds) return FDS_NOT_ALLOWED;
+ status_t status = writeInt32(BLOB_ASHMEM_IMMUTABLE);
+ if (status) return status;
+ return writeDupFileDescriptor(fd);
+}
+
status_t Parcel::write(const FlattenableHelperInterface& val)
{
status_t err;
@@ -881,6 +972,12 @@
const size_t len = val.getFlattenedSize();
const size_t fd_count = val.getFdCount();
+ if ((len > INT32_MAX) || (fd_count > INT32_MAX)) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
err = this->writeInt32(len);
if (err) return err;
@@ -888,7 +985,7 @@
if (err) return err;
// payload
- void* const buf = this->writeInplace(PAD_SIZE(len));
+ void* const buf = this->writeInplace(pad_size(len));
if (buf == NULL)
return BAD_VALUE;
@@ -917,6 +1014,15 @@
restart_write:
*reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
+ // remember if it's a file descriptor
+ if (val.type == BINDER_TYPE_FD) {
+ if (!mAllowFds) {
+ // fail before modifying our object index
+ return FDS_NOT_ALLOWED;
+ }
+ mHasFds = mFdsKnown = true;
+ }
+
// Need to write meta-data?
if (nullMetaData || val.binder != 0) {
mObjects[mObjectsSize] = mDataPos;
@@ -924,14 +1030,6 @@
mObjectsSize++;
}
- // remember if it's a file descriptor
- if (val.type == BINDER_TYPE_FD) {
- if (!mAllowFds) {
- return FDS_NOT_ALLOWED;
- }
- mHasFds = mFdsKnown = true;
- }
-
return finishWrite(sizeof(flat_binder_object));
}
@@ -941,6 +1039,7 @@
}
if (!enoughObjects) {
size_t newSize = ((mObjectsSize+2)*3)/2;
+ if (newSize < mObjectsSize) return NO_MEMORY; // overflow
binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
if (objects == NULL) return NO_MEMORY;
mObjects = objects;
@@ -962,10 +1061,16 @@
status_t Parcel::read(void* outData, size_t len) const
{
- if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize
- && len <= PAD_SIZE(len)) {
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
+ if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
+ && len <= pad_size(len)) {
memcpy(outData, mData+mDataPos, len);
- mDataPos += PAD_SIZE(len);
+ mDataPos += pad_size(len);
ALOGV("read Setting data pos of %p to %zu", this, mDataPos);
return NO_ERROR;
}
@@ -974,10 +1079,16 @@
const void* Parcel::readInplace(size_t len) const
{
- if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize
- && len <= PAD_SIZE(len)) {
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return NULL;
+ }
+
+ if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
+ && len <= pad_size(len)) {
const void* data = mData+mDataPos;
- mDataPos += PAD_SIZE(len);
+ mDataPos += pad_size(len);
ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
return data;
}
@@ -986,7 +1097,7 @@
template<class T>
status_t Parcel::readAligned(T *pArg) const {
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(T)) <= mDataSize) {
const void* data = mData+mDataPos;
@@ -1010,7 +1121,7 @@
template<class T>
status_t Parcel::writeAligned(T val) {
- COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
@@ -1033,6 +1144,15 @@
return readAligned<int32_t>();
}
+status_t Parcel::readUint32(uint32_t *pArg) const
+{
+ return readAligned(pArg);
+}
+
+uint32_t Parcel::readUint32() const
+{
+ return readAligned<uint32_t>();
+}
status_t Parcel::readInt64(int64_t *pArg) const
{
@@ -1045,6 +1165,16 @@
return readAligned<int64_t>();
}
+status_t Parcel::readUint64(uint64_t *pArg) const
+{
+ return readAligned(pArg);
+}
+
+uint64_t Parcel::readUint64() const
+{
+ return readAligned<uint64_t>();
+}
+
status_t Parcel::readPointer(uintptr_t *pArg) const
{
status_t ret;
@@ -1132,7 +1262,7 @@
const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
if (eos) {
const size_t len = eos - str;
- mDataPos += PAD_SIZE(len+1);
+ mDataPos += pad_size(len+1);
ALOGV("readCString Setting data pos of %p to %zu", this, mDataPos);
return str;
}
@@ -1246,46 +1376,31 @@
return BAD_TYPE;
}
-// WARNING: This method must stay in sync with writeToParcel()
-// in frameworks/base/core/java/android/os/ParcelFileDescriptor.java
-int Parcel::readParcelFileDescriptor(int& outCommChannel) const {
- int fd;
- outCommChannel = -1;
-
- if (readInt32() == 0) {
- fd = -1;
- } else {
- fd = readFileDescriptor();
- if (fd >= 0 && readInt32() != 0) {
- outCommChannel = readFileDescriptor();
- }
- }
- return fd;
-}
-
status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
{
- int32_t useAshmem;
- status_t status = readInt32(&useAshmem);
+ int32_t blobType;
+ status_t status = readInt32(&blobType);
if (status) return status;
- if (!useAshmem) {
+ if (blobType == BLOB_INPLACE) {
ALOGV("readBlob: read in place");
const void* ptr = readInplace(len);
if (!ptr) return BAD_VALUE;
- outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
+ outBlob->init(-1, const_cast<void*>(ptr), len, false);
return NO_ERROR;
}
ALOGV("readBlob: read from ashmem");
+ bool isMutable = (blobType == BLOB_ASHMEM_MUTABLE);
int fd = readFileDescriptor();
if (fd == int(BAD_TYPE)) return BAD_VALUE;
- void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ void* ptr = ::mmap(NULL, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
+ MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) return NO_MEMORY;
- outBlob->init(true /*mapped*/, ptr, len);
+ outBlob->init(fd, ptr, len, isMutable);
return NO_ERROR;
}
@@ -1295,8 +1410,14 @@
const size_t len = this->readInt32();
const size_t fd_count = this->readInt32();
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
// payload
- void const* const buf = this->readInplace(PAD_SIZE(len));
+ void const* const buf = this->readInplace(pad_size(len));
if (buf == NULL)
return BAD_VALUE;
@@ -1442,7 +1563,7 @@
for (size_t i = 0; i < mObjectsSize; i++) {
binder_size_t offset = mObjects[i];
if (offset < minOffset) {
- ALOGE("%s: bad object offset %"PRIu64" < %"PRIu64"\n",
+ ALOGE("%s: bad object offset %" PRIu64 " < %" PRIu64 "\n",
__func__, (uint64_t)offset, (uint64_t)minOffset);
mObjectsSize = 0;
break;
@@ -1535,6 +1656,12 @@
status_t Parcel::growData(size_t len)
{
+ if (len > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
size_t newSize = ((mDataSize+len)*3)/2;
return (newSize <= mDataSize)
? (status_t) NO_MEMORY
@@ -1543,6 +1670,12 @@
status_t Parcel::restartWrite(size_t desired)
{
+ if (desired > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
if (mOwner) {
freeData();
return continueWrite(desired);
@@ -1583,6 +1716,12 @@
status_t Parcel::continueWrite(size_t desired)
{
+ if (desired > INT32_MAX) {
+ // don't accept size_t values which may have come from an
+ // inadvertent conversion from a negative int.
+ return BAD_VALUE;
+ }
+
// If shrinking, first adjust for any objects that appear
// after the new data size.
size_t objectsSize = mObjectsSize;
@@ -1615,7 +1754,7 @@
binder_size_t* objects = NULL;
if (objectsSize) {
- objects = (binder_size_t*)malloc(objectsSize*sizeof(binder_size_t));
+ objects = (binder_size_t*)calloc(objectsSize, sizeof(binder_size_t));
if (!objects) {
free(data);
@@ -1751,6 +1890,7 @@
mFdsKnown = true;
mAllowFds = true;
mOwner = NULL;
+ mBlobAshmemSize = 0;
}
void Parcel::scanForFds() const
@@ -1768,10 +1908,15 @@
mFdsKnown = true;
}
+size_t Parcel::getBlobAshmemSize() const
+{
+ return mBlobAshmemSize;
+}
+
// --- Parcel::Blob ---
Parcel::Blob::Blob() :
- mMapped(false), mData(NULL), mSize(0) {
+ mFd(-1), mData(NULL), mSize(0), mMutable(false) {
}
Parcel::Blob::~Blob() {
@@ -1779,22 +1924,24 @@
}
void Parcel::Blob::release() {
- if (mMapped && mData) {
+ if (mFd != -1 && mData) {
::munmap(mData, mSize);
}
clear();
}
-void Parcel::Blob::init(bool mapped, void* data, size_t size) {
- mMapped = mapped;
+void Parcel::Blob::init(int fd, void* data, size_t size, bool isMutable) {
+ mFd = fd;
mData = data;
mSize = size;
+ mMutable = isMutable;
}
void Parcel::Blob::clear() {
- mMapped = false;
+ mFd = -1;
mData = NULL;
mSize = 0;
+ mMutable = false;
}
}; // namespace android
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
new file mode 100644
index 0000000..fb28643
--- /dev/null
+++ b/libs/binder/ProcessInfoService.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 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 <binder/ProcessInfoService.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+namespace android {
+
+ProcessInfoService::ProcessInfoService() {
+ updateBinderLocked();
+}
+
+status_t ProcessInfoService::getProcessStatesImpl(size_t length, /*in*/ int32_t* pids,
+ /*out*/ int32_t* states) {
+ status_t err = NO_ERROR;
+ sp<IProcessInfoService> pis;
+ mProcessInfoLock.lock();
+ pis = mProcessInfoService;
+ mProcessInfoLock.unlock();
+
+ for (int i = 0; i < BINDER_ATTEMPT_LIMIT; i++) {
+
+ if (pis != NULL) {
+ err = pis->getProcessStatesFromPids(length, /*in*/ pids, /*out*/ states);
+ if (err == NO_ERROR) return NO_ERROR; // success
+ if (IInterface::asBinder(pis)->isBinderAlive()) return err;
+ }
+ sleep(1);
+
+ mProcessInfoLock.lock();
+ if (pis == mProcessInfoService) {
+ updateBinderLocked();
+ }
+ pis = mProcessInfoService;
+ mProcessInfoLock.unlock();
+ }
+
+ ALOGW("%s: Could not retrieve process states from ProcessInfoService after %d retries.",
+ __FUNCTION__, BINDER_ATTEMPT_LIMIT);
+
+ return TIMED_OUT;
+}
+
+void ProcessInfoService::updateBinderLocked() {
+ const sp<IServiceManager> sm(defaultServiceManager());
+ if (sm != NULL) {
+ const String16 name("processinfo");
+ mProcessInfoService = interface_cast<IProcessInfoService>(sm->checkService(name));
+ }
+}
+
+ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
+
+}; // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 303d6cf..016d3c5 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -42,12 +42,13 @@
#include <sys/stat.h>
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
+#define DEFAULT_MAX_BINDER_THREADS 15
// ---------------------------------------------------------------------------
namespace android {
-
+
class PoolThread : public Thread
{
public:
@@ -294,7 +295,9 @@
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
status_t result = NO_ERROR;
- if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) == -1) {
+ if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {
+ mMaxThreads = maxThreads;
+ } else {
result = -errno;
ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
}
@@ -322,7 +325,7 @@
close(fd);
fd = -1;
}
- size_t maxThreads = 15;
+ size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
@@ -336,6 +339,10 @@
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
+ , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
+ , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
+ , mExecutingThreadsCount(0)
+ , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
diff --git a/libs/binder/tests/Android.mk b/libs/binder/tests/Android.mk
new file mode 100644
index 0000000..3668729
--- /dev/null
+++ b/libs/binder/tests/Android.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2014 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+ifneq ($(TARGET_USES_64_BIT_BINDER),true)
+ifneq ($(TARGET_IS_64_BIT),true)
+LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
+endif
+endif
+
+LOCAL_MODULE := binderDriverInterfaceTest
+LOCAL_SRC_FILES := binderDriverInterfaceTest.cpp
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := binderLibTest
+LOCAL_SRC_FILES := binderLibTest.cpp
+LOCAL_SHARED_LIBRARIES := libbinder libutils
+include $(BUILD_NATIVE_TEST)
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
new file mode 100644
index 0000000..315f349
--- /dev/null
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2014 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gtest/gtest.h>
+#include <linux/binder.h>
+#include <binder/IBinder.h>
+#include <sys/mman.h>
+#include <poll.h>
+
+#define BINDER_DEV_NAME "/dev/binder"
+
+testing::Environment* binder_env;
+
+class BinderDriverInterfaceTestEnv : public ::testing::Environment {
+ virtual void SetUp() {
+ int ret;
+ uint32_t max_threads = 0;
+
+ m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK);
+ ASSERT_GE(m_binderFd, 0);
+ m_buffer = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0);
+ ASSERT_NE(m_buffer, (void *)NULL);
+ ret = ioctl(m_binderFd, BINDER_SET_MAX_THREADS, &max_threads);
+ EXPECT_EQ(0, ret);
+ EnterLooper();
+ }
+ virtual void TearDown() {
+ close(m_binderFd);
+ }
+ private:
+ int m_binderFd;
+ void *m_buffer;
+ public:
+ int getBinderFd(void) {
+ return m_binderFd;
+ }
+ void EnterLooper(void) {
+ int ret;
+ const uint32_t bc[] = {
+ BC_ENTER_LOOPER,
+ };
+ struct binder_write_read bwr = binder_write_read();
+ bwr.write_buffer = (uintptr_t)bc;
+ bwr.write_size = sizeof(bc);
+ ret = ioctl(m_binderFd, BINDER_WRITE_READ, &bwr);
+ EXPECT_EQ(0, ret);
+ if (ret < 0) {
+ EXPECT_EQ(0, errno);
+ }
+ EXPECT_EQ(sizeof(bc), bwr.write_consumed);
+ }
+};
+
+class BinderDriverInterfaceTest : public ::testing::Test {
+ public:
+ virtual void SetUp() {
+ m_binderFd = static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->getBinderFd();
+ }
+ virtual void TearDown() {
+ }
+ protected:
+ void binderTestIoctlRetErr2(int cmd, void *arg, int expect_ret, int expect_errno, int accept_errno) {
+ int ret;
+
+ ret = ioctl(m_binderFd, cmd, arg);
+ EXPECT_EQ(expect_ret, ret);
+ if (ret < 0) {
+ if (errno != accept_errno)
+ EXPECT_EQ(expect_errno, errno);
+ }
+ }
+ void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) {
+ binderTestIoctlRetErr2(cmd, arg, -1, expect_errno, accept_errno);
+ }
+ void binderTestIoctlErr1(int cmd, void *arg, int expect_errno) {
+ binderTestIoctlErr2(cmd, arg, expect_errno, expect_errno);
+ }
+ void binderTestIoctl(int cmd, void *arg) {
+ binderTestIoctlRetErr2(cmd, arg, 0, 0, 0);
+ }
+ void binderTestIoctlUnimplemented(int cmd, void *arg) {
+ int ret;
+
+ ret = ioctl(m_binderFd, cmd, arg);
+ if (ret < 0) {
+ /* Not currently implmented. Allow ret == -1, errno == EINVAL */
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EINVAL, errno);
+ }
+ }
+ void binderTestReadEmpty(void) {
+ size_t i;
+ uint32_t br[32];
+ struct binder_write_read bwr = binder_write_read();
+ SCOPED_TRACE("TestReadEmpty");
+ bwr.read_buffer = (uintptr_t)br;
+ bwr.read_size = sizeof(br);
+ binderTestIoctlErr1(BINDER_WRITE_READ, &bwr, EAGAIN);
+ EXPECT_EQ(0u, bwr.read_consumed);
+ for (i = 0; i * sizeof(uint32_t) < bwr.read_consumed; i++) {
+ SCOPED_TRACE(testing::Message() << "i = " << i);
+ EXPECT_EQ(BR_NOOP, br[i]);
+ }
+ }
+ void binderWaitForReadData(int timeout_ms) {
+ int ret;
+ pollfd pfd = pollfd();
+
+ pfd.fd = m_binderFd;
+ pfd.events = POLLIN;
+ ret = poll(&pfd, 1, timeout_ms);
+ EXPECT_EQ(1, ret);
+ }
+ private:
+ int m_binderFd;
+};
+
+TEST_F(BinderDriverInterfaceTest, Version) {
+ struct binder_version version;
+ binderTestIoctl(BINDER_VERSION, &version);
+ ASSERT_EQ(BINDER_CURRENT_PROTOCOL_VERSION, version.protocol_version);
+}
+
+TEST_F(BinderDriverInterfaceTest, WriteReadNull) {
+ binderTestIoctlErr1(BINDER_WRITE_READ, NULL, EFAULT);
+}
+
+TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNull) {
+ binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, NULL, EFAULT, EINVAL);
+}
+
+TEST_F(BinderDriverInterfaceTest, SetMaxThreadsNull) {
+ binderTestIoctlErr2(BINDER_SET_MAX_THREADS, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
+}
+
+TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNull) {
+ binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, NULL, EFAULT, EINVAL);
+}
+
+TEST_F(BinderDriverInterfaceTest, VersionNull) {
+ binderTestIoctlErr2(BINDER_VERSION, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
+}
+
+TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNoTest) {
+ int64_t idle_timeout = 100000;
+ binderTestIoctlUnimplemented(BINDER_SET_IDLE_TIMEOUT, &idle_timeout);
+}
+
+TEST_F(BinderDriverInterfaceTest, SetMaxThreads) {
+ uint32_t max_threads = 0;
+ binderTestIoctl(BINDER_SET_MAX_THREADS, &max_threads);
+}
+
+TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNoTest) {
+ int idle_priority = 0;
+ binderTestIoctlUnimplemented(BINDER_SET_IDLE_PRIORITY, &idle_priority);
+}
+
+TEST_F(BinderDriverInterfaceTest, SetContextMgrBusy) {
+ int32_t dummy = 0;
+ binderTestIoctlErr1(BINDER_SET_CONTEXT_MGR, &dummy, EBUSY);
+}
+
+TEST_F(BinderDriverInterfaceTest, ThreadExit) {
+ int32_t dummy = 0;
+ binderTestIoctl(BINDER_THREAD_EXIT, &dummy);
+ static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->EnterLooper();
+}
+
+TEST_F(BinderDriverInterfaceTest, WriteReadEmpty) {
+ struct binder_write_read bwr = binder_write_read();
+ binderTestIoctl(BINDER_WRITE_READ, &bwr);
+}
+
+TEST_F(BinderDriverInterfaceTest, Read) {
+ binderTestReadEmpty();
+}
+
+TEST_F(BinderDriverInterfaceTest, IncRefsAcquireReleaseDecRefs) {
+ const uint32_t bc[] = {
+ BC_INCREFS,
+ 0,
+ BC_ACQUIRE,
+ 0,
+ BC_RELEASE,
+ 0,
+ BC_DECREFS,
+ 0,
+ };
+ struct binder_write_read bwr = binder_write_read();
+ bwr.write_buffer = (uintptr_t)bc;
+ bwr.write_size = sizeof(bc);
+ binderTestIoctl(BINDER_WRITE_READ, &bwr);
+ EXPECT_EQ(sizeof(bc), bwr.write_consumed);
+ binderTestReadEmpty();
+}
+
+TEST_F(BinderDriverInterfaceTest, Transaction) {
+ binder_uintptr_t cookie = 1234;
+ struct {
+ uint32_t cmd1;
+ struct binder_transaction_data arg1;
+ } __attribute__((packed)) bc1 = {
+ .cmd1 = BC_TRANSACTION,
+ .arg1 = {
+ .target = { 0 },
+ .cookie = 0,
+ .code = android::IBinder::PING_TRANSACTION,
+ .flags = 0,
+ .sender_pid = 0,
+ .sender_euid = 0,
+ .data_size = 0,
+ .offsets_size = 0,
+ .data = {0, 0},
+ },
+ };
+ struct {
+ uint32_t cmd0;
+ uint32_t cmd1;
+ uint32_t cmd2;
+ binder_transaction_data arg2;
+ uint32_t pad[16];
+ } __attribute__((packed)) br;
+ struct binder_write_read bwr = binder_write_read();
+
+ bwr.write_buffer = (uintptr_t)&bc1;
+ bwr.write_size = sizeof(bc1);
+ bwr.read_buffer = (uintptr_t)&br;
+ bwr.read_size = sizeof(br);
+
+ {
+ SCOPED_TRACE("1st WriteRead");
+ binderTestIoctl(BINDER_WRITE_READ, &bwr);
+ }
+ EXPECT_EQ(sizeof(bc1), bwr.write_consumed);
+ if (bwr.read_consumed < offsetof(typeof(br), pad)) {
+ SCOPED_TRACE("2nd WriteRead");
+ binderWaitForReadData(10000);
+ binderTestIoctl(BINDER_WRITE_READ, &bwr);
+ }
+ EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed);
+ if (bwr.read_consumed > offsetof(typeof(br), cmd0))
+ EXPECT_EQ(BR_NOOP, br.cmd0);
+ if (bwr.read_consumed > offsetof(typeof(br), cmd1))
+ EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1);
+ if (bwr.read_consumed > offsetof(typeof(br), cmd2))
+ EXPECT_EQ(BR_REPLY, br.cmd2);
+ if (bwr.read_consumed >= offsetof(typeof(br), pad)) {
+ EXPECT_EQ(0u, br.arg2.target.ptr);
+ EXPECT_EQ(0u, br.arg2.cookie);
+ EXPECT_EQ(0u, br.arg2.code);
+ EXPECT_EQ(0u, br.arg2.flags);
+ EXPECT_EQ(0u, br.arg2.data_size);
+ EXPECT_EQ(0u, br.arg2.offsets_size);
+
+ SCOPED_TRACE("3rd WriteRead");
+
+ binderTestReadEmpty();
+
+ struct {
+ uint32_t cmd1;
+ binder_uintptr_t arg1;
+ } __attribute__((packed)) bc2 = {
+ .cmd1 = BC_FREE_BUFFER,
+ .arg1 = br.arg2.data.ptr.buffer,
+ };
+
+ bwr.write_buffer = (uintptr_t)&bc2;
+ bwr.write_size = sizeof(bc2);
+ bwr.write_consumed = 0;
+ bwr.read_size = 0;
+
+ binderTestIoctl(BINDER_WRITE_READ, &bwr);
+ EXPECT_EQ(sizeof(bc2), bwr.write_consumed);
+ }
+ binderTestReadEmpty();
+}
+
+TEST_F(BinderDriverInterfaceTest, RequestDeathNotification) {
+ binder_uintptr_t cookie = 1234;
+ struct {
+ uint32_t cmd0;
+ uint32_t arg0;
+ uint32_t cmd1;
+ struct binder_handle_cookie arg1;
+ uint32_t cmd2;
+ struct binder_handle_cookie arg2;
+ uint32_t cmd3;
+ uint32_t arg3;
+ } __attribute__((packed)) bc = {
+ .cmd0 = BC_INCREFS,
+ .arg0 = 0,
+ .cmd1 = BC_REQUEST_DEATH_NOTIFICATION,
+ .arg1 = {
+ .handle = 0,
+ .cookie = cookie,
+ },
+ .cmd2 = BC_CLEAR_DEATH_NOTIFICATION,
+ .arg2 = {
+ .handle = 0,
+ .cookie = cookie,
+ },
+ .cmd3 = BC_DECREFS,
+ .arg3 = 0,
+ };
+ struct {
+ uint32_t cmd0;
+ uint32_t cmd1;
+ binder_uintptr_t arg1;
+ uint32_t pad[16];
+ } __attribute__((packed)) br;
+ struct binder_write_read bwr = binder_write_read();
+
+ bwr.write_buffer = (uintptr_t)&bc;
+ bwr.write_size = sizeof(bc);
+ bwr.read_buffer = (uintptr_t)&br;
+ bwr.read_size = sizeof(br);
+
+ binderTestIoctl(BINDER_WRITE_READ, &bwr);
+ EXPECT_EQ(sizeof(bc), bwr.write_consumed);
+ EXPECT_EQ(sizeof(br) - sizeof(br.pad), bwr.read_consumed);
+ EXPECT_EQ(BR_NOOP, br.cmd0);
+ EXPECT_EQ(BR_CLEAR_DEATH_NOTIFICATION_DONE, br.cmd1);
+ EXPECT_EQ(cookie, br.arg1);
+ binderTestReadEmpty();
+}
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv());
+
+ return RUN_ALL_TESTS();
+}
+
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
new file mode 100644
index 0000000..3df3acf
--- /dev/null
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -0,0 +1,954 @@
+/*
+ * Copyright (C) 2014 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 <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gtest/gtest.h>
+
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+
+using namespace android;
+
+static testing::Environment* binder_env;
+static char *binderservername;
+static char binderserverarg[] = "--binderserver";
+
+static String16 binderLibTestServiceName = String16("test.binderLib");
+
+enum BinderLibTestTranscationCode {
+ BINDER_LIB_TEST_NOP_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+ BINDER_LIB_TEST_REGISTER_SERVER,
+ BINDER_LIB_TEST_ADD_SERVER,
+ BINDER_LIB_TEST_CALL_BACK,
+ BINDER_LIB_TEST_NOP_CALL_BACK,
+ BINDER_LIB_TEST_GET_ID_TRANSACTION,
+ BINDER_LIB_TEST_INDIRECT_TRANSACTION,
+ BINDER_LIB_TEST_SET_ERROR_TRANSACTION,
+ BINDER_LIB_TEST_GET_STATUS_TRANSACTION,
+ BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION,
+ BINDER_LIB_TEST_LINK_DEATH_TRANSACTION,
+ BINDER_LIB_TEST_WRITE_FILE_TRANSACTION,
+ BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION,
+ BINDER_LIB_TEST_EXIT_TRANSACTION,
+ BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION,
+ BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION,
+};
+
+pid_t start_server_process(int arg2)
+{
+ int ret;
+ pid_t pid;
+ status_t status;
+ int pipefd[2];
+ char stri[16];
+ char strpipefd1[16];
+ char *childargv[] = {
+ binderservername,
+ binderserverarg,
+ stri,
+ strpipefd1,
+ NULL
+ };
+
+ ret = pipe(pipefd);
+ if (ret < 0)
+ return ret;
+
+ snprintf(stri, sizeof(stri), "%d", arg2);
+ snprintf(strpipefd1, sizeof(strpipefd1), "%d", pipefd[1]);
+
+ pid = fork();
+ if (pid == -1)
+ return pid;
+ if (pid == 0) {
+ close(pipefd[0]);
+ execv(binderservername, childargv);
+ status = -errno;
+ write(pipefd[1], &status, sizeof(status));
+ fprintf(stderr, "execv failed, %s\n", strerror(errno));
+ _exit(EXIT_FAILURE);
+ }
+ close(pipefd[1]);
+ ret = read(pipefd[0], &status, sizeof(status));
+ //printf("pipe read returned %d, status %d\n", ret, status);
+ close(pipefd[0]);
+ if (ret == sizeof(status)) {
+ ret = status;
+ } else {
+ kill(pid, SIGKILL);
+ if (ret >= 0) {
+ ret = NO_INIT;
+ }
+ }
+ if (ret < 0) {
+ wait(NULL);
+ return ret;
+ }
+ return pid;
+}
+
+class BinderLibTestEnv : public ::testing::Environment {
+ public:
+ BinderLibTestEnv() {}
+ sp<IBinder> getServer(void) {
+ return m_server;
+ }
+
+ private:
+ virtual void SetUp() {
+ m_serverpid = start_server_process(0);
+ //printf("m_serverpid %d\n", m_serverpid);
+ ASSERT_GT(m_serverpid, 0);
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ //printf("%s: pid %d, get service\n", __func__, m_pid);
+ m_server = sm->getService(binderLibTestServiceName);
+ ASSERT_TRUE(m_server != NULL);
+ //printf("%s: pid %d, get service done\n", __func__, m_pid);
+ }
+ virtual void TearDown() {
+ status_t ret;
+ Parcel data, reply;
+ int exitStatus;
+ pid_t pid;
+
+ //printf("%s: pid %d\n", __func__, m_pid);
+ if (m_server != NULL) {
+ ret = m_server->transact(BINDER_LIB_TEST_GET_STATUS_TRANSACTION, data, &reply);
+ EXPECT_EQ(0, ret);
+ ret = m_server->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY);
+ EXPECT_EQ(0, ret);
+ }
+ if (m_serverpid > 0) {
+ //printf("wait for %d\n", m_pids[i]);
+ pid = wait(&exitStatus);
+ EXPECT_EQ(m_serverpid, pid);
+ EXPECT_TRUE(WIFEXITED(exitStatus));
+ EXPECT_EQ(0, WEXITSTATUS(exitStatus));
+ }
+ }
+
+ pid_t m_serverpid;
+ sp<IBinder> m_server;
+};
+
+class BinderLibTest : public ::testing::Test {
+ public:
+ virtual void SetUp() {
+ m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer();
+ }
+ virtual void TearDown() {
+ }
+ protected:
+ sp<IBinder> addServer(int32_t *idPtr = NULL)
+ {
+ int ret;
+ int32_t id;
+ Parcel data, reply;
+ sp<IBinder> binder;
+
+ ret = m_server->transact(BINDER_LIB_TEST_ADD_SERVER, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
+
+ EXPECT_FALSE(binder != NULL);
+ binder = reply.readStrongBinder();
+ EXPECT_TRUE(binder != NULL);
+ ret = reply.readInt32(&id);
+ EXPECT_EQ(NO_ERROR, ret);
+ if (idPtr)
+ *idPtr = id;
+ return binder;
+ }
+ void waitForReadData(int fd, int timeout_ms) {
+ int ret;
+ pollfd pfd = pollfd();
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ ret = poll(&pfd, 1, timeout_ms);
+ EXPECT_EQ(1, ret);
+ }
+
+ sp<IBinder> m_server;
+};
+
+class BinderLibTestBundle : public Parcel
+{
+ public:
+ BinderLibTestBundle(void) {}
+ BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
+ int32_t mark;
+ int32_t bundleLen;
+ size_t pos;
+
+ if (source->readInt32(&mark))
+ return;
+ if (mark != MARK_START)
+ return;
+ if (source->readInt32(&bundleLen))
+ return;
+ pos = source->dataPosition();
+ if (Parcel::appendFrom(source, pos, bundleLen))
+ return;
+ source->setDataPosition(pos + bundleLen);
+ if (source->readInt32(&mark))
+ return;
+ if (mark != MARK_END)
+ return;
+ m_isValid = true;
+ setDataPosition(0);
+ }
+ void appendTo(Parcel *dest) {
+ dest->writeInt32(MARK_START);
+ dest->writeInt32(dataSize());
+ dest->appendFrom(this, 0, dataSize());
+ dest->writeInt32(MARK_END);
+ };
+ bool isValid(void) {
+ return m_isValid;
+ }
+ private:
+ enum {
+ MARK_START = B_PACK_CHARS('B','T','B','S'),
+ MARK_END = B_PACK_CHARS('B','T','B','E'),
+ };
+ bool m_isValid;
+};
+
+class BinderLibTestEvent
+{
+ public:
+ BinderLibTestEvent(void)
+ : m_eventTriggered(false)
+ {
+ pthread_mutex_init(&m_waitMutex, NULL);
+ pthread_cond_init(&m_waitCond, NULL);
+ }
+ int waitEvent(int timeout_s)
+ {
+ int ret;
+ pthread_mutex_lock(&m_waitMutex);
+ if (!m_eventTriggered) {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+ pthread_cond_timeout_np(&m_waitCond, &m_waitMutex, timeout_s * 1000);
+#else
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += timeout_s;
+ pthread_cond_timedwait(&m_waitCond, &m_waitMutex, &ts);
+#endif
+ }
+ ret = m_eventTriggered ? NO_ERROR : TIMED_OUT;
+ pthread_mutex_unlock(&m_waitMutex);
+ return ret;
+ }
+ protected:
+ void triggerEvent(void) {
+ pthread_mutex_lock(&m_waitMutex);
+ pthread_cond_signal(&m_waitCond);
+ m_eventTriggered = true;
+ pthread_mutex_unlock(&m_waitMutex);
+ };
+ private:
+ pthread_mutex_t m_waitMutex;
+ pthread_cond_t m_waitCond;
+ bool m_eventTriggered;
+};
+
+class BinderLibTestCallBack : public BBinder, public BinderLibTestEvent
+{
+ public:
+ BinderLibTestCallBack()
+ : m_result(NOT_ENOUGH_DATA)
+ {
+ }
+ status_t getResult(void)
+ {
+ return m_result;
+ }
+
+ private:
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data, Parcel* reply,
+ uint32_t flags = 0)
+ {
+ (void)reply;
+ (void)flags;
+ switch(code) {
+ case BINDER_LIB_TEST_CALL_BACK:
+ m_result = data.readInt32();
+ triggerEvent();
+ return NO_ERROR;
+ default:
+ return UNKNOWN_TRANSACTION;
+ }
+ }
+
+ status_t m_result;
+};
+
+class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestEvent
+{
+ private:
+ virtual void binderDied(const wp<IBinder>& who) {
+ (void)who;
+ triggerEvent();
+ };
+};
+
+TEST_F(BinderLibTest, NopTransaction) {
+ status_t ret;
+ Parcel data, reply;
+ ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
+}
+
+TEST_F(BinderLibTest, SetError) {
+ int32_t testValue[] = { 0, -123, 123 };
+ for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) {
+ status_t ret;
+ Parcel data, reply;
+ data.writeInt32(testValue[i]);
+ ret = m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply);
+ EXPECT_EQ(testValue[i], ret);
+ }
+}
+
+TEST_F(BinderLibTest, GetId) {
+ status_t ret;
+ int32_t id;
+ Parcel data, reply;
+ ret = m_server->transact(BINDER_LIB_TEST_GET_ID_TRANSACTION, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
+ ret = reply.readInt32(&id);
+ EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(0, id);
+}
+
+TEST_F(BinderLibTest, PtrSize) {
+ status_t ret;
+ int32_t ptrsize;
+ Parcel data, reply;
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != NULL);
+ ret = server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
+ ret = reply.readInt32(&ptrsize);
+ EXPECT_EQ(NO_ERROR, ret);
+ RecordProperty("TestPtrSize", sizeof(void *));
+ RecordProperty("ServerPtrSize", sizeof(void *));
+}
+
+TEST_F(BinderLibTest, IndirectGetId2)
+{
+ status_t ret;
+ int32_t id;
+ int32_t count;
+ Parcel data, reply;
+ int32_t serverId[3];
+
+ data.writeInt32(ARRAY_SIZE(serverId));
+ for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) {
+ sp<IBinder> server;
+ BinderLibTestBundle datai;
+
+ server = addServer(&serverId[i]);
+ ASSERT_TRUE(server != NULL);
+ data.writeStrongBinder(server);
+ data.writeInt32(BINDER_LIB_TEST_GET_ID_TRANSACTION);
+ datai.appendTo(&data);
+ }
+
+ ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ ret = reply.readInt32(&id);
+ ASSERT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(0, id);
+
+ ret = reply.readInt32(&count);
+ ASSERT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(ARRAY_SIZE(serverId), count);
+
+ for (size_t i = 0; i < (size_t)count; i++) {
+ BinderLibTestBundle replyi(&reply);
+ EXPECT_TRUE(replyi.isValid());
+ ret = replyi.readInt32(&id);
+ EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(serverId[i], id);
+ EXPECT_EQ(replyi.dataSize(), replyi.dataPosition());
+ }
+
+ EXPECT_EQ(reply.dataSize(), reply.dataPosition());
+}
+
+TEST_F(BinderLibTest, IndirectGetId3)
+{
+ status_t ret;
+ int32_t id;
+ int32_t count;
+ Parcel data, reply;
+ int32_t serverId[3];
+
+ data.writeInt32(ARRAY_SIZE(serverId));
+ for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) {
+ sp<IBinder> server;
+ BinderLibTestBundle datai;
+ BinderLibTestBundle datai2;
+
+ server = addServer(&serverId[i]);
+ ASSERT_TRUE(server != NULL);
+ data.writeStrongBinder(server);
+ data.writeInt32(BINDER_LIB_TEST_INDIRECT_TRANSACTION);
+
+ datai.writeInt32(1);
+ datai.writeStrongBinder(m_server);
+ datai.writeInt32(BINDER_LIB_TEST_GET_ID_TRANSACTION);
+ datai2.appendTo(&datai);
+
+ datai.appendTo(&data);
+ }
+
+ ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ ret = reply.readInt32(&id);
+ ASSERT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(0, id);
+
+ ret = reply.readInt32(&count);
+ ASSERT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(ARRAY_SIZE(serverId), count);
+
+ for (size_t i = 0; i < (size_t)count; i++) {
+ int32_t counti;
+
+ BinderLibTestBundle replyi(&reply);
+ EXPECT_TRUE(replyi.isValid());
+ ret = replyi.readInt32(&id);
+ EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(serverId[i], id);
+
+ ret = replyi.readInt32(&counti);
+ ASSERT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(1, counti);
+
+ BinderLibTestBundle replyi2(&replyi);
+ EXPECT_TRUE(replyi2.isValid());
+ ret = replyi2.readInt32(&id);
+ EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(0, id);
+ EXPECT_EQ(replyi2.dataSize(), replyi2.dataPosition());
+
+ EXPECT_EQ(replyi.dataSize(), replyi.dataPosition());
+ }
+
+ EXPECT_EQ(reply.dataSize(), reply.dataPosition());
+}
+
+TEST_F(BinderLibTest, CallBack)
+{
+ status_t ret;
+ Parcel data, reply;
+ sp<BinderLibTestCallBack> callBack = new BinderLibTestCallBack();
+ data.writeStrongBinder(callBack);
+ ret = m_server->transact(BINDER_LIB_TEST_NOP_CALL_BACK, data, &reply, TF_ONE_WAY);
+ EXPECT_EQ(NO_ERROR, ret);
+ ret = callBack->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+ ret = callBack->getResult();
+ EXPECT_EQ(NO_ERROR, ret);
+}
+
+TEST_F(BinderLibTest, AddServer)
+{
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != NULL);
+}
+
+TEST_F(BinderLibTest, DeathNotificationNoRefs)
+{
+ status_t ret;
+
+ sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+ {
+ sp<IBinder> binder = addServer();
+ ASSERT_TRUE(binder != NULL);
+ ret = binder->linkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+ IPCThreadState::self()->flushCommands();
+ ret = testDeathRecipient->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+#if 0 /* Is there an unlink api that does not require a strong reference? */
+ ret = binder->unlinkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+#endif
+}
+
+TEST_F(BinderLibTest, DeathNotificationWeakRef)
+{
+ status_t ret;
+ wp<IBinder> wbinder;
+
+ sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+ {
+ sp<IBinder> binder = addServer();
+ ASSERT_TRUE(binder != NULL);
+ ret = binder->linkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+ wbinder = binder;
+ }
+ IPCThreadState::self()->flushCommands();
+ ret = testDeathRecipient->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+#if 0 /* Is there an unlink api that does not require a strong reference? */
+ ret = binder->unlinkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+#endif
+}
+
+TEST_F(BinderLibTest, DeathNotificationStrongRef)
+{
+ status_t ret;
+ sp<IBinder> sbinder;
+
+ sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+
+ {
+ sp<IBinder> binder = addServer();
+ ASSERT_TRUE(binder != NULL);
+ ret = binder->linkToDeath(testDeathRecipient);
+ EXPECT_EQ(NO_ERROR, ret);
+ sbinder = binder;
+ }
+ {
+ Parcel data, reply;
+ ret = sbinder->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY);
+ EXPECT_EQ(0, ret);
+ }
+ IPCThreadState::self()->flushCommands();
+ ret = testDeathRecipient->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+ ret = sbinder->unlinkToDeath(testDeathRecipient);
+ EXPECT_EQ(DEAD_OBJECT, ret);
+}
+
+TEST_F(BinderLibTest, DeathNotificationMultiple)
+{
+ status_t ret;
+ const int clientcount = 2;
+ sp<IBinder> target;
+ sp<IBinder> linkedclient[clientcount];
+ sp<BinderLibTestCallBack> callBack[clientcount];
+ sp<IBinder> passiveclient[clientcount];
+
+ target = addServer();
+ ASSERT_TRUE(target != NULL);
+ for (int i = 0; i < clientcount; i++) {
+ {
+ Parcel data, reply;
+
+ linkedclient[i] = addServer();
+ ASSERT_TRUE(linkedclient[i] != NULL);
+ callBack[i] = new BinderLibTestCallBack();
+ data.writeStrongBinder(target);
+ data.writeStrongBinder(callBack[i]);
+ ret = linkedclient[i]->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply, TF_ONE_WAY);
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+ {
+ Parcel data, reply;
+
+ passiveclient[i] = addServer();
+ ASSERT_TRUE(passiveclient[i] != NULL);
+ data.writeStrongBinder(target);
+ ret = passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data, &reply, TF_ONE_WAY);
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+ }
+ {
+ Parcel data, reply;
+ ret = target->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY);
+ EXPECT_EQ(0, ret);
+ }
+
+ for (int i = 0; i < clientcount; i++) {
+ ret = callBack[i]->waitEvent(5);
+ EXPECT_EQ(NO_ERROR, ret);
+ ret = callBack[i]->getResult();
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+}
+
+TEST_F(BinderLibTest, PassFile) {
+ int ret;
+ int pipefd[2];
+ uint8_t buf[1] = { 0 };
+ uint8_t write_value = 123;
+
+ ret = pipe2(pipefd, O_NONBLOCK);
+ ASSERT_EQ(0, ret);
+
+ {
+ Parcel data, reply;
+ uint8_t writebuf[1] = { write_value };
+
+ ret = data.writeFileDescriptor(pipefd[1], true);
+ EXPECT_EQ(NO_ERROR, ret);
+
+ ret = data.writeInt32(sizeof(writebuf));
+ EXPECT_EQ(NO_ERROR, ret);
+
+ ret = data.write(writebuf, sizeof(writebuf));
+ EXPECT_EQ(NO_ERROR, ret);
+
+ ret = m_server->transact(BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, data, &reply);
+ EXPECT_EQ(NO_ERROR, ret);
+ }
+
+ ret = read(pipefd[0], buf, sizeof(buf));
+ EXPECT_EQ(sizeof(buf), ret);
+ EXPECT_EQ(write_value, buf[0]);
+
+ waitForReadData(pipefd[0], 5000); /* wait for other proccess to close pipe */
+
+ ret = read(pipefd[0], buf, sizeof(buf));
+ EXPECT_EQ(0, ret);
+
+ close(pipefd[0]);
+}
+
+TEST_F(BinderLibTest, PromoteLocal) {
+ sp<IBinder> strong = new BBinder();
+ wp<IBinder> weak = strong;
+ sp<IBinder> strong_from_weak = weak.promote();
+ EXPECT_TRUE(strong != NULL);
+ EXPECT_EQ(strong, strong_from_weak);
+ strong = NULL;
+ strong_from_weak = NULL;
+ strong_from_weak = weak.promote();
+ EXPECT_TRUE(strong_from_weak == NULL);
+}
+
+TEST_F(BinderLibTest, PromoteRemote) {
+ int ret;
+ Parcel data, reply;
+ sp<IBinder> strong = new BBinder();
+ sp<IBinder> server = addServer();
+
+ ASSERT_TRUE(server != NULL);
+ ASSERT_TRUE(strong != NULL);
+
+ ret = data.writeWeakBinder(strong);
+ EXPECT_EQ(NO_ERROR, ret);
+
+ ret = server->transact(BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION, data, &reply);
+ EXPECT_GE(ret, 0);
+}
+
+class BinderLibTestService : public BBinder
+{
+ public:
+ BinderLibTestService(int32_t id)
+ : m_id(id)
+ , m_nextServerId(id + 1)
+ , m_serverStartRequested(false)
+ {
+ pthread_mutex_init(&m_serverWaitMutex, NULL);
+ pthread_cond_init(&m_serverWaitCond, NULL);
+ }
+ ~BinderLibTestService()
+ {
+ exit(EXIT_SUCCESS);
+ }
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) {
+ //printf("%s: code %d\n", __func__, code);
+ (void)flags;
+
+ if (getuid() != (uid_t)IPCThreadState::self()->getCallingUid()) {
+ return PERMISSION_DENIED;
+ }
+ switch (code) {
+ case BINDER_LIB_TEST_REGISTER_SERVER: {
+ int32_t id;
+ sp<IBinder> binder;
+ id = data.readInt32();
+ binder = data.readStrongBinder();
+ if (binder == NULL) {
+ return BAD_VALUE;
+ }
+
+ if (m_id != 0)
+ return INVALID_OPERATION;
+
+ pthread_mutex_lock(&m_serverWaitMutex);
+ if (m_serverStartRequested) {
+ m_serverStartRequested = false;
+ m_serverStarted = binder;
+ pthread_cond_signal(&m_serverWaitCond);
+ }
+ pthread_mutex_unlock(&m_serverWaitMutex);
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_ADD_SERVER: {
+ int ret;
+ uint8_t buf[1] = { 0 };
+ int serverid;
+
+ if (m_id != 0) {
+ return INVALID_OPERATION;
+ }
+ pthread_mutex_lock(&m_serverWaitMutex);
+ if (m_serverStartRequested) {
+ ret = -EBUSY;
+ } else {
+ serverid = m_nextServerId++;
+ m_serverStartRequested = true;
+
+ pthread_mutex_unlock(&m_serverWaitMutex);
+ ret = start_server_process(serverid);
+ pthread_mutex_lock(&m_serverWaitMutex);
+ }
+ if (ret > 0) {
+ if (m_serverStartRequested) {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+ ret = pthread_cond_timeout_np(&m_serverWaitCond, &m_serverWaitMutex, 5000);
+#else
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += 5;
+ ret = pthread_cond_timedwait(&m_serverWaitCond, &m_serverWaitMutex, &ts);
+#endif
+ }
+ if (m_serverStartRequested) {
+ m_serverStartRequested = false;
+ ret = -ETIMEDOUT;
+ } else {
+ reply->writeStrongBinder(m_serverStarted);
+ reply->writeInt32(serverid);
+ m_serverStarted = NULL;
+ ret = NO_ERROR;
+ }
+ } else if (ret >= 0) {
+ m_serverStartRequested = false;
+ ret = UNKNOWN_ERROR;
+ }
+ pthread_mutex_unlock(&m_serverWaitMutex);
+ return ret;
+ }
+ case BINDER_LIB_TEST_NOP_TRANSACTION:
+ return NO_ERROR;
+ case BINDER_LIB_TEST_NOP_CALL_BACK: {
+ Parcel data2, reply2;
+ sp<IBinder> binder;
+ binder = data.readStrongBinder();
+ if (binder == NULL) {
+ return BAD_VALUE;
+ }
+ reply2.writeInt32(NO_ERROR);
+ binder->transact(BINDER_LIB_TEST_CALL_BACK, data2, &reply2);
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_GET_ID_TRANSACTION:
+ reply->writeInt32(m_id);
+ return NO_ERROR;
+ case BINDER_LIB_TEST_INDIRECT_TRANSACTION: {
+ int32_t count;
+ uint32_t indirect_code;
+ sp<IBinder> binder;
+
+ count = data.readInt32();
+ reply->writeInt32(m_id);
+ reply->writeInt32(count);
+ for (int i = 0; i < count; i++) {
+ binder = data.readStrongBinder();
+ if (binder == NULL) {
+ return BAD_VALUE;
+ }
+ indirect_code = data.readInt32();
+ BinderLibTestBundle data2(&data);
+ if (!data2.isValid()) {
+ return BAD_VALUE;
+ }
+ BinderLibTestBundle reply2;
+ binder->transact(indirect_code, data2, &reply2);
+ reply2.appendTo(reply);
+ }
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_SET_ERROR_TRANSACTION:
+ reply->setError(data.readInt32());
+ return NO_ERROR;
+ case BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION:
+ reply->writeInt32(sizeof(void *));
+ return NO_ERROR;
+ case BINDER_LIB_TEST_GET_STATUS_TRANSACTION:
+ return NO_ERROR;
+ case BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION:
+ m_strongRef = data.readStrongBinder();
+ return NO_ERROR;
+ case BINDER_LIB_TEST_LINK_DEATH_TRANSACTION: {
+ int ret;
+ Parcel data2, reply2;
+ sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
+ sp<IBinder> target;
+ sp<IBinder> callback;
+
+ target = data.readStrongBinder();
+ if (target == NULL) {
+ return BAD_VALUE;
+ }
+ callback = data.readStrongBinder();
+ if (callback == NULL) {
+ return BAD_VALUE;
+ }
+ ret = target->linkToDeath(testDeathRecipient);
+ if (ret == NO_ERROR)
+ ret = testDeathRecipient->waitEvent(5);
+ data2.writeInt32(ret);
+ callback->transact(BINDER_LIB_TEST_CALL_BACK, data2, &reply2);
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_WRITE_FILE_TRANSACTION: {
+ int ret;
+ int32_t size;
+ const void *buf;
+ int fd;
+
+ fd = data.readFileDescriptor();
+ if (fd < 0) {
+ return BAD_VALUE;
+ }
+ ret = data.readInt32(&size);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ buf = data.readInplace(size);
+ if (buf == NULL) {
+ return BAD_VALUE;
+ }
+ ret = write(fd, buf, size);
+ if (ret != size)
+ return UNKNOWN_ERROR;
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_PROMOTE_WEAK_REF_TRANSACTION: {
+ int ret;
+ wp<IBinder> weak;
+ sp<IBinder> strong;
+ Parcel data2, reply2;
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> server = sm->getService(binderLibTestServiceName);
+
+ weak = data.readWeakBinder();
+ if (weak == NULL) {
+ return BAD_VALUE;
+ }
+ strong = weak.promote();
+
+ ret = server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data2, &reply2);
+ if (ret != NO_ERROR)
+ exit(EXIT_FAILURE);
+
+ if (strong == NULL) {
+ reply->setError(1);
+ }
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION:
+ alarm(10);
+ return NO_ERROR;
+ case BINDER_LIB_TEST_EXIT_TRANSACTION:
+ while (wait(NULL) != -1 || errno != ECHILD)
+ ;
+ exit(EXIT_SUCCESS);
+ default:
+ return UNKNOWN_TRANSACTION;
+ };
+ }
+ private:
+ int32_t m_id;
+ int32_t m_nextServerId;
+ pthread_mutex_t m_serverWaitMutex;
+ pthread_cond_t m_serverWaitCond;
+ bool m_serverStartRequested;
+ sp<IBinder> m_serverStarted;
+ sp<IBinder> m_strongRef;
+};
+
+int run_server(int index, int readypipefd)
+{
+ status_t ret;
+ sp<IServiceManager> sm = defaultServiceManager();
+ {
+ sp<BinderLibTestService> testService = new BinderLibTestService(index);
+ if (index == 0) {
+ ret = sm->addService(binderLibTestServiceName, testService);
+ } else {
+ sp<IBinder> server = sm->getService(binderLibTestServiceName);
+ Parcel data, reply;
+ data.writeInt32(index);
+ data.writeStrongBinder(testService);
+
+ ret = server->transact(BINDER_LIB_TEST_REGISTER_SERVER, data, &reply);
+ }
+ }
+ write(readypipefd, &ret, sizeof(ret));
+ close(readypipefd);
+ //printf("%s: ret %d\n", __func__, ret);
+ if (ret)
+ return 1;
+ //printf("%s: joinThreadPool\n", __func__);
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+ //printf("%s: joinThreadPool returned\n", __func__);
+ return 1; /* joinThreadPool should not return */
+}
+
+int main(int argc, char **argv) {
+ int ret;
+
+ if (argc == 3 && !strcmp(argv[1], "--servername")) {
+ binderservername = argv[2];
+ } else {
+ binderservername = argv[0];
+ }
+
+ if (argc == 4 && !strcmp(argv[1], binderserverarg)) {
+ return run_server(atoi(argv[2]), atoi(argv[3]));
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ binder_env = AddGlobalTestEnvironment(new BinderLibTestEnv());
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
+
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 24e5af0..7576994 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -18,6 +18,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <unistd.h>
#include <diskusage/dirsize.h>
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index ca94aa3..8a965dd 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -1,7 +1,42 @@
-LOCAL_PATH:= $(call my-dir)
+# Copyright 2010 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.
+
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
+LOCAL_CLANG := true
+LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
+
+# The static constructors and destructors in this library have not been noted to
+# introduce significant overheads
+LOCAL_CPPFLAGS += -Wno-exit-time-destructors
+LOCAL_CPPFLAGS += -Wno-global-constructors
+
+# We only care about compiling as C++14
+LOCAL_CPPFLAGS += -Wno-c++98-compat-pedantic
+
+# We don't need to enumerate every case in a switch as long as a default case
+# is present
+LOCAL_CPPFLAGS += -Wno-switch-enum
+
+# Allow calling variadic macros without a __VA_ARGS__ list
+LOCAL_CPPFLAGS += -Wno-gnu-zero-variadic-macro-arguments
+
+# Don't warn about struct padding
+LOCAL_CPPFLAGS += -Wno-padded
+
+LOCAL_SRC_FILES := \
IGraphicBufferConsumer.cpp \
IConsumerListener.cpp \
BitTube.cpp \
@@ -47,7 +82,7 @@
liblog
-LOCAL_MODULE:= libgui
+LOCAL_MODULE := libgui
ifeq ($(TARGET_BOARD_PLATFORM), tegra)
LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 3ed1f37..b653c5b 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -149,12 +149,12 @@
ssize_t size = tube->write(vaddr, count*objSize);
// should never happen because of SOCK_SEQPACKET
- LOG_ALWAYS_FATAL_IF((size >= 0) && (size % objSize),
+ LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
"BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
count, objSize, size);
//ALOGE_IF(size<0, "error %d sending %d events", size, count);
- return size < 0 ? size : size / objSize;
+ return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
@@ -164,12 +164,12 @@
ssize_t size = tube->read(vaddr, count*objSize);
// should never happen because of SOCK_SEQPACKET
- LOG_ALWAYS_FATAL_IF((size >= 0) && (size % objSize),
+ LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
"BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
count, objSize, size);
//ALOGE_IF(size<0, "error %d receiving %d events", size, count);
- return size < 0 ? size : size / objSize;
+ return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index e6fc791..8f64ae0 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -28,6 +28,7 @@
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mTimestamp(0),
mIsAutoTimestamp(false),
+ mDataSpace(HAL_DATASPACE_UNKNOWN),
mFrameNumber(0),
mSlot(INVALID_BUFFER_SLOT),
mIsDroppable(false),
@@ -38,66 +39,67 @@
BufferItem::~BufferItem() {}
-BufferItem::operator IGraphicBufferConsumer::BufferItem() const {
- IGraphicBufferConsumer::BufferItem bufferItem;
- bufferItem.mGraphicBuffer = mGraphicBuffer;
- bufferItem.mFence = mFence;
- bufferItem.mCrop = mCrop;
- bufferItem.mTransform = mTransform;
- bufferItem.mScalingMode = mScalingMode;
- bufferItem.mTimestamp = mTimestamp;
- bufferItem.mIsAutoTimestamp = mIsAutoTimestamp;
- bufferItem.mFrameNumber = mFrameNumber;
- bufferItem.mBuf = mSlot;
- bufferItem.mIsDroppable = mIsDroppable;
- bufferItem.mAcquireCalled = mAcquireCalled;
- bufferItem.mTransformToDisplayInverse = mTransformToDisplayInverse;
- return bufferItem;
+template <typename T>
+static void addAligned(size_t& size, T /* value */) {
+ size = FlattenableUtils::align<sizeof(T)>(size);
+ size += sizeof(T);
}
size_t BufferItem::getPodSize() const {
- size_t c = sizeof(mCrop) +
- sizeof(mTransform) +
- sizeof(mScalingMode) +
- sizeof(mTimestamp) +
- sizeof(mIsAutoTimestamp) +
- sizeof(mFrameNumber) +
- sizeof(mSlot) +
- sizeof(mIsDroppable) +
- sizeof(mAcquireCalled) +
- sizeof(mTransformToDisplayInverse);
- return c;
+ size_t size = 0;
+ addAligned(size, mCrop);
+ addAligned(size, mTransform);
+ addAligned(size, mScalingMode);
+ addAligned(size, mTimestampLo);
+ addAligned(size, mTimestampHi);
+ addAligned(size, mIsAutoTimestamp);
+ addAligned(size, mDataSpace);
+ addAligned(size, mFrameNumberLo);
+ addAligned(size, mFrameNumberHi);
+ addAligned(size, mSlot);
+ addAligned(size, mIsDroppable);
+ addAligned(size, mAcquireCalled);
+ addAligned(size, mTransformToDisplayInverse);
+ return size;
}
size_t BufferItem::getFlattenedSize() const {
- size_t c = 0;
+ size_t size = sizeof(uint32_t); // Flags
if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFlattenedSize();
- FlattenableUtils::align<4>(c);
+ size += mGraphicBuffer->getFlattenedSize();
+ FlattenableUtils::align<4>(size);
}
if (mFence != 0) {
- c += mFence->getFlattenedSize();
- FlattenableUtils::align<4>(c);
+ size += mFence->getFlattenedSize();
+ FlattenableUtils::align<4>(size);
}
- return sizeof(int32_t) + c + getPodSize();
+ size += mSurfaceDamage.getFlattenedSize();
+ size = FlattenableUtils::align<8>(size);
+ return size + getPodSize();
}
size_t BufferItem::getFdCount() const {
- size_t c = 0;
+ size_t count = 0;
if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFdCount();
+ count += mGraphicBuffer->getFdCount();
}
if (mFence != 0) {
- c += mFence->getFdCount();
+ count += mFence->getFdCount();
}
- return c;
+ return count;
+}
+
+template <typename T>
+static void writeAligned(void*& buffer, size_t& size, T value) {
+ size -= FlattenableUtils::align<alignof(T)>(buffer);
+ FlattenableUtils::write(buffer, size, value);
}
status_t BufferItem::flatten(
void*& buffer, size_t& size, int*& fds, size_t& count) const {
// make sure we have enough space
- if (count < BufferItem::getFlattenedSize()) {
+ if (size < BufferItem::getFlattenedSize()) {
return NO_MEMORY;
}
@@ -121,30 +123,44 @@
flags |= 2;
}
- // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
+ status_t err = mSurfaceDamage.flatten(buffer, size);
+ if (err) return err;
+ FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
+
+ // Check we still have enough space
if (size < getPodSize()) {
return NO_MEMORY;
}
- FlattenableUtils::write(buffer, size, mCrop);
- FlattenableUtils::write(buffer, size, mTransform);
- FlattenableUtils::write(buffer, size, mScalingMode);
- FlattenableUtils::write(buffer, size, mTimestamp);
- FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::write(buffer, size, mFrameNumber);
- FlattenableUtils::write(buffer, size, mSlot);
- FlattenableUtils::write(buffer, size, mIsDroppable);
- FlattenableUtils::write(buffer, size, mAcquireCalled);
- FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
+ writeAligned(buffer, size, mCrop);
+ writeAligned(buffer, size, mTransform);
+ writeAligned(buffer, size, mScalingMode);
+ writeAligned(buffer, size, mTimestampLo);
+ writeAligned(buffer, size, mTimestampHi);
+ writeAligned(buffer, size, mIsAutoTimestamp);
+ writeAligned(buffer, size, mDataSpace);
+ writeAligned(buffer, size, mFrameNumberLo);
+ writeAligned(buffer, size, mFrameNumberHi);
+ writeAligned(buffer, size, mSlot);
+ writeAligned(buffer, size, mIsDroppable);
+ writeAligned(buffer, size, mAcquireCalled);
+ writeAligned(buffer, size, mTransformToDisplayInverse);
return NO_ERROR;
}
+template <typename T>
+static void readAligned(const void*& buffer, size_t& size, T& value) {
+ size -= FlattenableUtils::align<alignof(T)>(buffer);
+ FlattenableUtils::read(buffer, size, value);
+}
+
status_t BufferItem::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
- if (size < sizeof(uint32_t))
+ if (size < sizeof(uint32_t)) {
return NO_MEMORY;
+ }
uint32_t flags = 0;
FlattenableUtils::read(buffer, size, flags);
@@ -163,21 +179,28 @@
size -= FlattenableUtils::align<4>(buffer);
}
- // check we have enough space
+ status_t err = mSurfaceDamage.unflatten(buffer, size);
+ if (err) return err;
+ FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
+
+ // Check we still have enough space
if (size < getPodSize()) {
return NO_MEMORY;
}
- FlattenableUtils::read(buffer, size, mCrop);
- FlattenableUtils::read(buffer, size, mTransform);
- FlattenableUtils::read(buffer, size, mScalingMode);
- FlattenableUtils::read(buffer, size, mTimestamp);
- FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::read(buffer, size, mFrameNumber);
- FlattenableUtils::read(buffer, size, mSlot);
- FlattenableUtils::read(buffer, size, mIsDroppable);
- FlattenableUtils::read(buffer, size, mAcquireCalled);
- FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
+ readAligned(buffer, size, mCrop);
+ readAligned(buffer, size, mTransform);
+ readAligned(buffer, size, mScalingMode);
+ readAligned(buffer, size, mTimestampLo);
+ readAligned(buffer, size, mTimestampHi);
+ readAligned(buffer, size, mIsAutoTimestamp);
+ readAligned(buffer, size, mDataSpace);
+ readAligned(buffer, size, mFrameNumberLo);
+ readAligned(buffer, size, mFrameNumberHi);
+ readAligned(buffer, size, mSlot);
+ readAligned(buffer, size, mIsDroppable);
+ readAligned(buffer, size, mAcquireCalled);
+ readAligned(buffer, size, mTransformToDisplayInverse);
return NO_ERROR;
}
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index fe50c55..578b8d9 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -16,16 +16,17 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "BufferItemConsumer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Log.h>
+#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
-#define BI_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+//#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
namespace android {
@@ -44,8 +45,7 @@
}
}
-BufferItemConsumer::~BufferItemConsumer() {
-}
+BufferItemConsumer::~BufferItemConsumer() {}
void BufferItemConsumer::setName(const String8& name) {
Mutex::Autolock _l(mMutex);
@@ -100,14 +100,4 @@
return err;
}
-status_t BufferItemConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) {
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferSize(w, h);
-}
-
-status_t BufferItemConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
} // namespace android
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 61fd8c4..ccbb5a2 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -32,13 +32,21 @@
BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
void BufferQueue::ProxyConsumerListener::onFrameAvailable(
- const android::BufferItem& item) {
+ const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
if (listener != NULL) {
listener->onFrameAvailable(item);
}
}
+void BufferQueue::ProxyConsumerListener::onFrameReplaced(
+ const BufferItem& item) {
+ sp<ConsumerListener> listener(mConsumerListener.promote());
+ if (listener != NULL) {
+ listener->onFrameReplaced(item);
+ }
+}
+
void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
sp<ConsumerListener> listener(mConsumerListener.promote());
if (listener != NULL) {
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 36e3c06..bb3e1b0 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -36,143 +36,171 @@
BufferQueueConsumer::~BufferQueueConsumer() {}
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
- nsecs_t expectedPresent) {
+ nsecs_t expectedPresent, uint64_t maxFrameNumber) {
ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
- // Check that the consumer doesn't currently have the maximum number of
- // buffers acquired. We allow the max buffer count to be exceeded by one
- // buffer so that the consumer can successfully set up the newly acquired
- // buffer before releasing the old one.
- int numAcquiredBuffers = 0;
- for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
- ++numAcquiredBuffers;
+ int numDroppedBuffers = 0;
+ sp<IProducerListener> listener;
+ {
+ Mutex::Autolock lock(mCore->mMutex);
+
+ // Check that the consumer doesn't currently have the maximum number of
+ // buffers acquired. We allow the max buffer count to be exceeded by one
+ // buffer so that the consumer can successfully set up the newly acquired
+ // buffer before releasing the old one.
+ int numAcquiredBuffers = 0;
+ for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+ if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
+ ++numAcquiredBuffers;
+ }
}
- }
- if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
- BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
- numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
- return INVALID_OPERATION;
- }
+ if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
+ BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
+ numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
+ return INVALID_OPERATION;
+ }
- // Check if the queue is empty.
- // In asynchronous mode the list is guaranteed to be one buffer deep,
- // while in synchronous mode we use the oldest buffer.
- if (mCore->mQueue.empty()) {
- return NO_BUFFER_AVAILABLE;
- }
+ // Check if the queue is empty.
+ // In asynchronous mode the list is guaranteed to be one buffer deep,
+ // while in synchronous mode we use the oldest buffer.
+ if (mCore->mQueue.empty()) {
+ return NO_BUFFER_AVAILABLE;
+ }
- BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
+ BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
- // If expectedPresent is specified, we may not want to return a buffer yet.
- // If it's specified and there's more than one buffer queued, we may want
- // to drop a buffer.
- if (expectedPresent != 0) {
- const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
+ // If expectedPresent is specified, we may not want to return a buffer yet.
+ // If it's specified and there's more than one buffer queued, we may want
+ // to drop a buffer.
+ if (expectedPresent != 0) {
+ const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
- // The 'expectedPresent' argument indicates when the buffer is expected
- // to be presented on-screen. If the buffer's desired present time is
- // earlier (less) than expectedPresent -- meaning it will be displayed
- // on time or possibly late if we show it as soon as possible -- we
- // acquire and return it. If we don't want to display it until after the
- // expectedPresent time, we return PRESENT_LATER without acquiring it.
- //
- // To be safe, we don't defer acquisition if expectedPresent is more
- // than one second in the future beyond the desired present time
- // (i.e., we'd be holding the buffer for a long time).
- //
- // NOTE: Code assumes monotonic time values from the system clock
- // are positive.
-
- // Start by checking to see if we can drop frames. We skip this check if
- // the timestamps are being auto-generated by Surface. If the app isn't
- // generating timestamps explicitly, it probably doesn't want frames to
- // be discarded based on them.
- while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
- // If entry[1] is timely, drop entry[0] (and repeat). We apply an
- // additional criterion here: we only drop the earlier buffer if our
- // desiredPresent falls within +/- 1 second of the expected present.
- // Otherwise, bogus desiredPresent times (e.g., 0 or a small
- // relative timestamp), which normally mean "ignore the timestamp
- // and acquire immediately", would cause us to drop frames.
+ // The 'expectedPresent' argument indicates when the buffer is expected
+ // to be presented on-screen. If the buffer's desired present time is
+ // earlier (less) than expectedPresent -- meaning it will be displayed
+ // on time or possibly late if we show it as soon as possible -- we
+ // acquire and return it. If we don't want to display it until after the
+ // expectedPresent time, we return PRESENT_LATER without acquiring it.
//
- // We may want to add an additional criterion: don't drop the
- // earlier buffer if entry[1]'s fence hasn't signaled yet.
- const BufferItem& bufferItem(mCore->mQueue[1]);
- nsecs_t desiredPresent = bufferItem.mTimestamp;
- if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
- desiredPresent > expectedPresent) {
- // This buffer is set to display in the near future, or
- // desiredPresent is garbage. Either way we don't want to drop
- // the previous buffer just to get this on the screen sooner.
- BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
- PRId64 " (%" PRId64 ") now=%" PRId64,
+ // To be safe, we don't defer acquisition if expectedPresent is more
+ // than one second in the future beyond the desired present time
+ // (i.e., we'd be holding the buffer for a long time).
+ //
+ // NOTE: Code assumes monotonic time values from the system clock
+ // are positive.
+
+ // Start by checking to see if we can drop frames. We skip this check if
+ // the timestamps are being auto-generated by Surface. If the app isn't
+ // generating timestamps explicitly, it probably doesn't want frames to
+ // be discarded based on them.
+ while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
+ const BufferItem& bufferItem(mCore->mQueue[1]);
+
+ // If dropping entry[0] would leave us with a buffer that the
+ // consumer is not yet ready for, don't drop it.
+ if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
+ break;
+ }
+
+ // If entry[1] is timely, drop entry[0] (and repeat). We apply an
+ // additional criterion here: we only drop the earlier buffer if our
+ // desiredPresent falls within +/- 1 second of the expected present.
+ // Otherwise, bogus desiredPresent times (e.g., 0 or a small
+ // relative timestamp), which normally mean "ignore the timestamp
+ // and acquire immediately", would cause us to drop frames.
+ //
+ // We may want to add an additional criterion: don't drop the
+ // earlier buffer if entry[1]'s fence hasn't signaled yet.
+ nsecs_t desiredPresent = bufferItem.mTimestamp;
+ if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
+ desiredPresent > expectedPresent) {
+ // This buffer is set to display in the near future, or
+ // desiredPresent is garbage. Either way we don't want to drop
+ // the previous buffer just to get this on the screen sooner.
+ BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
+ PRId64 " (%" PRId64 ") now=%" PRId64,
+ desiredPresent, expectedPresent,
+ desiredPresent - expectedPresent,
+ systemTime(CLOCK_MONOTONIC));
+ break;
+ }
+
+ BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
+ " size=%zu",
+ desiredPresent, expectedPresent, mCore->mQueue.size());
+ if (mCore->stillTracking(front)) {
+ // Front buffer is still in mSlots, so mark the slot as free
+ mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
+ mCore->mFreeBuffers.push_back(front->mSlot);
+ listener = mCore->mConnectedProducerListener;
+ ++numDroppedBuffers;
+ }
+ mCore->mQueue.erase(front);
+ front = mCore->mQueue.begin();
+ }
+
+ // See if the front buffer is ready to be acquired
+ nsecs_t desiredPresent = front->mTimestamp;
+ bool bufferIsDue = desiredPresent <= expectedPresent ||
+ desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
+ bool consumerIsReady = maxFrameNumber > 0 ?
+ front->mFrameNumber <= maxFrameNumber : true;
+ if (!bufferIsDue || !consumerIsReady) {
+ BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
+ " (%" PRId64 ") now=%" PRId64 " frame=%" PRIu64
+ " consumer=%" PRIu64,
desiredPresent, expectedPresent,
desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
- break;
+ systemTime(CLOCK_MONOTONIC),
+ front->mFrameNumber, maxFrameNumber);
+ return PRESENT_LATER;
}
- BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
- " size=%zu",
- desiredPresent, expectedPresent, mCore->mQueue.size());
- if (mCore->stillTracking(front)) {
- // Front buffer is still in mSlots, so mark the slot as free
- mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
- }
- mCore->mQueue.erase(front);
- front = mCore->mQueue.begin();
- }
-
- // See if the front buffer is due
- nsecs_t desiredPresent = front->mTimestamp;
- if (desiredPresent > expectedPresent &&
- desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
- BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
- " (%" PRId64 ") now=%" PRId64,
- desiredPresent, expectedPresent,
+ BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
+ "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
desiredPresent - expectedPresent,
systemTime(CLOCK_MONOTONIC));
- return PRESENT_LATER;
}
- BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
- "(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
- desiredPresent - expectedPresent,
- systemTime(CLOCK_MONOTONIC));
+ int slot = front->mSlot;
+ *outBuffer = *front;
+ ATRACE_BUFFER_INDEX(slot);
+
+ BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
+ slot, front->mFrameNumber, front->mGraphicBuffer->handle);
+ // If the front buffer is still being tracked, update its slot state
+ if (mCore->stillTracking(front)) {
+ mSlots[slot].mAcquireCalled = true;
+ mSlots[slot].mNeedsCleanupOnRelease = false;
+ mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
+ mSlots[slot].mFence = Fence::NO_FENCE;
+ }
+
+ // If the buffer has previously been acquired by the consumer, set
+ // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
+ // on the consumer side
+ if (outBuffer->mAcquireCalled) {
+ outBuffer->mGraphicBuffer = NULL;
+ }
+
+ mCore->mQueue.erase(front);
+
+ // We might have freed a slot while dropping old buffers, or the producer
+ // may be blocked waiting for the number of buffers in the queue to
+ // decrease.
+ mCore->mDequeueCondition.broadcast();
+
+ ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
+
+ mCore->validateConsistencyLocked();
}
- int slot = front->mSlot;
- *outBuffer = *front;
- ATRACE_BUFFER_INDEX(slot);
-
- BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
- slot, front->mFrameNumber, front->mGraphicBuffer->handle);
- // If the front buffer is still being tracked, update its slot state
- if (mCore->stillTracking(front)) {
- mSlots[slot].mAcquireCalled = true;
- mSlots[slot].mNeedsCleanupOnRelease = false;
- mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
- mSlots[slot].mFence = Fence::NO_FENCE;
+ if (listener != NULL) {
+ for (int i = 0; i < numDroppedBuffers; ++i) {
+ listener->onBufferReleased();
+ }
}
- // If the buffer has previously been acquired by the consumer, set
- // mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
- // on the consumer side
- if (outBuffer->mAcquireCalled) {
- outBuffer->mGraphicBuffer = NULL;
- }
-
- mCore->mQueue.erase(front);
-
- // We might have freed a slot while dropping old buffers, or the producer
- // may be blocked waiting for the number of buffers in the queue to
- // decrease.
- mCore->mDequeueCondition.broadcast();
-
- ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
-
return NO_ERROR;
}
@@ -199,6 +227,7 @@
mCore->freeBufferLocked(slot);
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}
@@ -217,18 +246,11 @@
Mutex::Autolock lock(mCore->mMutex);
- // Make sure we don't have too many acquired buffers and find a free slot
- // to put the buffer into (the oldest if there are multiple).
+ // Make sure we don't have too many acquired buffers
int numAcquiredBuffers = 0;
- int found = BufferQueueCore::INVALID_BUFFER_SLOT;
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
++numAcquiredBuffers;
- } else if (mSlots[s].mBufferState == BufferSlot::FREE) {
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
- found = s;
- }
}
}
@@ -238,6 +260,24 @@
mCore->mMaxAcquiredBufferCount);
return INVALID_OPERATION;
}
+
+ if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
+ BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
+ "[queue %u]", buffer->getGenerationNumber(),
+ mCore->mGenerationNumber);
+ return BAD_VALUE;
+ }
+
+ // Find a free slot to put the buffer into
+ int found = BufferQueueCore::INVALID_BUFFER_SLOT;
+ if (!mCore->mFreeSlots.empty()) {
+ auto slot = mCore->mFreeSlots.begin();
+ found = *slot;
+ mCore->mFreeSlots.erase(slot);
+ } else if (!mCore->mFreeBuffers.empty()) {
+ found = mCore->mFreeBuffers.front();
+ mCore->mFreeBuffers.remove(found);
+ }
if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
BQ_LOGE("attachBuffer(P): could not find free buffer slot");
return NO_MEMORY;
@@ -271,6 +311,8 @@
// for attached buffers.
mSlots[*outSlot].mAcquireCalled = false;
+ mCore->validateConsistencyLocked();
+
return NO_ERROR;
}
@@ -282,6 +324,8 @@
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
releaseFence == NULL) {
+ BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
+ releaseFence.get());
return BAD_VALUE;
}
@@ -311,6 +355,7 @@
mSlots[slot].mEglFence = eglFence;
mSlots[slot].mFence = releaseFence;
mSlots[slot].mBufferState = BufferSlot::FREE;
+ mCore->mFreeBuffers.push_back(slot);
listener = mCore->mConnectedProducerListener;
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
} else if (mSlots[slot].mNeedsCleanupOnRelease) {
@@ -319,12 +364,13 @@
mSlots[slot].mNeedsCleanupOnRelease = false;
return STALE_BUFFER_SLOT;
} else {
- BQ_LOGV("releaseBuffer: attempted to release buffer slot %d "
+ BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
"but its state was %d", slot, mSlots[slot].mBufferState);
return BAD_VALUE;
}
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
} // Autolock scope
// Call back without lock held
@@ -488,7 +534,7 @@
mConsumerName = name;
}
-status_t BufferQueueConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
+status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
ATRACE_CALL();
BQ_LOGV("setDefaultBufferFormat: %u", defaultFormat);
Mutex::Autolock lock(mCore->mMutex);
@@ -496,6 +542,15 @@
return NO_ERROR;
}
+status_t BufferQueueConsumer::setDefaultBufferDataSpace(
+ android_dataspace defaultDataSpace) {
+ ATRACE_CALL();
+ BQ_LOGV("setDefaultBufferDataSpace: %u", defaultDataSpace);
+ Mutex::Autolock lock(mCore->mMutex);
+ mCore->mDefaultBufferDataSpace = defaultDataSpace;
+ return NO_ERROR;
+}
+
status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
ATRACE_CALL();
BQ_LOGV("setConsumerUsageBits: %#x", usage);
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index ec1e631..851a396 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -53,6 +53,8 @@
mConnectedProducerListener(),
mSlots(),
mQueue(),
+ mFreeSlots(),
+ mFreeBuffers(),
mOverrideMaxBufferCount(0),
mDequeueCondition(),
mUseAsyncBuffer(true),
@@ -60,13 +62,17 @@
mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
mDefaultWidth(1),
mDefaultHeight(1),
+ mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
mDefaultMaxBufferCount(2),
mMaxAcquiredBufferCount(1),
mBufferHasBeenQueued(false),
mFrameCounter(0),
mTransformHint(0),
mIsAllocating(false),
- mIsAllocatingCondition()
+ mIsAllocatingCondition(),
+ mAllowAllocation(true),
+ mBufferAge(0),
+ mGenerationNumber(0)
{
if (allocator == NULL) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -75,6 +81,9 @@
BQ_LOGE("createGraphicBufferAlloc failed");
}
}
+ for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
+ mFreeSlots.insert(slot);
+ }
}
BufferQueueCore::~BufferQueueCore() {}
@@ -189,13 +198,22 @@
void BufferQueueCore::freeBufferLocked(int slot) {
BQ_LOGV("freeBufferLocked: slot %d", slot);
+ bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL;
mSlots[slot].mGraphicBuffer.clear();
if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
mSlots[slot].mNeedsCleanupOnRelease = true;
}
+ if (mSlots[slot].mBufferState != BufferSlot::FREE) {
+ mFreeSlots.insert(slot);
+ } else if (hadBuffer) {
+ // If the slot was FREE, but we had a buffer, we need to move this slot
+ // from the free buffers list to the the free slots list
+ mFreeBuffers.remove(slot);
+ mFreeSlots.insert(slot);
+ }
mSlots[slot].mBufferState = BufferSlot::FREE;
- mSlots[slot].mFrameNumber = UINT32_MAX;
mSlots[slot].mAcquireCalled = false;
+ mSlots[slot].mFrameNumber = 0;
// Destroy fence as BufferQueue now takes ownership
if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
@@ -203,6 +221,7 @@
mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
}
mSlots[slot].mFence = Fence::NO_FENCE;
+ validateConsistencyLocked();
}
void BufferQueueCore::freeAllBuffersLocked() {
@@ -235,4 +254,48 @@
}
}
+void BufferQueueCore::validateConsistencyLocked() const {
+ static const useconds_t PAUSE_TIME = 0;
+ for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
+ bool isInFreeSlots = mFreeSlots.count(slot) != 0;
+ bool isInFreeBuffers =
+ std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
+ mFreeBuffers.cend();
+ if (mSlots[slot].mBufferState == BufferSlot::FREE) {
+ if (mSlots[slot].mGraphicBuffer == NULL) {
+ if (!isInFreeSlots) {
+ BQ_LOGE("Slot %d is FREE but is not in mFreeSlots", slot);
+ usleep(PAUSE_TIME);
+ }
+ if (isInFreeBuffers) {
+ BQ_LOGE("Slot %d is in mFreeSlots "
+ "but is also in mFreeBuffers", slot);
+ usleep(PAUSE_TIME);
+ }
+ } else {
+ if (!isInFreeBuffers) {
+ BQ_LOGE("Slot %d is FREE but is not in mFreeBuffers", slot);
+ usleep(PAUSE_TIME);
+ }
+ if (isInFreeSlots) {
+ BQ_LOGE("Slot %d is in mFreeBuffers "
+ "but is also in mFreeSlots", slot);
+ usleep(PAUSE_TIME);
+ }
+ }
+ } else {
+ if (isInFreeSlots) {
+ BQ_LOGE("Slot %d is in mFreeSlots but is not FREE (%d)",
+ slot, mSlots[slot].mBufferState);
+ usleep(PAUSE_TIME);
+ }
+ if (isInFreeBuffers) {
+ BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE (%d)",
+ slot, mSlots[slot].mBufferState);
+ usleep(PAUSE_TIME);
+ }
+ }
+ }
+}
+
} // namespace android
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 16b9747..87e5b4d 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -161,8 +161,6 @@
}
}
- // Look for a free buffer to give to the client
- *found = BufferQueueCore::INVALID_BUFFER_SLOT;
int dequeuedCount = 0;
int acquiredCount = 0;
for (int s = 0; s < maxBufferCount; ++s) {
@@ -173,15 +171,6 @@
case BufferSlot::ACQUIRED:
++acquiredCount;
break;
- case BufferSlot::FREE:
- // We return the oldest of the free buffers to avoid
- // stalling the producer if possible, since the consumer
- // may still have pending reads of in-flight buffers
- if (*found == BufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[*found].mFrameNumber) {
- *found = s;
- }
- break;
default:
break;
}
@@ -214,6 +203,8 @@
}
}
+ *found = BufferQueueCore::INVALID_BUFFER_SLOT;
+
// If we disconnect and reconnect quickly, we can be in a state where
// our slots are empty but we have many buffers in the queue. This can
// cause us to run out of memory if we outrun the consumer. Wait here if
@@ -223,6 +214,19 @@
if (tooManyBuffers) {
BQ_LOGV("%s: queue size is %zu, waiting", caller,
mCore->mQueue.size());
+ } else {
+ if (!mCore->mFreeBuffers.empty()) {
+ auto slot = mCore->mFreeBuffers.begin();
+ *found = *slot;
+ mCore->mFreeBuffers.erase(slot);
+ } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) {
+ auto slot = mCore->mFreeSlots.begin();
+ // Only return free slots up to the max buffer count
+ if (*slot < maxBufferCount) {
+ *found = *slot;
+ mCore->mFreeSlots.erase(slot);
+ }
+ }
}
// If no buffer is found, or if the queue has too many buffers
@@ -250,7 +254,7 @@
status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
sp<android::Fence> *outFence, bool async,
- uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
+ uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
ATRACE_CALL();
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
@@ -281,17 +285,39 @@
// Enable the usage bits the consumer requested
usage |= mCore->mConsumerUsageBits;
- int found;
- status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
- &found, &returnFlags);
- if (status != NO_ERROR) {
- return status;
+ const bool useDefaultSize = !width && !height;
+ if (useDefaultSize) {
+ width = mCore->mDefaultWidth;
+ height = mCore->mDefaultHeight;
}
- // This should not happen
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
- BQ_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
+ int found = BufferItem::INVALID_BUFFER_SLOT;
+ while (found == BufferItem::INVALID_BUFFER_SLOT) {
+ status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
+ &found, &returnFlags);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ // This should not happen
+ if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
+ BQ_LOGE("dequeueBuffer: no available buffer slots");
+ return -EBUSY;
+ }
+
+ const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
+
+ // If we are not allowed to allocate new buffers,
+ // waitForFreeSlotThenRelock must have returned a slot containing a
+ // buffer. If this buffer would require reallocation to meet the
+ // requested attributes, we free it and attempt to get another one.
+ if (!mCore->mAllowAllocation) {
+ if (buffer->needsReallocation(width, height, format, usage)) {
+ mCore->freeBufferLocked(found);
+ found = BufferItem::INVALID_BUFFER_SLOT;
+ continue;
+ }
+ }
}
*outSlot = found;
@@ -299,20 +325,11 @@
attachedByConsumer = mSlots[found].mAttachedByConsumer;
- const bool useDefaultSize = !width && !height;
- if (useDefaultSize) {
- width = mCore->mDefaultWidth;
- height = mCore->mDefaultHeight;
- }
-
mSlots[found].mBufferState = BufferSlot::DEQUEUED;
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if ((buffer == NULL) ||
- (static_cast<uint32_t>(buffer->width) != width) ||
- (static_cast<uint32_t>(buffer->height) != height) ||
- (static_cast<uint32_t>(buffer->format) != format) ||
- ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
+ buffer->needsReallocation(width, height, format, usage))
{
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
@@ -320,10 +337,19 @@
mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
+ mCore->mBufferAge = 0;
returnFlags |= BUFFER_NEEDS_REALLOCATION;
+ } else {
+ // We add 1 because that will be the frame number when this buffer
+ // is queued
+ mCore->mBufferAge =
+ mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
+ BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
+ mCore->mBufferAge);
+
if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
"slot=%d w=%d h=%d format=%u",
@@ -335,13 +361,15 @@
*outFence = mSlots[found].mFence;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
+
+ mCore->validateConsistencyLocked();
} // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
status_t error;
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
- width, height, format, usage, &error));
+ width, height, format, usage, &error));
if (graphicBuffer == NULL) {
BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
return error;
@@ -355,7 +383,7 @@
return NO_INIT;
}
- mSlots[*outSlot].mFrameNumber = UINT32_MAX;
+ graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
} // Autolock scope
}
@@ -414,6 +442,7 @@
mCore->freeBufferLocked(slot);
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}
@@ -438,27 +467,19 @@
return NO_INIT;
}
- // Find the oldest valid slot
- int found = BufferQueueCore::INVALID_BUFFER_SLOT;
- for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
- if (mSlots[s].mBufferState == BufferSlot::FREE &&
- mSlots[s].mGraphicBuffer != NULL) {
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT ||
- mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) {
- found = s;
- }
- }
- }
-
- if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
+ if (mCore->mFreeBuffers.empty()) {
return NO_MEMORY;
}
+ int found = mCore->mFreeBuffers.front();
+ mCore->mFreeBuffers.remove(found);
+
BQ_LOGV("detachNextBuffer detached slot %d", found);
*outBuffer = mSlots[found].mGraphicBuffer;
*outFence = mSlots[found].mFence;
mCore->freeBufferLocked(found);
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}
@@ -478,6 +499,13 @@
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
+ if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
+ BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
+ "[queue %u]", buffer->getGenerationNumber(),
+ mCore->mGenerationNumber);
+ return BAD_VALUE;
+ }
+
status_t returnFlags = NO_ERROR;
int found;
// TODO: Should we provide an async flag to attachBuffer? It seems
@@ -506,6 +534,8 @@
mSlots[*outSlot].mFence = Fence::NO_FENCE;
mSlots[*outSlot].mRequestBufferCalled = true;
+ mCore->validateConsistencyLocked();
+
return returnFlags;
}
@@ -516,14 +546,16 @@
int64_t timestamp;
bool isAutoTimestamp;
+ android_dataspace dataSpace;
Rect crop;
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
bool async;
sp<Fence> fence;
- input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
- &async, &fence, &stickyTransform);
+ input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
+ &transform, &async, &fence, &stickyTransform);
+ Region surfaceDamage = input.getSurfaceDamage();
if (fence == NULL) {
BQ_LOGE("queueBuffer: fence is NULL");
@@ -579,11 +611,11 @@
return BAD_VALUE;
}
- BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64
+ BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
" crop=[%d,%d,%d,%d] transform=%#x scale=%s",
- slot, mCore->mFrameCounter + 1, timestamp,
- crop.left, crop.top, crop.right, crop.bottom,
- transform, BufferItem::scalingModeName(scalingMode));
+ slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
+ crop.left, crop.top, crop.right, crop.bottom, transform,
+ BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
@@ -595,6 +627,11 @@
return BAD_VALUE;
}
+ // Override UNKNOWN dataspace with consumer default
+ if (dataSpace == HAL_DATASPACE_UNKNOWN) {
+ dataSpace = mCore->mDefaultBufferDataSpace;
+ }
+
mSlots[slot].mFence = fence;
mSlots[slot].mBufferState = BufferSlot::QUEUED;
++mCore->mFrameCounter;
@@ -603,16 +640,19 @@
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mCrop = crop;
- item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+ item.mTransform = transform &
+ ~static_cast<uint32_t>(NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
item.mTransformToDisplayInverse =
- bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
- item.mScalingMode = scalingMode;
+ (transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
+ item.mScalingMode = static_cast<uint32_t>(scalingMode);
item.mTimestamp = timestamp;
item.mIsAutoTimestamp = isAutoTimestamp;
+ item.mDataSpace = dataSpace;
item.mFrameNumber = mCore->mFrameCounter;
item.mSlot = slot;
item.mFence = fence;
item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
+ item.mSurfaceDamage = surfaceDamage;
mStickyTransform = stickyTransform;
@@ -630,9 +670,7 @@
// mark it as freed
if (mCore->stillTracking(front)) {
mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
- // Reset the frame number of the freed buffer so that it is
- // the first in line to be dequeued again
- mSlots[front->mSlot].mFrameNumber = 0;
+ mCore->mFreeBuffers.push_front(front->mSlot);
}
// Overwrite the droppable buffer with the incoming one
*front = item;
@@ -647,12 +685,15 @@
mCore->mDequeueCondition.broadcast();
output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint, mCore->mQueue.size());
+ mCore->mTransformHint,
+ static_cast<uint32_t>(mCore->mQueue.size()));
ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
// Take a ticket for the callback functions
callbackTicket = mNextCallbackTicket++;
+
+ mCore->validateConsistencyLocked();
} // Autolock scope
// Wait without lock held
@@ -713,10 +754,11 @@
return;
}
+ mCore->mFreeBuffers.push_front(slot);
mSlots[slot].mBufferState = BufferSlot::FREE;
- mSlots[slot].mFrameNumber = 0;
mSlots[slot].mFence = fence;
mCore->mDequeueCondition.broadcast();
+ mCore->validateConsistencyLocked();
}
int BufferQueueProducer::query(int what, int *outValue) {
@@ -736,25 +778,35 @@
int value;
switch (what) {
case NATIVE_WINDOW_WIDTH:
- value = mCore->mDefaultWidth;
+ value = static_cast<int32_t>(mCore->mDefaultWidth);
break;
case NATIVE_WINDOW_HEIGHT:
- value = mCore->mDefaultHeight;
+ value = static_cast<int32_t>(mCore->mDefaultHeight);
break;
case NATIVE_WINDOW_FORMAT:
- value = mCore->mDefaultBufferFormat;
+ value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
break;
case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
value = mCore->getMinUndequeuedBufferCountLocked(false);
break;
case NATIVE_WINDOW_STICKY_TRANSFORM:
- value = static_cast<int>(mStickyTransform);
+ value = static_cast<int32_t>(mStickyTransform);
break;
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
value = (mCore->mQueue.size() > 1);
break;
case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
- value = mCore->mConsumerUsageBits;
+ value = static_cast<int32_t>(mCore->mConsumerUsageBits);
+ break;
+ case NATIVE_WINDOW_DEFAULT_DATASPACE:
+ value = static_cast<int32_t>(mCore->mDefaultBufferDataSpace);
+ break;
+ case NATIVE_WINDOW_BUFFER_AGE:
+ if (mCore->mBufferAge > INT32_MAX) {
+ value = 0;
+ } else {
+ value = static_cast<int32_t>(mCore->mBufferAge);
+ }
break;
default:
return BAD_VALUE;
@@ -802,13 +854,14 @@
case NATIVE_WINDOW_API_CAMERA:
mCore->mConnectedApi = api;
output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint, mCore->mQueue.size());
+ mCore->mTransformHint,
+ static_cast<uint32_t>(mCore->mQueue.size()));
// Set up a death notification so that we can disconnect
// automatically if the remote producer dies
if (listener != NULL &&
- listener->asBinder()->remoteBinder() != NULL) {
- status = listener->asBinder()->linkToDeath(
+ IInterface::asBinder(listener)->remoteBinder() != NULL) {
+ status = IInterface::asBinder(listener)->linkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
if (status != NO_ERROR) {
BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
@@ -826,6 +879,7 @@
mCore->mBufferHasBeenQueued = false;
mCore->mDequeueBufferCannotBlock =
mCore->mConsumerControlledByApp && producerControlledByApp;
+ mCore->mAllowAllocation = true;
return status;
}
@@ -857,7 +911,7 @@
// Remove our death notification callback if we have one
if (mCore->mConnectedProducerListener != NULL) {
sp<IBinder> token =
- mCore->mConnectedProducerListener->asBinder();
+ IInterface::asBinder(mCore->mConnectedProducerListener);
// This can fail if we're here because of the death
// notification, but we just ignore it
token->unlinkToDeath(
@@ -868,8 +922,8 @@
mCore->mSidebandStream.clear();
mCore->mDequeueCondition.broadcast();
listener = mCore->mConsumerListener;
- } else {
- BQ_LOGE("disconnect(P): connected to another API "
+ } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("disconnect(P): still connected to another API "
"(cur=%d req=%d)", mCore->mConnectedApi, api);
status = BAD_VALUE;
}
@@ -904,19 +958,25 @@
}
void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
- uint32_t height, uint32_t format, uint32_t usage) {
+ uint32_t height, PixelFormat format, uint32_t usage) {
ATRACE_CALL();
while (true) {
Vector<int> freeSlots;
size_t newBufferCount = 0;
uint32_t allocWidth = 0;
uint32_t allocHeight = 0;
- uint32_t allocFormat = 0;
+ PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
uint32_t allocUsage = 0;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
+ if (!mCore->mAllowAllocation) {
+ BQ_LOGE("allocateBuffers: allocation is not allowed for this "
+ "BufferQueue");
+ return;
+ }
+
int currentBufferCount = 0;
for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
if (mSlots[slot].mGraphicBuffer != NULL) {
@@ -937,7 +997,8 @@
currentBufferCount, maxBufferCount);
if (maxBufferCount <= currentBufferCount)
return;
- newBufferCount = maxBufferCount - currentBufferCount;
+ newBufferCount =
+ static_cast<size_t>(maxBufferCount - currentBufferCount);
if (freeSlots.size() < newBufferCount) {
BQ_LOGE("allocateBuffers: ran out of free slots");
return;
@@ -950,7 +1011,7 @@
mCore->mIsAllocating = true;
} // Autolock scope
- Vector<sp<GraphicBuffer> > buffers;
+ Vector<sp<GraphicBuffer>> buffers;
for (size_t i = 0; i < newBufferCount; ++i) {
status_t result = NO_ERROR;
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
@@ -970,7 +1031,8 @@
Mutex::Autolock lock(mCore->mMutex);
uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
- uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
+ PixelFormat checkFormat = format != 0 ?
+ format : mCore->mDefaultBufferFormat;
uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
if (checkWidth != allocWidth || checkHeight != allocHeight ||
checkFormat != allocFormat || checkUsage != allocUsage) {
@@ -992,17 +1054,47 @@
}
mCore->freeBufferLocked(slot); // Clean up the slot first
mSlots[slot].mGraphicBuffer = buffers[i];
- mSlots[slot].mFrameNumber = 0;
mSlots[slot].mFence = Fence::NO_FENCE;
+
+ // freeBufferLocked puts this slot on the free slots list. Since
+ // we then attached a buffer, move the slot to free buffer list.
+ mCore->mFreeSlots.erase(slot);
+ mCore->mFreeBuffers.push_front(slot);
+
BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
}
mCore->mIsAllocating = false;
mCore->mIsAllocatingCondition.broadcast();
+ mCore->validateConsistencyLocked();
} // Autolock scope
}
}
+status_t BufferQueueProducer::allowAllocation(bool allow) {
+ ATRACE_CALL();
+ BQ_LOGV("allowAllocation: %s", allow ? "true" : "false");
+
+ Mutex::Autolock lock(mCore->mMutex);
+ mCore->mAllowAllocation = allow;
+ return NO_ERROR;
+}
+
+status_t BufferQueueProducer::setGenerationNumber(uint32_t generationNumber) {
+ ATRACE_CALL();
+ BQ_LOGV("setGenerationNumber: %u", generationNumber);
+
+ Mutex::Autolock lock(mCore->mMutex);
+ mCore->mGenerationNumber = generationNumber;
+ return NO_ERROR;
+}
+
+String8 BufferQueueProducer::getConsumerName() const {
+ ATRACE_CALL();
+ BQ_LOGV("getConsumerName: %s", mConsumerName.string());
+ return mConsumerName;
+}
+
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
// If we're here, it means that a producer we were connected to died.
// We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/BufferSlot.cpp b/libs/gui/BufferSlot.cpp
index b8877fe..01595de 100644
--- a/libs/gui/BufferSlot.cpp
+++ b/libs/gui/BufferSlot.cpp
@@ -24,8 +24,8 @@
case BufferSlot::QUEUED: return "QUEUED";
case BufferSlot::FREE: return "FREE";
case BufferSlot::ACQUIRED: return "ACQUIRED";
- default: return "Unknown";
}
+ return "Unknown";
}
} // namespace android
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 210e98e..04ab06b 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -27,6 +27,7 @@
#include <hardware/hardware.h>
+#include <gui/BufferItem.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
@@ -39,11 +40,11 @@
#include <utils/Trace.h>
// Macros for including the ConsumerBase name in log messages
-#define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define CB_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define CB_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
namespace android {
@@ -113,6 +114,21 @@
}
}
+void ConsumerBase::onFrameReplaced(const BufferItem &item) {
+ CB_LOGV("onFrameReplaced");
+
+ sp<FrameAvailableListener> listener;
+ {
+ Mutex::Autolock lock(mMutex);
+ listener = mFrameAvailableListener.promote();
+ }
+
+ if (listener != NULL) {
+ CB_LOGV("actually calling onFrameReplaced");
+ listener->onFrameReplaced(item);
+ }
+}
+
void ConsumerBase::onBuffersReleased() {
Mutex::Autolock lock(mMutex);
@@ -155,6 +171,11 @@
mConsumer.clear();
}
+bool ConsumerBase::isAbandoned() {
+ Mutex::Autolock _l(mMutex);
+ return mAbandoned;
+}
+
void ConsumerBase::setFrameAvailableListener(
const wp<FrameAvailableListener>& listener) {
CB_LOGV("setFrameAvailableListener");
@@ -162,6 +183,37 @@
mFrameAvailableListener = listener;
}
+status_t ConsumerBase::detachBuffer(int slot) {
+ CB_LOGV("detachBuffer");
+ Mutex::Autolock lock(mMutex);
+
+ status_t result = mConsumer->detachBuffer(slot);
+ if (result != NO_ERROR) {
+ CB_LOGE("Failed to detach buffer: %d", result);
+ return result;
+ }
+
+ freeBufferLocked(slot);
+
+ return result;
+}
+
+status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
+ Mutex::Autolock _l(mMutex);
+ return mConsumer->setDefaultBufferSize(width, height);
+}
+
+status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
+ Mutex::Autolock _l(mMutex);
+ return mConsumer->setDefaultBufferFormat(defaultFormat);
+}
+
+status_t ConsumerBase::setDefaultBufferDataSpace(
+ android_dataspace defaultDataSpace) {
+ Mutex::Autolock _l(mMutex);
+ return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
+}
+
void ConsumerBase::dump(String8& result) const {
dump(result, "");
}
@@ -179,9 +231,9 @@
}
}
-status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
- nsecs_t presentWhen) {
- status_t err = mConsumer->acquireBuffer(item, presentWhen);
+status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
+ nsecs_t presentWhen, uint64_t maxFrameNumber) {
+ status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
if (err != NO_ERROR) {
return err;
}
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index c541ff4..e29b740 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -16,22 +16,23 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "CpuConsumer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <cutils/compiler.h>
#include <utils/Log.h>
+#include <gui/BufferItem.h>
#include <gui/CpuConsumer.h>
-#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define CC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define CC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define CC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define CC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
namespace android {
CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
- uint32_t maxLockedBuffers, bool controlledByApp) :
+ size_t maxLockedBuffers, bool controlledByApp) :
ConsumerBase(bq, controlledByApp),
mMaxLockedBuffers(maxLockedBuffers),
mCurrentLockedBuffers(0)
@@ -40,7 +41,7 @@
mAcquiredBuffers.insertAt(0, maxLockedBuffers);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
- mConsumer->setMaxAcquiredBufferCount(maxLockedBuffers);
+ mConsumer->setMaxAcquiredBufferCount(static_cast<int32_t>(maxLockedBuffers));
}
CpuConsumer::~CpuConsumer() {
@@ -55,30 +56,16 @@
mConsumer->setConsumerName(name);
}
-status_t CpuConsumer::setDefaultBufferSize(uint32_t width, uint32_t height)
-{
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferSize(width, height);
-}
-
-status_t CpuConsumer::setDefaultBufferFormat(uint32_t defaultFormat)
-{
- Mutex::Autolock _l(mMutex);
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
static bool isPossiblyYUV(PixelFormat format) {
- switch ((int)format) {
+ switch (static_cast<int>(format)) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_sRGB_A_8888:
- case HAL_PIXEL_FORMAT_sRGB_X_8888:
case HAL_PIXEL_FORMAT_Y8:
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW16: // same as HAL_PIXEL_FORMAT_RAW_SENSOR
+ case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_RAW10:
case HAL_PIXEL_FORMAT_RAW_OPAQUE:
case HAL_PIXEL_FORMAT_BLOB:
@@ -100,12 +87,12 @@
if (!nativeBuffer) return BAD_VALUE;
if (mCurrentLockedBuffers == mMaxLockedBuffers) {
- CC_LOGW("Max buffers have been locked (%d), cannot lock anymore.",
+ CC_LOGW("Max buffers have been locked (%zd), cannot lock anymore.",
mMaxLockedBuffers);
return NOT_ENOUGH_DATA;
}
- BufferQueue::BufferItem b;
+ BufferItem b;
Mutex::Autolock _l(mMutex);
@@ -173,7 +160,7 @@
}
size_t lockedIdx = 0;
- for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) {
+ for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) {
if (mAcquiredBuffers[lockedIdx].mSlot ==
BufferQueue::INVALID_BUFFER_SLOT) {
break;
@@ -193,19 +180,20 @@
nativeBuffer->format = format;
nativeBuffer->flexFormat = flexFormat;
nativeBuffer->stride = (ycbcr.y != NULL) ?
- ycbcr.ystride :
+ static_cast<uint32_t>(ycbcr.ystride) :
mSlots[buf].mGraphicBuffer->getStride();
nativeBuffer->crop = b.mCrop;
nativeBuffer->transform = b.mTransform;
nativeBuffer->scalingMode = b.mScalingMode;
nativeBuffer->timestamp = b.mTimestamp;
+ nativeBuffer->dataSpace = b.mDataSpace;
nativeBuffer->frameNumber = b.mFrameNumber;
nativeBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
nativeBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
- nativeBuffer->chromaStride = ycbcr.cstride;
- nativeBuffer->chromaStep = ycbcr.chroma_step;
+ nativeBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
+ nativeBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
mCurrentLockedBuffers++;
@@ -215,10 +203,9 @@
status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
Mutex::Autolock _l(mMutex);
size_t lockedIdx = 0;
- status_t err;
void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
- for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) {
+ for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) {
if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break;
}
if (lockedIdx == mMaxLockedBuffers) {
@@ -229,13 +216,13 @@
return releaseAcquiredBufferLocked(lockedIdx);
}
-status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) {
+status_t CpuConsumer::releaseAcquiredBufferLocked(size_t lockedIdx) {
status_t err;
int fd = -1;
err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd);
if (err != OK) {
- CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
+ CC_LOGE("%s: Unable to unlock graphic buffer %zd", __FUNCTION__,
lockedIdx);
return err;
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 318c087..757e08a 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -29,6 +29,7 @@
#include <hardware/hardware.h>
+#include <gui/BufferItem.h>
#include <gui/GLConsumer.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
@@ -47,18 +48,28 @@
namespace android {
// Macros for including the GLConsumer name in log messages
-#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
+//#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
static const struct {
- size_t width, height;
+ uint32_t width, height;
char const* bits;
} kDebugData = { 15, 12,
- "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__"
- "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________"
+ "_______________"
+ "_______________"
+ "_____XX_XX_____"
+ "__X_X_____X_X__"
+ "__X_XXXXXXX_X__"
+ "__XXXXXXXXXXX__"
+ "___XX_XXX_XX___"
+ "____XXXXXXX____"
+ "_____X___X_____"
+ "____X_____X____"
+ "_______________"
+ "_______________"
};
// Transform matrices
@@ -135,7 +146,7 @@
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
mAttached(true)
{
- ST_LOGV("GLConsumer");
+ GLC_LOGV("GLConsumer");
memcpy(mCurrentTransformMatrix, mtxIdentity,
sizeof(mCurrentTransformMatrix));
@@ -154,7 +165,7 @@
mDefaultWidth(1),
mDefaultHeight(1),
mFilteringEnabled(true),
- mTexName(-1),
+ mTexName(0),
mUseFenceSync(useFenceSync),
mTexTarget(texTarget),
mEglDisplay(EGL_NO_DISPLAY),
@@ -162,7 +173,7 @@
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
mAttached(false)
{
- ST_LOGV("GLConsumer");
+ GLC_LOGV("GLConsumer");
memcpy(mCurrentTransformMatrix, mtxIdentity,
sizeof(mCurrentTransformMatrix));
@@ -186,11 +197,11 @@
status_t GLConsumer::updateTexImage() {
ATRACE_CALL();
- ST_LOGV("updateTexImage");
+ GLC_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
- ST_LOGE("updateTexImage: GLConsumer is abandoned!");
+ GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
return NO_INIT;
}
@@ -200,7 +211,7 @@
return err;
}
- BufferQueue::BufferItem item;
+ BufferItem item;
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
@@ -209,11 +220,11 @@
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
// We always bind the texture even if we don't update its contents.
- ST_LOGV("updateTexImage: no buffers were available");
+ GLC_LOGV("updateTexImage: no buffers were available");
glBindTexture(mTexTarget, mTexName);
err = NO_ERROR;
} else {
- ST_LOGE("updateTexImage: acquire failed: %s (%d)",
+ GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
strerror(-err), err);
}
return err;
@@ -234,11 +245,11 @@
status_t GLConsumer::releaseTexImage() {
ATRACE_CALL();
- ST_LOGV("releaseTexImage");
+ GLC_LOGV("releaseTexImage");
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
- ST_LOGE("releaseTexImage: GLConsumer is abandoned!");
+ GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
return NO_INIT;
}
@@ -258,13 +269,13 @@
int buf = mCurrentTexture;
if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
- ST_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
+ GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
if (mAttached) {
// Do whatever sync ops we need to do before releasing the slot.
err = syncForReleaseLocked(mEglDisplay);
if (err != NO_ERROR) {
- ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
+ GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
return err;
}
} else {
@@ -274,7 +285,7 @@
err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
if (err < NO_ERROR) {
- ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
+ GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
strerror(-err), err);
return err;
}
@@ -293,9 +304,9 @@
if (mAttached) {
// This binds a dummy buffer (mReleasedTexImage).
- status_t err = bindTextureImageLocked();
- if (err != NO_ERROR) {
- return err;
+ status_t result = bindTextureImageLocked();
+ if (result != NO_ERROR) {
+ return result;
}
} else {
// detached, don't touch the texture (and we may not even have an
@@ -316,14 +327,15 @@
GraphicBuffer::USAGE_SW_WRITE_RARELY);
uint32_t* bits;
buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
- size_t w = buffer->getStride();
- size_t h = buffer->getHeight();
- memset(bits, 0, w*h*4);
- for (size_t y=0 ; y<kDebugData.height ; y++) {
- for (size_t x=0 ; x<kDebugData.width ; x++) {
- bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF;
+ uint32_t stride = buffer->getStride();
+ uint32_t height = buffer->getHeight();
+ memset(bits, 0, stride * height * 4);
+ for (uint32_t y = 0; y < kDebugData.height; y++) {
+ for (uint32_t x = 0; x < kDebugData.width; x++) {
+ bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
+ 0xFF000000 : 0xFFFFFFFF;
}
- bits += w;
+ bits += stride;
}
buffer->unlock();
sReleasedTexImageBuffer = buffer;
@@ -331,9 +343,10 @@
return sReleasedTexImageBuffer;
}
-status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
- nsecs_t presentWhen) {
- status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
+status_t GLConsumer::acquireBufferLocked(BufferItem *item,
+ nsecs_t presentWhen, uint64_t maxFrameNumber) {
+ status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
+ maxFrameNumber);
if (err != NO_ERROR) {
return err;
}
@@ -362,14 +375,14 @@
return err;
}
-status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
+status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item)
{
status_t err = NO_ERROR;
int buf = item.mBuf;
if (!mAttached) {
- ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
+ GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
"ES context");
releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
@@ -391,7 +404,7 @@
// means the buffer was previously acquired).
err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
if (err != NO_ERROR) {
- ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
+ GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
mEglDisplay, buf);
releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
@@ -410,7 +423,7 @@
return err;
}
- ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
+ GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
mCurrentTexture, mCurrentTextureImage != NULL ?
mCurrentTextureImage->graphicBufferHandle() : 0,
buf, mSlots[buf].mGraphicBuffer->handle);
@@ -421,7 +434,7 @@
mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
if (status < NO_ERROR) {
- ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
+ GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
strerror(-status), status);
err = status;
// keep going, with error raised [?]
@@ -449,22 +462,22 @@
return INVALID_OPERATION;
}
- GLint error;
+ GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
+ GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
}
glBindTexture(mTexTarget, mTexName);
if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
mCurrentTextureImage == NULL) {
- ST_LOGE("bindTextureImage: no currently-bound texture");
+ GLC_LOGE("bindTextureImage: no currently-bound texture");
return NO_INIT;
}
status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
mCurrentCrop);
if (err != NO_ERROR) {
- ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
+ GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
mEglDisplay, mCurrentTexture);
return UNKNOWN_ERROR;
}
@@ -476,17 +489,17 @@
// forcing the creation of a new image.
if ((error = glGetError()) != GL_NO_ERROR) {
glBindTexture(mTexTarget, mTexName);
- status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
- mCurrentCrop,
- true);
- if (err != NO_ERROR) {
- ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
+ status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay,
+ mCurrentCrop,
+ true);
+ if (result != NO_ERROR) {
+ GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
mEglDisplay, mCurrentTexture);
return UNKNOWN_ERROR;
}
mCurrentTextureImage->bindToTextureTarget(mTexTarget);
if ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("bindTextureImage: error binding external image: %#04x", error);
+ GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
return UNKNOWN_ERROR;
}
}
@@ -511,12 +524,12 @@
}
if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
- ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
+ GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
return INVALID_OPERATION;
}
if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
- ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
+ GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
return INVALID_OPERATION;
}
@@ -531,7 +544,7 @@
status_t err = addReleaseFence(mCurrentTexture,
mCurrentTextureImage->graphicBuffer(), fence);
if (err != OK) {
- ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
+ GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
strerror(-err), err);
}
}
@@ -539,16 +552,16 @@
status_t GLConsumer::detachFromContext() {
ATRACE_CALL();
- ST_LOGV("detachFromContext");
+ GLC_LOGV("detachFromContext");
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
- ST_LOGE("detachFromContext: abandoned GLConsumer");
+ GLC_LOGE("detachFromContext: abandoned GLConsumer");
return NO_INIT;
}
if (!mAttached) {
- ST_LOGE("detachFromContext: GLConsumer is not attached to a "
+ GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
"context");
return INVALID_OPERATION;
}
@@ -557,12 +570,12 @@
EGLContext ctx = eglGetCurrentContext();
if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
- ST_LOGE("detachFromContext: invalid current EGLDisplay");
+ GLC_LOGE("detachFromContext: invalid current EGLDisplay");
return INVALID_OPERATION;
}
if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
- ST_LOGE("detachFromContext: invalid current EGLContext");
+ GLC_LOGE("detachFromContext: invalid current EGLContext");
return INVALID_OPERATION;
}
@@ -584,16 +597,16 @@
status_t GLConsumer::attachToContext(uint32_t tex) {
ATRACE_CALL();
- ST_LOGV("attachToContext");
+ GLC_LOGV("attachToContext");
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
- ST_LOGE("attachToContext: abandoned GLConsumer");
+ GLC_LOGE("attachToContext: abandoned GLConsumer");
return NO_INIT;
}
if (mAttached) {
- ST_LOGE("attachToContext: GLConsumer is already attached to a "
+ GLC_LOGE("attachToContext: GLConsumer is already attached to a "
"context");
return INVALID_OPERATION;
}
@@ -602,12 +615,12 @@
EGLContext ctx = eglGetCurrentContext();
if (dpy == EGL_NO_DISPLAY) {
- ST_LOGE("attachToContext: invalid current EGLDisplay");
+ GLC_LOGE("attachToContext: invalid current EGLDisplay");
return INVALID_OPERATION;
}
if (ctx == EGL_NO_CONTEXT) {
- ST_LOGE("attachToContext: invalid current EGLContext");
+ GLC_LOGE("attachToContext: invalid current EGLContext");
return INVALID_OPERATION;
}
@@ -636,14 +649,14 @@
status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
- ST_LOGV("syncForReleaseLocked");
+ GLC_LOGV("syncForReleaseLocked");
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (SyncFeatures::getInstance().useNativeFenceSync()) {
EGLSyncKHR sync = eglCreateSyncKHR(dpy,
EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
if (sync == EGL_NO_SYNC_KHR) {
- ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
+ GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
eglGetError());
return UNKNOWN_ERROR;
}
@@ -651,7 +664,7 @@
int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
eglDestroySyncKHR(dpy, sync);
if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
- ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
+ GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
"fd: %#x", eglGetError());
return UNKNOWN_ERROR;
}
@@ -659,7 +672,7 @@
status_t err = addReleaseFenceLocked(mCurrentTexture,
mCurrentTextureImage->graphicBuffer(), fence);
if (err != OK) {
- ST_LOGE("syncForReleaseLocked: error adding release fence: "
+ GLC_LOGE("syncForReleaseLocked: error adding release fence: "
"%s (%d)", strerror(-err), err);
return err;
}
@@ -672,11 +685,11 @@
// before the producer accesses it.
EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
if (result == EGL_FALSE) {
- ST_LOGE("syncForReleaseLocked: error waiting for previous "
+ GLC_LOGE("syncForReleaseLocked: error waiting for previous "
"fence: %#x", eglGetError());
return UNKNOWN_ERROR;
} else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
+ GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
"fence");
return TIMED_OUT;
}
@@ -687,7 +700,7 @@
// OpenGL ES context.
fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
if (fence == EGL_NO_SYNC_KHR) {
- ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
+ GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
eglGetError());
return UNKNOWN_ERROR;
}
@@ -699,7 +712,7 @@
return OK;
}
-bool GLConsumer::isExternalFormat(uint32_t format)
+bool GLConsumer::isExternalFormat(PixelFormat format)
{
switch (format) {
// supported YUV formats
@@ -730,14 +743,14 @@
void GLConsumer::setFilteringEnabled(bool enabled) {
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
- ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
+ GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
return;
}
bool needsRecompute = mFilteringEnabled != enabled;
mFilteringEnabled = enabled;
if (needsRecompute && mCurrentTextureImage==NULL) {
- ST_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
+ GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
}
if (needsRecompute && mCurrentTextureImage != NULL) {
@@ -746,7 +759,7 @@
}
void GLConsumer::computeCurrentTransformMatrixLocked() {
- ST_LOGV("computeCurrentTransformMatrixLocked");
+ GLC_LOGV("computeCurrentTransformMatrixLocked");
float xform[16];
for (int i = 0; i < 16; i++) {
@@ -778,7 +791,7 @@
NULL : mCurrentTextureImage->graphicBuffer();
if (buf == NULL) {
- ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL");
+ GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL");
}
float mtxBeforeFlipV[16];
@@ -850,13 +863,13 @@
}
nsecs_t GLConsumer::getTimestamp() {
- ST_LOGV("getTimestamp");
+ GLC_LOGV("getTimestamp");
Mutex::Autolock lock(mMutex);
return mCurrentTimestamp;
}
-nsecs_t GLConsumer::getFrameNumber() {
- ST_LOGV("getFrameNumber");
+uint64_t GLConsumer::getFrameNumber() {
+ GLC_LOGV("getFrameNumber");
Mutex::Autolock lock(mMutex);
return mCurrentFrameNumber;
}
@@ -872,30 +885,37 @@
Rect outCrop = mCurrentCrop;
if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- int32_t newWidth = mCurrentCrop.width();
- int32_t newHeight = mCurrentCrop.height();
+ uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
+ uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
newWidth = newHeight * mDefaultWidth / mDefaultHeight;
- ST_LOGV("too wide: newWidth = %d", newWidth);
+ GLC_LOGV("too wide: newWidth = %d", newWidth);
} else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
newHeight = newWidth * mDefaultHeight / mDefaultWidth;
- ST_LOGV("too tall: newHeight = %d", newHeight);
+ GLC_LOGV("too tall: newHeight = %d", newHeight);
}
+ uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
+ uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
+
// The crop is too wide
- if (newWidth < mCurrentCrop.width()) {
- int32_t dw = (newWidth - mCurrentCrop.width())/2;
- outCrop.left -=dw;
- outCrop.right += dw;
+ if (newWidth < currentWidth) {
+ uint32_t dw = currentWidth - newWidth;
+ auto halfdw = dw / 2;
+ outCrop.left += halfdw;
+ // Not halfdw because it would subtract 1 too few when dw is odd
+ outCrop.right -= (dw - halfdw);
// The crop is too tall
- } else if (newHeight < mCurrentCrop.height()) {
- int32_t dh = (newHeight - mCurrentCrop.height())/2;
- outCrop.top -= dh;
- outCrop.bottom += dh;
+ } else if (newHeight < currentHeight) {
+ uint32_t dh = currentHeight - newHeight;
+ auto halfdh = dh / 2;
+ outCrop.top += halfdh;
+ // Not halfdh because it would subtract 1 too few when dh is odd
+ outCrop.bottom -= (dh - halfdh);
}
- ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
+ GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
outCrop.left, outCrop.top,
outCrop.right,outCrop.bottom);
}
@@ -929,12 +949,12 @@
EGLContext ctx = eglGetCurrentContext();
if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
- ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
+ GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
return INVALID_OPERATION;
}
if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
- ST_LOGE("doGLFenceWait: invalid current EGLContext");
+ GLC_LOGE("doGLFenceWait: invalid current EGLContext");
return INVALID_OPERATION;
}
@@ -943,7 +963,7 @@
// Create an EGLSyncKHR from the current fence.
int fenceFd = mCurrentFence->dup();
if (fenceFd == -1) {
- ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
+ GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
return -errno;
}
EGLint attribs[] = {
@@ -954,7 +974,7 @@
EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
if (sync == EGL_NO_SYNC_KHR) {
close(fenceFd);
- ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
+ GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
eglGetError());
return UNKNOWN_ERROR;
}
@@ -966,7 +986,7 @@
EGLint eglErr = eglGetError();
eglDestroySyncKHR(dpy, sync);
if (eglErr != EGL_SUCCESS) {
- ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
+ GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
eglErr);
return UNKNOWN_ERROR;
}
@@ -974,7 +994,7 @@
status_t err = mCurrentFence->waitForever(
"GLConsumer::doGLFenceWaitLocked");
if (err != NO_ERROR) {
- ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
+ GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
return err;
}
}
@@ -984,7 +1004,7 @@
}
void GLConsumer::freeBufferLocked(int slotIndex) {
- ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
+ GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
if (slotIndex == mCurrentTexture) {
mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
}
@@ -993,7 +1013,7 @@
}
void GLConsumer::abandonLocked() {
- ST_LOGV("abandonLocked");
+ GLC_LOGV("abandonLocked");
mCurrentTextureImage.clear();
ConsumerBase::abandonLocked();
}
@@ -1004,11 +1024,17 @@
mConsumer->setConsumerName(name);
}
-status_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
+status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
Mutex::Autolock lock(mMutex);
return mConsumer->setDefaultBufferFormat(defaultFormat);
}
+status_t GLConsumer::setDefaultBufferDataSpace(
+ android_dataspace defaultDataSpace) {
+ Mutex::Autolock lock(mMutex);
+ return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
+}
+
status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
Mutex::Autolock lock(mMutex);
usage |= DEFAULT_USAGE_FLAGS;
@@ -1107,12 +1133,14 @@
}
void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
- glEGLImageTargetTexture2DOES(texTarget, (GLeglImageOES)mEglImage);
+ glEGLImageTargetTexture2DOES(texTarget,
+ static_cast<GLeglImageOES>(mEglImage));
}
EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
- EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
+ EGLClientBuffer cbuf =
+ static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
EGLint attrs[] = {
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_IMAGE_CROP_LEFT_ANDROID, crop.left,
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
index b360e81..9643402 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -31,9 +31,10 @@
GraphicBufferAlloc::~GraphicBufferAlloc() {
}
-sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error) {
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
+sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t usage, status_t* error) {
+ sp<GraphicBuffer> graphicBuffer(
+ new GraphicBuffer(width, height, format, usage));
status_t err = graphicBuffer->initCheck();
*error = err;
if (err != 0 || graphicBuffer->handle == 0) {
@@ -42,7 +43,7 @@
}
ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
"failed (%s), handle=%p",
- w, h, strerror(-err), graphicBuffer->handle);
+ width, height, strerror(-err), graphicBuffer->handle);
return 0;
}
return graphicBuffer;
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 409dfe4..cab7dc3 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -40,6 +40,8 @@
: BpInterface<IConsumerListener>(impl) {
}
+ virtual ~BpConsumerListener();
+
virtual void onFrameAvailable(const BufferItem& item) {
Parcel data, reply;
data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
@@ -60,6 +62,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpConsumerListener::~BpConsumerListener() {}
+
IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener");
// ----------------------------------------------------------------------
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index 887d176..9890f44 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -44,6 +44,8 @@
{
}
+ virtual ~BpDisplayEventConnection();
+
virtual sp<BitTube> getDataChannel() const
{
Parcel data, reply;
@@ -55,7 +57,7 @@
virtual void setVsyncRate(uint32_t count) {
Parcel data, reply;
data.writeInterfaceToken(IDisplayEventConnection::getInterfaceDescriptor());
- data.writeInt32(count);
+ data.writeUint32(count);
remote()->transact(SET_VSYNC_RATE, data, &reply);
}
@@ -66,6 +68,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpDisplayEventConnection::~BpDisplayEventConnection() {}
+
IMPLEMENT_META_INTERFACE(DisplayEventConnection, "android.gui.DisplayEventConnection");
// ----------------------------------------------------------------------------
@@ -79,17 +85,17 @@
sp<BitTube> channel(getDataChannel());
channel->writeToParcel(reply);
return NO_ERROR;
- } break;
+ }
case SET_VSYNC_RATE: {
CHECK_INTERFACE(IDisplayEventConnection, data, reply);
- setVsyncRate(data.readInt32());
+ setVsyncRate(data.readUint32());
return NO_ERROR;
- } break;
+ }
case REQUEST_NEXT_VSYNC: {
CHECK_INTERFACE(IDisplayEventConnection, data, reply);
requestNextVsync();
return NO_ERROR;
- } break;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index 139f219..3009989 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -42,20 +42,26 @@
{
}
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error) {
+ virtual ~BpGraphicBufferAlloc();
+
+ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t usage,
+ status_t* error) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
- data.writeInt32(w);
- data.writeInt32(h);
- data.writeInt32(format);
- data.writeInt32(usage);
+ data.writeUint32(width);
+ data.writeUint32(height);
+ data.writeInt32(static_cast<int32_t>(format));
+ data.writeUint32(usage);
remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
sp<GraphicBuffer> graphicBuffer;
status_t result = reply.readInt32();
if (result == NO_ERROR) {
graphicBuffer = new GraphicBuffer();
result = reply.read(*graphicBuffer);
+ if (result != NO_ERROR) {
+ graphicBuffer.clear();
+ }
// reply.readStrongBinder();
// here we don't even have to read the BufferReference from
// the parcel, it'll die with the parcel.
@@ -65,6 +71,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpGraphicBufferAlloc::~BpGraphicBufferAlloc() {}
+
IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
// ----------------------------------------------------------------------
@@ -74,27 +84,26 @@
{
// codes that don't require permission check
- /* BufferReference just keeps a strong reference to a
- * GraphicBuffer until it is destroyed (that is, until
- * no local or remote process have a reference to it).
- */
+ // BufferReference just keeps a strong reference to a GraphicBuffer until it
+ // is destroyed (that is, until no local or remote process have a reference
+ // to it).
class BufferReference : public BBinder {
- sp<GraphicBuffer> buffer;
+ sp<GraphicBuffer> mBuffer;
public:
- BufferReference(const sp<GraphicBuffer>& buffer) : buffer(buffer) { }
+ BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {}
};
- switch(code) {
+ switch (code) {
case CREATE_GRAPHIC_BUFFER: {
CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- PixelFormat format = data.readInt32();
- uint32_t usage = data.readInt32();
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ PixelFormat format = static_cast<PixelFormat>(data.readInt32());
+ uint32_t usage = data.readUint32();
status_t error;
sp<GraphicBuffer> result =
- createGraphicBuffer(w, h, format, usage, &error);
+ createGraphicBuffer(width, height, format, usage, &error);
reply->writeInt32(error);
if (result != 0) {
reply->write(*result);
@@ -107,7 +116,7 @@
reply->writeStrongBinder( new BufferReference(result) );
}
return NO_ERROR;
- } break;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index f6d087d..b86f4c5 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -23,6 +23,7 @@
#include <binder/Parcel.h>
#include <binder/IInterface.h>
+#include <gui/BufferItem.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferConsumer.h>
@@ -32,159 +33,6 @@
#include <system/window.h>
namespace android {
-// ---------------------------------------------------------------------------
-
-IGraphicBufferConsumer::BufferItem::BufferItem() :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mIsAutoTimestamp(false),
- mFrameNumber(0),
- mBuf(INVALID_BUFFER_SLOT),
- mIsDroppable(false),
- mAcquireCalled(false),
- mTransformToDisplayInverse(false) {
- mCrop.makeInvalid();
-}
-
-size_t IGraphicBufferConsumer::BufferItem::getPodSize() const {
- size_t c = sizeof(mCrop) +
- sizeof(mTransform) +
- sizeof(mScalingMode) +
- sizeof(mTimestamp) +
- sizeof(mIsAutoTimestamp) +
- sizeof(mFrameNumber) +
- sizeof(mBuf) +
- sizeof(mIsDroppable) +
- sizeof(mAcquireCalled) +
- sizeof(mTransformToDisplayInverse);
- return c;
-}
-
-size_t IGraphicBufferConsumer::BufferItem::getFlattenedSize() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFlattenedSize();
- c = FlattenableUtils::align<4>(c);
- }
- if (mFence != 0) {
- c += mFence->getFlattenedSize();
- c = FlattenableUtils::align<4>(c);
- }
- return sizeof(int32_t) + c + getPodSize();
-}
-
-size_t IGraphicBufferConsumer::BufferItem::getFdCount() const {
- size_t c = 0;
- if (mGraphicBuffer != 0) {
- c += mGraphicBuffer->getFdCount();
- }
- if (mFence != 0) {
- c += mFence->getFdCount();
- }
- return c;
-}
-
-static void writeBoolAsInt(void*& buffer, size_t& size, bool b) {
- FlattenableUtils::write(buffer, size, static_cast<int32_t>(b));
-}
-
-static bool readBoolFromInt(void const*& buffer, size_t& size) {
- int32_t i;
- FlattenableUtils::read(buffer, size, i);
- return static_cast<bool>(i);
-}
-
-status_t IGraphicBufferConsumer::BufferItem::flatten(
- void*& buffer, size_t& size, int*& fds, size_t& count) const {
-
- // make sure we have enough space
- if (size < BufferItem::getFlattenedSize()) {
- return NO_MEMORY;
- }
-
- // content flags are stored first
- uint32_t& flags = *static_cast<uint32_t*>(buffer);
-
- // advance the pointer
- FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
-
- flags = 0;
- if (mGraphicBuffer != 0) {
- status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 1;
- }
- if (mFence != 0) {
- status_t err = mFence->flatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- flags |= 2;
- }
-
- // check we have enough space (in case flattening the fence/graphicbuffer lied to us)
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, mCrop);
- FlattenableUtils::write(buffer, size, mTransform);
- FlattenableUtils::write(buffer, size, mScalingMode);
- FlattenableUtils::write(buffer, size, mTimestamp);
- writeBoolAsInt(buffer, size, mIsAutoTimestamp);
- FlattenableUtils::write(buffer, size, mFrameNumber);
- FlattenableUtils::write(buffer, size, mBuf);
- writeBoolAsInt(buffer, size, mIsDroppable);
- writeBoolAsInt(buffer, size, mAcquireCalled);
- writeBoolAsInt(buffer, size, mTransformToDisplayInverse);
-
- return NO_ERROR;
-}
-
-status_t IGraphicBufferConsumer::BufferItem::unflatten(
- void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-
- if (size < sizeof(uint32_t))
- return NO_MEMORY;
-
- uint32_t flags = 0;
- FlattenableUtils::read(buffer, size, flags);
-
- if (flags & 1) {
- mGraphicBuffer = new GraphicBuffer();
- status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- if (flags & 2) {
- mFence = new Fence();
- status_t err = mFence->unflatten(buffer, size, fds, count);
- if (err) return err;
- size -= FlattenableUtils::align<4>(buffer);
- }
-
- // check we have enough space
- if (size < getPodSize()) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, mCrop);
- FlattenableUtils::read(buffer, size, mTransform);
- FlattenableUtils::read(buffer, size, mScalingMode);
- FlattenableUtils::read(buffer, size, mTimestamp);
- mIsAutoTimestamp = readBoolFromInt(buffer, size);
- FlattenableUtils::read(buffer, size, mFrameNumber);
- FlattenableUtils::read(buffer, size, mBuf);
- mIsDroppable = readBoolFromInt(buffer, size);
- mAcquireCalled = readBoolFromInt(buffer, size);
- mTransformToDisplayInverse = readBoolFromInt(buffer, size);
-
- return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
enum {
ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
@@ -200,6 +48,7 @@
SET_MAX_ACQUIRED_BUFFER_COUNT,
SET_CONSUMER_NAME,
SET_DEFAULT_BUFFER_FORMAT,
+ SET_DEFAULT_BUFFER_DATA_SPACE,
SET_CONSUMER_USAGE_BITS,
SET_TRANSFORM_HINT,
GET_SIDEBAND_STREAM,
@@ -215,10 +64,14 @@
{
}
- virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) {
+ virtual ~BpGraphicBufferConsumer();
+
+ virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen,
+ uint64_t maxFrameNumber) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
data.writeInt64(presentWhen);
+ data.writeUint64(maxFrameNumber);
status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
if (result != NO_ERROR) {
return result;
@@ -261,7 +114,7 @@
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
data.writeInt32(buf);
- data.writeInt64(frameNumber);
+ data.writeInt64(static_cast<int64_t>(frameNumber));
data.write(*releaseFence);
status_t result = remote()->transact(RELEASE_BUFFER, data, &reply);
if (result != NO_ERROR) {
@@ -273,7 +126,7 @@
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeStrongBinder(consumer->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(consumer));
data.writeInt32(controlledByApp);
status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply);
if (result != NO_ERROR) {
@@ -303,15 +156,15 @@
if (result != NO_ERROR) {
return result;
}
- *slotMask = reply.readInt64();
+ *slotMask = static_cast<uint64_t>(reply.readInt64());
return reply.readInt32();
}
- virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) {
+ virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(w);
- data.writeInt32(h);
+ data.writeUint32(width);
+ data.writeUint32(height);
status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply);
if (result != NO_ERROR) {
return result;
@@ -358,10 +211,10 @@
remote()->transact(SET_CONSUMER_NAME, data, &reply);
}
- virtual status_t setDefaultBufferFormat(uint32_t defaultFormat) {
+ virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(defaultFormat);
+ data.writeInt32(static_cast<int32_t>(defaultFormat));
status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply);
if (result != NO_ERROR) {
return result;
@@ -369,10 +222,23 @@
return reply.readInt32();
}
+ virtual status_t setDefaultBufferDataSpace(
+ android_dataspace defaultDataSpace) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(defaultDataSpace));
+ status_t result = remote()->transact(SET_DEFAULT_BUFFER_DATA_SPACE,
+ data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ return reply.readInt32();
+ }
+
virtual status_t setConsumerUsageBits(uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(usage);
+ data.writeUint32(usage);
status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply);
if (result != NO_ERROR) {
return result;
@@ -383,7 +249,7 @@
virtual status_t setTransformHint(uint32_t hint) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(hint);
+ data.writeUint32(hint);
status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply);
if (result != NO_ERROR) {
return result;
@@ -415,6 +281,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpGraphicBufferConsumer::~BpGraphicBufferConsumer() {}
+
IMPLEMENT_META_INTERFACE(GraphicBufferConsumer, "android.gui.IGraphicBufferConsumer");
// ----------------------------------------------------------------------
@@ -427,19 +297,20 @@
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
BufferItem item;
int64_t presentWhen = data.readInt64();
- status_t result = acquireBuffer(&item, presentWhen);
+ uint64_t maxFrameNumber = data.readUint64();
+ status_t result = acquireBuffer(&item, presentWhen, maxFrameNumber);
status_t err = reply->write(item);
if (err) return err;
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case DETACH_BUFFER: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
int slot = data.readInt32();
int result = detachBuffer(slot);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case ATTACH_BUFFER: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
sp<GraphicBuffer> buffer = new GraphicBuffer();
@@ -449,11 +320,11 @@
reply->writeInt32(slot);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case RELEASE_BUFFER: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
int buf = data.readInt32();
- uint64_t frameNumber = data.readInt64();
+ uint64_t frameNumber = static_cast<uint64_t>(data.readInt64());
sp<Fence> releaseFence = new Fence();
status_t err = data.read(*releaseFence);
if (err) return err;
@@ -461,7 +332,7 @@
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case CONSUMER_CONNECT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() );
@@ -469,75 +340,92 @@
status_t result = consumerConnect(consumer, controlledByApp);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case CONSUMER_DISCONNECT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
status_t result = consumerDisconnect();
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case GET_RELEASED_BUFFERS: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
uint64_t slotMask;
status_t result = getReleasedBuffers(&slotMask);
- reply->writeInt64(slotMask);
+ reply->writeInt64(static_cast<int64_t>(slotMask));
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_DEFAULT_BUFFER_SIZE: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- status_t result = setDefaultBufferSize(w, h);
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ status_t result = setDefaultBufferSize(width, height);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_DEFAULT_MAX_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t bufferCount = data.readInt32();
+ int bufferCount = data.readInt32();
status_t result = setDefaultMaxBufferCount(bufferCount);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case DISABLE_ASYNC_BUFFER: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
status_t result = disableAsyncBuffer();
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_MAX_ACQUIRED_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t maxAcquiredBuffers = data.readInt32();
+ int maxAcquiredBuffers = data.readInt32();
status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_CONSUMER_NAME: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
setConsumerName( data.readString8() );
return NO_ERROR;
- } break;
+ }
case SET_DEFAULT_BUFFER_FORMAT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t defaultFormat = data.readInt32();
+ PixelFormat defaultFormat = static_cast<PixelFormat>(data.readInt32());
status_t result = setDefaultBufferFormat(defaultFormat);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
+ case SET_DEFAULT_BUFFER_DATA_SPACE: {
+ CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
+ android_dataspace defaultDataSpace =
+ static_cast<android_dataspace>(data.readInt32());
+ status_t result = setDefaultBufferDataSpace(defaultDataSpace);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
case SET_CONSUMER_USAGE_BITS: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t usage = data.readInt32();
+ uint32_t usage = data.readUint32();
status_t result = setConsumerUsageBits(usage);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_TRANSFORM_HINT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t hint = data.readInt32();
+ uint32_t hint = data.readUint32();
status_t result = setTransformHint(hint);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
+ case GET_SIDEBAND_STREAM: {
+ CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
+ sp<NativeHandle> stream = getSidebandStream();
+ reply->writeInt32(static_cast<int32_t>(stream != NULL));
+ if (stream != NULL) {
+ reply->writeNativeHandle(stream->handle());
+ }
+ return NO_ERROR;
+ }
case DUMP: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
String8 result = data.readString8();
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 1e28f9b..d7a7885 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -46,6 +46,9 @@
DISCONNECT,
SET_SIDEBAND_STREAM,
ALLOCATE_BUFFERS,
+ ALLOW_ALLOCATION,
+ SET_GENERATION_NUMBER,
+ GET_CONSUMER_NAME,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -56,6 +59,8 @@
{
}
+ virtual ~BpGraphicBufferProducer();
+
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
@@ -91,14 +96,15 @@
}
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+ uint32_t width, uint32_t height, PixelFormat format,
+ uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(async);
- data.writeInt32(w);
- data.writeInt32(h);
- data.writeInt32(format);
- data.writeInt32(usage);
+ data.writeInt32(static_cast<int32_t>(async));
+ data.writeUint32(width);
+ data.writeUint32(height);
+ data.writeInt32(static_cast<int32_t>(format));
+ data.writeUint32(usage);
status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
if (result != NO_ERROR) {
return result;
@@ -211,7 +217,7 @@
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
if (listener != NULL) {
data.writeInt32(1);
- data.writeStrongBinder(listener->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(listener));
} else {
data.writeInt32(0);
}
@@ -255,21 +261,59 @@
}
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage) {
+ PixelFormat format, uint32_t usage) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeInt32(static_cast<int32_t>(async));
- data.writeInt32(static_cast<int32_t>(width));
- data.writeInt32(static_cast<int32_t>(height));
+ data.writeUint32(width);
+ data.writeUint32(height);
data.writeInt32(static_cast<int32_t>(format));
- data.writeInt32(static_cast<int32_t>(usage));
+ data.writeUint32(usage);
status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
if (result != NO_ERROR) {
ALOGE("allocateBuffers failed to transact: %d", result);
}
}
+
+ virtual status_t allowAllocation(bool allow) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(allow));
+ status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
+ }
+
+ virtual status_t setGenerationNumber(uint32_t generationNumber) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeUint32(generationNumber);
+ status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
+ if (result == NO_ERROR) {
+ result = reply.readInt32();
+ }
+ return result;
+ }
+
+ virtual String8 getConsumerName() const {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ status_t result = remote()->transact(GET_CONSUMER_NAME, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getConsumerName failed to transact: %d", result);
+ return String8("TransactFailed");
+ }
+ return reply.readString8();
+ }
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpGraphicBufferProducer::~BpGraphicBufferProducer() {}
+
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
// ----------------------------------------------------------------------
@@ -289,24 +333,25 @@
}
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int bufferCount = data.readInt32();
int result = setBufferCount(bufferCount);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case DEQUEUE_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- bool async = data.readInt32();
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- uint32_t format = data.readInt32();
- uint32_t usage = data.readInt32();
+ bool async = static_cast<bool>(data.readInt32());
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ PixelFormat format = static_cast<PixelFormat>(data.readInt32());
+ uint32_t usage = data.readUint32();
int buf;
sp<Fence> fence;
- int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
+ int result = dequeueBuffer(&buf, &fence, async, width, height,
+ format, usage);
reply->writeInt32(buf);
reply->writeInt32(fence != NULL);
if (fence != NULL) {
@@ -314,14 +359,14 @@
}
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case DETACH_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int slot = data.readInt32();
int result = detachBuffer(slot);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case DETACH_NEXT_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
sp<GraphicBuffer> buffer;
@@ -339,7 +384,7 @@
}
}
return NO_ERROR;
- } break;
+ }
case ATTACH_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
sp<GraphicBuffer> buffer = new GraphicBuffer();
@@ -349,7 +394,7 @@
reply->writeInt32(slot);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case QUEUE_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int buf = data.readInt32();
@@ -360,7 +405,7 @@
status_t result = queueBuffer(buf, input, output);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case CANCEL_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int buf = data.readInt32();
@@ -368,7 +413,7 @@
data.read(*fence.get());
cancelBuffer(buf, fence);
return NO_ERROR;
- } break;
+ }
case QUERY: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int value;
@@ -377,7 +422,7 @@
reply->writeInt32(value);
reply->writeInt32(res);
return NO_ERROR;
- } break;
+ }
case CONNECT: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
sp<IProducerListener> listener;
@@ -392,14 +437,14 @@
status_t res = connect(listener, api, producerControlledByApp, output);
reply->writeInt32(res);
return NO_ERROR;
- } break;
+ }
case DISCONNECT: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int api = data.readInt32();
status_t res = disconnect(api);
reply->writeInt32(res);
return NO_ERROR;
- } break;
+ }
case SET_SIDEBAND_STREAM: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
sp<NativeHandle> stream;
@@ -409,16 +454,36 @@
status_t result = setSidebandStream(stream);
reply->writeInt32(result);
return NO_ERROR;
- } break;
- case ALLOCATE_BUFFERS:
+ }
+ case ALLOCATE_BUFFERS: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
bool async = static_cast<bool>(data.readInt32());
- uint32_t width = static_cast<uint32_t>(data.readInt32());
- uint32_t height = static_cast<uint32_t>(data.readInt32());
- uint32_t format = static_cast<uint32_t>(data.readInt32());
- uint32_t usage = static_cast<uint32_t>(data.readInt32());
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ PixelFormat format = static_cast<PixelFormat>(data.readInt32());
+ uint32_t usage = data.readUint32();
allocateBuffers(async, width, height, format, usage);
return NO_ERROR;
+ }
+ case ALLOW_ALLOCATION: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ bool allow = static_cast<bool>(data.readInt32());
+ status_t result = allowAllocation(allow);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case SET_GENERATION_NUMBER: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ uint32_t generationNumber = data.readUint32();
+ status_t result = setGenerationNumber(generationNumber);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case GET_CONSUMER_NAME: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ reply->writeString8(getConsumerName());
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
@@ -432,12 +497,14 @@
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
return sizeof(timestamp)
+ sizeof(isAutoTimestamp)
+ + sizeof(dataSpace)
+ sizeof(crop)
+ sizeof(scalingMode)
+ sizeof(transform)
+ sizeof(stickyTransform)
+ sizeof(async)
- + fence->getFlattenedSize();
+ + fence->getFlattenedSize()
+ + surfaceDamage.getFlattenedSize();
}
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
@@ -452,12 +519,17 @@
}
FlattenableUtils::write(buffer, size, timestamp);
FlattenableUtils::write(buffer, size, isAutoTimestamp);
+ FlattenableUtils::write(buffer, size, dataSpace);
FlattenableUtils::write(buffer, size, crop);
FlattenableUtils::write(buffer, size, scalingMode);
FlattenableUtils::write(buffer, size, transform);
FlattenableUtils::write(buffer, size, stickyTransform);
FlattenableUtils::write(buffer, size, async);
- return fence->flatten(buffer, size, fds, count);
+ status_t result = fence->flatten(buffer, size, fds, count);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ return surfaceDamage.flatten(buffer, size);
}
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
@@ -466,6 +538,7 @@
size_t minNeeded =
sizeof(timestamp)
+ sizeof(isAutoTimestamp)
+ + sizeof(dataSpace)
+ sizeof(crop)
+ sizeof(scalingMode)
+ sizeof(transform)
@@ -478,6 +551,7 @@
FlattenableUtils::read(buffer, size, timestamp);
FlattenableUtils::read(buffer, size, isAutoTimestamp);
+ FlattenableUtils::read(buffer, size, dataSpace);
FlattenableUtils::read(buffer, size, crop);
FlattenableUtils::read(buffer, size, scalingMode);
FlattenableUtils::read(buffer, size, transform);
@@ -485,7 +559,11 @@
FlattenableUtils::read(buffer, size, async);
fence = new Fence();
- return fence->unflatten(buffer, size, fds, count);
+ status_t result = fence->unflatten(buffer, size, fds, count);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ return surfaceDamage.unflatten(buffer, size);
}
}; // namespace android
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index efe4069..81adc95 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -30,6 +30,8 @@
BpProducerListener(const sp<IBinder>& impl)
: BpInterface<IProducerListener>(impl) {}
+ virtual ~BpProducerListener();
+
virtual void onBufferReleased() {
Parcel data, reply;
data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
@@ -37,6 +39,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpProducerListener::~BpProducerListener() {}
+
IMPLEMENT_META_INTERFACE(ProducerListener, "android.gui.IProducerListener")
status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp
index 28fcb53..dc7a35c 100644
--- a/libs/gui/ISensorEventConnection.cpp
+++ b/libs/gui/ISensorEventConnection.cpp
@@ -45,6 +45,8 @@
{
}
+ virtual ~BpSensorEventConnection();
+
virtual sp<BitTube> getSensorChannel() const
{
Parcel data, reply;
@@ -85,6 +87,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpSensorEventConnection::~BpSensorEventConnection() {}
+
IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection");
// ----------------------------------------------------------------------------
@@ -98,7 +104,7 @@
sp<BitTube> channel(getSensorChannel());
channel->writeToParcel(reply);
return NO_ERROR;
- } break;
+ }
case ENABLE_DISABLE: {
CHECK_INTERFACE(ISensorEventConnection, data, reply);
int handle = data.readInt32();
@@ -110,21 +116,21 @@
maxBatchReportLatencyNs, reservedFlags);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case SET_EVENT_RATE: {
CHECK_INTERFACE(ISensorEventConnection, data, reply);
int handle = data.readInt32();
- int ns = data.readInt64();
+ nsecs_t ns = data.readInt64();
status_t result = setEventRate(handle, ns);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case FLUSH_SENSOR: {
CHECK_INTERFACE(ISensorEventConnection, data, reply);
status_t result = flush();
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index 0b76f37..f581b5c 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -35,6 +35,7 @@
enum {
GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION,
CREATE_SENSOR_EVENT_CONNECTION,
+ ENABLE_DATA_INJECTION
};
class BpSensorServer : public BpInterface<ISensorServer>
@@ -45,14 +46,17 @@
{
}
- virtual Vector<Sensor> getSensorList()
+ virtual ~BpSensorServer();
+
+ virtual Vector<Sensor> getSensorList(const String16& opPackageName)
{
Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeString16(opPackageName);
remote()->transact(GET_SENSOR_LIST, data, &reply);
Sensor s;
Vector<Sensor> v;
- int32_t n = reply.readInt32();
+ uint32_t n = reply.readUint32();
v.setCapacity(n);
while (n--) {
reply.read(s);
@@ -61,15 +65,30 @@
return v;
}
- virtual sp<ISensorEventConnection> createSensorEventConnection()
+ virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
+ int mode, const String16& opPackageName)
{
Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ data.writeString8(packageName);
+ data.writeInt32(mode);
+ data.writeString16(opPackageName);
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
}
+
+ virtual int isDataInjectionEnabled() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+ remote()->transact(ENABLE_DATA_INJECTION, data, &reply);
+ return reply.readInt32();
+ }
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpSensorServer::~BpSensorServer() {}
+
IMPLEMENT_META_INTERFACE(SensorServer, "android.gui.SensorServer");
// ----------------------------------------------------------------------
@@ -80,20 +99,31 @@
switch(code) {
case GET_SENSOR_LIST: {
CHECK_INTERFACE(ISensorServer, data, reply);
- Vector<Sensor> v(getSensorList());
+ const String16& opPackageName = data.readString16();
+ Vector<Sensor> v(getSensorList(opPackageName));
size_t n = v.size();
- reply->writeInt32(n);
- for (size_t i=0 ; i<n ; i++) {
+ reply->writeUint32(static_cast<uint32_t>(n));
+ for (size_t i = 0; i < n; i++) {
reply->write(v[i]);
}
return NO_ERROR;
- } break;
+ }
case CREATE_SENSOR_EVENT_CONNECTION: {
CHECK_INTERFACE(ISensorServer, data, reply);
- sp<ISensorEventConnection> connection(createSensorEventConnection());
- reply->writeStrongBinder(connection->asBinder());
+ String8 packageName = data.readString8();
+ int32_t mode = data.readInt32();
+ const String16& opPackageName = data.readString16();
+ sp<ISensorEventConnection> connection(createSensorEventConnection(packageName, mode,
+ opPackageName));
+ reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
- } break;
+ }
+ case ENABLE_DATA_INJECTION: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ int32_t ret = isDataInjectionEnabled();
+ reply->writeInt32(static_cast<int32_t>(ret));
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index ebb687a..78886d5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -51,9 +51,10 @@
{
}
+ virtual ~BpSurfaceComposer();
+
virtual sp<ISurfaceComposerClient> createConnection()
{
- uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
@@ -62,7 +63,6 @@
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
{
- uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
@@ -76,23 +76,18 @@
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- {
- Vector<ComposerState>::const_iterator b(state.begin());
- Vector<ComposerState>::const_iterator e(state.end());
- data.writeInt32(state.size());
- for ( ; b != e ; ++b ) {
- b->write(data);
- }
+
+ data.writeUint32(static_cast<uint32_t>(state.size()));
+ for (const auto& s : state) {
+ s.write(data);
}
- {
- Vector<DisplayState>::const_iterator b(displays.begin());
- Vector<DisplayState>::const_iterator e(displays.end());
- data.writeInt32(displays.size());
- for ( ; b != e ; ++b ) {
- b->write(data);
- }
+
+ data.writeUint32(static_cast<uint32_t>(displays.size()));
+ for (const auto& d : displays) {
+ d.write(data);
}
- data.writeInt32(flags);
+
+ data.writeUint32(flags);
remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
@@ -113,12 +108,12 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
- data.writeStrongBinder(producer->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(producer));
data.write(sourceCrop);
- data.writeInt32(reqWidth);
- data.writeInt32(reqHeight);
- data.writeInt32(minLayerZ);
- data.writeInt32(maxLayerZ);
+ data.writeUint32(reqWidth);
+ data.writeUint32(reqHeight);
+ data.writeUint32(minLayerZ);
+ data.writeUint32(maxLayerZ);
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(rotation));
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
@@ -137,7 +132,7 @@
"interface descriptor: %s (%d)", strerror(-err), -err);
return false;
}
- err = data.writeStrongBinder(bufferProducer->asBinder());
+ err = data.writeStrongBinder(IInterface::asBinder(bufferProducer));
if (err != NO_ERROR) {
ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing "
"strong binder to parcel: %s (%d)", strerror(-err), -err);
@@ -226,7 +221,7 @@
remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply);
status_t result = reply.readInt32();
if (result == NO_ERROR) {
- size_t numConfigs = static_cast<size_t>(reply.readInt32());
+ size_t numConfigs = reply.readUint32();
configs->clear();
configs->resize(numConfigs);
for (size_t c = 0; c < numConfigs; ++c) {
@@ -289,6 +284,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpSurfaceComposer::~BpSurfaceComposer() {}
+
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
// ----------------------------------------------------------------------
@@ -299,46 +298,49 @@
switch(code) {
case CREATE_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = createConnection()->asBinder();
+ sp<IBinder> b = IInterface::asBinder(createConnection());
reply->writeStrongBinder(b);
return NO_ERROR;
}
case CREATE_GRAPHIC_BUFFER_ALLOC: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
+ sp<IBinder> b = IInterface::asBinder(createGraphicBufferAlloc());
reply->writeStrongBinder(b);
return NO_ERROR;
}
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- size_t count = data.readInt32();
+
+ size_t count = data.readUint32();
if (count > data.dataSize()) {
return BAD_VALUE;
}
ComposerState s;
Vector<ComposerState> state;
state.setCapacity(count);
- for (size_t i=0 ; i<count ; i++) {
+ for (size_t i = 0; i < count; i++) {
if (s.read(data) == BAD_VALUE) {
return BAD_VALUE;
}
state.add(s);
}
- count = data.readInt32();
+
+ count = data.readUint32();
if (count > data.dataSize()) {
return BAD_VALUE;
}
DisplayState d;
Vector<DisplayState> displays;
displays.setCapacity(count);
- for (size_t i=0 ; i<count ; i++) {
+ for (size_t i = 0; i < count; i++) {
if (d.read(data) == BAD_VALUE) {
return BAD_VALUE;
}
displays.add(d);
}
- uint32_t flags = data.readInt32();
- setTransactionState(state, displays, flags);
+
+ uint32_t stateFlags = data.readUint32();
+ setTransactionState(state, displays, stateFlags);
return NO_ERROR;
}
case BOOT_FINISHED: {
@@ -353,12 +355,12 @@
interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Rect sourceCrop;
data.read(sourceCrop);
- uint32_t reqWidth = data.readInt32();
- uint32_t reqHeight = data.readInt32();
- uint32_t minLayerZ = data.readInt32();
- uint32_t maxLayerZ = data.readInt32();
+ uint32_t reqWidth = data.readUint32();
+ uint32_t reqHeight = data.readUint32();
+ uint32_t minLayerZ = data.readUint32();
+ uint32_t maxLayerZ = data.readUint32();
bool useIdentityTransform = static_cast<bool>(data.readInt32());
- uint32_t rotation = data.readInt32();
+ int32_t rotation = data.readInt32();
status_t res = captureScreen(display, producer,
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
@@ -378,7 +380,7 @@
case CREATE_DISPLAY_EVENT_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IDisplayEventConnection> connection(createDisplayEventConnection());
- reply->writeStrongBinder(connection->asBinder());
+ reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
}
case CREATE_DISPLAY: {
@@ -409,7 +411,7 @@
status_t result = getDisplayConfigs(display, &configs);
reply->writeInt32(result);
if (result == NO_ERROR) {
- reply->writeInt32(static_cast<int32_t>(configs.size()));
+ reply->writeUint32(static_cast<uint32_t>(configs.size()));
for (size_t c = 0; c < configs.size(); ++c) {
memcpy(reply->writeInplace(sizeof(DisplayInfo)),
&configs[c], sizeof(DisplayInfo));
@@ -469,8 +471,6 @@
return BBinder::onTransact(code, data, reply, flags);
}
}
- // should be unreachable
- return NO_ERROR;
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 3da6423..2ecb908 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -51,17 +51,19 @@
: BpInterface<ISurfaceComposerClient>(impl) {
}
- virtual status_t createSurface(const String8& name, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t flags,
+ virtual ~BpSurfaceComposerClient();
+
+ virtual status_t createSurface(const String8& name, uint32_t width,
+ uint32_t height, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
data.writeString8(name);
- data.writeInt32(w);
- data.writeInt32(h);
- data.writeInt32(format);
- data.writeInt32(flags);
+ data.writeUint32(width);
+ data.writeUint32(height);
+ data.writeInt32(static_cast<int32_t>(format));
+ data.writeUint32(flags);
remote()->transact(CREATE_SURFACE, data, &reply);
*handle = reply.readStrongBinder();
*gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
@@ -94,6 +96,10 @@
}
};
+// Out-of-line virtual method definition to trigger vtable emission in this
+// translation unit (see clang warning -Wweak-vtables)
+BpSurfaceComposerClient::~BpSurfaceComposerClient() {}
+
IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
// ----------------------------------------------------------------------
@@ -105,31 +111,31 @@
case CREATE_SURFACE: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
String8 name = data.readString8();
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- PixelFormat format = data.readInt32();
- uint32_t flags = data.readInt32();
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ PixelFormat format = static_cast<PixelFormat>(data.readInt32());
+ uint32_t createFlags = data.readUint32();
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
- status_t result = createSurface(name, w, h, format, flags,
- &handle, &gbp);
+ status_t result = createSurface(name, width, height, format,
+ createFlags, &handle, &gbp);
reply->writeStrongBinder(handle);
- reply->writeStrongBinder(gbp->asBinder());
+ reply->writeStrongBinder(IInterface::asBinder(gbp));
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case DESTROY_SURFACE: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
reply->writeInt32(destroySurface( data.readStrongBinder() ) );
return NO_ERROR;
- } break;
+ }
case CLEAR_LAYER_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
sp<IBinder> handle = data.readStrongBinder();
status_t result = clearLayerFrameStats(handle);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
case GET_LAYER_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
sp<IBinder> handle = data.readStrongBinder();
@@ -138,7 +144,7 @@
reply->write(stats);
reply->writeInt32(result);
return NO_ERROR;
- } break;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 1183d59..00323dc 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -25,16 +25,16 @@
status_t layer_state_t::write(Parcel& output) const
{
output.writeStrongBinder(surface);
- output.writeInt32(what);
+ output.writeUint32(what);
output.writeFloat(x);
output.writeFloat(y);
- output.writeInt32(z);
- output.writeInt32(w);
- output.writeInt32(h);
- output.writeInt32(layerStack);
+ output.writeUint32(z);
+ output.writeUint32(w);
+ output.writeUint32(h);
+ output.writeUint32(layerStack);
output.writeFloat(alpha);
- output.writeInt32(flags);
- output.writeInt32(mask);
+ output.writeUint32(flags);
+ output.writeUint32(mask);
*reinterpret_cast<layer_state_t::matrix22_t *>(
output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix;
output.write(crop);
@@ -45,16 +45,16 @@
status_t layer_state_t::read(const Parcel& input)
{
surface = input.readStrongBinder();
- what = input.readInt32();
+ what = input.readUint32();
x = input.readFloat();
y = input.readFloat();
- z = input.readInt32();
- w = input.readInt32();
- h = input.readInt32();
- layerStack = input.readInt32();
+ z = input.readUint32();
+ w = input.readUint32();
+ h = input.readUint32();
+ layerStack = input.readUint32();
alpha = input.readFloat();
- flags = input.readInt32();
- mask = input.readInt32();
+ flags = static_cast<uint8_t>(input.readUint32());
+ mask = static_cast<uint8_t>(input.readUint32());
const void* matrix_data = input.readInplace(sizeof(layer_state_t::matrix22_t));
if (matrix_data) {
matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(matrix_data);
@@ -67,7 +67,7 @@
}
status_t ComposerState::write(Parcel& output) const {
- output.writeStrongBinder(client->asBinder());
+ output.writeStrongBinder(IInterface::asBinder(client));
return state.write(output);
}
@@ -79,27 +79,27 @@
status_t DisplayState::write(Parcel& output) const {
output.writeStrongBinder(token);
- output.writeStrongBinder(surface->asBinder());
- output.writeInt32(what);
- output.writeInt32(layerStack);
- output.writeInt32(orientation);
+ output.writeStrongBinder(IInterface::asBinder(surface));
+ output.writeUint32(what);
+ output.writeUint32(layerStack);
+ output.writeUint32(orientation);
output.write(viewport);
output.write(frame);
- output.writeInt32(width);
- output.writeInt32(height);
+ output.writeUint32(width);
+ output.writeUint32(height);
return NO_ERROR;
}
status_t DisplayState::read(const Parcel& input) {
token = input.readStrongBinder();
surface = interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
- what = input.readInt32();
- layerStack = input.readInt32();
- orientation = input.readInt32();
+ what = input.readUint32();
+ layerStack = input.readUint32();
+ orientation = input.readUint32();
input.read(viewport);
input.read(frame);
- width = input.readInt32();
- height = input.readInt32();
+ width = input.readUint32();
+ height = input.readUint32();
return NO_ERROR;
}
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 41a45fc..2545eec 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -25,6 +25,9 @@
#include <hardware/sensors.h>
+#include <binder/AppOpsManager.h>
+#include <binder/IServiceManager.h>
+
#include <gui/Sensor.h>
#include <log/log.h>
@@ -72,7 +75,7 @@
static_cast<int64_t>(hwSensor->maxDelay));
mMaxDelay = INT_MAX;
} else {
- mMaxDelay = (int32_t) hwSensor->maxDelay;
+ mMaxDelay = static_cast<int32_t>(hwSensor->maxDelay);
}
} else {
// For older hals set maxDelay to 0.
@@ -113,11 +116,13 @@
mStringType = SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED;
mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
break;
- case SENSOR_TYPE_HEART_RATE:
+ case SENSOR_TYPE_HEART_RATE: {
mStringType = SENSOR_STRING_TYPE_HEART_RATE;
mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
+ AppOpsManager appOps;
+ mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
- break;
+ } break;
case SENSOR_TYPE_LIGHT:
mStringType = SENSOR_STRING_TYPE_LIGHT;
mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
@@ -221,7 +226,7 @@
}
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
- mFlags = (int32_t) hwSensor->flags;
+ mFlags = static_cast<uint32_t>(hwSensor->flags);
} else {
// This is an OEM defined sensor on an older HAL. Use minDelay to determine the
// reporting mode of the sensor.
@@ -252,6 +257,17 @@
}
}
+
+ if (mRequiredPermission.length() > 0) {
+ // If the sensor is protected by a permission we need to know if it is
+ // a runtime one to determine whether we can use the permission cache.
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+ if (binder != 0) {
+ sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
+ mRequiredPermissionRuntime = permCtrl->isRuntimePermission(
+ String16(mRequiredPermission));
+ }
+ }
}
Sensor::~Sensor()
@@ -302,11 +318,11 @@
return mVersion;
}
-int32_t Sensor::getFifoReservedEventCount() const {
+uint32_t Sensor::getFifoReservedEventCount() const {
return mFifoReservedEventCount;
}
-int32_t Sensor::getFifoMaxEventCount() const {
+uint32_t Sensor::getFifoMaxEventCount() const {
return mFifoMaxEventCount;
}
@@ -318,11 +334,19 @@
return mRequiredPermission;
}
+bool Sensor::isRequiredPermissionRuntime() const {
+ return mRequiredPermissionRuntime;
+}
+
+int32_t Sensor::getRequiredAppOp() const {
+ return mRequiredAppOp;
+}
+
int32_t Sensor::getMaxDelay() const {
return mMaxDelay;
}
-int32_t Sensor::getFlags() const {
+uint32_t Sensor::getFlags() const {
return mFlags;
}
@@ -339,7 +363,8 @@
size_t fixedSize =
sizeof(int32_t) * 3 +
sizeof(float) * 4 +
- sizeof(int32_t) * 5;
+ sizeof(int32_t) * 6 +
+ sizeof(bool);
size_t variableSize =
sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) +
@@ -369,6 +394,8 @@
FlattenableUtils::write(buffer, size, mFifoMaxEventCount);
flattenString8(buffer, size, mStringType);
flattenString8(buffer, size, mRequiredPermission);
+ FlattenableUtils::write(buffer, size, mRequiredPermissionRuntime);
+ FlattenableUtils::write(buffer, size, mRequiredAppOp);
FlattenableUtils::write(buffer, size, mMaxDelay);
FlattenableUtils::write(buffer, size, mFlags);
return NO_ERROR;
@@ -407,6 +434,8 @@
if (!unflattenString8(buffer, size, mRequiredPermission)) {
return NO_MEMORY;
}
+ FlattenableUtils::read(buffer, size, mRequiredPermissionRuntime);
+ FlattenableUtils::read(buffer, size, mRequiredAppOp);
FlattenableUtils::read(buffer, size, mMaxDelay);
FlattenableUtils::read(buffer, size, mFlags);
return NO_ERROR;
@@ -414,7 +443,7 @@
void Sensor::flattenString8(void*& buffer, size_t& size,
const String8& string8) {
- uint32_t len = string8.length();
+ uint32_t len = static_cast<uint32_t>(string8.length());
FlattenableUtils::write(buffer, size, len);
memcpy(static_cast<char*>(buffer), string8.string(), len);
FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len));
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index 1305e9f..4b7986e 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -16,9 +16,11 @@
#define LOG_TAG "Sensors"
+#include <algorithm>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <linux/errno.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -31,6 +33,8 @@
#include <android/sensor.h>
+using std::min;
+
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
@@ -68,14 +72,14 @@
if (err < 0) {
return err;
}
- mAvailable = err;
+ mAvailable = static_cast<size_t>(err);
mConsumed = 0;
}
- size_t count = numEvents < mAvailable ? numEvents : mAvailable;
- memcpy(events, mRecBuffer + mConsumed, count*sizeof(ASensorEvent));
+ size_t count = min(numEvents, mAvailable);
+ memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent));
mAvailable -= count;
mConsumed += count;
- return count;
+ return static_cast<ssize_t>(count);
}
sp<Looper> SensorEventQueue::getLooper() const
@@ -146,6 +150,23 @@
return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
}
+status_t SensorEventQueue::injectSensorEvent(const ASensorEvent& event) {
+ do {
+ // Blocking call.
+ ssize_t size = ::send(mSensorChannel->getFd(), &event, sizeof(event), MSG_NOSIGNAL);
+ if (size >= 0) {
+ return NO_ERROR;
+ } else if (size < 0 && errno == EAGAIN) {
+ // If send is returning a "Try again" error, sleep for 100ms and try again. In all
+ // other cases log a failure and exit.
+ usleep(100000);
+ } else {
+ ALOGE("injectSensorEvent failure %s %zd", strerror(errno), size);
+ return INVALID_OPERATION;
+ }
+ } while (true);
+}
+
void SensorEventQueue::sendAck(const ASensorEvent* events, int count) {
for (int i = 0; i < count; ++i) {
if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) {
@@ -157,7 +178,7 @@
ssize_t size = ::send(mSensorChannel->getFd(), &mNumAcksToSend, sizeof(mNumAcksToSend),
MSG_DONTWAIT | MSG_NOSIGNAL);
if (size < 0) {
- ALOGE("sendAck failure %d %d", size, mNumAcksToSend);
+ ALOGE("sendAck failure %zd %d", size, mNumAcksToSend);
} else {
mNumAcksToSend = 0;
}
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 7b4fa2f..dd37781 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -36,10 +36,8 @@
namespace android {
// ----------------------------------------------------------------------------
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager)
-
-SensorManager::SensorManager()
- : mSensorList(0)
+SensorManager::SensorManager(const String16& opPackageName)
+ : mSensorList(0), mOpPackageName(opPackageName)
{
// okay we're not locked here, but it's not needed during construction
assertStateLocked();
@@ -86,11 +84,12 @@
};
mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
- mSensorServer->asBinder()->linkToDeath(mDeathObserver);
+ IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);
- mSensors = mSensorServer->getSensorList();
+ mSensors = mSensorServer->getSensorList(mOpPackageName);
size_t count = mSensors.size();
- mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*));
+ mSensorList =
+ static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
for (size_t i=0 ; i<count ; i++) {
mSensorList[i] = mSensors.array() + i;
}
@@ -99,17 +98,15 @@
return NO_ERROR;
}
-
-
ssize_t SensorManager::getSensorList(Sensor const* const** list) const
{
Mutex::Autolock _l(mLock);
status_t err = assertStateLocked();
if (err < 0) {
- return ssize_t(err);
+ return static_cast<ssize_t>(err);
}
*list = mSensorList;
- return mSensors.size();
+ return static_cast<ssize_t>(mSensors.size());
}
Sensor const* SensorManager::getDefaultSensor(int type)
@@ -138,18 +135,17 @@
return NULL;
}
-sp<SensorEventQueue> SensorManager::createEventQueue()
-{
+sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName, int mode) {
sp<SensorEventQueue> queue;
Mutex::Autolock _l(mLock);
while (assertStateLocked() == NO_ERROR) {
sp<ISensorEventConnection> connection =
- mSensorServer->createSensorEventConnection();
+ mSensorServer->createSensorEventConnection(packageName, mode, mOpPackageName);
if (connection == NULL) {
- // SensorService just died.
- ALOGE("createEventQueue: connection is NULL. SensorService died.");
- continue;
+ // SensorService just died or the app doesn't have required permissions.
+ ALOGE("createEventQueue: connection is NULL.");
+ return NULL;
}
queue = new SensorEventQueue(connection);
break;
@@ -157,5 +153,13 @@
return queue;
}
+bool SensorManager::isDataInjectionEnabled() {
+ Mutex::Autolock _l(mLock);
+ if (assertStateLocked() == NO_ERROR) {
+ return mSensorServer->isDataInjectionEnabled();
+ }
+ return false;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 5f39905..43f9214 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -20,6 +20,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
+#include <gui/BufferItem.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/StreamSplitter.h>
@@ -80,7 +81,7 @@
IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
sp<OutputListener> listener(new OutputListener(this, outputQueue));
- outputQueue->asBinder()->linkToDeath(listener);
+ IInterface::asBinder(outputQueue)->linkToDeath(listener);
status_t status = outputQueue->connect(listener, NATIVE_WINDOW_API_CPU,
/* producerControlledByApp */ false, &queueBufferOutput);
if (status != NO_ERROR) {
@@ -123,7 +124,7 @@
++mOutstandingBuffers;
// Acquire and detach the buffer from the input
- IGraphicBufferConsumer::BufferItem bufferItem;
+ BufferItem bufferItem;
status_t status = mInput->acquireBuffer(&bufferItem, /* presentWhen */ 0);
LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
"acquiring buffer from input failed (%d)", status);
@@ -141,7 +142,8 @@
IGraphicBufferProducer::QueueBufferInput queueInput(
bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp,
- bufferItem.mCrop, bufferItem.mScalingMode,
+ bufferItem.mDataSpace, bufferItem.mCrop,
+ static_cast<int32_t>(bufferItem.mScalingMode),
bufferItem.mTransform, bufferItem.mIsDroppable,
bufferItem.mFence);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 0e2baa2..4b76f98 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -27,6 +27,7 @@
#include <utils/NativeHandle.h>
#include <ui/Fence.h>
+#include <ui/Region.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
@@ -41,7 +42,8 @@
Surface::Surface(
const sp<IGraphicBufferProducer>& bufferProducer,
bool controlledByApp)
- : mGraphicBufferProducer(bufferProducer)
+ : mGraphicBufferProducer(bufferProducer),
+ mGenerationNumber(0)
{
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
@@ -64,6 +66,7 @@
mReqFormat = 0;
mReqUsage = 0;
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
+ mDataSpace = HAL_DATASPACE_UNKNOWN;
mCrop.clear();
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0;
@@ -96,8 +99,20 @@
void Surface::allocateBuffers() {
uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
- mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, mReqWidth,
- mReqHeight, mReqFormat, mReqUsage);
+ mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
+ reqHeight, mReqFormat, mReqUsage);
+}
+
+status_t Surface::setGenerationNumber(uint32_t generation) {
+ status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
+ if (result == NO_ERROR) {
+ mGenerationNumber = generation;
+ }
+ return result;
+}
+
+String8 Surface::getConsumerName() const {
+ return mGraphicBufferProducer->getConsumerName();
}
int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
@@ -193,17 +208,17 @@
ATRACE_CALL();
ALOGV("Surface::dequeueBuffer");
- int reqW;
- int reqH;
+ uint32_t reqWidth;
+ uint32_t reqHeight;
bool swapIntervalZero;
- uint32_t reqFormat;
+ PixelFormat reqFormat;
uint32_t reqUsage;
{
Mutex::Autolock lock(mMutex);
- reqW = mReqWidth ? mReqWidth : mUserWidth;
- reqH = mReqHeight ? mReqHeight : mUserHeight;
+ reqWidth = mReqWidth ? mReqWidth : mUserWidth;
+ reqHeight = mReqHeight ? mReqHeight : mUserHeight;
swapIntervalZero = mSwapIntervalZero;
reqFormat = mReqFormat;
@@ -213,12 +228,12 @@
int buf = -1;
sp<Fence> fence;
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
- reqW, reqH, reqFormat, reqUsage);
+ reqWidth, reqHeight, reqFormat, reqUsage);
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
- "failed: %d", swapIntervalZero, reqW, reqH, reqFormat, reqUsage,
- result);
+ "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat,
+ reqUsage, result);
return result;
}
@@ -265,6 +280,9 @@
Mutex::Autolock lock(mMutex);
int i = getSlotFromBufferLocked(buffer);
if (i < 0) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
return i;
}
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
@@ -274,7 +292,6 @@
int Surface::getSlotFromBufferLocked(
android_native_buffer_t* buffer) const {
- bool dumpedState = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i].buffer != NULL &&
mSlots[i].buffer->handle == buffer->handle) {
@@ -307,6 +324,9 @@
}
int i = getSlotFromBufferLocked(buffer);
if (i < 0) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
return i;
}
@@ -318,8 +338,72 @@
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
- crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,
- fence, mStickyTransform);
+ mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
+ mSwapIntervalZero, fence, mStickyTransform);
+
+ if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
+ input.setSurfaceDamage(Region::INVALID_REGION);
+ } else {
+ // Here we do two things:
+ // 1) The surface damage was specified using the OpenGL ES convention of
+ // the origin being in the bottom-left corner. Here we flip to the
+ // convention that the rest of the system uses (top-left corner) by
+ // subtracting all top/bottom coordinates from the buffer height.
+ // 2) If the buffer is coming in rotated (for example, because the EGL
+ // implementation is reacting to the transform hint coming back from
+ // SurfaceFlinger), the surface damage needs to be rotated the
+ // opposite direction, since it was generated assuming an unrotated
+ // buffer (the app doesn't know that the EGL implementation is
+ // reacting to the transform hint behind its back). The
+ // transformations in the switch statement below apply those
+ // complementary rotations (e.g., if 90 degrees, rotate 270 degrees).
+
+ int width = buffer->width;
+ int height = buffer->height;
+ bool rotated90 = (mTransform ^ mStickyTransform) &
+ NATIVE_WINDOW_TRANSFORM_ROT_90;
+ if (rotated90) {
+ std::swap(width, height);
+ }
+
+ Region flippedRegion;
+ for (auto rect : mDirtyRegion) {
+ int left = rect.left;
+ int right = rect.right;
+ int top = height - rect.bottom; // Flip from OpenGL convention
+ int bottom = height - rect.top; // Flip from OpenGL convention
+ switch (mTransform ^ mStickyTransform) {
+ case NATIVE_WINDOW_TRANSFORM_ROT_90: {
+ // Rotate 270 degrees
+ Rect flippedRect{top, width - right, bottom, width - left};
+ flippedRegion.orSelf(flippedRect);
+ break;
+ }
+ case NATIVE_WINDOW_TRANSFORM_ROT_180: {
+ // Rotate 180 degrees
+ Rect flippedRect{width - right, height - bottom,
+ width - left, height - top};
+ flippedRegion.orSelf(flippedRect);
+ break;
+ }
+ case NATIVE_WINDOW_TRANSFORM_ROT_270: {
+ // Rotate 90 degrees
+ Rect flippedRect{height - bottom, left,
+ height - top, right};
+ flippedRegion.orSelf(flippedRect);
+ break;
+ }
+ default: {
+ Rect flippedRect{left, top, right, bottom};
+ flippedRegion.orSelf(flippedRect);
+ break;
+ }
+ }
+ }
+
+ input.setSurfaceDamage(flippedRegion);
+ }
+
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
@@ -336,6 +420,11 @@
mConsumerRunningBehind = (numPendingBuffers >= 2);
+ if (!mConnectedToCpu) {
+ // Clear surface damage back to full-buffer
+ mDirtyRegion = Region::INVALID_REGION;
+ }
+
return err;
}
@@ -347,7 +436,7 @@
switch (what) {
case NATIVE_WINDOW_FORMAT:
if (mReqFormat) {
- *value = mReqFormat;
+ *value = static_cast<int>(mReqFormat);
return NO_ERROR;
}
break;
@@ -365,13 +454,15 @@
*value = NATIVE_WINDOW_SURFACE;
return NO_ERROR;
case NATIVE_WINDOW_DEFAULT_WIDTH:
- *value = mUserWidth ? mUserWidth : mDefaultWidth;
+ *value = static_cast<int>(
+ mUserWidth ? mUserWidth : mDefaultWidth);
return NO_ERROR;
case NATIVE_WINDOW_DEFAULT_HEIGHT:
- *value = mUserHeight ? mUserHeight : mDefaultHeight;
+ *value = static_cast<int>(
+ mUserHeight ? mUserHeight : mDefaultHeight);
return NO_ERROR;
case NATIVE_WINDOW_TRANSFORM_HINT:
- *value = mTransformHint;
+ *value = static_cast<int>(mTransformHint);
return NO_ERROR;
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
status_t err = NO_ERROR;
@@ -448,6 +539,12 @@
case NATIVE_WINDOW_SET_SIDEBAND_STREAM:
res = dispatchSetSidebandStream(args);
break;
+ case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
+ res = dispatchSetBuffersDataSpace(args);
+ break;
+ case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
+ res = dispatchSetSurfaceDamage(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -467,7 +564,7 @@
int Surface::dispatchSetUsage(va_list args) {
int usage = va_arg(args, int);
- return setUsage(usage);
+ return setUsage(static_cast<uint32_t>(usage));
}
int Surface::dispatchSetCrop(va_list args) {
@@ -477,49 +574,49 @@
int Surface::dispatchSetBufferCount(va_list args) {
size_t bufferCount = va_arg(args, size_t);
- return setBufferCount(bufferCount);
+ return setBufferCount(static_cast<int32_t>(bufferCount));
}
int Surface::dispatchSetBuffersGeometry(va_list args) {
- int w = va_arg(args, int);
- int h = va_arg(args, int);
- int f = va_arg(args, int);
- int err = setBuffersDimensions(w, h);
+ uint32_t width = va_arg(args, uint32_t);
+ uint32_t height = va_arg(args, uint32_t);
+ PixelFormat format = va_arg(args, PixelFormat);
+ int err = setBuffersDimensions(width, height);
if (err != 0) {
return err;
}
- return setBuffersFormat(f);
+ return setBuffersFormat(format);
}
int Surface::dispatchSetBuffersDimensions(va_list args) {
- int w = va_arg(args, int);
- int h = va_arg(args, int);
- return setBuffersDimensions(w, h);
+ uint32_t width = va_arg(args, uint32_t);
+ uint32_t height = va_arg(args, uint32_t);
+ return setBuffersDimensions(width, height);
}
int Surface::dispatchSetBuffersUserDimensions(va_list args) {
- int w = va_arg(args, int);
- int h = va_arg(args, int);
- return setBuffersUserDimensions(w, h);
+ uint32_t width = va_arg(args, uint32_t);
+ uint32_t height = va_arg(args, uint32_t);
+ return setBuffersUserDimensions(width, height);
}
int Surface::dispatchSetBuffersFormat(va_list args) {
- int f = va_arg(args, int);
- return setBuffersFormat(f);
+ PixelFormat format = va_arg(args, PixelFormat);
+ return setBuffersFormat(format);
}
int Surface::dispatchSetScalingMode(va_list args) {
- int m = va_arg(args, int);
- return setScalingMode(m);
+ int mode = va_arg(args, int);
+ return setScalingMode(mode);
}
int Surface::dispatchSetBuffersTransform(va_list args) {
- int transform = va_arg(args, int);
+ uint32_t transform = va_arg(args, uint32_t);
return setBuffersTransform(transform);
}
int Surface::dispatchSetBuffersStickyTransform(va_list args) {
- int transform = va_arg(args, int);
+ uint32_t transform = va_arg(args, uint32_t);
return setBuffersStickyTransform(transform);
}
@@ -545,10 +642,27 @@
return OK;
}
+int Surface::dispatchSetBuffersDataSpace(va_list args) {
+ android_dataspace dataspace =
+ static_cast<android_dataspace>(va_arg(args, int));
+ return setBuffersDataSpace(dataspace);
+}
+
+int Surface::dispatchSetSurfaceDamage(va_list args) {
+ android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
+ size_t numRects = va_arg(args, size_t);
+ setSurfaceDamage(rects, numRects);
+ return NO_ERROR;
+}
+
int Surface::connect(int api) {
+ static sp<IProducerListener> listener = new DummyProducerListener();
+ return connect(api, listener);
+}
+
+int Surface::connect(int api, const sp<IProducerListener>& listener) {
ATRACE_CALL();
ALOGV("Surface::connect");
- static sp<IProducerListener> listener = new DummyProducerListener();
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput output;
int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
@@ -567,7 +681,13 @@
}
if (!err && api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = true;
+ // Clear the dirty region in case we're switching from a non-CPU API
+ mDirtyRegion.clear();
+ } else if (!err) {
+ // Initialize the dirty region for tracking surface damage
+ mDirtyRegion = Region::INVALID_REGION;
}
+
return err;
}
@@ -595,6 +715,58 @@
return err;
}
+int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
+ sp<Fence>* outFence) {
+ ATRACE_CALL();
+ ALOGV("Surface::detachNextBuffer");
+
+ if (outBuffer == NULL || outFence == NULL) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ sp<GraphicBuffer> buffer(NULL);
+ sp<Fence> fence(NULL);
+ status_t result = mGraphicBufferProducer->detachNextBuffer(
+ &buffer, &fence);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ *outBuffer = buffer;
+ if (fence != NULL && fence->isValid()) {
+ *outFence = fence;
+ } else {
+ *outFence = Fence::NO_FENCE;
+ }
+
+ return NO_ERROR;
+}
+
+int Surface::attachBuffer(ANativeWindowBuffer* buffer)
+{
+ ATRACE_CALL();
+ ALOGV("Surface::attachBuffer");
+
+ Mutex::Autolock lock(mMutex);
+
+ sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
+ uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
+ graphicBuffer->mGenerationNumber = mGenerationNumber;
+ int32_t attachedSlot = -1;
+ status_t result = mGraphicBufferProducer->attachBuffer(
+ &attachedSlot, graphicBuffer);
+ if (result != NO_ERROR) {
+ ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
+ graphicBuffer->mGenerationNumber = priorGeneration;
+ return result;
+ }
+ mSlots[attachedSlot].buffer = graphicBuffer;
+
+ return NO_ERROR;
+}
+
int Surface::setUsage(uint32_t reqUsage)
{
ALOGV("Surface::setUsage");
@@ -639,47 +811,38 @@
return err;
}
-int Surface::setBuffersDimensions(int w, int h)
+int Surface::setBuffersDimensions(uint32_t width, uint32_t height)
{
ATRACE_CALL();
ALOGV("Surface::setBuffersDimensions");
- if (w<0 || h<0)
- return BAD_VALUE;
-
- if ((w && !h) || (!w && h))
+ if ((width && !height) || (!width && height))
return BAD_VALUE;
Mutex::Autolock lock(mMutex);
- mReqWidth = w;
- mReqHeight = h;
+ mReqWidth = width;
+ mReqHeight = height;
return NO_ERROR;
}
-int Surface::setBuffersUserDimensions(int w, int h)
+int Surface::setBuffersUserDimensions(uint32_t width, uint32_t height)
{
ATRACE_CALL();
ALOGV("Surface::setBuffersUserDimensions");
- if (w<0 || h<0)
- return BAD_VALUE;
-
- if ((w && !h) || (!w && h))
+ if ((width && !height) || (!width && height))
return BAD_VALUE;
Mutex::Autolock lock(mMutex);
- mUserWidth = w;
- mUserHeight = h;
+ mUserWidth = width;
+ mUserHeight = height;
return NO_ERROR;
}
-int Surface::setBuffersFormat(int format)
+int Surface::setBuffersFormat(PixelFormat format)
{
ALOGV("Surface::setBuffersFormat");
- if (format<0)
- return BAD_VALUE;
-
Mutex::Autolock lock(mMutex);
mReqFormat = format;
return NO_ERROR;
@@ -705,7 +868,7 @@
return NO_ERROR;
}
-int Surface::setBuffersTransform(int transform)
+int Surface::setBuffersTransform(uint32_t transform)
{
ATRACE_CALL();
ALOGV("Surface::setBuffersTransform");
@@ -714,7 +877,7 @@
return NO_ERROR;
}
-int Surface::setBuffersStickyTransform(int transform)
+int Surface::setBuffersStickyTransform(uint32_t transform)
{
ATRACE_CALL();
ALOGV("Surface::setBuffersStickyTransform");
@@ -731,12 +894,41 @@
return NO_ERROR;
}
+int Surface::setBuffersDataSpace(android_dataspace dataSpace)
+{
+ ALOGV("Surface::setBuffersDataSpace");
+ Mutex::Autolock lock(mMutex);
+ mDataSpace = dataSpace;
+ return NO_ERROR;
+}
+
void Surface::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].buffer = 0;
}
}
+void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) {
+ ATRACE_CALL();
+ ALOGV("Surface::setSurfaceDamage");
+ Mutex::Autolock lock(mMutex);
+
+ if (mConnectedToCpu || numRects == 0) {
+ mDirtyRegion = Region::INVALID_REGION;
+ return;
+ }
+
+ mDirtyRegion.clear();
+ for (size_t r = 0; r < numRects; ++r) {
+ // We intentionally flip top and bottom here, since because they're
+ // specified with a bottom-left origin, top > bottom, which fails
+ // validation in the Region class. We will fix this up when we flip to a
+ // top-left origin in queueBuffer.
+ Rect rect(rects[r].left, rects[r].bottom, rects[r].right, rects[r].top);
+ mDirtyRegion.orSelf(rect);
+ }
+}
+
// ----------------------------------------------------------------------
// the lock/unlock APIs must be used from the same thread
@@ -748,30 +940,34 @@
// src and dst with, height and format must be identical. no verification
// is done here.
status_t err;
- uint8_t const * src_bits = NULL;
- err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits);
+ uint8_t* src_bits = NULL;
+ err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
+ reinterpret_cast<void**>(&src_bits));
ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
uint8_t* dst_bits = NULL;
- err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits);
+ err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
+ reinterpret_cast<void**>(&dst_bits));
ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
Region::const_iterator head(reg.begin());
Region::const_iterator tail(reg.end());
if (head != tail && src_bits && dst_bits) {
const size_t bpp = bytesPerPixel(src->format);
- const size_t dbpr = dst->stride * bpp;
- const size_t sbpr = src->stride * bpp;
+ const size_t dbpr = static_cast<uint32_t>(dst->stride) * bpp;
+ const size_t sbpr = static_cast<uint32_t>(src->stride) * bpp;
while (head != tail) {
const Rect& r(*head++);
- ssize_t h = r.height();
+ int32_t h = r.height();
if (h <= 0) continue;
- size_t size = r.width() * bpp;
- uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
- uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+ size_t size = static_cast<uint32_t>(r.width()) * bpp;
+ uint8_t const * s = src_bits +
+ static_cast<uint32_t>(r.left + src->stride * r.top) * bpp;
+ uint8_t * d = dst_bits +
+ static_cast<uint32_t>(r.left + dst->stride * r.top) * bpp;
if (dbpr==sbpr && size==sbpr) {
- size *= h;
+ size *= static_cast<size_t>(h);
h = 1;
}
do {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6446926..6ad47d8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -71,7 +71,7 @@
};
mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
- mComposerService->asBinder()->linkToDeath(mDeathObserver);
+ IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
}
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
@@ -143,7 +143,7 @@
status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
uint32_t w, uint32_t h);
status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- int32_t z);
+ uint32_t z);
status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(
@@ -293,7 +293,7 @@
}
status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t z) {
+ const sp<IBinder>& id, uint32_t z) {
Mutex::Autolock _l(mLock);
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
@@ -310,11 +310,10 @@
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
- if (mask & layer_state_t::eLayerOpaque) {
- s->what |= layer_state_t::eOpacityChanged;
- }
- if (mask & layer_state_t::eLayerHidden) {
- s->what |= layer_state_t::eVisibilityChanged;
+ if (mask & layer_state_t::eLayerOpaque ||
+ mask & layer_state_t::eLayerHidden ||
+ mask & layer_state_t::eLayerSecure) {
+ s->what |= layer_state_t::eFlagsChanged;
}
s->flags &= ~mask;
s->flags |= (flags & mask);
@@ -395,7 +394,7 @@
s.what = 0;
index = mDisplayStates.add(s);
}
- return mDisplayStates.editItemAt(index);
+ return mDisplayStates.editItemAt(static_cast<size_t>(index));
}
void Composer::setDisplaySurface(const sp<IBinder>& token,
@@ -462,14 +461,14 @@
}
sp<IBinder> SurfaceComposerClient::connection() const {
- return (mClient != 0) ? mClient->asBinder() : 0;
+ return IInterface::asBinder(mClient);
}
status_t SurfaceComposerClient::linkToComposerDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return sm->asBinder()->linkToDeath(recipient, cookie, flags);
+ return IInterface::asBinder(sm)->linkToDeath(recipient, cookie, flags);
}
void SurfaceComposerClient::dispose() {
@@ -571,7 +570,7 @@
return getComposer().setSize(this, id, w, h);
}
-status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
+status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, uint32_t z) {
return getComposer().setLayer(this, id, z);
}
@@ -657,7 +656,7 @@
return NAME_NOT_FOUND;
}
- *info = configs[activeId];
+ *info = configs[static_cast<size_t>(activeId)];
return NO_ERROR;
}
@@ -752,14 +751,14 @@
status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
bool useIdentityTransform) {
- return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1UL,
+ return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1U,
useIdentityTransform, ISurfaceComposer::eRotateNone);
}
status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
- 0, -1UL, useIdentityTransform, ISurfaceComposer::eRotateNone);
+ 0, -1U, useIdentityTransform, ISurfaceComposer::eRotateNone);
}
void ScreenshotClient::release() {
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7597c99..1983027 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -89,12 +89,12 @@
return lhs->mHandle == rhs->mHandle;
}
-status_t SurfaceControl::setLayerStack(int32_t layerStack) {
+status_t SurfaceControl::setLayerStack(uint32_t layerStack) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayerStack(mHandle, layerStack);
}
-status_t SurfaceControl::setLayer(int32_t layer) {
+status_t SurfaceControl::setLayer(uint32_t layer) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayer(mHandle, layer);
@@ -176,7 +176,7 @@
if (control != NULL) {
bp = control->mGraphicBufferProducer;
}
- return parcel->writeStrongBinder(bp->asBinder());
+ return parcel->writeStrongBinder(IInterface::asBinder(bp));
}
sp<Surface> SurfaceControl::getSurface() const
diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp
index e5804a7..187b211 100644
--- a/libs/gui/SyncFeatures.cpp
+++ b/libs/gui/SyncFeatures.cpp
@@ -16,7 +16,6 @@
#define LOG_TAG "GLConsumer"
-#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#include <EGL/egl.h>
@@ -78,10 +77,11 @@
// on some devices it's better to not use EGL_KHR_fence_sync
// even if they have it
return false;
-#endif
+#else
// currently we shall only attempt to use EGL_KHR_fence_sync if
// USE_FENCE_SYNC is set in our makefile
return !mHasNativeFenceSync && mHasFenceSync;
+#endif
}
bool SyncFeatures::useWaitSync() const {
return (useNativeFenceSync() || useFenceSync()) && mHasWaitSync;
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index e460290..6ad9986 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -1,6 +1,9 @@
# Build the unit tests,
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_CLANG := true
LOCAL_MODULE := libgui_test
@@ -31,17 +34,10 @@
libbinder \
libcutils \
libgui \
- libstlport \
libsync \
libui \
libutils \
-LOCAL_C_INCLUDES := \
- bionic \
- bionic/libstdc++/include \
- external/gtest/include \
- external/stlport/stlport \
-
# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
# to integrate with auto-test framework.
include $(BUILD_NATIVE_TEST)
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 96de11f..1a54875 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -17,6 +17,9 @@
#define LOG_TAG "BufferQueue_test"
//#define LOG_NDEBUG 0
+#include "DummyConsumer.h"
+
+#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/IProducerListener.h>
@@ -66,11 +69,7 @@
sp<IGraphicBufferConsumer> mConsumer;
};
-struct DummyConsumer : public BnConsumerListener {
- virtual void onFrameAvailable(const BufferItem& /* item */) {}
- virtual void onBuffersReleased() {}
- virtual void onSidebandStreamChanged() {}
-};
+static const uint32_t TEST_DATA = 0x12345678u;
// XXX: Tests that fork a process to hold the BufferQueue must run before tests
// that use a local BufferQueue, or else Binder will get unhappy
@@ -87,8 +86,8 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
sp<IServiceManager> serviceManager = defaultServiceManager();
- serviceManager->addService(PRODUCER_NAME, producer->asBinder());
- serviceManager->addService(CONSUMER_NAME, consumer->asBinder());
+ serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
+ serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOG_ALWAYS_FATAL("Shouldn't be here");
@@ -121,20 +120,21 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
- IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+ IGraphicBufferProducer::QueueBufferInput input(0, false,
+ HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
- IGraphicBufferConsumer::BufferItem item;
+ BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
@@ -150,9 +150,10 @@
int slot;
sp<Fence> fence;
sp<GraphicBuffer> buf;
- IGraphicBufferProducer::QueueBufferInput qbi(0, false, Rect(0, 0, 1, 1),
+ IGraphicBufferProducer::QueueBufferInput qbi(0, false,
+ HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
- BufferQueue::BufferItem item;
+ BufferItem item;
for (int i = 0; i < 2; i++) {
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
@@ -236,7 +237,7 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
int newSlot;
@@ -244,17 +245,18 @@
ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&newSlot, NULL));
ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
- IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+ IGraphicBufferProducer::QueueBufferInput input(0, false,
+ HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
- IGraphicBufferConsumer::BufferItem item;
+ BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
@@ -273,7 +275,8 @@
mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
GRALLOC_USAGE_SW_WRITE_OFTEN));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
- IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+ IGraphicBufferProducer::QueueBufferInput input(0, false,
+ HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
@@ -282,7 +285,7 @@
BufferQueueDefs::NUM_BUFFER_SLOTS)); // Index too high
ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(0)); // Not acquired
- IGraphicBufferConsumer::BufferItem item;
+ BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
@@ -292,7 +295,7 @@
ASSERT_EQ(OK, item.mGraphicBuffer->lock(
GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
int newSlot;
@@ -312,7 +315,7 @@
uint32_t* dataOut;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, buffer->unlock());
}
@@ -335,14 +338,15 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
- IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+ IGraphicBufferProducer::QueueBufferInput input(0, false,
+ HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
- IGraphicBufferConsumer::BufferItem item;
+ BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
@@ -354,8 +358,86 @@
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
+TEST_F(BufferQueueTest, TestDisallowingAllocation) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ NATIVE_WINDOW_API_CPU, true, &output));
+
+ static const uint32_t WIDTH = 320;
+ static const uint32_t HEIGHT = 240;
+
+ ASSERT_EQ(OK, mConsumer->setDefaultBufferSize(WIDTH, HEIGHT));
+
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+ // This should return an error since it would require an allocation
+ ASSERT_EQ(OK, mProducer->allowAllocation(false));
+ ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
+ 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ // This should succeed, now that we've lifted the prohibition
+ ASSERT_EQ(OK, mProducer->allowAllocation(true));
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+ GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ // Release the previous buffer back to the BufferQueue
+ mProducer->cancelBuffer(slot, fence);
+
+ // This should fail since we're requesting a different size
+ ASSERT_EQ(OK, mProducer->allowAllocation(false));
+ ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false,
+ WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+}
+
+TEST_F(BufferQueueTest, TestGenerationNumbers) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+ IGraphicBufferProducer::QueueBufferOutput output;
+ ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+ NATIVE_WINDOW_API_CPU, true, &output));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(1));
+
+ // Get one buffer to play with
+ int slot;
+ sp<Fence> fence;
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0));
+
+ sp<GraphicBuffer> buffer;
+ ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+
+ // Ensure that the generation number we set propagates to allocated buffers
+ ASSERT_EQ(1U, buffer->getGenerationNumber());
+
+ ASSERT_EQ(OK, mProducer->detachBuffer(slot));
+
+ ASSERT_EQ(OK, mProducer->setGenerationNumber(2));
+
+ // These should fail, since we've changed the generation number on the queue
+ int outSlot;
+ ASSERT_EQ(BAD_VALUE, mProducer->attachBuffer(&outSlot, buffer));
+ ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&outSlot, buffer));
+
+ buffer->setGenerationNumber(2);
+
+ // This should succeed now that we've changed the buffer's generation number
+ ASSERT_EQ(OK, mProducer->attachBuffer(&outSlot, buffer));
+
+ ASSERT_EQ(OK, mProducer->detachBuffer(outSlot));
+
+ // This should also succeed with the new generation number
+ ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
+}
+
} // namespace android
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index abd3724..2dc9ccc 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -94,7 +94,7 @@
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem&) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mCondition.signal();
@@ -125,7 +125,7 @@
mPendingFrames--;
}
- virtual void onFrameAvailable() {
+ virtual void onFrameAvailable(const BufferItem&) {
Mutex::Autolock lock(mMutex);
mPendingFrames++;
mFrameCondition.signal();
@@ -166,7 +166,7 @@
uint32_t x, uint32_t y, uint32_t r, uint32_t g=0, uint32_t b=0) {
// Ignores components that don't exist for given pixel
switch(buf.format) {
- case HAL_PIXEL_FORMAT_RAW_SENSOR: {
+ case HAL_PIXEL_FORMAT_RAW16: {
String8 msg;
uint16_t *bPtr = (uint16_t*)buf.data;
bPtr += y * buf.stride + x;
@@ -429,7 +429,7 @@
void checkAnyBuffer(const CpuConsumer::LockedBuffer &buf, int format) {
switch (format) {
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
checkBayerRawBuffer(buf);
break;
case HAL_PIXEL_FORMAT_Y8:
@@ -457,9 +457,12 @@
const CpuConsumerTestParams& params,
int maxBufferSlack) {
status_t err;
- err = native_window_set_buffers_geometry(anw.get(),
- params.width, params.height, params.format);
- ASSERT_NO_ERROR(err, "set_buffers_geometry error: ");
+ err = native_window_set_buffers_dimensions(anw.get(),
+ params.width, params.height);
+ ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
+
+ err = native_window_set_buffers_format(anw.get(), params.format);
+ ASSERT_NO_ERROR(err, "set_buffers_format error: ");
err = native_window_set_usage(anw.get(),
GRALLOC_USAGE_SW_WRITE_OFTEN);
@@ -505,7 +508,7 @@
case HAL_PIXEL_FORMAT_YV12:
fillYV12Buffer(img, params.width, params.height, *stride);
break;
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
fillBayerRawBuffer(img, params.width, params.height, buf->getStride());
break;
case HAL_PIXEL_FORMAT_Y8:
@@ -537,7 +540,7 @@
ASSERT_NO_ERROR(err, "queueBuffer error:");
};
-// This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
+// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not
// supported on all devices.
TEST_P(CpuConsumerTest, FromCpuSingle) {
status_t err;
@@ -571,7 +574,7 @@
mCC->unlockBuffer(b);
}
-// This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
+// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not
// supported on all devices.
TEST_P(CpuConsumerTest, FromCpuManyInQueue) {
status_t err;
@@ -614,7 +617,7 @@
}
}
-// This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
+// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not
// supported on all devices.
TEST_P(CpuConsumerTest, FromCpuLockMax) {
status_t err;
@@ -710,12 +713,12 @@
};
CpuConsumerTestParams rawTestSets[] = {
- { 512, 512, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
- { 512, 512, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
- { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
- { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
- { 100, 100, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
- { 100, 100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
+ { 512, 512, 1, HAL_PIXEL_FORMAT_RAW16},
+ { 512, 512, 3, HAL_PIXEL_FORMAT_RAW16},
+ { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW16},
+ { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW16},
+ { 100, 100, 1, HAL_PIXEL_FORMAT_RAW16},
+ { 100, 100, 3, HAL_PIXEL_FORMAT_RAW16},
};
CpuConsumerTestParams rgba8888TestSets[] = {
diff --git a/libs/gui/tests/DummyConsumer.h b/libs/gui/tests/DummyConsumer.h
new file mode 100644
index 0000000..0511e16
--- /dev/null
+++ b/libs/gui/tests/DummyConsumer.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 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 <gui/IConsumerListener.h>
+
+namespace android {
+
+struct DummyConsumer : public BnConsumerListener {
+ virtual void onFrameAvailable(const BufferItem& /* item */) {}
+ virtual void onBuffersReleased() {}
+ virtual void onSidebandStreamChanged() {}
+};
+
+} // namespace android
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 8d5fd8f..4ef9a69 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -38,30 +38,31 @@
#define TEST_CONTROLLED_BY_APP false
#define TEST_PRODUCER_USAGE_BITS (0)
-// TODO: Make these public constants in a header
-enum {
- // Default dimensions before setDefaultBufferSize is called
- DEFAULT_WIDTH = 1,
- DEFAULT_HEIGHT = 1,
-
- // Default format before setDefaultBufferFormat is called
- DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888,
-
- // Default transform hint before setTransformHint is called
- DEFAULT_TRANSFORM_HINT = 0,
-};
-
namespace android {
namespace {
-// Parameters for a generic "valid" input for queueBuffer.
-const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
-const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
-const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
-const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
-const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
-const bool QUEUE_BUFFER_INPUT_ASYNC = false;
-const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
+ // Default dimensions before setDefaultBufferSize is called
+ const uint32_t DEFAULT_WIDTH = 1;
+ const uint32_t DEFAULT_HEIGHT = 1;
+
+ // Default format before setDefaultBufferFormat is called
+ const PixelFormat DEFAULT_FORMAT = HAL_PIXEL_FORMAT_RGBA_8888;
+
+ // Default transform hint before setTransformHint is called
+ const uint32_t DEFAULT_TRANSFORM_HINT = 0;
+
+ // TODO: Make these constants in header
+ const int DEFAULT_CONSUMER_USAGE_BITS = 0;
+
+ // Parameters for a generic "valid" input for queueBuffer.
+ const int64_t QUEUE_BUFFER_INPUT_TIMESTAMP = 1384888611;
+ const bool QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP = false;
+ const android_dataspace QUEUE_BUFFER_INPUT_DATASPACE = HAL_DATASPACE_UNKNOWN;
+ const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
+ const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
+ const bool QUEUE_BUFFER_INPUT_ASYNC = false;
+ const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
}; // namespace anonymous
struct DummyConsumer : public BnConsumerListener {
@@ -126,6 +127,7 @@
QueueBufferInputBuilder() {
timestamp = QUEUE_BUFFER_INPUT_TIMESTAMP;
isAutoTimestamp = QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP;
+ dataSpace = QUEUE_BUFFER_INPUT_DATASPACE;
crop = QUEUE_BUFFER_INPUT_RECT;
scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
transform = QUEUE_BUFFER_INPUT_TRANSFORM;
@@ -137,6 +139,7 @@
return IGraphicBufferProducer::QueueBufferInput(
timestamp,
isAutoTimestamp,
+ dataSpace,
crop,
scalingMode,
transform,
@@ -154,6 +157,11 @@
return *this;
}
+ QueueBufferInputBuilder& setDataSpace(android_dataspace dataSpace) {
+ this->dataSpace = dataSpace;
+ return *this;
+ }
+
QueueBufferInputBuilder& setCrop(Rect crop) {
this->crop = crop;
return *this;
@@ -182,6 +190,7 @@
private:
int64_t timestamp;
bool isAutoTimestamp;
+ android_dataspace dataSpace;
Rect crop;
int scalingMode;
uint32_t transform;
@@ -264,15 +273,12 @@
TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
- // TODO: Make these constants in header
- const int DEFAULT_CONSUMER_USAGE_BITS = 0;
-
- int value = -1;
+ int32_t value = -1;
EXPECT_OK(mProducer->query(NATIVE_WINDOW_WIDTH, &value));
- EXPECT_EQ(DEFAULT_WIDTH, value);
+ EXPECT_EQ(DEFAULT_WIDTH, static_cast<uint32_t>(value));
EXPECT_OK(mProducer->query(NATIVE_WINDOW_HEIGHT, &value));
- EXPECT_EQ(DEFAULT_HEIGHT, value);
+ EXPECT_EQ(DEFAULT_HEIGHT, static_cast<uint32_t>(value));
EXPECT_OK(mProducer->query(NATIVE_WINDOW_FORMAT, &value));
EXPECT_EQ(DEFAULT_FORMAT, value);
@@ -293,7 +299,7 @@
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// One past the end of the last 'query' enum value. Update this if we add more enums.
- const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_CONSUMER_USAGE_BITS + 1;
+ const int NATIVE_WINDOW_QUERY_LAST_OFF_BY_ONE = NATIVE_WINDOW_BUFFER_AGE + 1;
int value;
// What was out of range
@@ -360,7 +366,7 @@
EXPECT_EQ(DEFAULT_WIDTH, width);
EXPECT_EQ(DEFAULT_HEIGHT, height);
EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint);
- EXPECT_EQ(1, numPendingBuffers); // since queueBuffer was called exactly once
+ EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once
}
// Buffer was not in the dequeued state
diff --git a/libs/gui/tests/SRGB_test.cpp b/libs/gui/tests/SRGB_test.cpp
index 2d5b8aa..3b11b97 100644
--- a/libs/gui/tests/SRGB_test.cpp
+++ b/libs/gui/tests/SRGB_test.cpp
@@ -17,8 +17,14 @@
#define LOG_TAG "SRGB_test"
//#define LOG_NDEBUG 0
+// Ignore for this file because it flags every instance of
+// ASSERT_EQ(GL_NO_ERROR, glGetError());
+#pragma clang diagnostic ignored "-Wsign-compare"
+
#include "GLTest.h"
+#include <math.h>
+
#include <gui/CpuConsumer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -212,10 +218,11 @@
ASSERT_EQ(GL_NO_ERROR, glGetError());
}
- void checkLockedBuffer(PixelFormat format) {
+ void checkLockedBuffer(PixelFormat format, android_dataspace dataSpace) {
ASSERT_EQ(mLockedBuffer.format, format);
ASSERT_EQ(mLockedBuffer.width, DISPLAY_WIDTH);
ASSERT_EQ(mLockedBuffer.height, DISPLAY_HEIGHT);
+ ASSERT_EQ(mLockedBuffer.dataSpace, dataSpace);
}
static bool withinTolerance(int a, int b) {
@@ -326,14 +333,15 @@
ANativeWindow_Buffer outBuffer;
ARect outBufferBounds;
mOutputSurface->lock(&outBuffer, &outBufferBounds);
- ASSERT_EQ(mLockedBuffer.width, outBuffer.width);
- ASSERT_EQ(mLockedBuffer.height, outBuffer.height);
- ASSERT_EQ(mLockedBuffer.stride, outBuffer.stride);
+ ASSERT_EQ(mLockedBuffer.width, static_cast<uint32_t>(outBuffer.width));
+ ASSERT_EQ(mLockedBuffer.height, static_cast<uint32_t>(outBuffer.height));
+ ASSERT_EQ(mLockedBuffer.stride, static_cast<uint32_t>(outBuffer.stride));
if (mLockedBuffer.format == outBuffer.format) {
memcpy(outBuffer.bits, mLockedBuffer.data, bufferSize);
} else {
- ASSERT_EQ(mLockedBuffer.format, PIXEL_FORMAT_sRGB_A_8888);
+ ASSERT_EQ(mLockedBuffer.format, PIXEL_FORMAT_RGBA_8888);
+ ASSERT_EQ(mLockedBuffer.dataSpace, HAL_DATASPACE_SRGB);
ASSERT_EQ(outBuffer.format, PIXEL_FORMAT_RGBA_8888);
uint8_t* outPointer = reinterpret_cast<uint8_t*>(outBuffer.bits);
for (int y = 0; y < outBuffer.height; ++y) {
@@ -378,7 +386,8 @@
// Lock
ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer));
- ASSERT_NO_FATAL_FAILURE(checkLockedBuffer(PIXEL_FORMAT_RGBA_8888));
+ ASSERT_NO_FATAL_FAILURE(
+ checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_UNKNOWN));
// Compare a pixel in the middle of each texture
int midSRGBOffset = (DISPLAY_HEIGHT / 4) * mLockedBuffer.stride *
@@ -396,7 +405,8 @@
// the debug surface if necessary
}
-TEST_F(SRGBTest, RenderToSRGBSurface) {
+// XXX: Disabled since we don't currently expect this to work
+TEST_F(SRGBTest, DISABLED_RenderToSRGBSurface) {
ASSERT_NO_FATAL_FAILURE(initShaders());
// By default, the first buffer we write into will be RGB
@@ -409,7 +419,8 @@
// Lock
ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer));
- ASSERT_NO_FATAL_FAILURE(checkLockedBuffer(PIXEL_FORMAT_RGBA_8888));
+ ASSERT_NO_FATAL_FAILURE(
+ checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_UNKNOWN));
// Save the values of the middle pixel for later comparison against SRGB
uint8_t values[PIXEL_SIZE] = {};
@@ -458,7 +469,8 @@
ASSERT_EQ(NO_ERROR, mCpuConsumer->lockNextBuffer(&mLockedBuffer));
// Make sure we actually got the SRGB buffer on the consumer side
- ASSERT_NO_FATAL_FAILURE(checkLockedBuffer(PIXEL_FORMAT_sRGB_A_8888));
+ ASSERT_NO_FATAL_FAILURE(
+ checkLockedBuffer(PIXEL_FORMAT_RGBA_8888, HAL_DATASPACE_SRGB));
// Verify that the stored value is the same, accounting for RGB/SRGB
for (int c = 0; c < PIXEL_SIZE; ++c) {
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 4e63a6f..00cc39d 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "StreamSplitter_test"
//#define LOG_NDEBUG 0
+#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/IConsumerListener.h>
#include <gui/ISurfaceComposer.h>
@@ -75,6 +76,8 @@
int mAllocCount;
};
+static const uint32_t TEST_DATA = 0x12345678u;
+
TEST_F(StreamSplitterTest, OneInputOneOutput) {
sp<CountedAllocator> allocator(new CountedAllocator);
@@ -107,21 +110,22 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
+ HAL_DATASPACE_UNKNOWN,
Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
Fence::NO_FENCE);
ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
- IGraphicBufferConsumer::BufferItem item;
+ BufferItem item;
ASSERT_EQ(OK, outputConsumer->acquireBuffer(&item, 0));
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
@@ -173,22 +177,23 @@
uint32_t* dataIn;
ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&dataIn)));
- *dataIn = 0x12345678;
+ *dataIn = TEST_DATA;
ASSERT_EQ(OK, buffer->unlock());
IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
+ HAL_DATASPACE_UNKNOWN,
Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
Fence::NO_FENCE);
ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
for (int output = 0; output < NUM_OUTPUTS; ++output) {
- IGraphicBufferConsumer::BufferItem item;
+ BufferItem item;
ASSERT_EQ(OK, outputConsumers[output]->acquireBuffer(&item, 0));
uint32_t* dataOut;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, 0x12345678);
+ ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf,
@@ -234,6 +239,7 @@
outputConsumer->consumerDisconnect();
IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
+ HAL_DATASPACE_UNKNOWN,
Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
Fence::NO_FENCE);
ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 8cdf3bc..1a50b24 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -27,6 +27,9 @@
#include <utils/Log.h>
#include <utils/Thread.h>
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+#define CROP_EXT_STR "EGL_ANDROID_image_crop"
+
namespace android {
class SurfaceTextureClientTest : public ::testing::Test {
@@ -207,12 +210,8 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, 0, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, -1, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, -1));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, -1, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 8, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 8, 0, 0));
+ EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 8));
+ EXPECT_GT(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 0));
}
TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
@@ -226,7 +225,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, PIXEL_FORMAT_RGB_565));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
@@ -236,7 +236,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
@@ -246,7 +247,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
@@ -256,13 +258,15 @@
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
@@ -272,7 +276,8 @@
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
@@ -330,7 +335,8 @@
EXPECT_EQ(8, buf[1]->height);
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 12, 24, 0));
+ EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 12, 24));
+ EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
@@ -468,7 +474,8 @@
// Once we've queued a buffer, however we should not be able to dequeue more
// than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case.
- EXPECT_EQ(-EBUSY, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+ EXPECT_EQ(INVALID_OPERATION,
+ native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1));
@@ -611,6 +618,18 @@
}
TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWithCrop) {
+ // Query to see if the image crop extension exists
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
+ size_t cropExtLen = strlen(CROP_EXT_STR);
+ size_t extsLen = strlen(exts);
+ bool equal = !strcmp(CROP_EXT_STR, exts);
+ bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
+ bool atEnd = (cropExtLen+1) < extsLen &&
+ !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
+ bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
+ bool hasEglAndroidImageCrop = equal || atStart || atEnd || inMiddle;
+
android_native_buffer_t* buf[3];
float mtx[16] = {};
android_native_rect_t crop;
@@ -620,7 +639,8 @@
crop.bottom = 5;
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
- ASSERT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 8, 8, 0));
+ ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8));
+ ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -628,15 +648,17 @@
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
mST->getTransformMatrix(mtx);
- // This accounts for the .5 texel shrink for each edge that's included in the
- // transform matrix to avoid texturing outside the crop region.
- EXPECT_EQ(0.5, mtx[0]);
+ // If the egl image crop extension is not present, this accounts for the
+ // .5 texel shrink for each edge that's included in the transform matrix
+ // to avoid texturing outside the crop region. Otherwise the crop is not
+ // included in the transform matrix.
+ EXPECT_EQ(hasEglAndroidImageCrop ? 1 : 0.5, mtx[0]);
EXPECT_EQ(0.f, mtx[1]);
EXPECT_EQ(0.f, mtx[2]);
EXPECT_EQ(0.f, mtx[3]);
EXPECT_EQ(0.f, mtx[4]);
- EXPECT_EQ(-0.5, mtx[5]);
+ EXPECT_EQ(hasEglAndroidImageCrop ? -1 : -0.5, mtx[5]);
EXPECT_EQ(0.f, mtx[6]);
EXPECT_EQ(0.f, mtx[7]);
@@ -645,8 +667,8 @@
EXPECT_EQ(1.f, mtx[10]);
EXPECT_EQ(0.f, mtx[11]);
- EXPECT_EQ(0.0625f, mtx[12]);
- EXPECT_EQ(0.5625f, mtx[13]);
+ EXPECT_EQ(hasEglAndroidImageCrop ? 0 : 0.0625f, mtx[12]);
+ EXPECT_EQ(hasEglAndroidImageCrop ? 1 : 0.5625f, mtx[13]);
EXPECT_EQ(0.f, mtx[14]);
EXPECT_EQ(1.f, mtx[15]);
}
@@ -668,7 +690,8 @@
const int numFmts = (sizeof(fmts) / sizeof(fmts[0]));
for (int i = 0; i < numFmts; i++) {
int fmt = -1;
- ASSERT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, fmts[i]));
+ ASSERT_EQ(OK, native_window_set_buffers_dimensions(anw.get(), 0, 0));
+ ASSERT_EQ(OK, native_window_set_buffers_format(anw.get(), fmts[i]));
ASSERT_EQ(OK, anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt));
EXPECT_EQ(fmts[i], fmt);
}
diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp
index b165ae6..c243fc0 100644
--- a/libs/gui/tests/SurfaceTextureFBO_test.cpp
+++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp
@@ -27,8 +27,10 @@
const int texWidth = 64;
const int texHeight = 64;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_RGBA_8888));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
diff --git a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
index f4c7961..6edbfb8 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
@@ -188,10 +188,10 @@
// This test should have the only reference to buffer 0.
EXPECT_EQ(1, buffers[0]->getStrongCount());
- // The GLConsumer should hold a single reference to buffer 1 in its
- // mCurrentBuffer member. All of the references in the slots should have
- // been released.
- EXPECT_EQ(2, buffers[1]->getStrongCount());
+ // The GLConsumer should hold one reference to buffer 1 in its
+ // mCurrentTextureImage member and another reference in mEglSlots. The third
+ // reference is in this test.
+ EXPECT_EQ(3, buffers[1]->getStrongCount());
}
TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
@@ -235,14 +235,19 @@
ASSERT_EQ(EGL_SUCCESS, eglGetError());
mProducerEglSurface = EGL_NO_SURFACE;
- EXPECT_EQ(1, buffers[0]->getStrongCount());
EXPECT_EQ(1, buffers[1]->getStrongCount());
// Depending on how lazily the GL driver dequeues buffers, we may end up
- // with either two or three total buffers. If there are three, make sure
- // the last one was properly down-ref'd.
+ // with either two or three total buffers. If there are three, each entry
+ // of the buffers array will be unique and there should only be one
+ // reference (the one in this test). If there are two the first and last
+ // element in the array will be equal meaning that buffer representing both
+ // 0 and 2 will have two references (one for 0 and one for 2).
if (buffers[2] != buffers[0]) {
+ EXPECT_EQ(1, buffers[0]->getStrongCount());
EXPECT_EQ(1, buffers[2]->getStrongCount());
+ } else {
+ EXPECT_EQ(2, buffers[0]->getStrongCount());
}
}
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index fa1e1b7..fad133f 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -28,8 +28,10 @@
const int texWidth = 64;
const int texHeight = 66;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -74,8 +76,10 @@
const int texWidth = 64;
const int texHeight = 64;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -120,8 +124,10 @@
const int texWidth = 64;
const int texHeight = 66;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -185,8 +191,10 @@
enum { numFrames = 1024 };
ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -326,8 +334,10 @@
const int texWidth = 64;
const int texHeight = 66;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_RGBA_8888));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -368,8 +378,10 @@
const int texWidth = 64;
const int texHeight = 64;
- ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ texWidth, texHeight));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_RGBA_8888));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 5e6aeef..3f495f8 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "DummyConsumer.h"
+
#include <gtest/gtest.h>
#include <binder/IMemory.h>
@@ -155,4 +157,75 @@
ASSERT_EQ(TEST_USAGE_FLAGS, flags);
}
+TEST_F(SurfaceTest, QueryDefaultBuffersDataSpace) {
+ const android_dataspace TEST_DATASPACE = HAL_DATASPACE_SRGB;
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+
+ cpuConsumer->setDefaultBufferDataSpace(TEST_DATASPACE);
+
+ sp<Surface> s = new Surface(producer);
+
+ sp<ANativeWindow> anw(s);
+
+ android_dataspace dataSpace;
+
+ int err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
+ reinterpret_cast<int*>(&dataSpace));
+
+ ASSERT_EQ(NO_ERROR, err);
+ ASSERT_EQ(TEST_DATASPACE, dataSpace);
+}
+
+TEST_F(SurfaceTest, SettingGenerationNumber) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+
+ // Allocate a buffer with a generation number of 0
+ ANativeWindowBuffer* buffer;
+ int fenceFd;
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
+
+ // Detach the buffer and check its generation number
+ sp<GraphicBuffer> graphicBuffer;
+ sp<Fence> fence;
+ ASSERT_EQ(NO_ERROR, surface->detachNextBuffer(&graphicBuffer, &fence));
+ ASSERT_EQ(0U, graphicBuffer->getGenerationNumber());
+
+ ASSERT_EQ(NO_ERROR, surface->setGenerationNumber(1));
+ buffer = static_cast<ANativeWindowBuffer*>(graphicBuffer.get());
+
+ // This should change the generation number of the GraphicBuffer
+ ASSERT_EQ(NO_ERROR, surface->attachBuffer(buffer));
+
+ // Check that the new generation number sticks with the buffer
+ ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, -1));
+ ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
+ graphicBuffer = static_cast<GraphicBuffer*>(buffer);
+ ASSERT_EQ(1U, graphicBuffer->getGenerationNumber());
+}
+
+TEST_F(SurfaceTest, GetConsumerName) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+ native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+
+ EXPECT_STREQ("TestConsumer", surface->getConsumerName().string());
+}
+
}
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index f1921a4..944ac7f 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -27,6 +27,7 @@
deviceSources := \
$(commonSources) \
+ IInputFlinger.cpp \
InputTransport.cpp \
VelocityControl.cpp \
VelocityTracker.cpp
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
new file mode 100644
index 0000000..e009731
--- /dev/null
+++ b/libs/input/IInputFlinger.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 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 <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <input/IInputFlinger.h>
+
+
+namespace android {
+
+class BpInputFlinger : public BpInterface<IInputFlinger> {
+public:
+ BpInputFlinger(const sp<IBinder>& impl) :
+ BpInterface<IInputFlinger>(impl) { }
+
+ virtual status_t doSomething() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+ remote()->transact(BnInputFlinger::DO_SOMETHING_TRANSACTION, data, &reply);
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
+
+
+status_t BnInputFlinger::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ switch(code) {
+ case DO_SOMETHING_TRANSACTION: {
+ CHECK_INTERFACE(IInputFlinger, data, reply);
+ reply->writeInt32(0);
+ break;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+ return NO_ERROR;
+}
+
+};
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 3a7afe9..2c1418e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -216,6 +216,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t actionButton,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
@@ -231,6 +232,7 @@
const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source);
mAction = action;
+ mActionButton = actionButton;
mFlags = flags;
mEdgeFlags = edgeFlags;
mMetaState = metaState;
@@ -250,6 +252,7 @@
void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
InputEvent::initialize(other->mDeviceId, other->mSource);
mAction = other->mAction;
+ mActionButton = other->mActionButton;
mFlags = other->mFlags;
mEdgeFlags = other->mEdgeFlags;
mMetaState = other->mMetaState;
@@ -428,6 +431,7 @@
mDeviceId = parcel->readInt32();
mSource = parcel->readInt32();
mAction = parcel->readInt32();
+ mActionButton = parcel->readInt32();
mFlags = parcel->readInt32();
mEdgeFlags = parcel->readInt32();
mMetaState = parcel->readInt32();
@@ -475,6 +479,7 @@
parcel->writeInt32(mDeviceId);
parcel->writeInt32(mSource);
parcel->writeInt32(mAction);
+ parcel->writeInt32(mActionButton);
parcel->writeInt32(mFlags);
parcel->writeInt32(mEdgeFlags);
parcel->writeInt32(mMetaState);
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index b11110a..d755ed3 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -127,28 +127,31 @@
// --- InputDeviceInfo ---
InputDeviceInfo::InputDeviceInfo() {
- initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false);
+ initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false, false);
}
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
mId(other.mId), mGeneration(other.mGeneration), mControllerNumber(other.mControllerNumber),
mIdentifier(other.mIdentifier), mAlias(other.mAlias), mIsExternal(other.mIsExternal),
- mSources(other.mSources), mKeyboardType(other.mKeyboardType),
- mKeyCharacterMap(other.mKeyCharacterMap), mHasVibrator(other.mHasVibrator),
- mHasButtonUnderPad(other.mHasButtonUnderPad), mMotionRanges(other.mMotionRanges) {
+ mHasMic(other.mHasMic), mSources(other.mSources),
+ mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap),
+ mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad),
+ mMotionRanges(other.mMotionRanges) {
}
InputDeviceInfo::~InputDeviceInfo() {
}
void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal) {
+ const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
+ bool hasMic) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
mIdentifier = identifier;
mAlias = alias;
mIsExternal = isExternal;
+ mHasMic = hasMic;
mSources = 0;
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
mHasVibrator = false;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 090ee53..0382f57 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -283,6 +283,7 @@
int32_t deviceId,
int32_t source,
int32_t action,
+ int32_t actionButton,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
@@ -298,12 +299,12 @@
const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
- "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
- "xOffset=%f, yOffset=%f, "
+ "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
+ "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
"pointerCount=%" PRIu32,
mChannel->getName().string(), seq,
- deviceId, source, action, flags, edgeFlags, metaState, buttonState,
+ deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState,
xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif
@@ -324,6 +325,7 @@
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.action = action;
+ msg.body.motion.actionButton = actionButton;
msg.body.motion.flags = flags;
msg.body.motion.edgeFlags = edgeFlags;
msg.body.motion.metaState = metaState;
@@ -907,6 +909,7 @@
msg->body.motion.deviceId,
msg->body.motion.source,
msg->body.motion.action,
+ msg->body.motion.actionButton,
msg->body.motion.flags,
msg->body.motion.edgeFlags,
msg->body.motion.metaState,
diff --git a/libs/input/tests/Android.mk b/libs/input/tests/Android.mk
index 9612a65..5bfa3d4 100644
--- a/libs/input/tests/Android.mk
+++ b/libs/input/tests/Android.mk
@@ -1,6 +1,5 @@
# Build the unit tests.
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
# Build the unit tests.
test_src_files := \
@@ -14,14 +13,10 @@
libutils \
libbinder \
libui \
- libstlport
-
-static_libraries := \
- libgtest \
- libgtest_main
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
+ $(eval LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk) \
$(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
$(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
$(eval LOCAL_SRC_FILES := $(file)) \
@@ -33,6 +28,7 @@
# run. All assertions are static_asserts and will fail during
# buildtime if something's wrong.
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES := StructLayout_test.cpp
LOCAL_MODULE := StructLayout_test
LOCAL_CFLAGS := -std=c++11 -O0
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 9105ae5..3fb1c6d 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -248,7 +248,7 @@
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
- event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
+ event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, 0,
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
@@ -557,7 +557,7 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
- event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0,
+ event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index de192f1..8e69c9c 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -133,6 +133,7 @@
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
const int32_t action = AMOTION_EVENT_ACTION_MOVE;
+ const int32_t actionButton = 0;
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
@@ -163,8 +164,8 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
}
- status = mPublisher->publishMotionEvent(seq, deviceId, source, action, flags, edgeFlags,
- metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
+ status = mPublisher->publishMotionEvent(seq, deviceId, source, action, actionButton,
+ flags, edgeFlags, metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
downTime, eventTime, pointerCount,
pointerProperties, pointerCoords);
ASSERT_EQ(OK, status)
@@ -255,7 +256,7 @@
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
@@ -271,7 +272,7 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 83bc6ae..8d73f45 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -51,10 +51,11 @@
CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
CHECK_OFFSET(InputMessage::Body::Motion, action, 24);
- CHECK_OFFSET(InputMessage::Body::Motion, flags, 28);
- CHECK_OFFSET(InputMessage::Body::Motion, metaState, 32);
- CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 36);
- CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 40);
+ CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 28);
+ CHECK_OFFSET(InputMessage::Body::Motion, flags, 32);
+ CHECK_OFFSET(InputMessage::Body::Motion, metaState, 36);
+ CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 40);
+ CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 44);
CHECK_OFFSET(InputMessage::Body::Motion, downTime, 48);
CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 56);
CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 60);
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index eec97be..1ce8626 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -12,10 +12,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
+LOCAL_CLANG := true
+LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
+
+# The static constructors and destructors in this library have not been noted to
+# introduce significant overheads
+LOCAL_CPPFLAGS += -Wno-exit-time-destructors
+LOCAL_CPPFLAGS += -Wno-global-constructors
+
+# We only care about compiling as C++14
+LOCAL_CPPFLAGS += -Wno-c++98-compat-pedantic
+
+# We use four-character constants for the GraphicBuffer header, and don't care
+# that they're non-portable as long as they're consistent within one execution
+LOCAL_CPPFLAGS += -Wno-four-char-constants
+
+# Don't warn about struct padding
+LOCAL_CPPFLAGS += -Wno-padded
+
+LOCAL_SRC_FILES := \
Fence.cpp \
FramebufferNativeWindow.cpp \
FrameStats.cpp \
@@ -38,7 +56,7 @@
LOCAL_CFLAGS += -DFRAMEBUFFER_FORCE_FORMAT=$(BOARD_FRAMEBUFFER_FORCE_FORMAT)
endif
-LOCAL_MODULE:= libui
+LOCAL_MODULE := libui
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index 3c0306c..bf24ffb 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -18,10 +18,13 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
- // This is needed for stdint.h to define INT64_MAX in C++
- #define __STDC_LIMIT_MACROS
-
+// We would eliminate the non-conforming zero-length array, but we can't since
+// this is effectively included from the Linux kernel
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
#include <sync/sync.h>
+#pragma clang diagnostic pop
+
#include <ui/Fence.h>
#include <unistd.h>
#include <utils/Log.h>
@@ -45,7 +48,7 @@
}
}
-status_t Fence::wait(unsigned int timeout) {
+status_t Fence::wait(int timeout) {
ATRACE_CALL();
if (mFenceFd == -1) {
return NO_ERROR;
@@ -59,7 +62,7 @@
if (mFenceFd == -1) {
return NO_ERROR;
}
- unsigned int warningTimeout = 3000;
+ int warningTimeout = 3000;
int err = sync_wait(mFenceFd, warningTimeout);
if (err < 0 && errno == ETIME) {
ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
@@ -127,7 +130,7 @@
}
size_t Fence::getFlattenedSize() const {
- return 1;
+ return 4;
}
size_t Fence::getFdCount() const {
@@ -138,7 +141,9 @@
if (size < getFlattenedSize() || count < getFdCount()) {
return NO_MEMORY;
}
- FlattenableUtils::write(buffer, size, (uint32_t)getFdCount());
+ // Cast to uint32_t since the size of a size_t can vary between 32- and
+ // 64-bit processes
+ FlattenableUtils::write(buffer, size, static_cast<uint32_t>(getFdCount()));
if (isValid()) {
*fds++ = mFenceFd;
count--;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 918f2e7..3ead25c 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -1,17 +1,17 @@
-/*
+/*
**
** Copyright 2007 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
+** 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
+** 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
+** 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.
*/
@@ -29,7 +29,9 @@
#include <ui/ANativeObjectBase.h>
#include <ui/Fence.h>
+#define INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
#include <ui/FramebufferNativeWindow.h>
+#undef INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
#include <ui/Rect.h>
#include <EGL/egl.h>
@@ -41,11 +43,11 @@
namespace android {
// ----------------------------------------------------------------------------
-class NativeBuffer
+class NativeBuffer final
: public ANativeObjectBase<
- ANativeWindowBuffer,
- NativeBuffer,
- LightRefBase<NativeBuffer> >
+ ANativeWindowBuffer,
+ NativeBuffer,
+ LightRefBase<NativeBuffer>>
{
public:
NativeBuffer(int w, int h, int f, int u) : BASE() {
@@ -55,43 +57,41 @@
ANativeWindowBuffer::usage = u;
}
private:
- friend class LightRefBase<NativeBuffer>;
- ~NativeBuffer() { }; // this class cannot be overloaded
+ friend class LightRefBase<NativeBuffer>;
};
/*
* This implements the (main) framebuffer management. This class is used
* mostly by SurfaceFlinger, but also by command line GL application.
- *
+ *
* In fact this is an implementation of ANativeWindow on top of
* the framebuffer.
- *
- * Currently it is pretty simple, it manages only two buffers (the front and
+ *
+ * Currently it is pretty simple, it manages only two buffers (the front and
* back buffer).
- *
+ *
*/
-FramebufferNativeWindow::FramebufferNativeWindow()
+FramebufferNativeWindow::FramebufferNativeWindow()
: BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{
hw_module_t const* module;
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
- int stride;
int err;
int i;
err = framebuffer_open(module, &fbDev);
ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
-
+
err = gralloc_open(module, &grDev);
ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
// bail out if we can't initialize the modules
if (!fbDev || !grDev)
return;
-
+
mUpdateOnDemand = (fbDev->setUpdateRect != 0);
-
+
// initialize the buffer FIFO
if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS &&
fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){
@@ -114,36 +114,37 @@
*((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT;
#endif
- for (i = 0; i < mNumBuffers; i++)
- {
- buffers[i] = new NativeBuffer(
- fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+ for (i = 0; i < mNumBuffers; i++) {
+ buffers[i] = new NativeBuffer(
+ static_cast<int>(fbDev->width),
+ static_cast<int>(fbDev->height),
+ fbDev->format, GRALLOC_USAGE_HW_FB);
}
- for (i = 0; i < mNumBuffers; i++)
- {
- err = grDev->alloc(grDev,
- fbDev->width, fbDev->height, fbDev->format,
- GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
+ for (i = 0; i < mNumBuffers; i++) {
+ err = grDev->alloc(grDev,
+ static_cast<int>(fbDev->width),
+ static_cast<int>(fbDev->height),
+ fbDev->format, GRALLOC_USAGE_HW_FB,
+ &buffers[i]->handle, &buffers[i]->stride);
- ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
- i, fbDev->width, fbDev->height, strerror(-err));
+ ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
+ i, fbDev->width, fbDev->height, strerror(-err));
- if (err)
- {
- mNumBuffers = i;
- mNumFreeBuffers = i;
- mBufferHead = mNumBuffers-1;
- break;
- }
+ if (err) {
+ mNumBuffers = i;
+ mNumFreeBuffers = i;
+ mBufferHead = mNumBuffers-1;
+ break;
+ }
}
- const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
+ const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
- const_cast<int&>(ANativeWindow::minSwapInterval) =
+ const_cast<int&>(ANativeWindow::minSwapInterval) =
fbDev->minSwapInterval;
- const_cast<int&>(ANativeWindow::maxSwapInterval) =
+ const_cast<int&>(ANativeWindow::maxSwapInterval) =
fbDev->maxSwapInterval;
} else {
ALOGE("Couldn't get gralloc module");
@@ -160,7 +161,7 @@
ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED;
}
-FramebufferNativeWindow::~FramebufferNativeWindow()
+FramebufferNativeWindow::~FramebufferNativeWindow()
{
if (grDev) {
for(int i = 0; i < mNumBuffers; i++) {
@@ -176,7 +177,7 @@
}
}
-status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r)
+status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r)
{
if (!mUpdateOnDemand) {
return INVALID_OPERATION;
@@ -193,7 +194,7 @@
}
int FramebufferNativeWindow::setSwapInterval(
- ANativeWindow* window, int interval)
+ ANativeWindow* window, int interval)
{
framebuffer_device_t* fb = getSelf(window)->fbDev;
return fb->setSwapInterval(fb, interval);
@@ -217,7 +218,7 @@
return index;
}
-int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window,
+int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer** buffer)
{
int fenceFd = -1;
@@ -232,12 +233,11 @@
return result;
}
-int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
+int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
ANativeWindowBuffer** buffer, int* fenceFd)
{
FramebufferNativeWindow* self = getSelf(window);
Mutex::Autolock _l(self->mutex);
- framebuffer_device_t* fb = self->fbDev;
int index = self->mBufferHead++;
if (self->mBufferHead >= self->mNumBuffers)
@@ -247,7 +247,7 @@
while (self->mNumFreeBuffers < 2) {
self->mCondition.wait(self->mutex);
}
- ALOG_ASSERT(self->buffers[index] != self->front);
+ ALOG_ASSERT(self->buffers[index] != self->front, "");
// get this buffer
self->mNumFreeBuffers--;
@@ -259,19 +259,19 @@
return 0;
}
-int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* /*window*/,
+int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* /*window*/,
ANativeWindowBuffer* /*buffer*/)
{
return NO_ERROR;
}
-int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window,
+int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer* buffer)
{
return queueBuffer(window, buffer, -1);
}
-int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
+int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
ANativeWindowBuffer* buffer, int fenceFd)
{
FramebufferNativeWindow* self = getSelf(window);
@@ -282,7 +282,6 @@
sp<Fence> fence(new Fence(fenceFd));
fence->wait(Fence::TIMEOUT_NEVER);
- const int index = self->mCurrentBufferIndex;
int res = fb->post(fb, handle);
self->front = static_cast<NativeBuffer*>(buffer);
self->mNumFreeBuffers++;
@@ -291,17 +290,17 @@
}
int FramebufferNativeWindow::query(const ANativeWindow* window,
- int what, int* value)
+ int what, int* value)
{
const FramebufferNativeWindow* self = getSelf(window);
Mutex::Autolock _l(self->mutex);
framebuffer_device_t* fb = self->fbDev;
switch (what) {
case NATIVE_WINDOW_WIDTH:
- *value = fb->width;
+ *value = static_cast<int>(fb->width);
return NO_ERROR;
case NATIVE_WINDOW_HEIGHT:
- *value = fb->height;
+ *value = static_cast<int>(fb->height);
return NO_ERROR;
case NATIVE_WINDOW_FORMAT:
*value = fb->format;
@@ -313,10 +312,10 @@
*value = 0;
return NO_ERROR;
case NATIVE_WINDOW_DEFAULT_WIDTH:
- *value = fb->width;
+ *value = static_cast<int>(fb->width);
return NO_ERROR;
case NATIVE_WINDOW_DEFAULT_HEIGHT:
- *value = fb->height;
+ *value = static_cast<int>(fb->height);
return NO_ERROR;
case NATIVE_WINDOW_TRANSFORM_HINT:
*value = 0;
@@ -357,7 +356,8 @@
}; // namespace android
// ----------------------------------------------------------------------------
-using namespace android;
+using android::sp;
+using android::FramebufferNativeWindow;
EGLNativeWindowType android_createDisplaySurface(void)
{
@@ -368,5 +368,5 @@
sp<FramebufferNativeWindow> ref(w);
return NULL;
}
- return (EGLNativeWindowType)w;
+ return static_cast<EGLNativeWindowType>(w);
}
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3ae8840..e55db30 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -45,40 +45,40 @@
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mId(getUniqueId())
{
- width =
- height =
- stride =
- format =
+ width =
+ height =
+ stride =
+ format =
usage = 0;
handle = NULL;
}
-GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat reqFormat, uint32_t reqUsage)
+GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage)
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mId(getUniqueId())
{
- width =
- height =
- stride =
- format =
+ width =
+ height =
+ stride =
+ format =
usage = 0;
handle = NULL;
- mInitCheck = initSize(w, h, reqFormat, reqUsage);
+ mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage);
}
-GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat inFormat, uint32_t inUsage,
- uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
+GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage, uint32_t inStride,
+ native_handle_t* inHandle, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mId(getUniqueId())
{
- width = w;
- height = h;
- stride = inStride;
+ width = static_cast<int>(inWidth);
+ height = static_cast<int>(inHeight);
+ stride = static_cast<int>(inStride);
format = inFormat;
- usage = inUsage;
+ usage = static_cast<int>(inUsage);
handle = inHandle;
}
@@ -116,7 +116,7 @@
}
status_t GraphicBuffer::initCheck() const {
- return mInitCheck;
+ return static_cast<status_t>(mInitCheck);
}
void GraphicBuffer::dumpAllocationsToSystemLog()
@@ -131,13 +131,17 @@
const_cast<GraphicBuffer*>(this));
}
-status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
- uint32_t reqUsage)
+status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage)
{
if (mOwner != ownData)
return INVALID_OPERATION;
- if (handle && w==width && h==height && f==format && reqUsage==usage)
+ if (handle &&
+ static_cast<int>(inWidth) == width &&
+ static_cast<int>(inHeight) == height &&
+ inFormat == format &&
+ static_cast<int>(inUsage) == usage)
return NO_ERROR;
if (handle) {
@@ -145,61 +149,74 @@
allocator.free(handle);
handle = 0;
}
- return initSize(w, h, f, reqUsage);
+ return initSize(inWidth, inHeight, inFormat, inUsage);
}
-status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
- uint32_t reqUsage)
+bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage)
+{
+ if (static_cast<int>(inWidth) != width) return true;
+ if (static_cast<int>(inHeight) != height) return true;
+ if (inFormat != format) return true;
+ if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
+ return false;
+}
+
+status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
+ PixelFormat inFormat, uint32_t inUsage)
{
GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
- status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);
+ uint32_t outStride = 0;
+ status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage,
+ &handle, &outStride);
if (err == NO_ERROR) {
- this->width = w;
- this->height = h;
- this->format = format;
- this->usage = reqUsage;
+ width = static_cast<int>(inWidth);
+ height = static_cast<int>(inHeight);
+ format = inFormat;
+ usage = static_cast<int>(inUsage);
+ stride = static_cast<int>(outStride);
}
return err;
}
-status_t GraphicBuffer::lock(uint32_t usage, void** vaddr)
+status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
{
const Rect lockBounds(width, height);
- status_t res = lock(usage, lockBounds, vaddr);
+ status_t res = lock(inUsage, lockBounds, vaddr);
return res;
}
-status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
+status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
{
- if (rect.left < 0 || rect.right > this->width ||
- rect.top < 0 || rect.bottom > this->height) {
- ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
- rect.left, rect.top, rect.right, rect.bottom,
- this->width, this->height);
- return BAD_VALUE;
- }
- status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
- return res;
-}
-
-status_t GraphicBuffer::lockYCbCr(uint32_t usage, android_ycbcr *ycbcr)
-{
- const Rect lockBounds(width, height);
- status_t res = lockYCbCr(usage, lockBounds, ycbcr);
- return res;
-}
-
-status_t GraphicBuffer::lockYCbCr(uint32_t usage, const Rect& rect,
- android_ycbcr *ycbcr)
-{
- if (rect.left < 0 || rect.right > this->width ||
- rect.top < 0 || rect.bottom > this->height) {
+ if (rect.left < 0 || rect.right > width ||
+ rect.top < 0 || rect.bottom > height) {
ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
rect.left, rect.top, rect.right, rect.bottom,
- this->width, this->height);
+ width, height);
return BAD_VALUE;
}
- status_t res = getBufferMapper().lockYCbCr(handle, usage, rect, ycbcr);
+ status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr);
+ return res;
+}
+
+status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
+{
+ const Rect lockBounds(width, height);
+ status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);
+ return res;
+}
+
+status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
+ android_ycbcr* ycbcr)
+{
+ if (rect.left < 0 || rect.right > width ||
+ rect.top < 0 || rect.bottom > height) {
+ ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
+ rect.left, rect.top, rect.right, rect.bottom,
+ width, height);
+ return BAD_VALUE;
+ }
+ status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr);
return res;
}
@@ -209,43 +226,48 @@
return res;
}
-status_t GraphicBuffer::lockAsync(uint32_t usage, void** vaddr, int fenceFd)
+status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
{
const Rect lockBounds(width, height);
- status_t res = lockAsync(usage, lockBounds, vaddr, fenceFd);
+ status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);
return res;
}
-status_t GraphicBuffer::lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd)
+status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
+ void** vaddr, int fenceFd)
{
- if (rect.left < 0 || rect.right > this->width ||
- rect.top < 0 || rect.bottom > this->height) {
+ if (rect.left < 0 || rect.right > width ||
+ rect.top < 0 || rect.bottom > height) {
ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
rect.left, rect.top, rect.right, rect.bottom,
- this->width, this->height);
+ width, height);
return BAD_VALUE;
}
- status_t res = getBufferMapper().lockAsync(handle, usage, rect, vaddr, fenceFd);
+ status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr,
+ fenceFd);
return res;
}
-status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd)
+status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
+ int fenceFd)
{
const Rect lockBounds(width, height);
- status_t res = lockAsyncYCbCr(usage, lockBounds, ycbcr, fenceFd);
+ status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);
return res;
}
-status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd)
+status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
+ android_ycbcr* ycbcr, int fenceFd)
{
- if (rect.left < 0 || rect.right > this->width ||
- rect.top < 0 || rect.bottom > this->height) {
+ if (rect.left < 0 || rect.right > width ||
+ rect.top < 0 || rect.bottom > height) {
ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
rect.left, rect.top, rect.right, rect.bottom,
- this->width, this->height);
+ width, height);
return BAD_VALUE;
}
- status_t res = getBufferMapper().lockAsyncYCbCr(handle, usage, rect, ycbcr, fenceFd);
+ status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,
+ ycbcr, fenceFd);
return res;
}
@@ -256,11 +278,11 @@
}
size_t GraphicBuffer::getFlattenedSize() const {
- return (10 + (handle ? handle->numInts : 0))*sizeof(int);
+ return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int);
}
size_t GraphicBuffer::getFdCount() const {
- return handle ? handle->numFds : 0;
+ return static_cast<size_t>(handle ? handle->numFds : 0);
}
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
@@ -279,22 +301,24 @@
buf[5] = usage;
buf[6] = static_cast<int32_t>(mId >> 32);
buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
- buf[8] = 0;
+ buf[8] = static_cast<int32_t>(mGenerationNumber);
buf[9] = 0;
+ buf[10] = 0;
if (handle) {
- buf[8] = handle->numFds;
- buf[9] = handle->numInts;
- native_handle_t const* const h = handle;
- memcpy(fds, h->data, h->numFds*sizeof(int));
- memcpy(&buf[10], h->data + h->numFds, h->numInts*sizeof(int));
+ buf[9] = handle->numFds;
+ buf[10] = handle->numInts;
+ memcpy(fds, handle->data,
+ static_cast<size_t>(handle->numFds) * sizeof(int));
+ memcpy(&buf[11], handle->data + handle->numFds,
+ static_cast<size_t>(handle->numInts) * sizeof(int));
}
- buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded);
+ buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
size -= sizeNeeded;
if (handle) {
fds += handle->numFds;
- count -= handle->numFds;
+ count -= static_cast<size_t>(handle->numFds);
}
return NO_ERROR;
@@ -302,28 +326,28 @@
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
- if (size < 8*sizeof(int)) return NO_MEMORY;
+ if (size < 11 * sizeof(int)) return NO_MEMORY;
int const* buf = static_cast<int const*>(buffer);
if (buf[0] != 'GBFR') return BAD_TYPE;
- const size_t numFds = buf[8];
- const size_t numInts = buf[9];
+ const size_t numFds = static_cast<size_t>(buf[9]);
+ const size_t numInts = static_cast<size_t>(buf[10]);
// Limit the maxNumber to be relatively small. The number of fds or ints
// should not come close to this number, and the number itself was simply
// chosen to be high enough to not cause issues and low enough to prevent
// overflow problems.
const size_t maxNumber = 4096;
- if (numFds >= maxNumber || numInts >= (maxNumber - 10)) {
+ if (numFds >= maxNumber || numInts >= (maxNumber - 11)) {
width = height = stride = format = usage = 0;
handle = NULL;
- ALOGE("unflatten: numFds or numInts is too large: %d, %d",
+ ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
numFds, numInts);
return BAD_VALUE;
}
- const size_t sizeNeeded = (10 + numInts) * sizeof(int);
+ const size_t sizeNeeded = (11 + numInts) * sizeof(int);
if (size < sizeNeeded) return NO_MEMORY;
size_t fdCountNeeded = numFds;
@@ -340,15 +364,16 @@
stride = buf[3];
format = buf[4];
usage = buf[5];
- native_handle* h = native_handle_create(numFds, numInts);
+ native_handle* h = native_handle_create(
+ static_cast<int>(numFds), static_cast<int>(numInts));
if (!h) {
width = height = stride = format = usage = 0;
handle = NULL;
ALOGE("unflatten: native_handle_create failed");
return NO_MEMORY;
}
- memcpy(h->data, fds, numFds*sizeof(int));
- memcpy(h->data + numFds, &buf[10], numInts*sizeof(int));
+ memcpy(h->data, fds, numFds * sizeof(int));
+ memcpy(h->data + numFds, &buf[11], numInts * sizeof(int));
handle = h;
} else {
width = height = stride = format = usage = 0;
@@ -358,6 +383,8 @@
mId = static_cast<uint64_t>(buf[6]) << 32;
mId |= static_cast<uint32_t>(buf[7]);
+ mGenerationNumber = static_cast<uint32_t>(buf[8]);
+
mOwner = ownHandle;
if (handle != 0) {
@@ -371,7 +398,7 @@
}
}
- buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded);
+ buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
size -= sizeNeeded;
fds += numFds;
count -= numFds;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index ff550d9..9b265af 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -1,17 +1,17 @@
-/*
+/*
**
** Copyright 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
+** 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
+** 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
+** 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.
*/
@@ -66,11 +66,11 @@
if (rec.size) {
snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n",
list.keyAt(i), rec.size/1024.0f,
- rec.w, rec.s, rec.h, rec.format, rec.usage);
+ rec.width, rec.stride, rec.height, rec.format, rec.usage);
} else {
snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %8X | 0x%08x\n",
list.keyAt(i),
- rec.w, rec.s, rec.h, rec.format, rec.usage);
+ rec.width, rec.stride, rec.height, rec.format, rec.usage);
}
result.append(buffer);
total += rec.size;
@@ -90,39 +90,43 @@
ALOGD("%s", s.string());
}
-status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
- int usage, buffer_handle_t* handle, int32_t* stride)
+status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,
+ PixelFormat format, uint32_t usage, buffer_handle_t* handle,
+ uint32_t* stride)
{
ATRACE_CALL();
+
// make sure to not allocate a N x 0 or 0 x N buffer, since this is
// allowed from an API stand-point allocate a 1x1 buffer instead.
- if (!w || !h)
- w = h = 1;
+ if (!width || !height)
+ width = height = 1;
// we have a h/w allocator and h/w buffer is requested
- status_t err;
-
- err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
+ status_t err;
+
+ // Filter out any usage bits that should not be passed to the gralloc module
+ usage &= GRALLOC_USAGE_ALLOC_MASK;
+
+ int outStride = 0;
+ err = mAllocDev->alloc(mAllocDev, static_cast<int>(width),
+ static_cast<int>(height), format, static_cast<int>(usage), handle,
+ &outStride);
+ *stride = static_cast<uint32_t>(outStride);
ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
- w, h, format, usage, err, strerror(-err));
-
+ width, height, format, usage, err, strerror(-err));
+
if (err == NO_ERROR) {
Mutex::Autolock _l(sLock);
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
- int bpp = bytesPerPixel(format);
- if (bpp < 0) {
- // probably a HAL custom format. in any case, we don't know
- // what its pixel size is.
- bpp = 0;
- }
+ uint32_t bpp = bytesPerPixel(format);
alloc_rec_t rec;
- rec.w = w;
- rec.h = h;
- rec.s = *stride;
+ rec.width = width;
+ rec.height = height;
+ rec.stride = *stride;
rec.format = format;
rec.usage = usage;
- rec.size = h * stride[0] * bpp;
+ rec.size = static_cast<size_t>(height * (*stride) * bpp);
list.add(*handle, rec);
}
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index e949b0c..90a1c11 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,7 +20,12 @@
#include <stdint.h>
#include <errno.h>
+// We would eliminate the non-conforming zero-length array, but we can't since
+// this is effectively included from the Linux kernel
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
#include <sync/sync.h>
+#pragma clang diagnostic pop
#include <utils/Errors.h>
#include <utils/Log.h>
@@ -44,7 +49,7 @@
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
if (err == 0) {
- mAllocMod = (gralloc_module_t const *)module;
+ mAllocMod = reinterpret_cast<gralloc_module_t const *>(module);
}
}
@@ -72,13 +77,13 @@
return err;
}
-status_t GraphicBufferMapper::lock(buffer_handle_t handle,
- int usage, const Rect& bounds, void** vaddr)
+status_t GraphicBufferMapper::lock(buffer_handle_t handle,
+ uint32_t usage, const Rect& bounds, void** vaddr)
{
ATRACE_CALL();
status_t err;
- err = mAllocMod->lock(mAllocMod, handle, usage,
+ err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage),
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr);
@@ -87,7 +92,7 @@
}
status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle,
- int usage, const Rect& bounds, android_ycbcr *ycbcr)
+ uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr)
{
ATRACE_CALL();
status_t err;
@@ -96,7 +101,7 @@
return -EINVAL; // do not log failure
}
- err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage,
+ err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage),
bounds.left, bounds.top, bounds.width(), bounds.height(),
ycbcr);
@@ -116,19 +121,21 @@
}
status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
- int usage, const Rect& bounds, void** vaddr, int fenceFd)
+ uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
{
ATRACE_CALL();
status_t err;
if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
- err = mAllocMod->lockAsync(mAllocMod, handle, usage,
+ err = mAllocMod->lockAsync(mAllocMod, handle, static_cast<int>(usage),
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr, fenceFd);
} else {
- sync_wait(fenceFd, -1);
- close(fenceFd);
- err = mAllocMod->lock(mAllocMod, handle, usage,
+ if (fenceFd >= 0) {
+ sync_wait(fenceFd, -1);
+ close(fenceFd);
+ }
+ err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage),
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr);
}
@@ -138,23 +145,28 @@
}
status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
- int usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
+ uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
{
ATRACE_CALL();
status_t err;
if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3
&& mAllocMod->lockAsync_ycbcr != NULL) {
- err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle, usage,
- bounds.left, bounds.top, bounds.width(), bounds.height(),
- ycbcr, fenceFd);
+ err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle,
+ static_cast<int>(usage), bounds.left, bounds.top,
+ bounds.width(), bounds.height(), ycbcr, fenceFd);
} else if (mAllocMod->lock_ycbcr != NULL) {
- sync_wait(fenceFd, -1);
- close(fenceFd);
- err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage,
+ if (fenceFd >= 0) {
+ sync_wait(fenceFd, -1);
+ close(fenceFd);
+ }
+ err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage),
bounds.left, bounds.top, bounds.width(), bounds.height(),
ycbcr);
} else {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
return -EINVAL; // do not log failure
}
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index 5ce7fba..cab1dde 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -15,19 +15,16 @@
*/
#include <ui/PixelFormat.h>
-#include <hardware/hardware.h>
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
-ssize_t bytesPerPixel(PixelFormat format) {
+uint32_t bytesPerPixel(PixelFormat format) {
switch (format) {
case PIXEL_FORMAT_RGBA_8888:
case PIXEL_FORMAT_RGBX_8888:
case PIXEL_FORMAT_BGRA_8888:
- case PIXEL_FORMAT_sRGB_A_8888:
- case PIXEL_FORMAT_sRGB_X_8888:
return 4;
case PIXEL_FORMAT_RGB_888:
return 3;
@@ -36,10 +33,10 @@
case PIXEL_FORMAT_RGBA_4444:
return 2;
}
- return BAD_VALUE;
+ return 0;
}
-ssize_t bitsPerPixel(PixelFormat format) {
+uint32_t bitsPerPixel(PixelFormat format) {
switch (format) {
case PIXEL_FORMAT_RGBA_8888:
case PIXEL_FORMAT_RGBX_8888:
@@ -52,10 +49,9 @@
case PIXEL_FORMAT_RGBA_4444:
return 16;
}
- return BAD_VALUE;
+ return 0;
}
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
-
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index b480f3a..dcce21f 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -19,6 +19,8 @@
namespace android {
+const Rect Rect::INVALID_RECT{0, 0, -1, -1};
+
static inline int32_t min(int32_t a, int32_t b) {
return (a < b) ? a : b;
}
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index fa812f4..3810da4 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -53,6 +53,8 @@
direction_RTL
};
+const Region Region::INVALID_REGION(Rect::INVALID_RECT);
+
// ----------------------------------------------------------------------------
Region::Region() {
@@ -102,8 +104,8 @@
current--;
} while (current->top == lastTop && current >= begin);
- unsigned int beginLastSpan = -1;
- unsigned int endLastSpan = -1;
+ int beginLastSpan = -1;
+ int endLastSpan = -1;
int top = -1;
int bottom = -1;
@@ -118,7 +120,7 @@
} else {
beginLastSpan = endLastSpan + 1;
}
- endLastSpan = dst.size() - 1;
+ endLastSpan = static_cast<int>(dst.size()) - 1;
top = current->top;
bottom = current->bottom;
@@ -126,43 +128,46 @@
int left = current->left;
int right = current->right;
- for (unsigned int prevIndex = beginLastSpan; prevIndex <= endLastSpan; prevIndex++) {
- const Rect* prev = &dst[prevIndex];
+ for (int prevIndex = beginLastSpan; prevIndex <= endLastSpan; prevIndex++) {
+ // prevIndex can't be -1 here because if endLastSpan is set to a
+ // value greater than -1 (allowing the loop to execute),
+ // beginLastSpan (and therefore prevIndex) will also be increased
+ const Rect prev = dst[static_cast<size_t>(prevIndex)];
if (spanDirection == direction_RTL) {
// iterating over previous span RTL, quit if it's too far left
- if (prev->right <= left) break;
+ if (prev.right <= left) break;
- if (prev->right > left && prev->right < right) {
- dst.add(Rect(prev->right, top, right, bottom));
- right = prev->right;
+ if (prev.right > left && prev.right < right) {
+ dst.add(Rect(prev.right, top, right, bottom));
+ right = prev.right;
}
- if (prev->left > left && prev->left < right) {
- dst.add(Rect(prev->left, top, right, bottom));
- right = prev->left;
+ if (prev.left > left && prev.left < right) {
+ dst.add(Rect(prev.left, top, right, bottom));
+ right = prev.left;
}
// if an entry in the previous span is too far right, nothing further left in the
// current span will need it
- if (prev->left >= right) {
+ if (prev.left >= right) {
beginLastSpan = prevIndex;
}
} else {
// iterating over previous span LTR, quit if it's too far right
- if (prev->left >= right) break;
+ if (prev.left >= right) break;
- if (prev->left > left && prev->left < right) {
- dst.add(Rect(left, top, prev->left, bottom));
- left = prev->left;
+ if (prev.left > left && prev.left < right) {
+ dst.add(Rect(left, top, prev.left, bottom));
+ left = prev.left;
}
- if (prev->right > left && prev->right < right) {
- dst.add(Rect(left, top, prev->right, bottom));
- left = prev->right;
+ if (prev.right > left && prev.right < right) {
+ dst.add(Rect(left, top, prev.right, bottom));
+ left = prev.right;
}
// if an entry in the previous span is too far left, nothing further right in the
// current span will need it
- if (prev->right <= left) {
+ if (prev.right <= left) {
beginLastSpan = prevIndex;
}
}
@@ -250,10 +255,16 @@
mStorage.add(r);
}
+void Region::set(int32_t w, int32_t h)
+{
+ mStorage.clear();
+ mStorage.add(Rect(w, h));
+}
+
void Region::set(uint32_t w, uint32_t h)
{
mStorage.clear();
- mStorage.add(Rect(w,h));
+ mStorage.add(Rect(w, h));
}
bool Region::isTriviallyEqual(const Region& region) const {
@@ -404,7 +415,7 @@
// This is our region rasterizer, which merges rects and spans together
// to obtain an optimal region.
-class Region::rasterizer : public region_operator<Rect>::region_rasterizer
+class Region::rasterizer : public region_operator<Rect>::region_rasterizer
{
Rect bounds;
Vector<Rect>& storage;
@@ -413,81 +424,92 @@
Vector<Rect> span;
Rect* cur;
public:
- rasterizer(Region& reg)
+ rasterizer(Region& reg)
: bounds(INT_MAX, 0, INT_MIN, 0), storage(reg.mStorage), head(), tail(), cur() {
storage.clear();
}
- ~rasterizer() {
- if (span.size()) {
- flushSpan();
- }
- if (storage.size()) {
- bounds.top = storage.itemAt(0).top;
- bounds.bottom = storage.top().bottom;
- if (storage.size() == 1) {
- storage.clear();
- }
- } else {
- bounds.left = 0;
- bounds.right = 0;
- }
- storage.add(bounds);
- }
-
- virtual void operator()(const Rect& rect) {
- //ALOGD(">>> %3d, %3d, %3d, %3d",
- // rect.left, rect.top, rect.right, rect.bottom);
- if (span.size()) {
- if (cur->top != rect.top) {
- flushSpan();
- } else if (cur->right == rect.left) {
- cur->right = rect.right;
- return;
- }
- }
- span.add(rect);
- cur = span.editArray() + (span.size() - 1);
- }
+ virtual ~rasterizer();
+
+ virtual void operator()(const Rect& rect);
+
private:
- template<typename T>
+ template<typename T>
static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; }
- template<typename T>
+ template<typename T>
static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; }
- void flushSpan() {
- bool merge = false;
- if (tail-head == ssize_t(span.size())) {
- Rect const* p = span.editArray();
- Rect const* q = head;
- if (p->top == q->bottom) {
- merge = true;
- while (q != tail) {
- if ((p->left != q->left) || (p->right != q->right)) {
- merge = false;
- break;
- }
- p++, q++;
- }
- }
- }
- if (merge) {
- const int bottom = span[0].bottom;
- Rect* r = head;
- while (r != tail) {
- r->bottom = bottom;
- r++;
- }
- } else {
- bounds.left = min(span.itemAt(0).left, bounds.left);
- bounds.right = max(span.top().right, bounds.right);
- storage.appendVector(span);
- tail = storage.editArray() + storage.size();
- head = tail - span.size();
- }
- span.clear();
- }
+
+ void flushSpan();
};
+Region::rasterizer::~rasterizer()
+{
+ if (span.size()) {
+ flushSpan();
+ }
+ if (storage.size()) {
+ bounds.top = storage.itemAt(0).top;
+ bounds.bottom = storage.top().bottom;
+ if (storage.size() == 1) {
+ storage.clear();
+ }
+ } else {
+ bounds.left = 0;
+ bounds.right = 0;
+ }
+ storage.add(bounds);
+}
+
+void Region::rasterizer::operator()(const Rect& rect)
+{
+ //ALOGD(">>> %3d, %3d, %3d, %3d",
+ // rect.left, rect.top, rect.right, rect.bottom);
+ if (span.size()) {
+ if (cur->top != rect.top) {
+ flushSpan();
+ } else if (cur->right == rect.left) {
+ cur->right = rect.right;
+ return;
+ }
+ }
+ span.add(rect);
+ cur = span.editArray() + (span.size() - 1);
+}
+
+void Region::rasterizer::flushSpan()
+{
+ bool merge = false;
+ if (tail-head == ssize_t(span.size())) {
+ Rect const* p = span.editArray();
+ Rect const* q = head;
+ if (p->top == q->bottom) {
+ merge = true;
+ while (q != tail) {
+ if ((p->left != q->left) || (p->right != q->right)) {
+ merge = false;
+ break;
+ }
+ p++, q++;
+ }
+ }
+ }
+ if (merge) {
+ const int bottom = span[0].bottom;
+ Rect* r = head;
+ while (r != tail) {
+ r->bottom = bottom;
+ r++;
+ }
+ } else {
+ bounds.left = min(span.itemAt(0).left, bounds.left);
+ bounds.right = max(span.top().right, bounds.right);
+ storage.appendVector(span);
+ tail = storage.editArray() + storage.size();
+ head = tail - span.size();
+ }
+ span.clear();
+}
+
bool Region::validate(const Region& reg, const char* name, bool silent)
{
bool result = true;
@@ -497,8 +519,12 @@
Rect b(*prev);
while (cur != tail) {
if (cur->isValid() == false) {
- ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
- result = false;
+ // We allow this particular flavor of invalid Rect, since it is used
+ // as a signal value in various parts of the system
+ if (*cur != Rect::INVALID_RECT) {
+ ALOGE_IF(!silent, "%s: region contains an invalid Rect", name);
+ result = false;
+ }
}
if (cur->right > region_operator<Rect>::max_value) {
ALOGE_IF(!silent, "%s: rect->right > max_value", name);
@@ -670,7 +696,9 @@
const Region& lhs,
const Rect& rhs, int dx, int dy)
{
- if (!rhs.isValid()) {
+ // We allow this particular flavor of invalid Rect, since it is used as a
+ // signal value in various parts of the system
+ if (!rhs.isValid() && rhs != Rect::INVALID_RECT) {
ALOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}",
op, rhs.left, rhs.top, rhs.right, rhs.bottom);
return;
@@ -733,35 +761,52 @@
// ----------------------------------------------------------------------------
size_t Region::getFlattenedSize() const {
- return mStorage.size() * sizeof(Rect);
+ return sizeof(uint32_t) + mStorage.size() * sizeof(Rect);
}
status_t Region::flatten(void* buffer, size_t size) const {
#if VALIDATE_REGIONS
validate(*this, "Region::flatten");
#endif
- if (size < mStorage.size() * sizeof(Rect)) {
+ if (size < getFlattenedSize()) {
return NO_MEMORY;
}
- Rect* rects = reinterpret_cast<Rect*>(buffer);
- memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
+ // Cast to uint32_t since the size of a size_t can vary between 32- and
+ // 64-bit processes
+ FlattenableUtils::write(buffer, size, static_cast<uint32_t>(mStorage.size()));
+ for (auto rect : mStorage) {
+ status_t result = rect.flatten(buffer, size);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ FlattenableUtils::advance(buffer, size, sizeof(rect));
+ }
return NO_ERROR;
}
status_t Region::unflatten(void const* buffer, size_t size) {
- Region result;
- if (size >= sizeof(Rect)) {
- Rect const* rects = reinterpret_cast<Rect const*>(buffer);
- size_t count = size / sizeof(Rect);
- if (count > 0) {
- result.mStorage.clear();
- ssize_t err = result.mStorage.insertAt(0, count);
- if (err < 0) {
- return status_t(err);
- }
- memcpy(result.mStorage.editArray(), rects, count*sizeof(Rect));
- }
+ if (size < sizeof(uint32_t)) {
+ return NO_MEMORY;
}
+
+ uint32_t numRects = 0;
+ FlattenableUtils::read(buffer, size, numRects);
+ if (size < numRects * sizeof(Rect)) {
+ return NO_MEMORY;
+ }
+
+ Region result;
+ result.mStorage.clear();
+ for (size_t r = 0; r < numRects; ++r) {
+ Rect rect;
+ status_t status = rect.unflatten(buffer, size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ FlattenableUtils::advance(buffer, size, sizeof(rect));
+ result.mStorage.push_back(rect);
+ }
+
#if VALIDATE_REGIONS
validate(result, "Region::unflatten");
#endif
@@ -786,10 +831,8 @@
}
Rect const* Region::getArray(size_t* count) const {
- const_iterator const b(begin());
- const_iterator const e(end());
- if (count) *count = e-b;
- return b;
+ if (count) *count = static_cast<size_t>(end() - begin());
+ return begin();
}
SharedBuffer const* Region::getSharedBuffer(size_t* count) const {
@@ -806,29 +849,22 @@
// ----------------------------------------------------------------------------
-void Region::dump(String8& out, const char* what, uint32_t flags) const
+void Region::dump(String8& out, const char* what, uint32_t /* flags */) const
{
- (void)flags;
const_iterator head = begin();
const_iterator const tail = end();
- size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, " Region %s (this=%p, count=%" PRIdPTR ")\n",
- what, this, tail-head);
- out.append(buffer);
+ out.appendFormat(" Region %s (this=%p, count=%" PRIdPTR ")\n",
+ what, this, tail - head);
while (head != tail) {
- snprintf(buffer, SIZE, " [%3d, %3d, %3d, %3d]\n",
- head->left, head->top, head->right, head->bottom);
- out.append(buffer);
- head++;
+ out.appendFormat(" [%3d, %3d, %3d, %3d]\n", head->left, head->top,
+ head->right, head->bottom);
+ ++head;
}
}
-void Region::dump(const char* what, uint32_t flags) const
+void Region::dump(const char* what, uint32_t /* flags */) const
{
- (void)flags;
const_iterator head = begin();
const_iterator const tail = end();
ALOGD(" Region %s (this=%p, count=%" PRIdPTR ")\n", what, this, tail-head);
diff --git a/libs/ui/UiConfig.cpp b/libs/ui/UiConfig.cpp
index 8b2130e..9e7ba8e 100644
--- a/libs/ui/UiConfig.cpp
+++ b/libs/ui/UiConfig.cpp
@@ -18,8 +18,11 @@
namespace android {
+#ifdef FRAMEBUFFER_FORCE_FORMAT
+// We need the two-level macro to stringify the contents of a macro argument
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
+#endif
void appendUiConfigString(String8& configStr)
{
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index b0c57db..6438b1f 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -1,31 +1,36 @@
-# Build the unit tests.
+#
+# Copyright (C) 2014 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.
+#
+
LOCAL_PATH := $(call my-dir)
+
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_SHARED_LIBRARIES := libui
+LOCAL_SRC_FILES := Region_test.cpp
+LOCAL_MODULE := Region_test
+include $(BUILD_NATIVE_TEST)
-# Build the unit tests.
-test_src_files := \
- Region_test.cpp \
- vec_test.cpp \
- mat_test.cpp
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_SRC_FILES := vec_test.cpp
+LOCAL_MODULE := vec_test
+include $(BUILD_NATIVE_TEST)
-shared_libraries := \
- libutils \
- libui
-
-static_libraries := \
- libgtest \
- libgtest_main
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-# Build the unit tests.
-
-# Build the manual test programs.
-include $(call all-makefiles-under, $(LOCAL_PATH))
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_SRC_FILES := mat_test.cpp
+LOCAL_MODULE := mat_test
+include $(BUILD_NATIVE_TEST)
diff --git a/libs/ui/tests/vec_test.cpp b/libs/ui/tests/vec_test.cpp
index 00f737e..454c999 100644
--- a/libs/ui/tests/vec_test.cpp
+++ b/libs/ui/tests/vec_test.cpp
@@ -16,17 +16,18 @@
#define LOG_TAG "RegionTest"
+#include <math.h>
#include <stdlib.h>
+
#include <ui/Region.h>
#include <ui/Rect.h>
-#include <gtest/gtest.h>
-
#include <ui/vec4.h>
+#include <gtest/gtest.h>
+
namespace android {
class VecTest : public testing::Test {
-protected:
};
TEST_F(VecTest, Basics) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 3b2984a..b2abdb1 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -176,6 +176,15 @@
#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
#endif
+#ifndef EGL_KHR_partial_update
+#define EGL_KHR_partial_update 1
+#define EGL_BUFFER_AGE_KHR 0x313D
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_partial_update */
+
#ifndef EGL_NV_coverage_sample
#define EGL_NV_coverage_sample 1
#define EGL_COVERAGE_BUFFERS_NV 0x30E0
@@ -435,11 +444,24 @@
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
#endif
+#ifndef EGL_KHR_create_context_no_error
+#define EGL_KHR_create_context_no_error 1
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
+#endif /* EGL_KHR_create_context_no_error */
+
#ifndef EGL_KHR_surfaceless_context
#define EGL_KHR_surfaceless_context 1
/* No tokens/entry points, just relaxes an error condition */
#endif
+#ifndef EGL_KHR_swap_buffers_with_damage
+#define EGL_KHR_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_swap_buffers_with_damage */
+
#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
#ifndef EGL_KHR_stream_cross_process_fd
#define EGL_KHR_stream_cross_process_fd 1
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 64320cf..4b08749 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -31,7 +31,9 @@
LOCAL_SRC_FILES_arm += fixed_asm.S iterators.S
LOCAL_CFLAGS_arm += -fstrict-aliasing
+ifndef ARCH_MIPS_REV6
LOCAL_SRC_FILES_mips += arch-mips/fixed_asm.S
+endif
LOCAL_CFLAGS_mips += -fstrict-aliasing
# The graphics code can generate division by zero
LOCAL_CFLAGS_mips += -mno-check-zero-division
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 1feac8b..593d0c2 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -394,7 +394,13 @@
depth.width = width;
depth.height = height;
depth.stride = depth.width; // use the width here
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
+ static_cast<uint64_t>(depth.height) * 2;
+ if (depth.stride < 0 || depth.height > INT_MAX ||
+ allocSize > UINT32_MAX) {
+ return setError(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+ depth.data = (GGLubyte*)malloc(allocSize);
if (depth.data == 0) {
return setError(EGL_BAD_ALLOC, EGL_FALSE);
}
@@ -548,7 +554,14 @@
depth.width = width;
depth.height = height;
depth.stride = buffer->stride;
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
+ static_cast<uint64_t>(depth.height) * 2;
+ if (depth.stride < 0 || depth.height > INT_MAX ||
+ allocSize > UINT32_MAX) {
+ setError(EGL_BAD_ALLOC, EGL_FALSE);
+ return EGL_FALSE;
+ }
+ depth.data = (GGLubyte*)malloc(allocSize);
if (depth.data == 0) {
setError(EGL_BAD_ALLOC, EGL_FALSE);
return EGL_FALSE;
@@ -666,7 +679,14 @@
depth.width = pixmap->width;
depth.height = pixmap->height;
depth.stride = depth.width; // use the width here
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
+ static_cast<uint64_t>(depth.height) * 2;
+ if (depth.stride < 0 || depth.height > INT_MAX ||
+ allocSize > UINT32_MAX) {
+ setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ return;
+ }
+ depth.data = (GGLubyte*)malloc(allocSize);
if (depth.data == 0) {
setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
}
@@ -746,7 +766,14 @@
depth.width = pbuffer.width;
depth.height = pbuffer.height;
depth.stride = depth.width; // use the width here
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ uint64_t allocSize = static_cast<uint64_t>(depth.stride) *
+ static_cast<uint64_t>(depth.height) * 2;
+ if (depth.stride < 0 || depth.height > INT_MAX ||
+ allocSize > UINT32_MAX) {
+ setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ return;
+ }
+ depth.data = (GGLubyte*)malloc(allocSize);
if (depth.data == 0) {
setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
return;
diff --git a/opengl/libagl/fp.cpp b/opengl/libagl/fp.cpp
index aea4449..a7a4f7b 100644
--- a/opengl/libagl/fp.cpp
+++ b/opengl/libagl/fp.cpp
@@ -19,7 +19,7 @@
// ----------------------------------------------------------------------------
-#if !defined(__arm__) && !defined(__mips__)
+#if !(defined(__arm__) || (defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6))
GGLfixed gglFloatToFixed(float v) {
return GGLfixed(floorf(v * 65536.0f + 0.5f));
}
diff --git a/opengl/libagl/matrix.h b/opengl/libagl/matrix.h
index 5bd717a..cafc119 100644
--- a/opengl/libagl/matrix.h
+++ b/opengl/libagl/matrix.h
@@ -74,7 +74,7 @@
);
return r;
-#elif defined(__mips__)
+#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
GLfixed res;
int32_t t1,t2,t3;
@@ -160,7 +160,7 @@
);
return r;
-#elif defined(__mips__)
+#elif defined(__mips__) && !defined(__LP64__) && __mips_isa_rev < 6
GLfixed res;
int32_t t1,t2;
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index cc5d544..18ad300 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -47,9 +47,6 @@
ifeq ($(BOARD_ALLOW_EGL_HIBERNATION),true)
LOCAL_CFLAGS += -DBOARD_ALLOW_EGL_HIBERNATION
endif
-ifeq ($(TARGET_BOARD_PLATFORM), omap4)
- LOCAL_CFLAGS += -DWORKAROUND_BUG_10194508=1
-endif
ifneq ($(MAX_EGL_CACHE_ENTRY_SIZE),)
LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE)
endif
@@ -77,6 +74,7 @@
GLES_CM/gl.cpp.arm \
#
+LOCAL_CLANG := false
LOCAL_SHARED_LIBRARIES += libcutils liblog libEGL
LOCAL_MODULE:= libGLESv1_CM
@@ -88,6 +86,9 @@
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
+# TODO: This is to work around b/20093774. Remove after root cause is fixed
+LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
+
include $(BUILD_SHARED_LIBRARY)
@@ -101,6 +102,7 @@
GLES2/gl2.cpp.arm \
#
+LOCAL_CLANG := false
LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
LOCAL_MODULE:= libGLESv2
@@ -112,6 +114,9 @@
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
+# TODO: This is to work around b/20093774. Remove after root cause is fixed
+LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
+
# Symlink libGLESv3.so -> libGLESv2.so
# Platform modules should link against libGLESv2.so (-lGLESv2), but NDK apps
# will be linked against libGLESv3.so.
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 7c70fa0..4e0e5bc 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -292,6 +292,44 @@
return (const GLubyte *)c->gl_extensions.string();
}
+const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) {
+ // NOTE: returning NULL here will fall-back to the default
+ // implementation.
+
+ EGLContext context = egl_tls_t::getContext();
+ if (context == EGL_NO_CONTEXT)
+ return NULL;
+
+ egl_context_t const * const c = get_context(context);
+ if (c == NULL) // this should never happen, by construction
+ return NULL;
+
+ if (name != GL_EXTENSIONS)
+ return NULL;
+
+ // if index is out of bounds, assume it will be in the default
+ // implementation too, so we don't have to generate a GL error here
+ if (index >= c->tokenized_gl_extensions.size())
+ return NULL;
+
+ return (const GLubyte *)c->tokenized_gl_extensions.itemAt(index).string();
+}
+
+GLint egl_get_num_extensions_for_current_context() {
+ // NOTE: returning -1 here will fall-back to the default
+ // implementation.
+
+ EGLContext context = egl_tls_t::getContext();
+ if (context == EGL_NO_CONTEXT)
+ return -1;
+
+ egl_context_t const * const c = get_context(context);
+ if (c == NULL) // this should never happen, by construction
+ return -1;
+
+ return (GLint)c->tokenized_gl_extensions.size();
+}
+
// ----------------------------------------------------------------------------
// this mutex protects:
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 6e77e45..8378907 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -80,6 +80,7 @@
extern char const * const gBuiltinExtensionString =
"EGL_KHR_get_all_proc_addresses "
"EGL_ANDROID_presentation_time "
+ "EGL_KHR_swap_buffers_with_damage "
;
extern char const * const gExtensionString =
"EGL_KHR_image " // mandatory
@@ -90,16 +91,27 @@
"EGL_KHR_gl_colorspace "
#endif
"EGL_KHR_gl_texture_2D_image "
+ "EGL_KHR_gl_texture_3D_image "
"EGL_KHR_gl_texture_cubemap_image "
"EGL_KHR_gl_renderbuffer_image "
"EGL_KHR_reusable_sync "
"EGL_KHR_fence_sync "
"EGL_KHR_create_context "
+ "EGL_KHR_config_attribs "
+ "EGL_KHR_surfaceless_context "
+ "EGL_KHR_stream "
+ "EGL_KHR_stream_fifo "
+ "EGL_KHR_stream_producer_eglsurface "
+ "EGL_KHR_stream_consumer_gltexture "
+ "EGL_KHR_stream_cross_process_fd "
"EGL_EXT_create_context_robustness "
"EGL_NV_system_time "
"EGL_ANDROID_image_native_buffer " // mandatory
"EGL_KHR_wait_sync " // strongly recommended
"EGL_ANDROID_recordable " // mandatory
+ "EGL_KHR_partial_update " // strongly recommended
+ "EGL_EXT_buffer_age " // strongly recommended with partial_update
+ "EGL_KHR_create_context_no_error "
;
// extensions not exposed to applications but used by the ANDROID system
@@ -152,6 +164,39 @@
// EGL_ANDROID_presentation_time
{ "eglPresentationTimeANDROID",
(__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
+
+ // EGL_KHR_swap_buffers_with_damage
+ { "eglSwapBuffersWithDamageKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
+
+ // EGL_KHR_partial_update
+ { "eglSetDamageRegionKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
+
+ { "eglCreateStreamKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
+ { "eglDestroyStreamKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
+ { "eglStreamAttribKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
+ { "eglQueryStreamKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
+ { "eglQueryStreamu64KHR",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
+ { "eglQueryStreamTimeKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
+ { "eglCreateStreamProducerSurfaceKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
+ { "eglStreamConsumerGLTextureExternalKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
+ { "eglStreamConsumerAcquireKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
+ { "eglStreamConsumerReleaseKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
+ { "eglGetStreamFileDescriptorKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
+ { "eglCreateStreamFromFileDescriptorKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
};
/*
@@ -381,20 +426,15 @@
// Turn linear formats into corresponding sRGB formats when colorspace is
// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
-// the modification isn't possible, the original format is returned.
-static int modifyFormatColorspace(int fmt, EGLint colorspace) {
+// the modification isn't possible, the original dataSpace is returned.
+static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
+ EGLint colorspace) {
if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
- switch (fmt) {
- case HAL_PIXEL_FORMAT_sRGB_A_8888: return HAL_PIXEL_FORMAT_RGBA_8888;
- case HAL_PIXEL_FORMAT_sRGB_X_8888: return HAL_PIXEL_FORMAT_RGBX_8888;
- }
+ return HAL_DATASPACE_SRGB_LINEAR;
} else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
- switch (fmt) {
- case HAL_PIXEL_FORMAT_RGBA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888;
- case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_X_8888;
- }
+ return HAL_DATASPACE_SRGB;
}
- return fmt;
+ return dataSpace;
}
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
@@ -421,37 +461,10 @@
// of our native format. So if sRGB gamma is requested, we have to
// modify the EGLconfig's format before setting the native window's
// format.
-#if WORKAROUND_BUG_10194508
-#warning "WORKAROUND_10194508 enabled"
- EGLint format;
- if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
- &format)) {
- ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x",
- eglGetError());
- format = 0;
- }
- if (attrib_list) {
- for (const EGLint* attr = attrib_list; *attr != EGL_NONE;
- attr += 2) {
- if (*attr == EGL_GL_COLORSPACE_KHR &&
- dp->haveExtension("EGL_KHR_gl_colorspace")) {
- if (ENABLE_EGL_KHR_GL_COLORSPACE) {
- format = modifyFormatColorspace(format, *(attr+1));
- } else {
- // Normally we'd pass through unhandled attributes to
- // the driver. But in case the driver implements this
- // extension but we're disabling it, we want to prevent
- // it getting through -- support will be broken without
- // our help.
- ALOGE("sRGB window surfaces not supported");
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
- }
- }
- }
- }
-#else
+
// by default, just pick RGBA_8888
EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
+ android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
EGLint a = 0;
cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
@@ -477,7 +490,7 @@
for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
if (*attr == EGL_GL_COLORSPACE_KHR) {
if (ENABLE_EGL_KHR_GL_COLORSPACE) {
- format = modifyFormatColorspace(format, *(attr+1));
+ dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
} else {
// Normally we'd pass through unhandled attributes to
// the driver. But in case the driver implements this
@@ -490,7 +503,7 @@
}
}
}
-#endif
+
if (format != 0) {
int err = native_window_set_buffers_format(window, format);
if (err != 0) {
@@ -501,6 +514,16 @@
}
}
+ if (dataSpace != 0) {
+ int err = native_window_set_buffers_data_space(window, dataSpace);
+ if (err != 0) {
+ ALOGE("error setting native window pixel dataSpace: %s (%d)",
+ strerror(-err), err);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
+ }
+
// the EGL spec requires that a new EGLSurface default to swap interval
// 1, so explicitly set that on the window here.
ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
@@ -572,6 +595,15 @@
return setError(EGL_BAD_SURFACE, EGL_FALSE);
egl_surface_t * const s = get_surface(surface);
+ ANativeWindow* window = s->win.get();
+ if (window) {
+ int result = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ if (result != OK) {
+ ALOGE("eglDestroySurface: native_window_api_disconnect (win=%p) "
+ "failed (%#x)",
+ window, result);
+ }
+ }
EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
@@ -1043,7 +1075,8 @@
Mutex mMutex;
};
-EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
+EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
+ EGLint *rects, EGLint n_rects)
{
ATRACE_CALL();
clearError();
@@ -1102,7 +1135,38 @@
}
}
- return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
+ if (n_rects == 0) {
+ return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
+ }
+
+ Vector<android_native_rect_t> androidRects;
+ for (int r = 0; r < n_rects; ++r) {
+ int offset = r * 4;
+ int x = rects[offset];
+ int y = rects[offset + 1];
+ int width = rects[offset + 2];
+ int height = rects[offset + 3];
+ android_native_rect_t androidRect;
+ androidRect.left = x;
+ androidRect.top = y + height;
+ androidRect.right = x + width;
+ androidRect.bottom = y;
+ androidRects.push_back(androidRect);
+ }
+ native_window_set_surface_damage(s->win.get(), androidRects.array(),
+ androidRects.size());
+
+ if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
+ return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
+ rects, n_rects);
+ } else {
+ return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
+ }
+}
+
+EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+ return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
}
EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
@@ -1496,6 +1560,212 @@
return result;
}
+EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_STREAM_KHR;
+
+ EGLStreamKHR result = EGL_NO_STREAM_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
+ result = cnx->egl.eglCreateStreamKHR(
+ dp->disp.dpy, attrib_list);
+ }
+ return result;
+}
+
+EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
+ result = cnx->egl.eglDestroyStreamKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLint value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
+ result = cnx->egl.eglStreamAttribKHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLint *value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
+ result = cnx->egl.eglQueryStreamKHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLuint64KHR *value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
+ result = cnx->egl.eglQueryStreamu64KHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLTimeKHR *value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
+ result = cnx->egl.eglQueryStreamTimeKHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
+ EGLStreamKHR stream, const EGLint *attrib_list)
+{
+ clearError();
+
+ egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_SURFACE;
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
+ EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
+ dp->disp.dpy, config, stream, attrib_list);
+ if (surface != EGL_NO_SURFACE) {
+ egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
+ surface, cnx);
+ return s;
+ }
+ }
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
+ EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
+ result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
+ EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
+ result = cnx->egl.eglStreamConsumerAcquireKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
+ EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
+ result = cnx->egl.eglStreamConsumerReleaseKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
+ EGLDisplay dpy, EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
+
+ EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
+ result = cnx->egl.eglGetStreamFileDescriptorKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
+ EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_STREAM_KHR;
+
+ EGLStreamKHR result = EGL_NO_STREAM_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
+ result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
+ dp->disp.dpy, file_descriptor);
+ }
+ return result;
+}
+
// ----------------------------------------------------------------------------
// EGL_EGLEXT_VERSION 15
// ----------------------------------------------------------------------------
@@ -1591,3 +1861,32 @@
return setErrorQuiet(EGL_BAD_DISPLAY, 0);
}
+
+// ----------------------------------------------------------------------------
+// Partial update extension
+// ----------------------------------------------------------------------------
+EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
+ EGLint *rects, EGLint n_rects)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) {
+ setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ SurfaceRef _s(dp.get(), surface);
+ if (!_s.get()) {
+ setError(EGL_BAD_SURFACE, EGL_FALSE);
+ return EGL_FALSE;
+ }
+
+ egl_surface_t const * const s = get_surface(surface);
+ if (s->cnx->egl.eglSetDamageRegionKHR) {
+ return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
+ rects, n_rects);
+ }
+
+ return EGL_FALSE;
+}
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 4949ef2..2d86295 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -39,7 +39,7 @@
class egl_object_t;
class egl_context_t;
-class egl_connection_t;
+struct egl_connection_t;
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 70d0e52..498b2fc 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -61,18 +61,18 @@
/* EGL_EGLEXT_VERSION 15 */
-// EGL_ENTRY(EGLStreamKHR, eglCreateStreamKHR, EGLDisplay, const EGLint *)
-// EGL_ENTRY(EGLBoolean, eglDestroyStreamKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLBoolean, eglStreamAttribKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint)
-// EGL_ENTRY(EGLBoolean, eglQueryStreamKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint *)
-// EGL_ENTRY(EGLBoolean, eglQueryStreamu64KHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLuint64KHR *)
-// EGL_ENTRY(EGLBoolean, eglStreamConsumerGLTextureExternalKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLBoolean, eglStreamConsumerAcquireKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLBoolean, eglStreamConsumerReleaseKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLSurface, eglCreateStreamProducerSurfaceKHR, EGLDisplay, EGLConfig, EGLStreamKHR, const EGLint *)
-// EGL_ENTRY(EGLBoolean, eglQueryStreamTimeKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLTimeKHR*)
-// EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR)
+EGL_ENTRY(EGLStreamKHR, eglCreateStreamKHR, EGLDisplay, const EGLint *)
+EGL_ENTRY(EGLBoolean, eglDestroyStreamKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamAttribKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint)
+EGL_ENTRY(EGLBoolean, eglQueryStreamKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint *)
+EGL_ENTRY(EGLBoolean, eglQueryStreamu64KHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLuint64KHR *)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerGLTextureExternalKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerAcquireKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerReleaseKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLSurface, eglCreateStreamProducerSurfaceKHR, EGLDisplay, EGLConfig, EGLStreamKHR, const EGLint *)
+EGL_ENTRY(EGLBoolean, eglQueryStreamTimeKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLTimeKHR*)
+EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR)
EGL_ENTRY(EGLint, eglWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint)
/* ANDROID extensions */
@@ -89,4 +89,9 @@
/* IMG extensions */
EGL_ENTRY(EGLBoolean, eglHibernateProcessIMG, void)
-EGL_ENTRY(EGLBoolean, eglAwakenProcessIMG, void)
\ No newline at end of file
+EGL_ENTRY(EGLBoolean, eglAwakenProcessIMG, void)
+
+/* Partial update extensions */
+
+EGL_ENTRY(EGLBoolean, eglSwapBuffersWithDamageKHR, EGLDisplay, EGLSurface, EGLint *, EGLint)
+EGL_ENTRY(EGLBoolean, eglSetDamageRegionKHR, EGLDisplay, EGLSurface, EGLint *, EGLint)
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index d3ee76d..d511940 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -113,6 +113,18 @@
temp.append(gl_extensions);
gl_extensions.setTo(temp);
}
+
+ // tokenize the supported extensions for the glGetStringi() wrapper
+ exts = gl_extensions.string();
+ while (1) {
+ const char *end = strchr(exts, ' ');
+ if (end == NULL) {
+ tokenized_gl_extensions.push(String8(exts));
+ break;
+ }
+ tokenized_gl_extensions.push(String8(exts, end - exts));
+ exts = end + 1;
+ }
}
}
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 518fdec..f5a9f58 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -27,6 +27,7 @@
#include <utils/threads.h>
#include <utils/String8.h>
+#include <utils/Vector.h>
#include <system/window.h>
@@ -159,6 +160,7 @@
egl_connection_t const* cnx;
int version;
String8 gl_extensions;
+ Vector<String8> tokenized_gl_extensions;
};
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index fc61134..660af33 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -78,7 +78,7 @@
#elif defined(__i386__)
- #define API_ENTRY(_api) __attribute__((noinline)) _api
+ #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
#define CALL_GL_EXTENSION_API(_api) \
register void** fn; \
@@ -100,7 +100,7 @@
#elif defined(__x86_64__)
- #define API_ENTRY(_api) __attribute__((noinline)) _api
+ #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
#define CALL_GL_EXTENSION_API(_api) \
register void** fn; \
@@ -120,14 +120,46 @@
: "cc" \
);
+#elif defined(__mips64)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_EXTENSION_API(_api, ...) \
+ register unsigned int _t0 asm("$12"); \
+ register unsigned int _fn asm("$25"); \
+ register unsigned int _tls asm("$3"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "ld %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn], $ra\n\t" \
+ "ld %[t0], %[API](%[t0])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " nop\n\t" \
+ "move %[fn], %[t0]\n\t" \
+ "1:\n\t" \
+ "jalr $0, %[fn]\n\t" \
+ " nop\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(_fn), \
+ [tls] "=&r"(_tls), \
+ [t0] "=&r"(_t0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4), \
+ [API] "I"(__builtin_offsetof(gl_hooks_t, \
+ ext.extensions[_api])) \
+ : \
+ );
+
#elif defined(__mips__)
#define API_ENTRY(_api) __attribute__((noinline)) _api
#define CALL_GL_EXTENSION_API(_api, ...) \
- register unsigned int _t0 asm("t0"); \
- register unsigned int _fn asm("t1"); \
- register unsigned int _tls asm("v1"); \
+ register unsigned int _t0 asm("$8"); \
+ register unsigned int _fn asm("$25"); \
+ register unsigned int _tls asm("$3"); \
asm volatile( \
".set push\n\t" \
".set noreorder\n\t" \
@@ -136,10 +168,12 @@
"lw %[t0], %[OPENGL_API](%[tls])\n\t" \
"beqz %[t0], 1f\n\t" \
" move %[fn], $ra\n\t" \
- "lw %[fn], %[API](%[t0])\n\t" \
- "movz %[fn], $ra, %[fn]\n\t" \
+ "lw %[t0], %[API](%[t0])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " nop\n\t" \
+ "move %[fn], %[t0]\n\t" \
"1:\n\t" \
- "j %[fn]\n\t" \
+ "jalr $0, %[fn]\n\t" \
" nop\n\t" \
".set pop\n\t" \
: [fn] "=c"(_fn), \
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index b07228f..6034a8e 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -82,7 +82,7 @@
#elif defined(__i386__)
- #define API_ENTRY(_api) __attribute__((noinline)) _api
+ #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
#define CALL_GL_API(_api, ...) \
register void** fn; \
@@ -101,7 +101,7 @@
#elif defined(__x86_64__)
- #define API_ENTRY(_api) __attribute__((noinline)) _api
+ #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
#define CALL_GL_API(_api, ...) \
register void** fn; \
@@ -118,27 +118,62 @@
: "cc" \
);
+#elif defined(__mips64)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_API(_api, ...) \
+ register unsigned long _t0 asm("$12"); \
+ register unsigned long _fn asm("$25"); \
+ register unsigned long _tls asm("$3"); \
+ register unsigned long _v0 asm("$2"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "ld %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn], $ra\n\t" \
+ "ld %[t0], %[API](%[t0])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " nop\n\t" \
+ "move %[fn], %[t0]\n\t" \
+ "1:\n\t" \
+ "jalr $0, %[fn]\n\t" \
+ " move %[v0], $0\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(_fn), \
+ [tls] "=&r"(_tls), \
+ [t0] "=&r"(_t0), \
+ [v0] "=&r"(_v0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
+ [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+ : \
+ );
+
#elif defined(__mips__)
#define API_ENTRY(_api) __attribute__((noinline)) _api
#define CALL_GL_API(_api, ...) \
- register unsigned int _t0 asm("t0"); \
- register unsigned int _fn asm("t1"); \
- register unsigned int _tls asm("v1"); \
- register unsigned int _v0 asm("v0"); \
+ register unsigned int _t0 asm("$8"); \
+ register unsigned int _fn asm("$25"); \
+ register unsigned int _tls asm("$3"); \
+ register unsigned int _v0 asm("$2"); \
asm volatile( \
".set push\n\t" \
".set noreorder\n\t" \
- ".set mips32r2\n\t" \
+ ".set mips32r2\n\t" \
"rdhwr %[tls], $29\n\t" \
"lw %[t0], %[OPENGL_API](%[tls])\n\t" \
"beqz %[t0], 1f\n\t" \
" move %[fn],$ra\n\t" \
- "lw %[fn], %[API](%[t0])\n\t" \
- "movz %[fn], $ra, %[fn]\n\t" \
+ "lw %[t0], %[API](%[t0])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " nop\n\t" \
+ "move %[fn], %[t0]\n\t" \
"1:\n\t" \
- "j %[fn]\n\t" \
+ "jalr $0, %[fn]\n\t" \
" move %[v0], $0\n\t" \
".set pop\n\t" \
: [fn] "=c"(_fn), \
@@ -170,17 +205,87 @@
#undef CALL_GL_API_RETURN
/*
- * glGetString() is special because we expose some extensions in the wrapper
+ * glGetString() and glGetStringi() are special because we expose some
+ * extensions in the wrapper. Also, wrapping glGetXXX() is required because
+ * the value returned for GL_NUM_EXTENSIONS may have been altered by the
+ * injection of the additional extensions.
*/
-extern "C" const GLubyte * __glGetString(GLenum name);
+extern "C" {
+ const GLubyte * __glGetString(GLenum name);
+ const GLubyte * __glGetStringi(GLenum name, GLuint index);
+ void __glGetBooleanv(GLenum pname, GLboolean * data);
+ void __glGetFloatv(GLenum pname, GLfloat * data);
+ void __glGetIntegerv(GLenum pname, GLint * data);
+ void __glGetInteger64v(GLenum pname, GLint64 * data);
+}
-const GLubyte * glGetString(GLenum name)
-{
+const GLubyte * glGetString(GLenum name) {
const GLubyte * ret = egl_get_string_for_current_context(name);
if (ret == NULL) {
gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
- ret = _c->glGetString(name);
+ if(_c) ret = _c->glGetString(name);
}
return ret;
}
+
+const GLubyte * glGetStringi(GLenum name, GLuint index) {
+ const GLubyte * ret = egl_get_string_for_current_context(name, index);
+ if (ret == NULL) {
+ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+ if(_c) ret = _c->glGetStringi(name, index);
+ }
+ return ret;
+}
+
+void glGetBooleanv(GLenum pname, GLboolean * data) {
+ if (pname == GL_NUM_EXTENSIONS) {
+ int num_exts = egl_get_num_extensions_for_current_context();
+ if (num_exts >= 0) {
+ *data = num_exts > 0 ? GL_TRUE : GL_FALSE;
+ return;
+ }
+ }
+
+ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+ if (_c) _c->glGetBooleanv(pname, data);
+}
+
+void glGetFloatv(GLenum pname, GLfloat * data) {
+ if (pname == GL_NUM_EXTENSIONS) {
+ int num_exts = egl_get_num_extensions_for_current_context();
+ if (num_exts >= 0) {
+ *data = (GLfloat)num_exts;
+ return;
+ }
+ }
+
+ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+ if (_c) _c->glGetFloatv(pname, data);
+}
+
+void glGetIntegerv(GLenum pname, GLint * data) {
+ if (pname == GL_NUM_EXTENSIONS) {
+ int num_exts = egl_get_num_extensions_for_current_context();
+ if (num_exts >= 0) {
+ *data = (GLint)num_exts;
+ return;
+ }
+ }
+
+ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+ if (_c) _c->glGetIntegerv(pname, data);
+}
+
+void glGetInteger64v(GLenum pname, GLint64 * data) {
+ if (pname == GL_NUM_EXTENSIONS) {
+ int num_exts = egl_get_num_extensions_for_current_context();
+ if (num_exts >= 0) {
+ *data = (GLint64)num_exts;
+ return;
+ }
+ }
+
+ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
+ if (_c) _c->glGetInteger64v(pname, data);
+}
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
index 8363960..09d8b00 100644
--- a/opengl/libs/GLES2/gl2_api.in
+++ b/opengl/libs/GLES2/gl2_api.in
@@ -172,7 +172,7 @@
GLint API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar * name) {
CALL_GL_API_RETURN(glGetAttribLocation, program, name);
}
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean * data) {
+void API_ENTRY(__glGetBooleanv)(GLenum pname, GLboolean * data) {
CALL_GL_API(glGetBooleanv, pname, data);
}
void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint * params) {
@@ -181,13 +181,13 @@
GLenum API_ENTRY(glGetError)(void) {
CALL_GL_API_RETURN(glGetError);
}
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat * data) {
+void API_ENTRY(__glGetFloatv)(GLenum pname, GLfloat * data) {
CALL_GL_API(glGetFloatv, pname, data);
}
void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params) {
CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
}
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint * data) {
+void API_ENTRY(__glGetIntegerv)(GLenum pname, GLint * data) {
CALL_GL_API(glGetIntegerv, pname, data);
}
void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint * params) {
@@ -604,7 +604,7 @@
void API_ENTRY(glClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
CALL_GL_API(glClearBufferfi, buffer, drawbuffer, depth, stencil);
}
-const GLubyte * API_ENTRY(glGetStringi)(GLenum name, GLuint index) {
+const GLubyte * API_ENTRY(__glGetStringi)(GLenum name, GLuint index) {
CALL_GL_API_RETURN(glGetStringi, name, index);
}
void API_ENTRY(glCopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
@@ -649,7 +649,7 @@
void API_ENTRY(glWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout) {
CALL_GL_API(glWaitSync, sync, flags, timeout);
}
-void API_ENTRY(glGetInteger64v)(GLenum pname, GLint64 * data) {
+void API_ENTRY(__glGetInteger64v)(GLenum pname, GLint64 * data) {
CALL_GL_API(glGetInteger64v, pname, data);
}
void API_ENTRY(glGetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) {
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index f05983c..b1b31f8 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -138,7 +138,7 @@
#elif defined(__i386__)
- #define API_ENTRY(_api) __attribute__((noinline)) _api
+ #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
#define CALL_GL_API(_api, ...) \
register void* fn; \
@@ -157,7 +157,7 @@
#elif defined(__x86_64__)
- #define API_ENTRY(_api) __attribute__((noinline)) _api
+ #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
#define CALL_GL_API(_api, ...) \
register void** fn; \
@@ -174,15 +174,48 @@
: "cc" \
);
+#elif defined(__mips64)
+
+ #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+ #define CALL_GL_API(_api, ...) \
+ register unsigned long _t0 asm("$12"); \
+ register unsigned long _fn asm("$25"); \
+ register unsigned long _tls asm("$3"); \
+ register unsigned long _v0 asm("$2"); \
+ asm volatile( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ "rdhwr %[tls], $29\n\t" \
+ "ld %[t0], %[OPENGL_API](%[tls])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " move %[fn], $ra\n\t" \
+ "ld %[t0], %[API](%[t0])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " nop\n\t" \
+ "move %[fn], %[t0]\n\t" \
+ "1:\n\t" \
+ "jalr $0, %[fn]\n\t" \
+ " move %[v0], $0\n\t" \
+ ".set pop\n\t" \
+ : [fn] "=c"(_fn), \
+ [tls] "=&r"(_tls), \
+ [t0] "=&r"(_t0), \
+ [v0] "=&r"(_v0) \
+ : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
+ [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+ : \
+ );
+
#elif defined(__mips__)
#define API_ENTRY(_api) __attribute__((noinline)) _api
#define CALL_GL_API(_api, ...) \
- register unsigned int _t0 asm("t0"); \
- register unsigned int _fn asm("t1"); \
- register unsigned int _tls asm("v1"); \
- register unsigned int _v0 asm("v0"); \
+ register unsigned int _t0 asm("$8"); \
+ register unsigned int _fn asm("$25"); \
+ register unsigned int _tls asm("$3"); \
+ register unsigned int _v0 asm("$2"); \
asm volatile( \
".set push\n\t" \
".set noreorder\n\t" \
@@ -191,10 +224,12 @@
"lw %[t0], %[OPENGL_API](%[tls])\n\t" \
"beqz %[t0], 1f\n\t" \
" move %[fn], $ra\n\t" \
- "lw %[fn], %[API](%[t0])\n\t" \
- "movz %[fn], $ra, %[fn]\n\t" \
+ "lw %[t0], %[API](%[t0])\n\t" \
+ "beqz %[t0], 1f\n\t" \
+ " nop\n\t" \
+ "move %[fn], %[t0]\n\t" \
"1:\n\t" \
- "j %[fn]\n\t" \
+ "jalr $0, %[fn]\n\t" \
" move %[v0], $0\n\t" \
".set pop\n\t" \
: [fn] "=c"(_fn), \
diff --git a/opengl/libs/GLES_trace/Android.mk b/opengl/libs/GLES_trace/Android.mk
index 846932d..24c4be2 100644
--- a/opengl/libs/GLES_trace/Android.mk
+++ b/opengl/libs/GLES_trace/Android.mk
@@ -1,6 +1,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES := \
src/gltrace_api.cpp \
@@ -9,20 +10,18 @@
src/gltrace_eglapi.cpp \
src/gltrace_fixup.cpp \
src/gltrace_hooks.cpp \
- src/gltrace.pb.cpp \
- src/gltrace_transport.cpp
+ src/gltrace_transport.cpp \
+ $(call all-proto-files-under, proto)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/../ \
- external/stlport/stlport \
- external/protobuf/src \
- external \
- bionic
+ external
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI
-LOCAL_STATIC_LIBRARIES := libprotobuf-cpp-2.3.0-lite liblzf
-LOCAL_SHARED_LIBRARIES := libcutils libutils liblog libstlport
+LOCAL_STATIC_LIBRARIES := liblzf
+LOCAL_SHARED_LIBRARIES := libcutils libutils liblog
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := lite
LOCAL_CFLAGS += -DLOG_TAG=\"libGLES_trace\"
diff --git a/opengl/libs/GLES_trace/dev.make b/opengl/libs/GLES_trace/dev.make
index a46260c..3405d8e 100644
--- a/opengl/libs/GLES_trace/dev.make
+++ b/opengl/libs/GLES_trace/dev.make
@@ -1,11 +1,6 @@
## NOTE
## This file is used for development purposes only. It is not used by the build system.
-# generate protocol buffer files
-genproto: gltrace.proto
- aprotoc --cpp_out=src --java_out=java gltrace.proto
- mv src/gltrace.pb.cc src/gltrace.pb.cpp
-
sync:
adb root
adb remount
diff --git a/opengl/libs/GLES_trace/gltrace.proto b/opengl/libs/GLES_trace/proto/gltrace.proto
similarity index 99%
rename from opengl/libs/GLES_trace/gltrace.proto
rename to opengl/libs/GLES_trace/proto/gltrace.proto
index 00303c2..0344787 100644
--- a/opengl/libs/GLES_trace/gltrace.proto
+++ b/opengl/libs/GLES_trace/proto/gltrace.proto
@@ -23,6 +23,8 @@
message GLMessage {
enum Function {
+ option allow_alias = true;
+
glActiveTexture = 0;
glAlphaFunc = 1;
glAlphaFuncx = 2;
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.cpp b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
deleted file mode 100644
index c0867cd..0000000
--- a/opengl/libs/GLES_trace/src/gltrace.pb.cpp
+++ /dev/null
@@ -1,2715 +0,0 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-
-#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
-#include "gltrace.pb.h"
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format_lite_inl.h>
-// @@protoc_insertion_point(includes)
-
-namespace android {
-namespace gltrace {
-
-void protobuf_ShutdownFile_gltrace_2eproto() {
- delete GLMessage::default_instance_;
- delete GLMessage_DataType::default_instance_;
- delete GLMessage_FrameBuffer::default_instance_;
-}
-
-void protobuf_AddDesc_gltrace_2eproto() {
- static bool already_here = false;
- if (already_here) return;
- already_here = true;
- GOOGLE_PROTOBUF_VERIFY_VERSION;
-
- GLMessage::default_instance_ = new GLMessage();
- GLMessage_DataType::default_instance_ = new GLMessage_DataType();
- GLMessage_FrameBuffer::default_instance_ = new GLMessage_FrameBuffer();
- GLMessage::default_instance_->InitAsDefaultInstance();
- GLMessage_DataType::default_instance_->InitAsDefaultInstance();
- GLMessage_FrameBuffer::default_instance_->InitAsDefaultInstance();
- ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_gltrace_2eproto);
-}
-
-// Force AddDescriptors() to be called at static initialization time.
-struct StaticDescriptorInitializer_gltrace_2eproto {
- StaticDescriptorInitializer_gltrace_2eproto() {
- protobuf_AddDesc_gltrace_2eproto();
- }
-} static_descriptor_initializer_gltrace_2eproto_;
-
-
-// ===================================================================
-
-bool GLMessage_Function_IsValid(int value) {
- switch(value) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
- case 18:
- case 19:
- case 20:
- case 21:
- case 22:
- case 23:
- case 24:
- case 25:
- case 26:
- case 27:
- case 28:
- case 29:
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- case 38:
- case 39:
- case 40:
- case 41:
- case 42:
- case 43:
- case 44:
- case 45:
- case 46:
- case 47:
- case 48:
- case 49:
- case 50:
- case 51:
- case 52:
- case 53:
- case 54:
- case 55:
- case 56:
- case 57:
- case 58:
- case 59:
- case 60:
- case 61:
- case 62:
- case 63:
- case 64:
- case 65:
- case 66:
- case 67:
- case 68:
- case 69:
- case 70:
- case 71:
- case 72:
- case 73:
- case 74:
- case 75:
- case 76:
- case 77:
- case 78:
- case 79:
- case 80:
- case 81:
- case 82:
- case 83:
- case 84:
- case 85:
- case 86:
- case 87:
- case 88:
- case 89:
- case 90:
- case 91:
- case 92:
- case 93:
- case 94:
- case 95:
- case 96:
- case 97:
- case 98:
- case 99:
- case 100:
- case 101:
- case 102:
- case 103:
- case 104:
- case 105:
- case 106:
- case 107:
- case 108:
- case 109:
- case 110:
- case 111:
- case 112:
- case 113:
- case 114:
- case 115:
- case 116:
- case 117:
- case 118:
- case 119:
- case 120:
- case 121:
- case 122:
- case 123:
- case 124:
- case 125:
- case 126:
- case 127:
- case 128:
- case 129:
- case 130:
- case 131:
- case 132:
- case 133:
- case 134:
- case 135:
- case 136:
- case 137:
- case 138:
- case 139:
- case 140:
- case 141:
- case 142:
- case 143:
- case 144:
- case 145:
- case 146:
- case 147:
- case 148:
- case 149:
- case 150:
- case 151:
- case 152:
- case 153:
- case 154:
- case 155:
- case 156:
- case 157:
- case 158:
- case 159:
- case 160:
- case 161:
- case 162:
- case 163:
- case 164:
- case 165:
- case 166:
- case 167:
- case 168:
- case 169:
- case 170:
- case 171:
- case 172:
- case 173:
- case 174:
- case 175:
- case 176:
- case 177:
- case 178:
- case 179:
- case 180:
- case 181:
- case 182:
- case 183:
- case 184:
- case 185:
- case 186:
- case 187:
- case 188:
- case 189:
- case 190:
- case 191:
- case 192:
- case 193:
- case 194:
- case 195:
- case 196:
- case 197:
- case 198:
- case 199:
- case 200:
- case 201:
- case 202:
- case 203:
- case 204:
- case 205:
- case 206:
- case 207:
- case 208:
- case 209:
- case 210:
- case 211:
- case 212:
- case 213:
- case 214:
- case 215:
- case 216:
- case 217:
- case 218:
- case 219:
- case 220:
- case 221:
- case 222:
- case 223:
- case 224:
- case 225:
- case 226:
- case 227:
- case 228:
- case 229:
- case 230:
- case 231:
- case 232:
- case 233:
- case 234:
- case 235:
- case 236:
- case 237:
- case 238:
- case 239:
- case 240:
- case 241:
- case 242:
- case 243:
- case 244:
- case 245:
- case 246:
- case 247:
- case 248:
- case 249:
- case 250:
- case 251:
- case 252:
- case 253:
- case 254:
- case 255:
- case 256:
- case 257:
- case 258:
- case 259:
- case 260:
- case 261:
- case 262:
- case 263:
- case 264:
- case 265:
- case 266:
- case 267:
- case 268:
- case 269:
- case 270:
- case 271:
- case 272:
- case 273:
- case 274:
- case 275:
- case 276:
- case 277:
- case 278:
- case 279:
- case 280:
- case 281:
- case 282:
- case 283:
- case 284:
- case 285:
- case 286:
- case 287:
- case 288:
- case 289:
- case 290:
- case 291:
- case 292:
- case 293:
- case 294:
- case 295:
- case 296:
- case 297:
- case 298:
- case 299:
- case 300:
- case 301:
- case 302:
- case 303:
- case 304:
- case 305:
- case 306:
- case 307:
- case 308:
- case 309:
- case 310:
- case 311:
- case 312:
- case 313:
- case 314:
- case 315:
- case 316:
- case 317:
- case 318:
- case 319:
- case 320:
- case 321:
- case 322:
- case 323:
- case 324:
- case 325:
- case 326:
- case 327:
- case 328:
- case 329:
- case 330:
- case 331:
- case 332:
- case 333:
- case 334:
- case 335:
- case 336:
- case 337:
- case 338:
- case 339:
- case 340:
- case 341:
- case 342:
- case 343:
- case 344:
- case 345:
- case 346:
- case 347:
- case 348:
- case 349:
- case 350:
- case 351:
- case 352:
- case 353:
- case 354:
- case 355:
- case 356:
- case 357:
- case 358:
- case 359:
- case 360:
- case 361:
- case 362:
- case 363:
- case 364:
- case 365:
- case 366:
- case 367:
- case 368:
- case 369:
- case 370:
- case 371:
- case 372:
- case 373:
- case 374:
- case 375:
- case 376:
- case 377:
- case 378:
- case 379:
- case 380:
- case 381:
- case 382:
- case 383:
- case 384:
- case 385:
- case 386:
- case 387:
- case 388:
- case 389:
- case 390:
- case 391:
- case 392:
- case 393:
- case 394:
- case 395:
- case 396:
- case 397:
- case 398:
- case 399:
- case 400:
- case 401:
- case 402:
- case 403:
- case 404:
- case 405:
- case 406:
- case 407:
- case 408:
- case 409:
- case 410:
- case 411:
- case 412:
- case 413:
- case 414:
- case 415:
- case 416:
- case 417:
- case 418:
- case 419:
- case 420:
- case 421:
- case 422:
- case 423:
- case 424:
- case 425:
- case 426:
- case 427:
- case 428:
- case 429:
- case 430:
- case 431:
- case 432:
- case 433:
- case 434:
- case 435:
- case 436:
- case 437:
- case 438:
- case 439:
- case 440:
- case 441:
- case 442:
- case 443:
- case 444:
- case 445:
- case 446:
- case 447:
- case 448:
- case 449:
- case 450:
- case 451:
- case 452:
- case 453:
- case 454:
- case 455:
- case 456:
- case 457:
- case 458:
- case 459:
- case 460:
- case 461:
- case 462:
- case 463:
- case 464:
- case 465:
- case 466:
- case 467:
- case 468:
- case 469:
- case 470:
- case 471:
- case 472:
- case 473:
- case 474:
- case 475:
- case 476:
- case 477:
- case 478:
- case 479:
- case 480:
- case 481:
- case 482:
- case 483:
- case 484:
- case 485:
- case 486:
- case 487:
- case 488:
- case 489:
- case 490:
- case 491:
- case 492:
- case 493:
- case 494:
- case 495:
- case 496:
- case 497:
- case 498:
- case 499:
- case 500:
- case 501:
- case 502:
- case 503:
- case 504:
- case 505:
- case 506:
- case 507:
- case 508:
- case 509:
- case 510:
- case 511:
- case 512:
- case 513:
- case 514:
- case 515:
- case 516:
- case 517:
- case 518:
- case 519:
- case 520:
- case 521:
- case 522:
- case 523:
- case 524:
- case 525:
- case 526:
- case 527:
- case 528:
- case 529:
- case 530:
- case 531:
- case 532:
- case 533:
- case 534:
- case 535:
- case 536:
- case 537:
- case 538:
- case 539:
- case 540:
- case 541:
- case 542:
- case 543:
- case 544:
- case 545:
- case 546:
- case 547:
- case 548:
- case 549:
- case 550:
- case 551:
- case 552:
- case 553:
- case 554:
- case 555:
- case 556:
- case 557:
- case 558:
- case 559:
- case 560:
- case 561:
- case 562:
- case 563:
- case 564:
- case 565:
- case 566:
- case 567:
- case 568:
- case 569:
- case 570:
- case 571:
- case 572:
- case 573:
- case 574:
- case 575:
- case 576:
- case 577:
- case 578:
- case 579:
- case 580:
- case 581:
- case 582:
- case 583:
- case 584:
- case 585:
- case 586:
- case 587:
- case 588:
- case 589:
- case 590:
- case 591:
- case 592:
- case 593:
- case 594:
- case 595:
- case 596:
- case 597:
- case 598:
- case 599:
- case 600:
- case 601:
- case 602:
- case 603:
- case 604:
- case 605:
- case 606:
- case 607:
- case 608:
- case 609:
- case 610:
- case 611:
- case 612:
- case 613:
- case 614:
- case 615:
- case 616:
- case 617:
- case 618:
- case 619:
- case 620:
- case 621:
- case 622:
- case 623:
- case 624:
- case 625:
- case 626:
- case 627:
- case 628:
- case 629:
- case 630:
- case 631:
- case 632:
- case 633:
- case 634:
- case 635:
- case 636:
- case 637:
- case 638:
- case 639:
- case 640:
- case 641:
- case 642:
- case 643:
- case 644:
- case 645:
- case 646:
- case 647:
- case 648:
- case 649:
- case 650:
- case 651:
- case 652:
- case 653:
- case 654:
- case 655:
- case 656:
- case 657:
- case 658:
- case 659:
- case 660:
- case 661:
- case 662:
- case 663:
- case 664:
- case 665:
- case 666:
- case 667:
- case 668:
- case 669:
- case 670:
- case 671:
- case 672:
- case 673:
- case 674:
- case 675:
- case 676:
- case 677:
- case 678:
- case 679:
- case 680:
- case 681:
- case 682:
- case 683:
- case 684:
- case 685:
- case 686:
- case 687:
- case 688:
- case 689:
- case 690:
- case 691:
- case 692:
- case 693:
- case 694:
- case 695:
- case 696:
- case 697:
- case 698:
- case 699:
- case 700:
- case 701:
- case 702:
- case 703:
- case 704:
- case 705:
- case 706:
- case 707:
- case 708:
- case 709:
- case 710:
- case 711:
- case 712:
- case 713:
- case 714:
- case 715:
- case 716:
- case 717:
- case 718:
- case 719:
- case 720:
- case 721:
- case 722:
- case 723:
- case 724:
- case 725:
- case 726:
- case 727:
- case 728:
- case 729:
- case 730:
- case 2000:
- case 2001:
- case 2002:
- case 2003:
- case 2004:
- case 2005:
- case 2006:
- case 2007:
- case 2008:
- case 2009:
- case 2010:
- case 2011:
- case 2012:
- case 2013:
- case 2014:
- case 2015:
- case 2016:
- case 2017:
- case 2018:
- case 2019:
- case 2020:
- case 2021:
- case 2022:
- case 2023:
- case 2024:
- case 2025:
- case 2026:
- case 2027:
- case 2028:
- case 2029:
- case 2030:
- case 2031:
- case 2032:
- case 2033:
- case 2034:
- case 2035:
- case 2036:
- case 2037:
- case 2038:
- case 2039:
- case 2040:
- case 2041:
- case 2042:
- case 2043:
- case 2044:
- case 2045:
- case 3000:
- case 3001:
- return true;
- default:
- return false;
- }
-}
-
-#ifndef _MSC_VER
-const GLMessage_Function GLMessage::glActiveTexture;
-const GLMessage_Function GLMessage::glAlphaFunc;
-const GLMessage_Function GLMessage::glAlphaFuncx;
-const GLMessage_Function GLMessage::glAlphaFuncxOES;
-const GLMessage_Function GLMessage::glAttachShader;
-const GLMessage_Function GLMessage::glBeginPerfMonitorAMD;
-const GLMessage_Function GLMessage::glBindAttribLocation;
-const GLMessage_Function GLMessage::glBindBuffer;
-const GLMessage_Function GLMessage::glBindFramebuffer;
-const GLMessage_Function GLMessage::glBindFramebufferOES;
-const GLMessage_Function GLMessage::glBindRenderbuffer;
-const GLMessage_Function GLMessage::glBindRenderbufferOES;
-const GLMessage_Function GLMessage::glBindTexture;
-const GLMessage_Function GLMessage::glBindVertexArrayOES;
-const GLMessage_Function GLMessage::glBlendColor;
-const GLMessage_Function GLMessage::glBlendEquation;
-const GLMessage_Function GLMessage::glBlendEquationOES;
-const GLMessage_Function GLMessage::glBlendEquationSeparate;
-const GLMessage_Function GLMessage::glBlendEquationSeparateOES;
-const GLMessage_Function GLMessage::glBlendFunc;
-const GLMessage_Function GLMessage::glBlendFuncSeparate;
-const GLMessage_Function GLMessage::glBlendFuncSeparateOES;
-const GLMessage_Function GLMessage::glBufferData;
-const GLMessage_Function GLMessage::glBufferSubData;
-const GLMessage_Function GLMessage::glCheckFramebufferStatus;
-const GLMessage_Function GLMessage::glCheckFramebufferStatusOES;
-const GLMessage_Function GLMessage::glClearColor;
-const GLMessage_Function GLMessage::glClearColorx;
-const GLMessage_Function GLMessage::glClearColorxOES;
-const GLMessage_Function GLMessage::glClearDepthf;
-const GLMessage_Function GLMessage::glClearDepthfOES;
-const GLMessage_Function GLMessage::glClearDepthx;
-const GLMessage_Function GLMessage::glClearDepthxOES;
-const GLMessage_Function GLMessage::glClear;
-const GLMessage_Function GLMessage::glClearStencil;
-const GLMessage_Function GLMessage::glClientActiveTexture;
-const GLMessage_Function GLMessage::glClipPlanef;
-const GLMessage_Function GLMessage::glClipPlanefIMG;
-const GLMessage_Function GLMessage::glClipPlanefOES;
-const GLMessage_Function GLMessage::glClipPlanex;
-const GLMessage_Function GLMessage::glClipPlanexIMG;
-const GLMessage_Function GLMessage::glClipPlanexOES;
-const GLMessage_Function GLMessage::glColor4f;
-const GLMessage_Function GLMessage::glColor4ub;
-const GLMessage_Function GLMessage::glColor4x;
-const GLMessage_Function GLMessage::glColor4xOES;
-const GLMessage_Function GLMessage::glColorMask;
-const GLMessage_Function GLMessage::glColorPointer;
-const GLMessage_Function GLMessage::glCompileShader;
-const GLMessage_Function GLMessage::glCompressedTexImage2D;
-const GLMessage_Function GLMessage::glCompressedTexImage3DOES;
-const GLMessage_Function GLMessage::glCompressedTexSubImage2D;
-const GLMessage_Function GLMessage::glCompressedTexSubImage3DOES;
-const GLMessage_Function GLMessage::glCopyTexImage2D;
-const GLMessage_Function GLMessage::glCopyTexSubImage2D;
-const GLMessage_Function GLMessage::glCopyTexSubImage3DOES;
-const GLMessage_Function GLMessage::glCoverageMaskNV;
-const GLMessage_Function GLMessage::glCoverageOperationNV;
-const GLMessage_Function GLMessage::glCreateProgram;
-const GLMessage_Function GLMessage::glCreateShader;
-const GLMessage_Function GLMessage::glCullFace;
-const GLMessage_Function GLMessage::glCurrentPaletteMatrixOES;
-const GLMessage_Function GLMessage::glDeleteBuffers;
-const GLMessage_Function GLMessage::glDeleteFencesNV;
-const GLMessage_Function GLMessage::glDeleteFramebuffers;
-const GLMessage_Function GLMessage::glDeleteFramebuffersOES;
-const GLMessage_Function GLMessage::glDeletePerfMonitorsAMD;
-const GLMessage_Function GLMessage::glDeleteProgram;
-const GLMessage_Function GLMessage::glDeleteRenderbuffers;
-const GLMessage_Function GLMessage::glDeleteRenderbuffersOES;
-const GLMessage_Function GLMessage::glDeleteShader;
-const GLMessage_Function GLMessage::glDeleteTextures;
-const GLMessage_Function GLMessage::glDeleteVertexArraysOES;
-const GLMessage_Function GLMessage::glDepthFunc;
-const GLMessage_Function GLMessage::glDepthMask;
-const GLMessage_Function GLMessage::glDepthRangef;
-const GLMessage_Function GLMessage::glDepthRangefOES;
-const GLMessage_Function GLMessage::glDepthRangex;
-const GLMessage_Function GLMessage::glDepthRangexOES;
-const GLMessage_Function GLMessage::glDetachShader;
-const GLMessage_Function GLMessage::glDisableClientState;
-const GLMessage_Function GLMessage::glDisableDriverControlQCOM;
-const GLMessage_Function GLMessage::glDisable;
-const GLMessage_Function GLMessage::glDisableVertexAttribArray;
-const GLMessage_Function GLMessage::glDiscardFramebufferEXT;
-const GLMessage_Function GLMessage::glDrawArrays;
-const GLMessage_Function GLMessage::glDrawElements;
-const GLMessage_Function GLMessage::glDrawTexfOES;
-const GLMessage_Function GLMessage::glDrawTexfvOES;
-const GLMessage_Function GLMessage::glDrawTexiOES;
-const GLMessage_Function GLMessage::glDrawTexivOES;
-const GLMessage_Function GLMessage::glDrawTexsOES;
-const GLMessage_Function GLMessage::glDrawTexsvOES;
-const GLMessage_Function GLMessage::glDrawTexxOES;
-const GLMessage_Function GLMessage::glDrawTexxvOES;
-const GLMessage_Function GLMessage::glEGLImageTargetRenderbufferStorageOES;
-const GLMessage_Function GLMessage::glEGLImageTargetTexture2DOES;
-const GLMessage_Function GLMessage::glEnableClientState;
-const GLMessage_Function GLMessage::glEnableDriverControlQCOM;
-const GLMessage_Function GLMessage::glEnable;
-const GLMessage_Function GLMessage::glEnableVertexAttribArray;
-const GLMessage_Function GLMessage::glEndPerfMonitorAMD;
-const GLMessage_Function GLMessage::glEndTilingQCOM;
-const GLMessage_Function GLMessage::glExtGetBufferPointervQCOM;
-const GLMessage_Function GLMessage::glExtGetBuffersQCOM;
-const GLMessage_Function GLMessage::glExtGetFramebuffersQCOM;
-const GLMessage_Function GLMessage::glExtGetProgramBinarySourceQCOM;
-const GLMessage_Function GLMessage::glExtGetProgramsQCOM;
-const GLMessage_Function GLMessage::glExtGetRenderbuffersQCOM;
-const GLMessage_Function GLMessage::glExtGetShadersQCOM;
-const GLMessage_Function GLMessage::glExtGetTexLevelParameterivQCOM;
-const GLMessage_Function GLMessage::glExtGetTexSubImageQCOM;
-const GLMessage_Function GLMessage::glExtGetTexturesQCOM;
-const GLMessage_Function GLMessage::glExtIsProgramBinaryQCOM;
-const GLMessage_Function GLMessage::glExtTexObjectStateOverrideiQCOM;
-const GLMessage_Function GLMessage::glFinishFenceNV;
-const GLMessage_Function GLMessage::glFinish;
-const GLMessage_Function GLMessage::glFlush;
-const GLMessage_Function GLMessage::glFogf;
-const GLMessage_Function GLMessage::glFogfv;
-const GLMessage_Function GLMessage::glFogx;
-const GLMessage_Function GLMessage::glFogxOES;
-const GLMessage_Function GLMessage::glFogxv;
-const GLMessage_Function GLMessage::glFogxvOES;
-const GLMessage_Function GLMessage::glFramebufferRenderbuffer;
-const GLMessage_Function GLMessage::glFramebufferRenderbufferOES;
-const GLMessage_Function GLMessage::glFramebufferTexture2D;
-const GLMessage_Function GLMessage::glFramebufferTexture2DMultisampleIMG;
-const GLMessage_Function GLMessage::glFramebufferTexture2DOES;
-const GLMessage_Function GLMessage::glFramebufferTexture3DOES;
-const GLMessage_Function GLMessage::glFrontFace;
-const GLMessage_Function GLMessage::glFrustumf;
-const GLMessage_Function GLMessage::glFrustumfOES;
-const GLMessage_Function GLMessage::glFrustumx;
-const GLMessage_Function GLMessage::glFrustumxOES;
-const GLMessage_Function GLMessage::glGenBuffers;
-const GLMessage_Function GLMessage::glGenerateMipmap;
-const GLMessage_Function GLMessage::glGenerateMipmapOES;
-const GLMessage_Function GLMessage::glGenFencesNV;
-const GLMessage_Function GLMessage::glGenFramebuffers;
-const GLMessage_Function GLMessage::glGenFramebuffersOES;
-const GLMessage_Function GLMessage::glGenPerfMonitorsAMD;
-const GLMessage_Function GLMessage::glGenRenderbuffers;
-const GLMessage_Function GLMessage::glGenRenderbuffersOES;
-const GLMessage_Function GLMessage::glGenTextures;
-const GLMessage_Function GLMessage::glGenVertexArraysOES;
-const GLMessage_Function GLMessage::glGetActiveAttrib;
-const GLMessage_Function GLMessage::glGetActiveUniform;
-const GLMessage_Function GLMessage::glGetAttachedShaders;
-const GLMessage_Function GLMessage::glGetAttribLocation;
-const GLMessage_Function GLMessage::glGetBooleanv;
-const GLMessage_Function GLMessage::glGetBufferParameteriv;
-const GLMessage_Function GLMessage::glGetBufferPointervOES;
-const GLMessage_Function GLMessage::glGetClipPlanef;
-const GLMessage_Function GLMessage::glGetClipPlanefOES;
-const GLMessage_Function GLMessage::glGetClipPlanex;
-const GLMessage_Function GLMessage::glGetClipPlanexOES;
-const GLMessage_Function GLMessage::glGetDriverControlsQCOM;
-const GLMessage_Function GLMessage::glGetDriverControlStringQCOM;
-const GLMessage_Function GLMessage::glGetError;
-const GLMessage_Function GLMessage::glGetFenceivNV;
-const GLMessage_Function GLMessage::glGetFixedv;
-const GLMessage_Function GLMessage::glGetFixedvOES;
-const GLMessage_Function GLMessage::glGetFloatv;
-const GLMessage_Function GLMessage::glGetFramebufferAttachmentParameteriv;
-const GLMessage_Function GLMessage::glGetFramebufferAttachmentParameterivOES;
-const GLMessage_Function GLMessage::glGetIntegerv;
-const GLMessage_Function GLMessage::glGetLightfv;
-const GLMessage_Function GLMessage::glGetLightxv;
-const GLMessage_Function GLMessage::glGetLightxvOES;
-const GLMessage_Function GLMessage::glGetMaterialfv;
-const GLMessage_Function GLMessage::glGetMaterialxv;
-const GLMessage_Function GLMessage::glGetMaterialxvOES;
-const GLMessage_Function GLMessage::glGetPerfMonitorCounterDataAMD;
-const GLMessage_Function GLMessage::glGetPerfMonitorCounterInfoAMD;
-const GLMessage_Function GLMessage::glGetPerfMonitorCountersAMD;
-const GLMessage_Function GLMessage::glGetPerfMonitorCounterStringAMD;
-const GLMessage_Function GLMessage::glGetPerfMonitorGroupsAMD;
-const GLMessage_Function GLMessage::glGetPerfMonitorGroupStringAMD;
-const GLMessage_Function GLMessage::glGetPointerv;
-const GLMessage_Function GLMessage::glGetProgramBinaryOES;
-const GLMessage_Function GLMessage::glGetProgramInfoLog;
-const GLMessage_Function GLMessage::glGetProgramiv;
-const GLMessage_Function GLMessage::glGetRenderbufferParameteriv;
-const GLMessage_Function GLMessage::glGetRenderbufferParameterivOES;
-const GLMessage_Function GLMessage::glGetShaderInfoLog;
-const GLMessage_Function GLMessage::glGetShaderiv;
-const GLMessage_Function GLMessage::glGetShaderPrecisionFormat;
-const GLMessage_Function GLMessage::glGetShaderSource;
-const GLMessage_Function GLMessage::glGetString;
-const GLMessage_Function GLMessage::glGetTexEnvfv;
-const GLMessage_Function GLMessage::glGetTexEnviv;
-const GLMessage_Function GLMessage::glGetTexEnvxv;
-const GLMessage_Function GLMessage::glGetTexEnvxvOES;
-const GLMessage_Function GLMessage::glGetTexGenfvOES;
-const GLMessage_Function GLMessage::glGetTexGenivOES;
-const GLMessage_Function GLMessage::glGetTexGenxvOES;
-const GLMessage_Function GLMessage::glGetTexParameterfv;
-const GLMessage_Function GLMessage::glGetTexParameteriv;
-const GLMessage_Function GLMessage::glGetTexParameterxv;
-const GLMessage_Function GLMessage::glGetTexParameterxvOES;
-const GLMessage_Function GLMessage::glGetUniformfv;
-const GLMessage_Function GLMessage::glGetUniformiv;
-const GLMessage_Function GLMessage::glGetUniformLocation;
-const GLMessage_Function GLMessage::glGetVertexAttribfv;
-const GLMessage_Function GLMessage::glGetVertexAttribiv;
-const GLMessage_Function GLMessage::glGetVertexAttribPointerv;
-const GLMessage_Function GLMessage::glHint;
-const GLMessage_Function GLMessage::glIsBuffer;
-const GLMessage_Function GLMessage::glIsEnabled;
-const GLMessage_Function GLMessage::glIsFenceNV;
-const GLMessage_Function GLMessage::glIsFramebuffer;
-const GLMessage_Function GLMessage::glIsFramebufferOES;
-const GLMessage_Function GLMessage::glIsProgram;
-const GLMessage_Function GLMessage::glIsRenderbuffer;
-const GLMessage_Function GLMessage::glIsRenderbufferOES;
-const GLMessage_Function GLMessage::glIsShader;
-const GLMessage_Function GLMessage::glIsTexture;
-const GLMessage_Function GLMessage::glIsVertexArrayOES;
-const GLMessage_Function GLMessage::glLightf;
-const GLMessage_Function GLMessage::glLightfv;
-const GLMessage_Function GLMessage::glLightModelf;
-const GLMessage_Function GLMessage::glLightModelfv;
-const GLMessage_Function GLMessage::glLightModelx;
-const GLMessage_Function GLMessage::glLightModelxOES;
-const GLMessage_Function GLMessage::glLightModelxv;
-const GLMessage_Function GLMessage::glLightModelxvOES;
-const GLMessage_Function GLMessage::glLightx;
-const GLMessage_Function GLMessage::glLightxOES;
-const GLMessage_Function GLMessage::glLightxv;
-const GLMessage_Function GLMessage::glLightxvOES;
-const GLMessage_Function GLMessage::glLineWidth;
-const GLMessage_Function GLMessage::glLineWidthx;
-const GLMessage_Function GLMessage::glLineWidthxOES;
-const GLMessage_Function GLMessage::glLinkProgram;
-const GLMessage_Function GLMessage::glLoadIdentity;
-const GLMessage_Function GLMessage::glLoadMatrixf;
-const GLMessage_Function GLMessage::glLoadMatrixx;
-const GLMessage_Function GLMessage::glLoadMatrixxOES;
-const GLMessage_Function GLMessage::glLoadPaletteFromModelViewMatrixOES;
-const GLMessage_Function GLMessage::glLogicOp;
-const GLMessage_Function GLMessage::glMapBufferOES;
-const GLMessage_Function GLMessage::glMaterialf;
-const GLMessage_Function GLMessage::glMaterialfv;
-const GLMessage_Function GLMessage::glMaterialx;
-const GLMessage_Function GLMessage::glMaterialxOES;
-const GLMessage_Function GLMessage::glMaterialxv;
-const GLMessage_Function GLMessage::glMaterialxvOES;
-const GLMessage_Function GLMessage::glMatrixIndexPointerOES;
-const GLMessage_Function GLMessage::glMatrixMode;
-const GLMessage_Function GLMessage::glMultiDrawArraysEXT;
-const GLMessage_Function GLMessage::glMultiDrawElementsEXT;
-const GLMessage_Function GLMessage::glMultiTexCoord4f;
-const GLMessage_Function GLMessage::glMultiTexCoord4x;
-const GLMessage_Function GLMessage::glMultiTexCoord4xOES;
-const GLMessage_Function GLMessage::glMultMatrixf;
-const GLMessage_Function GLMessage::glMultMatrixx;
-const GLMessage_Function GLMessage::glMultMatrixxOES;
-const GLMessage_Function GLMessage::glNormal3f;
-const GLMessage_Function GLMessage::glNormal3x;
-const GLMessage_Function GLMessage::glNormal3xOES;
-const GLMessage_Function GLMessage::glNormalPointer;
-const GLMessage_Function GLMessage::glOrthof;
-const GLMessage_Function GLMessage::glOrthofOES;
-const GLMessage_Function GLMessage::glOrthox;
-const GLMessage_Function GLMessage::glOrthoxOES;
-const GLMessage_Function GLMessage::glPixelStorei;
-const GLMessage_Function GLMessage::glPointParameterf;
-const GLMessage_Function GLMessage::glPointParameterfv;
-const GLMessage_Function GLMessage::glPointParameterx;
-const GLMessage_Function GLMessage::glPointParameterxOES;
-const GLMessage_Function GLMessage::glPointParameterxv;
-const GLMessage_Function GLMessage::glPointParameterxvOES;
-const GLMessage_Function GLMessage::glPointSize;
-const GLMessage_Function GLMessage::glPointSizePointerOES;
-const GLMessage_Function GLMessage::glPointSizex;
-const GLMessage_Function GLMessage::glPointSizexOES;
-const GLMessage_Function GLMessage::glPolygonOffset;
-const GLMessage_Function GLMessage::glPolygonOffsetx;
-const GLMessage_Function GLMessage::glPolygonOffsetxOES;
-const GLMessage_Function GLMessage::glPopMatrix;
-const GLMessage_Function GLMessage::glProgramBinaryOES;
-const GLMessage_Function GLMessage::glPushMatrix;
-const GLMessage_Function GLMessage::glQueryMatrixxOES;
-const GLMessage_Function GLMessage::glReadPixels;
-const GLMessage_Function GLMessage::glReleaseShaderCompiler;
-const GLMessage_Function GLMessage::glRenderbufferStorage;
-const GLMessage_Function GLMessage::glRenderbufferStorageMultisampleIMG;
-const GLMessage_Function GLMessage::glRenderbufferStorageOES;
-const GLMessage_Function GLMessage::glRotatef;
-const GLMessage_Function GLMessage::glRotatex;
-const GLMessage_Function GLMessage::glRotatexOES;
-const GLMessage_Function GLMessage::glSampleCoverage;
-const GLMessage_Function GLMessage::glSampleCoveragex;
-const GLMessage_Function GLMessage::glSampleCoveragexOES;
-const GLMessage_Function GLMessage::glScalef;
-const GLMessage_Function GLMessage::glScalex;
-const GLMessage_Function GLMessage::glScalexOES;
-const GLMessage_Function GLMessage::glScissor;
-const GLMessage_Function GLMessage::glSelectPerfMonitorCountersAMD;
-const GLMessage_Function GLMessage::glSetFenceNV;
-const GLMessage_Function GLMessage::glShadeModel;
-const GLMessage_Function GLMessage::glShaderBinary;
-const GLMessage_Function GLMessage::glShaderSource;
-const GLMessage_Function GLMessage::glStartTilingQCOM;
-const GLMessage_Function GLMessage::glStencilFunc;
-const GLMessage_Function GLMessage::glStencilFuncSeparate;
-const GLMessage_Function GLMessage::glStencilMask;
-const GLMessage_Function GLMessage::glStencilMaskSeparate;
-const GLMessage_Function GLMessage::glStencilOp;
-const GLMessage_Function GLMessage::glStencilOpSeparate;
-const GLMessage_Function GLMessage::glTestFenceNV;
-const GLMessage_Function GLMessage::glTexCoordPointer;
-const GLMessage_Function GLMessage::glTexEnvf;
-const GLMessage_Function GLMessage::glTexEnvfv;
-const GLMessage_Function GLMessage::glTexEnvi;
-const GLMessage_Function GLMessage::glTexEnviv;
-const GLMessage_Function GLMessage::glTexEnvx;
-const GLMessage_Function GLMessage::glTexEnvxOES;
-const GLMessage_Function GLMessage::glTexEnvxv;
-const GLMessage_Function GLMessage::glTexEnvxvOES;
-const GLMessage_Function GLMessage::glTexGenfOES;
-const GLMessage_Function GLMessage::glTexGenfvOES;
-const GLMessage_Function GLMessage::glTexGeniOES;
-const GLMessage_Function GLMessage::glTexGenivOES;
-const GLMessage_Function GLMessage::glTexGenxOES;
-const GLMessage_Function GLMessage::glTexGenxvOES;
-const GLMessage_Function GLMessage::glTexImage2D;
-const GLMessage_Function GLMessage::glTexImage3DOES;
-const GLMessage_Function GLMessage::glTexParameterf;
-const GLMessage_Function GLMessage::glTexParameterfv;
-const GLMessage_Function GLMessage::glTexParameteri;
-const GLMessage_Function GLMessage::glTexParameteriv;
-const GLMessage_Function GLMessage::glTexParameterx;
-const GLMessage_Function GLMessage::glTexParameterxOES;
-const GLMessage_Function GLMessage::glTexParameterxv;
-const GLMessage_Function GLMessage::glTexParameterxvOES;
-const GLMessage_Function GLMessage::glTexSubImage2D;
-const GLMessage_Function GLMessage::glTexSubImage3DOES;
-const GLMessage_Function GLMessage::glTranslatef;
-const GLMessage_Function GLMessage::glTranslatex;
-const GLMessage_Function GLMessage::glTranslatexOES;
-const GLMessage_Function GLMessage::glUniform1f;
-const GLMessage_Function GLMessage::glUniform1fv;
-const GLMessage_Function GLMessage::glUniform1i;
-const GLMessage_Function GLMessage::glUniform1iv;
-const GLMessage_Function GLMessage::glUniform2f;
-const GLMessage_Function GLMessage::glUniform2fv;
-const GLMessage_Function GLMessage::glUniform2i;
-const GLMessage_Function GLMessage::glUniform2iv;
-const GLMessage_Function GLMessage::glUniform3f;
-const GLMessage_Function GLMessage::glUniform3fv;
-const GLMessage_Function GLMessage::glUniform3i;
-const GLMessage_Function GLMessage::glUniform3iv;
-const GLMessage_Function GLMessage::glUniform4f;
-const GLMessage_Function GLMessage::glUniform4fv;
-const GLMessage_Function GLMessage::glUniform4i;
-const GLMessage_Function GLMessage::glUniform4iv;
-const GLMessage_Function GLMessage::glUniformMatrix2fv;
-const GLMessage_Function GLMessage::glUniformMatrix3fv;
-const GLMessage_Function GLMessage::glUniformMatrix4fv;
-const GLMessage_Function GLMessage::glUnmapBufferOES;
-const GLMessage_Function GLMessage::glUseProgram;
-const GLMessage_Function GLMessage::glValidateProgram;
-const GLMessage_Function GLMessage::glVertexAttrib1f;
-const GLMessage_Function GLMessage::glVertexAttrib1fv;
-const GLMessage_Function GLMessage::glVertexAttrib2f;
-const GLMessage_Function GLMessage::glVertexAttrib2fv;
-const GLMessage_Function GLMessage::glVertexAttrib3f;
-const GLMessage_Function GLMessage::glVertexAttrib3fv;
-const GLMessage_Function GLMessage::glVertexAttrib4f;
-const GLMessage_Function GLMessage::glVertexAttrib4fv;
-const GLMessage_Function GLMessage::glVertexAttribPointer;
-const GLMessage_Function GLMessage::glVertexPointer;
-const GLMessage_Function GLMessage::glViewport;
-const GLMessage_Function GLMessage::glWeightPointerOES;
-const GLMessage_Function GLMessage::glReadBuffer;
-const GLMessage_Function GLMessage::glDrawRangeElements;
-const GLMessage_Function GLMessage::glTexImage3D;
-const GLMessage_Function GLMessage::glTexSubImage3D;
-const GLMessage_Function GLMessage::glCopyTexSubImage3D;
-const GLMessage_Function GLMessage::glCompressedTexImage3D;
-const GLMessage_Function GLMessage::glCompressedTexSubImage3D;
-const GLMessage_Function GLMessage::glGenQueries;
-const GLMessage_Function GLMessage::glDeleteQueries;
-const GLMessage_Function GLMessage::glIsQuery;
-const GLMessage_Function GLMessage::glBeginQuery;
-const GLMessage_Function GLMessage::glEndQuery;
-const GLMessage_Function GLMessage::glGetQueryiv;
-const GLMessage_Function GLMessage::glGetQueryObjectuiv;
-const GLMessage_Function GLMessage::glUnmapBuffer;
-const GLMessage_Function GLMessage::glGetBufferPointerv;
-const GLMessage_Function GLMessage::glDrawBuffers;
-const GLMessage_Function GLMessage::glUniformMatrix2x3fv;
-const GLMessage_Function GLMessage::glUniformMatrix3x2fv;
-const GLMessage_Function GLMessage::glUniformMatrix2x4fv;
-const GLMessage_Function GLMessage::glUniformMatrix4x2fv;
-const GLMessage_Function GLMessage::glUniformMatrix3x4fv;
-const GLMessage_Function GLMessage::glUniformMatrix4x3fv;
-const GLMessage_Function GLMessage::glBlitFramebuffer;
-const GLMessage_Function GLMessage::glRenderbufferStorageMultisample;
-const GLMessage_Function GLMessage::glFramebufferTextureLayer;
-const GLMessage_Function GLMessage::glMapBufferRange;
-const GLMessage_Function GLMessage::glFlushMappedBufferRange;
-const GLMessage_Function GLMessage::glBindVertexArray;
-const GLMessage_Function GLMessage::glDeleteVertexArrays;
-const GLMessage_Function GLMessage::glGenVertexArrays;
-const GLMessage_Function GLMessage::glIsVertexArray;
-const GLMessage_Function GLMessage::glGetIntegeri_v;
-const GLMessage_Function GLMessage::glBeginTransformFeedback;
-const GLMessage_Function GLMessage::glEndTransformFeedback;
-const GLMessage_Function GLMessage::glBindBufferRange;
-const GLMessage_Function GLMessage::glBindBufferBase;
-const GLMessage_Function GLMessage::glTransformFeedbackVaryings;
-const GLMessage_Function GLMessage::glGetTransformFeedbackVarying;
-const GLMessage_Function GLMessage::glVertexAttribIPointer;
-const GLMessage_Function GLMessage::glGetVertexAttribIiv;
-const GLMessage_Function GLMessage::glGetVertexAttribIuiv;
-const GLMessage_Function GLMessage::glVertexAttribI4i;
-const GLMessage_Function GLMessage::glVertexAttribI4ui;
-const GLMessage_Function GLMessage::glVertexAttribI4iv;
-const GLMessage_Function GLMessage::glVertexAttribI4uiv;
-const GLMessage_Function GLMessage::glGetUniformuiv;
-const GLMessage_Function GLMessage::glGetFragDataLocation;
-const GLMessage_Function GLMessage::glUniform1ui;
-const GLMessage_Function GLMessage::glUniform2ui;
-const GLMessage_Function GLMessage::glUniform3ui;
-const GLMessage_Function GLMessage::glUniform4ui;
-const GLMessage_Function GLMessage::glUniform1uiv;
-const GLMessage_Function GLMessage::glUniform2uiv;
-const GLMessage_Function GLMessage::glUniform3uiv;
-const GLMessage_Function GLMessage::glUniform4uiv;
-const GLMessage_Function GLMessage::glClearBufferiv;
-const GLMessage_Function GLMessage::glClearBufferuiv;
-const GLMessage_Function GLMessage::glClearBufferfv;
-const GLMessage_Function GLMessage::glClearBufferfi;
-const GLMessage_Function GLMessage::glGetStringi;
-const GLMessage_Function GLMessage::glCopyBufferSubData;
-const GLMessage_Function GLMessage::glGetUniformIndices;
-const GLMessage_Function GLMessage::glGetActiveUniformsiv;
-const GLMessage_Function GLMessage::glGetUniformBlockIndex;
-const GLMessage_Function GLMessage::glGetActiveUniformBlockiv;
-const GLMessage_Function GLMessage::glGetActiveUniformBlockName;
-const GLMessage_Function GLMessage::glUniformBlockBinding;
-const GLMessage_Function GLMessage::glDrawArraysInstanced;
-const GLMessage_Function GLMessage::glDrawElementsInstanced;
-const GLMessage_Function GLMessage::glFenceSync;
-const GLMessage_Function GLMessage::glIsSync;
-const GLMessage_Function GLMessage::glDeleteSync;
-const GLMessage_Function GLMessage::glClientWaitSync;
-const GLMessage_Function GLMessage::glWaitSync;
-const GLMessage_Function GLMessage::glGetInteger64v;
-const GLMessage_Function GLMessage::glGetSynciv;
-const GLMessage_Function GLMessage::glGetInteger64i_v;
-const GLMessage_Function GLMessage::glGetBufferParameteri64v;
-const GLMessage_Function GLMessage::glGenSamplers;
-const GLMessage_Function GLMessage::glDeleteSamplers;
-const GLMessage_Function GLMessage::glIsSampler;
-const GLMessage_Function GLMessage::glBindSampler;
-const GLMessage_Function GLMessage::glSamplerParameteri;
-const GLMessage_Function GLMessage::glSamplerParameteriv;
-const GLMessage_Function GLMessage::glSamplerParameterf;
-const GLMessage_Function GLMessage::glSamplerParameterfv;
-const GLMessage_Function GLMessage::glGetSamplerParameteriv;
-const GLMessage_Function GLMessage::glGetSamplerParameterfv;
-const GLMessage_Function GLMessage::glVertexAttribDivisor;
-const GLMessage_Function GLMessage::glBindTransformFeedback;
-const GLMessage_Function GLMessage::glDeleteTransformFeedbacks;
-const GLMessage_Function GLMessage::glGenTransformFeedbacks;
-const GLMessage_Function GLMessage::glIsTransformFeedback;
-const GLMessage_Function GLMessage::glPauseTransformFeedback;
-const GLMessage_Function GLMessage::glResumeTransformFeedback;
-const GLMessage_Function GLMessage::glGetProgramBinary;
-const GLMessage_Function GLMessage::glProgramBinary;
-const GLMessage_Function GLMessage::glProgramParameteri;
-const GLMessage_Function GLMessage::glInvalidateFramebuffer;
-const GLMessage_Function GLMessage::glInvalidateSubFramebuffer;
-const GLMessage_Function GLMessage::glTexStorage2D;
-const GLMessage_Function GLMessage::glTexStorage3D;
-const GLMessage_Function GLMessage::glGetInternalformativ;
-const GLMessage_Function GLMessage::glBeginPerfQueryINTEL;
-const GLMessage_Function GLMessage::glCreatePerfQueryINTEL;
-const GLMessage_Function GLMessage::glDeletePerfQueryINTEL;
-const GLMessage_Function GLMessage::glEndPerfQueryINTEL;
-const GLMessage_Function GLMessage::glGetFirstPerfQueryIdINTEL;
-const GLMessage_Function GLMessage::glGetNextPerfQueryIdINTEL;
-const GLMessage_Function GLMessage::glGetPerfCounterInfoINTEL;
-const GLMessage_Function GLMessage::glGetPerfQueryDataINTEL;
-const GLMessage_Function GLMessage::glGetPerfQueryIdByNameINTEL;
-const GLMessage_Function GLMessage::glGetPerfQueryInfoINTEL;
-const GLMessage_Function GLMessage::glBlendBarrierKHR;
-const GLMessage_Function GLMessage::glBlendBarrierNV;
-const GLMessage_Function GLMessage::glBlendParameteriNV;
-const GLMessage_Function GLMessage::glBlitFramebufferNV;
-const GLMessage_Function GLMessage::glFenceSyncAPPLE;
-const GLMessage_Function GLMessage::glIsSyncAPPLE;
-const GLMessage_Function GLMessage::glDeleteSyncAPPLE;
-const GLMessage_Function GLMessage::glClientWaitSyncAPPLE;
-const GLMessage_Function GLMessage::glWaitSyncAPPLE;
-const GLMessage_Function GLMessage::glGetInteger64vAPPLE;
-const GLMessage_Function GLMessage::glGetSyncivAPPLE;
-const GLMessage_Function GLMessage::glCopyBufferSubDataNV;
-const GLMessage_Function GLMessage::glActiveShaderProgramEXT;
-const GLMessage_Function GLMessage::glAlphaFuncQCOM;
-const GLMessage_Function GLMessage::glBeginQueryEXT;
-const GLMessage_Function GLMessage::glBindProgramPipelineEXT;
-const GLMessage_Function GLMessage::glBlitFramebufferANGLE;
-const GLMessage_Function GLMessage::glCreateShaderProgramvEXT;
-const GLMessage_Function GLMessage::glDeleteProgramPipelinesEXT;
-const GLMessage_Function GLMessage::glDeleteQueriesEXT;
-const GLMessage_Function GLMessage::glDrawBuffersNV;
-const GLMessage_Function GLMessage::glEndQueryEXT;
-const GLMessage_Function GLMessage::glFramebufferTexture2DMultisampleEXT;
-const GLMessage_Function GLMessage::glGenProgramPipelinesEXT;
-const GLMessage_Function GLMessage::glGenQueriesEXT;
-const GLMessage_Function GLMessage::glGetGraphicsResetStatusEXT;
-const GLMessage_Function GLMessage::glGetObjectLabelEXT;
-const GLMessage_Function GLMessage::glGetProgramPipelineInfoLogEXT;
-const GLMessage_Function GLMessage::glGetProgramPipelineivEXT;
-const GLMessage_Function GLMessage::glGetQueryObjectuivEXT;
-const GLMessage_Function GLMessage::glGetQueryivEXT;
-const GLMessage_Function GLMessage::glGetnUniformfvEXT;
-const GLMessage_Function GLMessage::glGetnUniformivEXT;
-const GLMessage_Function GLMessage::glInsertEventMarkerEXT;
-const GLMessage_Function GLMessage::glIsProgramPipelineEXT;
-const GLMessage_Function GLMessage::glIsQueryEXT;
-const GLMessage_Function GLMessage::glLabelObjectEXT;
-const GLMessage_Function GLMessage::glPopGroupMarkerEXT;
-const GLMessage_Function GLMessage::glProgramParameteriEXT;
-const GLMessage_Function GLMessage::glProgramUniform1fEXT;
-const GLMessage_Function GLMessage::glProgramUniform1fvEXT;
-const GLMessage_Function GLMessage::glProgramUniform1iEXT;
-const GLMessage_Function GLMessage::glProgramUniform1ivEXT;
-const GLMessage_Function GLMessage::glProgramUniform2fEXT;
-const GLMessage_Function GLMessage::glProgramUniform2fvEXT;
-const GLMessage_Function GLMessage::glProgramUniform2iEXT;
-const GLMessage_Function GLMessage::glProgramUniform2ivEXT;
-const GLMessage_Function GLMessage::glProgramUniform3fEXT;
-const GLMessage_Function GLMessage::glProgramUniform3fvEXT;
-const GLMessage_Function GLMessage::glProgramUniform3iEXT;
-const GLMessage_Function GLMessage::glProgramUniform3ivEXT;
-const GLMessage_Function GLMessage::glProgramUniform4fEXT;
-const GLMessage_Function GLMessage::glProgramUniform4fvEXT;
-const GLMessage_Function GLMessage::glProgramUniform4iEXT;
-const GLMessage_Function GLMessage::glProgramUniform4ivEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix2fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix3fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix4fvEXT;
-const GLMessage_Function GLMessage::glPushGroupMarkerEXT;
-const GLMessage_Function GLMessage::glReadBufferNV;
-const GLMessage_Function GLMessage::glReadnPixelsEXT;
-const GLMessage_Function GLMessage::glRenderbufferStorageMultisampleANGLE;
-const GLMessage_Function GLMessage::glRenderbufferStorageMultisampleAPPLE;
-const GLMessage_Function GLMessage::glRenderbufferStorageMultisampleEXT;
-const GLMessage_Function GLMessage::glResolveMultisampleFramebufferAPPLE;
-const GLMessage_Function GLMessage::glTexStorage1DEXT;
-const GLMessage_Function GLMessage::glTexStorage2DEXT;
-const GLMessage_Function GLMessage::glTexStorage3DEXT;
-const GLMessage_Function GLMessage::glTextureStorage1DEXT;
-const GLMessage_Function GLMessage::glTextureStorage2DEXT;
-const GLMessage_Function GLMessage::glTextureStorage3DEXT;
-const GLMessage_Function GLMessage::glUseProgramStagesEXT;
-const GLMessage_Function GLMessage::glValidateProgramPipelineEXT;
-const GLMessage_Function GLMessage::glCopyTextureLevelsAPPLE;
-const GLMessage_Function GLMessage::glDebugMessageControlKHR;
-const GLMessage_Function GLMessage::glDebugMessageInsertKHR;
-const GLMessage_Function GLMessage::glDebugMessageCallbackKHR;
-const GLMessage_Function GLMessage::glGetDebugMessageLogKHR;
-const GLMessage_Function GLMessage::glPushDebugGroupKHR;
-const GLMessage_Function GLMessage::glPopDebugGroupKHR;
-const GLMessage_Function GLMessage::glObjectLabelKHR;
-const GLMessage_Function GLMessage::glGetObjectLabelKHR;
-const GLMessage_Function GLMessage::glObjectPtrLabelKHR;
-const GLMessage_Function GLMessage::glGetObjectPtrLabelKHR;
-const GLMessage_Function GLMessage::glGetPointervKHR;
-const GLMessage_Function GLMessage::glDrawArraysInstancedANGLE;
-const GLMessage_Function GLMessage::glDrawElementsInstancedANGLE;
-const GLMessage_Function GLMessage::glVertexAttribDivisorANGLE;
-const GLMessage_Function GLMessage::glDrawArraysInstancedEXT;
-const GLMessage_Function GLMessage::glDrawElementsInstancedEXT;
-const GLMessage_Function GLMessage::glVertexAttribDivisorEXT;
-const GLMessage_Function GLMessage::glDrawArraysInstancedNV;
-const GLMessage_Function GLMessage::glDrawElementsInstancedNV;
-const GLMessage_Function GLMessage::glVertexAttribDivisorNV;
-const GLMessage_Function GLMessage::glDrawBuffersEXT;
-const GLMessage_Function GLMessage::glReadBufferIndexedEXT;
-const GLMessage_Function GLMessage::glDrawBuffersIndexedEXT;
-const GLMessage_Function GLMessage::glGetIntegeri_vEXT;
-const GLMessage_Function GLMessage::glMapBufferRangeEXT;
-const GLMessage_Function GLMessage::glFlushMappedBufferRangeEXT;
-const GLMessage_Function GLMessage::glQueryCounterEXT;
-const GLMessage_Function GLMessage::glGetQueryObjecti64vEXT;
-const GLMessage_Function GLMessage::glGetQueryObjectivEXT;
-const GLMessage_Function GLMessage::glGetQueryObjectui64vEXT;
-const GLMessage_Function GLMessage::glGetTranslatedShaderSourceANGLE;
-const GLMessage_Function GLMessage::glMinSampleShadingOES;
-const GLMessage_Function GLMessage::glMultiTexCoord1bOES;
-const GLMessage_Function GLMessage::glMultiTexCoord1bvOES;
-const GLMessage_Function GLMessage::glMultiTexCoord2bOES;
-const GLMessage_Function GLMessage::glMultiTexCoord2bvOES;
-const GLMessage_Function GLMessage::glMultiTexCoord3bOES;
-const GLMessage_Function GLMessage::glMultiTexCoord3bvOES;
-const GLMessage_Function GLMessage::glMultiTexCoord4bOES;
-const GLMessage_Function GLMessage::glMultiTexCoord4bvOES;
-const GLMessage_Function GLMessage::glTexCoord1bOES;
-const GLMessage_Function GLMessage::glTexCoord1bvOES;
-const GLMessage_Function GLMessage::glTexCoord2bOES;
-const GLMessage_Function GLMessage::glTexCoord2bvOES;
-const GLMessage_Function GLMessage::glTexCoord3bOES;
-const GLMessage_Function GLMessage::glTexCoord3bvOES;
-const GLMessage_Function GLMessage::glTexCoord4bOES;
-const GLMessage_Function GLMessage::glTexCoord4bvOES;
-const GLMessage_Function GLMessage::glVertex2bOES;
-const GLMessage_Function GLMessage::glVertex2bvOES;
-const GLMessage_Function GLMessage::glVertex3bOES;
-const GLMessage_Function GLMessage::glVertex3bvOES;
-const GLMessage_Function GLMessage::glVertex4bOES;
-const GLMessage_Function GLMessage::glVertex4bvOES;
-const GLMessage_Function GLMessage::glProgramUniform1uiEXT;
-const GLMessage_Function GLMessage::glProgramUniform2uiEXT;
-const GLMessage_Function GLMessage::glProgramUniform3uiEXT;
-const GLMessage_Function GLMessage::glProgramUniform4uiEXT;
-const GLMessage_Function GLMessage::glProgramUniform1uivEXT;
-const GLMessage_Function GLMessage::glProgramUniform2uivEXT;
-const GLMessage_Function GLMessage::glProgramUniform3uivEXT;
-const GLMessage_Function GLMessage::glProgramUniform4uivEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix2x3fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix3x2fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix2x4fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix4x2fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix3x4fvEXT;
-const GLMessage_Function GLMessage::glProgramUniformMatrix4x3fvEXT;
-const GLMessage_Function GLMessage::glRenderbufferStorageMultisampleNV;
-const GLMessage_Function GLMessage::glSampleCoverageOES;
-const GLMessage_Function GLMessage::glTexStorage3DMultisampleOES;
-const GLMessage_Function GLMessage::glUniformMatrix2x3fvNV;
-const GLMessage_Function GLMessage::glUniformMatrix3x2fvNV;
-const GLMessage_Function GLMessage::glUniformMatrix2x4fvNV;
-const GLMessage_Function GLMessage::glUniformMatrix4x2fvNV;
-const GLMessage_Function GLMessage::glUniformMatrix3x4fvNV;
-const GLMessage_Function GLMessage::glUniformMatrix4x3fvNV;
-const GLMessage_Function GLMessage::glActiveShaderProgram;
-const GLMessage_Function GLMessage::glBindImageTexture;
-const GLMessage_Function GLMessage::glBindProgramPipeline;
-const GLMessage_Function GLMessage::glBindVertexBuffer;
-const GLMessage_Function GLMessage::glCreateShaderProgramv;
-const GLMessage_Function GLMessage::glDeleteProgramPipelines;
-const GLMessage_Function GLMessage::glDispatchCompute;
-const GLMessage_Function GLMessage::glDispatchComputeIndirect;
-const GLMessage_Function GLMessage::glDrawArraysIndirect;
-const GLMessage_Function GLMessage::glDrawElementsIndirect;
-const GLMessage_Function GLMessage::glFramebufferParameteri;
-const GLMessage_Function GLMessage::glGenProgramPipelines;
-const GLMessage_Function GLMessage::glGetBooleani_v;
-const GLMessage_Function GLMessage::glGetFramebufferParameteriv;
-const GLMessage_Function GLMessage::glGetMultisamplefv;
-const GLMessage_Function GLMessage::glGetProgramInterfaceiv;
-const GLMessage_Function GLMessage::glGetProgramPipelineInfoLog;
-const GLMessage_Function GLMessage::glGetProgramPipelineiv;
-const GLMessage_Function GLMessage::glGetProgramResourceIndex;
-const GLMessage_Function GLMessage::glGetProgramResourceLocation;
-const GLMessage_Function GLMessage::glGetProgramResourceName;
-const GLMessage_Function GLMessage::glGetProgramResourceiv;
-const GLMessage_Function GLMessage::glGetTexLevelParameterfv;
-const GLMessage_Function GLMessage::glGetTexLevelParameteriv;
-const GLMessage_Function GLMessage::glIsProgramPipeline;
-const GLMessage_Function GLMessage::glMemoryBarrier;
-const GLMessage_Function GLMessage::glMemoryBarrierByRegion;
-const GLMessage_Function GLMessage::glProgramUniform1f;
-const GLMessage_Function GLMessage::glProgramUniform1fv;
-const GLMessage_Function GLMessage::glProgramUniform1i;
-const GLMessage_Function GLMessage::glProgramUniform1iv;
-const GLMessage_Function GLMessage::glProgramUniform1ui;
-const GLMessage_Function GLMessage::glProgramUniform1uiv;
-const GLMessage_Function GLMessage::glProgramUniform2f;
-const GLMessage_Function GLMessage::glProgramUniform2fv;
-const GLMessage_Function GLMessage::glProgramUniform2i;
-const GLMessage_Function GLMessage::glProgramUniform2iv;
-const GLMessage_Function GLMessage::glProgramUniform2ui;
-const GLMessage_Function GLMessage::glProgramUniform2uiv;
-const GLMessage_Function GLMessage::glProgramUniform3f;
-const GLMessage_Function GLMessage::glProgramUniform3fv;
-const GLMessage_Function GLMessage::glProgramUniform3i;
-const GLMessage_Function GLMessage::glProgramUniform3iv;
-const GLMessage_Function GLMessage::glProgramUniform3ui;
-const GLMessage_Function GLMessage::glProgramUniform3uiv;
-const GLMessage_Function GLMessage::glProgramUniform4f;
-const GLMessage_Function GLMessage::glProgramUniform4fv;
-const GLMessage_Function GLMessage::glProgramUniform4i;
-const GLMessage_Function GLMessage::glProgramUniform4iv;
-const GLMessage_Function GLMessage::glProgramUniform4ui;
-const GLMessage_Function GLMessage::glProgramUniform4uiv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix2fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix2x3fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix2x4fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix3fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix3x2fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix3x4fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix4fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix4x2fv;
-const GLMessage_Function GLMessage::glProgramUniformMatrix4x3fv;
-const GLMessage_Function GLMessage::glSampleMaski;
-const GLMessage_Function GLMessage::glTexStorage2DMultisample;
-const GLMessage_Function GLMessage::glUseProgramStages;
-const GLMessage_Function GLMessage::glValidateProgramPipeline;
-const GLMessage_Function GLMessage::glVertexAttribBinding;
-const GLMessage_Function GLMessage::glVertexAttribFormat;
-const GLMessage_Function GLMessage::glVertexAttribIFormat;
-const GLMessage_Function GLMessage::glVertexBindingDivisor;
-const GLMessage_Function GLMessage::glBlendEquationSeparateiEXT;
-const GLMessage_Function GLMessage::glBlendEquationiEXT;
-const GLMessage_Function GLMessage::glBlendFuncSeparateiEXT;
-const GLMessage_Function GLMessage::glBlendFunciEXT;
-const GLMessage_Function GLMessage::glColorMaskiEXT;
-const GLMessage_Function GLMessage::glCopyImageSubDataEXT;
-const GLMessage_Function GLMessage::glDisableiEXT;
-const GLMessage_Function GLMessage::glEnableiEXT;
-const GLMessage_Function GLMessage::glFramebufferTextureEXT;
-const GLMessage_Function GLMessage::glGetSamplerParameterIivEXT;
-const GLMessage_Function GLMessage::glGetSamplerParameterIuivEXT;
-const GLMessage_Function GLMessage::glGetTexParameterIivEXT;
-const GLMessage_Function GLMessage::glGetTexParameterIuivEXT;
-const GLMessage_Function GLMessage::glIsEnablediEXT;
-const GLMessage_Function GLMessage::glPatchParameteriEXT;
-const GLMessage_Function GLMessage::glPrimitiveBoundingBoxEXT;
-const GLMessage_Function GLMessage::glSamplerParameterIivEXT;
-const GLMessage_Function GLMessage::glSamplerParameterIuivEXT;
-const GLMessage_Function GLMessage::glTexBufferEXT;
-const GLMessage_Function GLMessage::glTexBufferRangeEXT;
-const GLMessage_Function GLMessage::glTexParameterIivEXT;
-const GLMessage_Function GLMessage::glTexParameterIuivEXT;
-const GLMessage_Function GLMessage::glTextureViewEXT;
-const GLMessage_Function GLMessage::eglGetDisplay;
-const GLMessage_Function GLMessage::eglInitialize;
-const GLMessage_Function GLMessage::eglTerminate;
-const GLMessage_Function GLMessage::eglGetConfigs;
-const GLMessage_Function GLMessage::eglChooseConfig;
-const GLMessage_Function GLMessage::eglGetConfigAttrib;
-const GLMessage_Function GLMessage::eglCreateWindowSurface;
-const GLMessage_Function GLMessage::eglCreatePixmapSurface;
-const GLMessage_Function GLMessage::eglCreatePbufferSurface;
-const GLMessage_Function GLMessage::eglDestroySurface;
-const GLMessage_Function GLMessage::eglQuerySurface;
-const GLMessage_Function GLMessage::eglCreateContext;
-const GLMessage_Function GLMessage::eglDestroyContext;
-const GLMessage_Function GLMessage::eglMakeCurrent;
-const GLMessage_Function GLMessage::eglGetCurrentContext;
-const GLMessage_Function GLMessage::eglGetCurrentSurface;
-const GLMessage_Function GLMessage::eglGetCurrentDisplay;
-const GLMessage_Function GLMessage::eglQueryContext;
-const GLMessage_Function GLMessage::eglWaitGL;
-const GLMessage_Function GLMessage::eglWaitNative;
-const GLMessage_Function GLMessage::eglSwapBuffers;
-const GLMessage_Function GLMessage::eglCopyBuffers;
-const GLMessage_Function GLMessage::eglGetError;
-const GLMessage_Function GLMessage::eglQueryString;
-const GLMessage_Function GLMessage::eglGetProcAddress;
-const GLMessage_Function GLMessage::eglSurfaceAttrib;
-const GLMessage_Function GLMessage::eglBindTexImage;
-const GLMessage_Function GLMessage::eglReleaseTexImage;
-const GLMessage_Function GLMessage::eglSwapInterval;
-const GLMessage_Function GLMessage::eglBindAPI;
-const GLMessage_Function GLMessage::eglQueryAPI;
-const GLMessage_Function GLMessage::eglWaitClient;
-const GLMessage_Function GLMessage::eglReleaseThread;
-const GLMessage_Function GLMessage::eglCreatePbufferFromClientBuffer;
-const GLMessage_Function GLMessage::eglLockSurfaceKHR;
-const GLMessage_Function GLMessage::eglUnlockSurfaceKHR;
-const GLMessage_Function GLMessage::eglCreateImageKHR;
-const GLMessage_Function GLMessage::eglDestroyImageKHR;
-const GLMessage_Function GLMessage::eglCreateSyncKHR;
-const GLMessage_Function GLMessage::eglDestroySyncKHR;
-const GLMessage_Function GLMessage::eglClientWaitSyncKHR;
-const GLMessage_Function GLMessage::eglGetSyncAttribKHR;
-const GLMessage_Function GLMessage::eglSetSwapRectangleANDROID;
-const GLMessage_Function GLMessage::eglGetRenderBufferANDROID;
-const GLMessage_Function GLMessage::eglGetSystemTimeFrequencyNV;
-const GLMessage_Function GLMessage::eglGetSystemTimeNV;
-const GLMessage_Function GLMessage::invalid;
-const GLMessage_Function GLMessage::glVertexAttribPointerData;
-const GLMessage_Function GLMessage::Function_MIN;
-const GLMessage_Function GLMessage::Function_MAX;
-const int GLMessage::Function_ARRAYSIZE;
-#endif // _MSC_VER
-bool GLMessage_DataType_Type_IsValid(int value) {
- switch(value) {
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- return true;
- default:
- return false;
- }
-}
-
-#ifndef _MSC_VER
-const GLMessage_DataType_Type GLMessage_DataType::VOID;
-const GLMessage_DataType_Type GLMessage_DataType::CHAR;
-const GLMessage_DataType_Type GLMessage_DataType::BYTE;
-const GLMessage_DataType_Type GLMessage_DataType::INT;
-const GLMessage_DataType_Type GLMessage_DataType::FLOAT;
-const GLMessage_DataType_Type GLMessage_DataType::BOOL;
-const GLMessage_DataType_Type GLMessage_DataType::ENUM;
-const GLMessage_DataType_Type GLMessage_DataType::INT64;
-const GLMessage_DataType_Type GLMessage_DataType::Type_MIN;
-const GLMessage_DataType_Type GLMessage_DataType::Type_MAX;
-const int GLMessage_DataType::Type_ARRAYSIZE;
-#endif // _MSC_VER
-#ifndef _MSC_VER
-const int GLMessage_DataType::kTypeFieldNumber;
-const int GLMessage_DataType::kIsArrayFieldNumber;
-const int GLMessage_DataType::kIntValueFieldNumber;
-const int GLMessage_DataType::kFloatValueFieldNumber;
-const int GLMessage_DataType::kCharValueFieldNumber;
-const int GLMessage_DataType::kRawBytesFieldNumber;
-const int GLMessage_DataType::kBoolValueFieldNumber;
-const int GLMessage_DataType::kInt64ValueFieldNumber;
-#endif // !_MSC_VER
-
-GLMessage_DataType::GLMessage_DataType()
- : ::google::protobuf::MessageLite() {
- SharedCtor();
-}
-
-void GLMessage_DataType::InitAsDefaultInstance() {
-}
-
-GLMessage_DataType::GLMessage_DataType(const GLMessage_DataType& from)
- : ::google::protobuf::MessageLite() {
- SharedCtor();
- MergeFrom(from);
-}
-
-void GLMessage_DataType::SharedCtor() {
- _cached_size_ = 0;
- type_ = 1;
- isarray_ = false;
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
-}
-
-GLMessage_DataType::~GLMessage_DataType() {
- SharedDtor();
-}
-
-void GLMessage_DataType::SharedDtor() {
- if (this != default_instance_) {
- }
-}
-
-void GLMessage_DataType::SetCachedSize(int size) const {
- GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = size;
- GOOGLE_SAFE_CONCURRENT_WRITES_END();
-}
-const GLMessage_DataType& GLMessage_DataType::default_instance() {
- if (default_instance_ == NULL) protobuf_AddDesc_gltrace_2eproto(); return *default_instance_;
-}
-
-GLMessage_DataType* GLMessage_DataType::default_instance_ = NULL;
-
-GLMessage_DataType* GLMessage_DataType::New() const {
- return new GLMessage_DataType;
-}
-
-void GLMessage_DataType::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- type_ = 1;
- isarray_ = false;
- }
- intvalue_.Clear();
- floatvalue_.Clear();
- charvalue_.Clear();
- rawbytes_.Clear();
- boolvalue_.Clear();
- int64value_.Clear();
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
-}
-
-bool GLMessage_DataType::MergePartialFromCodedStream(
- ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
- ::google::protobuf::uint32 tag;
- while ((tag = input->ReadTag()) != 0) {
- switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
- // required .android.gltrace.GLMessage.DataType.Type type = 1 [default = VOID];
- case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- int value;
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
- input, &value)));
- if (::android::gltrace::GLMessage_DataType_Type_IsValid(value)) {
- set_type(static_cast< ::android::gltrace::GLMessage_DataType_Type >(value));
- }
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(16)) goto parse_isArray;
- break;
- }
-
- // required bool isArray = 2 [default = false];
- case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_isArray:
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
- input, &isarray_)));
- _set_bit(1);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(24)) goto parse_intValue;
- break;
- }
-
- // repeated int32 intValue = 3;
- case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_intValue:
- DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- 1, 24, input, this->mutable_intvalue())));
- } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_LENGTH_DELIMITED) {
- DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- input, this->mutable_intvalue())));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(24)) goto parse_intValue;
- if (input->ExpectTag(37)) goto parse_floatValue;
- break;
- }
-
- // repeated float floatValue = 4;
- case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) {
- parse_floatValue:
- DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
- float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
- 1, 37, input, this->mutable_floatvalue())));
- } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_LENGTH_DELIMITED) {
- DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
- float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
- input, this->mutable_floatvalue())));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(37)) goto parse_floatValue;
- if (input->ExpectTag(42)) goto parse_charValue;
- break;
- }
-
- // repeated bytes charValue = 5;
- case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
- parse_charValue:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
- input, this->add_charvalue()));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(42)) goto parse_charValue;
- if (input->ExpectTag(50)) goto parse_rawBytes;
- break;
- }
-
- // repeated bytes rawBytes = 6;
- case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
- parse_rawBytes:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
- input, this->add_rawbytes()));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(50)) goto parse_rawBytes;
- if (input->ExpectTag(56)) goto parse_boolValue;
- break;
- }
-
- // repeated bool boolValue = 7;
- case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_boolValue:
- DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
- bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
- 1, 56, input, this->mutable_boolvalue())));
- } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_LENGTH_DELIMITED) {
- DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
- bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
- input, this->mutable_boolvalue())));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(56)) goto parse_boolValue;
- if (input->ExpectTag(64)) goto parse_int64Value;
- break;
- }
-
- // repeated int64 int64Value = 8;
- case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_int64Value:
- DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
- ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
- 1, 64, input, this->mutable_int64value())));
- } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_LENGTH_DELIMITED) {
- DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
- ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
- input, this->mutable_int64value())));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(64)) goto parse_int64Value;
- if (input->ExpectAtEnd()) return true;
- break;
- }
-
- default: {
- handle_uninterpreted:
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
- return true;
- }
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
- break;
- }
- }
- }
- return true;
-#undef DO_
-}
-
-void GLMessage_DataType::SerializeWithCachedSizes(
- ::google::protobuf::io::CodedOutputStream* output) const {
- // required .android.gltrace.GLMessage.DataType.Type type = 1 [default = VOID];
- if (_has_bit(0)) {
- ::google::protobuf::internal::WireFormatLite::WriteEnum(
- 1, this->type(), output);
- }
-
- // required bool isArray = 2 [default = false];
- if (_has_bit(1)) {
- ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->isarray(), output);
- }
-
- // repeated int32 intValue = 3;
- for (int i = 0; i < this->intvalue_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteInt32(
- 3, this->intvalue(i), output);
- }
-
- // repeated float floatValue = 4;
- for (int i = 0; i < this->floatvalue_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteFloat(
- 4, this->floatvalue(i), output);
- }
-
- // repeated bytes charValue = 5;
- for (int i = 0; i < this->charvalue_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteBytes(
- 5, this->charvalue(i), output);
- }
-
- // repeated bytes rawBytes = 6;
- for (int i = 0; i < this->rawbytes_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteBytes(
- 6, this->rawbytes(i), output);
- }
-
- // repeated bool boolValue = 7;
- for (int i = 0; i < this->boolvalue_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteBool(
- 7, this->boolvalue(i), output);
- }
-
- // repeated int64 int64Value = 8;
- for (int i = 0; i < this->int64value_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteInt64(
- 8, this->int64value(i), output);
- }
-
-}
-
-int GLMessage_DataType::ByteSize() const {
- int total_size = 0;
-
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // required .android.gltrace.GLMessage.DataType.Type type = 1 [default = VOID];
- if (has_type()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
- }
-
- // required bool isArray = 2 [default = false];
- if (has_isarray()) {
- total_size += 1 + 1;
- }
-
- }
- // repeated int32 intValue = 3;
- {
- int data_size = 0;
- for (int i = 0; i < this->intvalue_size(); i++) {
- data_size += ::google::protobuf::internal::WireFormatLite::
- Int32Size(this->intvalue(i));
- }
- total_size += 1 * this->intvalue_size() + data_size;
- }
-
- // repeated float floatValue = 4;
- {
- int data_size = 0;
- data_size = 4 * this->floatvalue_size();
- total_size += 1 * this->floatvalue_size() + data_size;
- }
-
- // repeated bytes charValue = 5;
- total_size += 1 * this->charvalue_size();
- for (int i = 0; i < this->charvalue_size(); i++) {
- total_size += ::google::protobuf::internal::WireFormatLite::BytesSize(
- this->charvalue(i));
- }
-
- // repeated bytes rawBytes = 6;
- total_size += 1 * this->rawbytes_size();
- for (int i = 0; i < this->rawbytes_size(); i++) {
- total_size += ::google::protobuf::internal::WireFormatLite::BytesSize(
- this->rawbytes(i));
- }
-
- // repeated bool boolValue = 7;
- {
- int data_size = 0;
- data_size = 1 * this->boolvalue_size();
- total_size += 1 * this->boolvalue_size() + data_size;
- }
-
- // repeated int64 int64Value = 8;
- {
- int data_size = 0;
- for (int i = 0; i < this->int64value_size(); i++) {
- data_size += ::google::protobuf::internal::WireFormatLite::
- Int64Size(this->int64value(i));
- }
- total_size += 1 * this->int64value_size() + data_size;
- }
-
- GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = total_size;
- GOOGLE_SAFE_CONCURRENT_WRITES_END();
- return total_size;
-}
-
-void GLMessage_DataType::CheckTypeAndMergeFrom(
- const ::google::protobuf::MessageLite& from) {
- MergeFrom(*::google::protobuf::down_cast<const GLMessage_DataType*>(&from));
-}
-
-void GLMessage_DataType::MergeFrom(const GLMessage_DataType& from) {
- GOOGLE_CHECK_NE(&from, this);
- intvalue_.MergeFrom(from.intvalue_);
- floatvalue_.MergeFrom(from.floatvalue_);
- charvalue_.MergeFrom(from.charvalue_);
- rawbytes_.MergeFrom(from.rawbytes_);
- boolvalue_.MergeFrom(from.boolvalue_);
- int64value_.MergeFrom(from.int64value_);
- if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- if (from._has_bit(0)) {
- set_type(from.type());
- }
- if (from._has_bit(1)) {
- set_isarray(from.isarray());
- }
- }
-}
-
-void GLMessage_DataType::CopyFrom(const GLMessage_DataType& from) {
- if (&from == this) return;
- Clear();
- MergeFrom(from);
-}
-
-bool GLMessage_DataType::IsInitialized() const {
- if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
-
- return true;
-}
-
-void GLMessage_DataType::Swap(GLMessage_DataType* other) {
- if (other != this) {
- std::swap(type_, other->type_);
- std::swap(isarray_, other->isarray_);
- intvalue_.Swap(&other->intvalue_);
- floatvalue_.Swap(&other->floatvalue_);
- charvalue_.Swap(&other->charvalue_);
- rawbytes_.Swap(&other->rawbytes_);
- boolvalue_.Swap(&other->boolvalue_);
- int64value_.Swap(&other->int64value_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
-::std::string GLMessage_DataType::GetTypeName() const {
- return "android.gltrace.GLMessage.DataType";
-}
-
-
-// -------------------------------------------------------------------
-
-#ifndef _MSC_VER
-const int GLMessage_FrameBuffer::kWidthFieldNumber;
-const int GLMessage_FrameBuffer::kHeightFieldNumber;
-const int GLMessage_FrameBuffer::kContentsFieldNumber;
-#endif // !_MSC_VER
-
-GLMessage_FrameBuffer::GLMessage_FrameBuffer()
- : ::google::protobuf::MessageLite() {
- SharedCtor();
-}
-
-void GLMessage_FrameBuffer::InitAsDefaultInstance() {
-}
-
-GLMessage_FrameBuffer::GLMessage_FrameBuffer(const GLMessage_FrameBuffer& from)
- : ::google::protobuf::MessageLite() {
- SharedCtor();
- MergeFrom(from);
-}
-
-void GLMessage_FrameBuffer::SharedCtor() {
- _cached_size_ = 0;
- width_ = 0;
- height_ = 0;
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
-}
-
-GLMessage_FrameBuffer::~GLMessage_FrameBuffer() {
- SharedDtor();
-}
-
-void GLMessage_FrameBuffer::SharedDtor() {
- if (this != default_instance_) {
- }
-}
-
-void GLMessage_FrameBuffer::SetCachedSize(int size) const {
- GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = size;
- GOOGLE_SAFE_CONCURRENT_WRITES_END();
-}
-const GLMessage_FrameBuffer& GLMessage_FrameBuffer::default_instance() {
- if (default_instance_ == NULL) protobuf_AddDesc_gltrace_2eproto(); return *default_instance_;
-}
-
-GLMessage_FrameBuffer* GLMessage_FrameBuffer::default_instance_ = NULL;
-
-GLMessage_FrameBuffer* GLMessage_FrameBuffer::New() const {
- return new GLMessage_FrameBuffer;
-}
-
-void GLMessage_FrameBuffer::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- width_ = 0;
- height_ = 0;
- }
- contents_.Clear();
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
-}
-
-bool GLMessage_FrameBuffer::MergePartialFromCodedStream(
- ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
- ::google::protobuf::uint32 tag;
- while ((tag = input->ReadTag()) != 0) {
- switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
- // required int32 width = 1;
- case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- input, &width_)));
- _set_bit(0);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(16)) goto parse_height;
- break;
- }
-
- // required int32 height = 2;
- case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_height:
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- input, &height_)));
- _set_bit(1);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(26)) goto parse_contents;
- break;
- }
-
- // repeated bytes contents = 3;
- case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
- parse_contents:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
- input, this->add_contents()));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(26)) goto parse_contents;
- if (input->ExpectAtEnd()) return true;
- break;
- }
-
- default: {
- handle_uninterpreted:
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
- return true;
- }
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
- break;
- }
- }
- }
- return true;
-#undef DO_
-}
-
-void GLMessage_FrameBuffer::SerializeWithCachedSizes(
- ::google::protobuf::io::CodedOutputStream* output) const {
- // required int32 width = 1;
- if (_has_bit(0)) {
- ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->width(), output);
- }
-
- // required int32 height = 2;
- if (_has_bit(1)) {
- ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->height(), output);
- }
-
- // repeated bytes contents = 3;
- for (int i = 0; i < this->contents_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteBytes(
- 3, this->contents(i), output);
- }
-
-}
-
-int GLMessage_FrameBuffer::ByteSize() const {
- int total_size = 0;
-
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // required int32 width = 1;
- if (has_width()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::Int32Size(
- this->width());
- }
-
- // required int32 height = 2;
- if (has_height()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::Int32Size(
- this->height());
- }
-
- }
- // repeated bytes contents = 3;
- total_size += 1 * this->contents_size();
- for (int i = 0; i < this->contents_size(); i++) {
- total_size += ::google::protobuf::internal::WireFormatLite::BytesSize(
- this->contents(i));
- }
-
- GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = total_size;
- GOOGLE_SAFE_CONCURRENT_WRITES_END();
- return total_size;
-}
-
-void GLMessage_FrameBuffer::CheckTypeAndMergeFrom(
- const ::google::protobuf::MessageLite& from) {
- MergeFrom(*::google::protobuf::down_cast<const GLMessage_FrameBuffer*>(&from));
-}
-
-void GLMessage_FrameBuffer::MergeFrom(const GLMessage_FrameBuffer& from) {
- GOOGLE_CHECK_NE(&from, this);
- contents_.MergeFrom(from.contents_);
- if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- if (from._has_bit(0)) {
- set_width(from.width());
- }
- if (from._has_bit(1)) {
- set_height(from.height());
- }
- }
-}
-
-void GLMessage_FrameBuffer::CopyFrom(const GLMessage_FrameBuffer& from) {
- if (&from == this) return;
- Clear();
- MergeFrom(from);
-}
-
-bool GLMessage_FrameBuffer::IsInitialized() const {
- if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
-
- return true;
-}
-
-void GLMessage_FrameBuffer::Swap(GLMessage_FrameBuffer* other) {
- if (other != this) {
- std::swap(width_, other->width_);
- std::swap(height_, other->height_);
- contents_.Swap(&other->contents_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
-::std::string GLMessage_FrameBuffer::GetTypeName() const {
- return "android.gltrace.GLMessage.FrameBuffer";
-}
-
-
-// -------------------------------------------------------------------
-
-#ifndef _MSC_VER
-const int GLMessage::kContextIdFieldNumber;
-const int GLMessage::kStartTimeFieldNumber;
-const int GLMessage::kDurationFieldNumber;
-const int GLMessage::kFunctionFieldNumber;
-const int GLMessage::kArgsFieldNumber;
-const int GLMessage::kReturnValueFieldNumber;
-const int GLMessage::kFbFieldNumber;
-const int GLMessage::kThreadtimeFieldNumber;
-#endif // !_MSC_VER
-
-GLMessage::GLMessage()
- : ::google::protobuf::MessageLite() {
- SharedCtor();
-}
-
-void GLMessage::InitAsDefaultInstance() {
- returnvalue_ = const_cast< ::android::gltrace::GLMessage_DataType*>(&::android::gltrace::GLMessage_DataType::default_instance());
- fb_ = const_cast< ::android::gltrace::GLMessage_FrameBuffer*>(&::android::gltrace::GLMessage_FrameBuffer::default_instance());
-}
-
-GLMessage::GLMessage(const GLMessage& from)
- : ::google::protobuf::MessageLite() {
- SharedCtor();
- MergeFrom(from);
-}
-
-void GLMessage::SharedCtor() {
- _cached_size_ = 0;
- context_id_ = 0;
- start_time_ = GOOGLE_LONGLONG(0);
- duration_ = 0;
- function_ = 3000;
- returnvalue_ = NULL;
- fb_ = NULL;
- threadtime_ = 0;
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
-}
-
-GLMessage::~GLMessage() {
- SharedDtor();
-}
-
-void GLMessage::SharedDtor() {
- if (this != default_instance_) {
- delete returnvalue_;
- delete fb_;
- }
-}
-
-void GLMessage::SetCachedSize(int size) const {
- GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = size;
- GOOGLE_SAFE_CONCURRENT_WRITES_END();
-}
-const GLMessage& GLMessage::default_instance() {
- if (default_instance_ == NULL) protobuf_AddDesc_gltrace_2eproto(); return *default_instance_;
-}
-
-GLMessage* GLMessage::default_instance_ = NULL;
-
-GLMessage* GLMessage::New() const {
- return new GLMessage;
-}
-
-void GLMessage::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- context_id_ = 0;
- start_time_ = GOOGLE_LONGLONG(0);
- duration_ = 0;
- function_ = 3000;
- if (_has_bit(5)) {
- if (returnvalue_ != NULL) returnvalue_->::android::gltrace::GLMessage_DataType::Clear();
- }
- if (_has_bit(6)) {
- if (fb_ != NULL) fb_->::android::gltrace::GLMessage_FrameBuffer::Clear();
- }
- threadtime_ = 0;
- }
- args_.Clear();
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
-}
-
-bool GLMessage::MergePartialFromCodedStream(
- ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
- ::google::protobuf::uint32 tag;
- while ((tag = input->ReadTag()) != 0) {
- switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
- // required int32 context_id = 1;
- case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- input, &context_id_)));
- _set_bit(0);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(16)) goto parse_start_time;
- break;
- }
-
- // required int64 start_time = 2;
- case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_start_time:
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
- input, &start_time_)));
- _set_bit(1);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(24)) goto parse_duration;
- break;
- }
-
- // required int32 duration = 3;
- case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_duration:
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- input, &duration_)));
- _set_bit(2);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(32)) goto parse_function;
- break;
- }
-
- // required .android.gltrace.GLMessage.Function function = 4 [default = invalid];
- case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_function:
- int value;
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
- input, &value)));
- if (::android::gltrace::GLMessage_Function_IsValid(value)) {
- set_function(static_cast< ::android::gltrace::GLMessage_Function >(value));
- }
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(42)) goto parse_args;
- break;
- }
-
- // repeated .android.gltrace.GLMessage.DataType args = 5;
- case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
- parse_args:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_args()));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(42)) goto parse_args;
- if (input->ExpectTag(50)) goto parse_returnValue;
- break;
- }
-
- // optional .android.gltrace.GLMessage.DataType returnValue = 6;
- case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
- parse_returnValue:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_returnvalue()));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(58)) goto parse_fb;
- break;
- }
-
- // optional .android.gltrace.GLMessage.FrameBuffer fb = 7;
- case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
- parse_fb:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_fb()));
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectTag(64)) goto parse_threadtime;
- break;
- }
-
- // optional int32 threadtime = 8;
- case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- parse_threadtime:
- DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
- ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
- input, &threadtime_)));
- _set_bit(7);
- } else {
- goto handle_uninterpreted;
- }
- if (input->ExpectAtEnd()) return true;
- break;
- }
-
- default: {
- handle_uninterpreted:
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
- return true;
- }
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
- break;
- }
- }
- }
- return true;
-#undef DO_
-}
-
-void GLMessage::SerializeWithCachedSizes(
- ::google::protobuf::io::CodedOutputStream* output) const {
- // required int32 context_id = 1;
- if (_has_bit(0)) {
- ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->context_id(), output);
- }
-
- // required int64 start_time = 2;
- if (_has_bit(1)) {
- ::google::protobuf::internal::WireFormatLite::WriteInt64(2, this->start_time(), output);
- }
-
- // required int32 duration = 3;
- if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->duration(), output);
- }
-
- // required .android.gltrace.GLMessage.Function function = 4 [default = invalid];
- if (_has_bit(3)) {
- ::google::protobuf::internal::WireFormatLite::WriteEnum(
- 4, this->function(), output);
- }
-
- // repeated .android.gltrace.GLMessage.DataType args = 5;
- for (int i = 0; i < this->args_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessage(
- 5, this->args(i), output);
- }
-
- // optional .android.gltrace.GLMessage.DataType returnValue = 6;
- if (_has_bit(5)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessage(
- 6, this->returnvalue(), output);
- }
-
- // optional .android.gltrace.GLMessage.FrameBuffer fb = 7;
- if (_has_bit(6)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessage(
- 7, this->fb(), output);
- }
-
- // optional int32 threadtime = 8;
- if (_has_bit(7)) {
- ::google::protobuf::internal::WireFormatLite::WriteInt32(8, this->threadtime(), output);
- }
-
-}
-
-int GLMessage::ByteSize() const {
- int total_size = 0;
-
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // required int32 context_id = 1;
- if (has_context_id()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::Int32Size(
- this->context_id());
- }
-
- // required int64 start_time = 2;
- if (has_start_time()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::Int64Size(
- this->start_time());
- }
-
- // required int32 duration = 3;
- if (has_duration()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::Int32Size(
- this->duration());
- }
-
- // required .android.gltrace.GLMessage.Function function = 4 [default = invalid];
- if (has_function()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::EnumSize(this->function());
- }
-
- // optional .android.gltrace.GLMessage.DataType returnValue = 6;
- if (has_returnvalue()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- this->returnvalue());
- }
-
- // optional .android.gltrace.GLMessage.FrameBuffer fb = 7;
- if (has_fb()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- this->fb());
- }
-
- // optional int32 threadtime = 8;
- if (has_threadtime()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::Int32Size(
- this->threadtime());
- }
-
- }
- // repeated .android.gltrace.GLMessage.DataType args = 5;
- total_size += 1 * this->args_size();
- for (int i = 0; i < this->args_size(); i++) {
- total_size +=
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- this->args(i));
- }
-
- GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = total_size;
- GOOGLE_SAFE_CONCURRENT_WRITES_END();
- return total_size;
-}
-
-void GLMessage::CheckTypeAndMergeFrom(
- const ::google::protobuf::MessageLite& from) {
- MergeFrom(*::google::protobuf::down_cast<const GLMessage*>(&from));
-}
-
-void GLMessage::MergeFrom(const GLMessage& from) {
- GOOGLE_CHECK_NE(&from, this);
- args_.MergeFrom(from.args_);
- if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- if (from._has_bit(0)) {
- set_context_id(from.context_id());
- }
- if (from._has_bit(1)) {
- set_start_time(from.start_time());
- }
- if (from._has_bit(2)) {
- set_duration(from.duration());
- }
- if (from._has_bit(3)) {
- set_function(from.function());
- }
- if (from._has_bit(5)) {
- mutable_returnvalue()->::android::gltrace::GLMessage_DataType::MergeFrom(from.returnvalue());
- }
- if (from._has_bit(6)) {
- mutable_fb()->::android::gltrace::GLMessage_FrameBuffer::MergeFrom(from.fb());
- }
- if (from._has_bit(7)) {
- set_threadtime(from.threadtime());
- }
- }
-}
-
-void GLMessage::CopyFrom(const GLMessage& from) {
- if (&from == this) return;
- Clear();
- MergeFrom(from);
-}
-
-bool GLMessage::IsInitialized() const {
- if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false;
-
- for (int i = 0; i < args_size(); i++) {
- if (!this->args(i).IsInitialized()) return false;
- }
- if (has_returnvalue()) {
- if (!this->returnvalue().IsInitialized()) return false;
- }
- if (has_fb()) {
- if (!this->fb().IsInitialized()) return false;
- }
- return true;
-}
-
-void GLMessage::Swap(GLMessage* other) {
- if (other != this) {
- std::swap(context_id_, other->context_id_);
- std::swap(start_time_, other->start_time_);
- std::swap(duration_, other->duration_);
- std::swap(function_, other->function_);
- args_.Swap(&other->args_);
- std::swap(returnvalue_, other->returnvalue_);
- std::swap(fb_, other->fb_);
- std::swap(threadtime_, other->threadtime_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- std::swap(_cached_size_, other->_cached_size_);
- }
-}
-
-::std::string GLMessage::GetTypeName() const {
- return "android.gltrace.GLMessage";
-}
-
-
-// @@protoc_insertion_point(namespace_scope)
-
-} // namespace gltrace
-} // namespace android
-
-// @@protoc_insertion_point(global_scope)
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.h b/opengl/libs/GLES_trace/src/gltrace.pb.h
deleted file mode 100644
index 9bc7c58..0000000
--- a/opengl/libs/GLES_trace/src/gltrace.pb.h
+++ /dev/null
@@ -1,2525 +0,0 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
-// source: gltrace.proto
-
-#ifndef PROTOBUF_gltrace_2eproto__INCLUDED
-#define PROTOBUF_gltrace_2eproto__INCLUDED
-
-#include <string>
-
-#include <google/protobuf/stubs/common.h>
-
-#if GOOGLE_PROTOBUF_VERSION < 2003000
-#error This file was generated by a newer version of protoc which is
-#error incompatible with your Protocol Buffer headers. Please update
-#error your headers.
-#endif
-#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
-#error This file was generated by an older version of protoc which is
-#error incompatible with your Protocol Buffer headers. Please
-#error regenerate this file with a newer version of protoc.
-#endif
-
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/extension_set.h>
-// @@protoc_insertion_point(includes)
-
-namespace android {
-namespace gltrace {
-
-// Internal implementation detail -- do not call these.
-void protobuf_AddDesc_gltrace_2eproto();
-void protobuf_AssignDesc_gltrace_2eproto();
-void protobuf_ShutdownFile_gltrace_2eproto();
-
-class GLMessage;
-class GLMessage_DataType;
-class GLMessage_FrameBuffer;
-
-enum GLMessage_DataType_Type {
- GLMessage_DataType_Type_VOID = 1,
- GLMessage_DataType_Type_CHAR = 2,
- GLMessage_DataType_Type_BYTE = 3,
- GLMessage_DataType_Type_INT = 4,
- GLMessage_DataType_Type_FLOAT = 5,
- GLMessage_DataType_Type_BOOL = 6,
- GLMessage_DataType_Type_ENUM = 7,
- GLMessage_DataType_Type_INT64 = 8
-};
-bool GLMessage_DataType_Type_IsValid(int value);
-const GLMessage_DataType_Type GLMessage_DataType_Type_Type_MIN = GLMessage_DataType_Type_VOID;
-const GLMessage_DataType_Type GLMessage_DataType_Type_Type_MAX = GLMessage_DataType_Type_INT64;
-const int GLMessage_DataType_Type_Type_ARRAYSIZE = GLMessage_DataType_Type_Type_MAX + 1;
-
-enum GLMessage_Function {
- GLMessage_Function_glActiveTexture = 0,
- GLMessage_Function_glAlphaFunc = 1,
- GLMessage_Function_glAlphaFuncx = 2,
- GLMessage_Function_glAlphaFuncxOES = 3,
- GLMessage_Function_glAttachShader = 4,
- GLMessage_Function_glBeginPerfMonitorAMD = 5,
- GLMessage_Function_glBindAttribLocation = 6,
- GLMessage_Function_glBindBuffer = 7,
- GLMessage_Function_glBindFramebuffer = 8,
- GLMessage_Function_glBindFramebufferOES = 9,
- GLMessage_Function_glBindRenderbuffer = 10,
- GLMessage_Function_glBindRenderbufferOES = 11,
- GLMessage_Function_glBindTexture = 12,
- GLMessage_Function_glBindVertexArrayOES = 13,
- GLMessage_Function_glBlendColor = 14,
- GLMessage_Function_glBlendEquation = 15,
- GLMessage_Function_glBlendEquationOES = 16,
- GLMessage_Function_glBlendEquationSeparate = 17,
- GLMessage_Function_glBlendEquationSeparateOES = 18,
- GLMessage_Function_glBlendFunc = 19,
- GLMessage_Function_glBlendFuncSeparate = 20,
- GLMessage_Function_glBlendFuncSeparateOES = 21,
- GLMessage_Function_glBufferData = 22,
- GLMessage_Function_glBufferSubData = 23,
- GLMessage_Function_glCheckFramebufferStatus = 24,
- GLMessage_Function_glCheckFramebufferStatusOES = 25,
- GLMessage_Function_glClearColor = 26,
- GLMessage_Function_glClearColorx = 27,
- GLMessage_Function_glClearColorxOES = 28,
- GLMessage_Function_glClearDepthf = 29,
- GLMessage_Function_glClearDepthfOES = 30,
- GLMessage_Function_glClearDepthx = 31,
- GLMessage_Function_glClearDepthxOES = 32,
- GLMessage_Function_glClear = 33,
- GLMessage_Function_glClearStencil = 34,
- GLMessage_Function_glClientActiveTexture = 35,
- GLMessage_Function_glClipPlanef = 36,
- GLMessage_Function_glClipPlanefIMG = 37,
- GLMessage_Function_glClipPlanefOES = 38,
- GLMessage_Function_glClipPlanex = 39,
- GLMessage_Function_glClipPlanexIMG = 40,
- GLMessage_Function_glClipPlanexOES = 41,
- GLMessage_Function_glColor4f = 42,
- GLMessage_Function_glColor4ub = 43,
- GLMessage_Function_glColor4x = 44,
- GLMessage_Function_glColor4xOES = 45,
- GLMessage_Function_glColorMask = 46,
- GLMessage_Function_glColorPointer = 47,
- GLMessage_Function_glCompileShader = 48,
- GLMessage_Function_glCompressedTexImage2D = 49,
- GLMessage_Function_glCompressedTexImage3DOES = 50,
- GLMessage_Function_glCompressedTexSubImage2D = 51,
- GLMessage_Function_glCompressedTexSubImage3DOES = 52,
- GLMessage_Function_glCopyTexImage2D = 53,
- GLMessage_Function_glCopyTexSubImage2D = 54,
- GLMessage_Function_glCopyTexSubImage3DOES = 55,
- GLMessage_Function_glCoverageMaskNV = 56,
- GLMessage_Function_glCoverageOperationNV = 57,
- GLMessage_Function_glCreateProgram = 58,
- GLMessage_Function_glCreateShader = 59,
- GLMessage_Function_glCullFace = 60,
- GLMessage_Function_glCurrentPaletteMatrixOES = 61,
- GLMessage_Function_glDeleteBuffers = 62,
- GLMessage_Function_glDeleteFencesNV = 63,
- GLMessage_Function_glDeleteFramebuffers = 64,
- GLMessage_Function_glDeleteFramebuffersOES = 65,
- GLMessage_Function_glDeletePerfMonitorsAMD = 66,
- GLMessage_Function_glDeleteProgram = 67,
- GLMessage_Function_glDeleteRenderbuffers = 68,
- GLMessage_Function_glDeleteRenderbuffersOES = 69,
- GLMessage_Function_glDeleteShader = 70,
- GLMessage_Function_glDeleteTextures = 71,
- GLMessage_Function_glDeleteVertexArraysOES = 72,
- GLMessage_Function_glDepthFunc = 73,
- GLMessage_Function_glDepthMask = 74,
- GLMessage_Function_glDepthRangef = 75,
- GLMessage_Function_glDepthRangefOES = 76,
- GLMessage_Function_glDepthRangex = 77,
- GLMessage_Function_glDepthRangexOES = 78,
- GLMessage_Function_glDetachShader = 79,
- GLMessage_Function_glDisableClientState = 80,
- GLMessage_Function_glDisableDriverControlQCOM = 81,
- GLMessage_Function_glDisable = 82,
- GLMessage_Function_glDisableVertexAttribArray = 83,
- GLMessage_Function_glDiscardFramebufferEXT = 84,
- GLMessage_Function_glDrawArrays = 85,
- GLMessage_Function_glDrawElements = 86,
- GLMessage_Function_glDrawTexfOES = 87,
- GLMessage_Function_glDrawTexfvOES = 88,
- GLMessage_Function_glDrawTexiOES = 89,
- GLMessage_Function_glDrawTexivOES = 90,
- GLMessage_Function_glDrawTexsOES = 91,
- GLMessage_Function_glDrawTexsvOES = 92,
- GLMessage_Function_glDrawTexxOES = 93,
- GLMessage_Function_glDrawTexxvOES = 94,
- GLMessage_Function_glEGLImageTargetRenderbufferStorageOES = 95,
- GLMessage_Function_glEGLImageTargetTexture2DOES = 96,
- GLMessage_Function_glEnableClientState = 97,
- GLMessage_Function_glEnableDriverControlQCOM = 98,
- GLMessage_Function_glEnable = 99,
- GLMessage_Function_glEnableVertexAttribArray = 100,
- GLMessage_Function_glEndPerfMonitorAMD = 101,
- GLMessage_Function_glEndTilingQCOM = 102,
- GLMessage_Function_glExtGetBufferPointervQCOM = 103,
- GLMessage_Function_glExtGetBuffersQCOM = 104,
- GLMessage_Function_glExtGetFramebuffersQCOM = 105,
- GLMessage_Function_glExtGetProgramBinarySourceQCOM = 106,
- GLMessage_Function_glExtGetProgramsQCOM = 107,
- GLMessage_Function_glExtGetRenderbuffersQCOM = 108,
- GLMessage_Function_glExtGetShadersQCOM = 109,
- GLMessage_Function_glExtGetTexLevelParameterivQCOM = 110,
- GLMessage_Function_glExtGetTexSubImageQCOM = 111,
- GLMessage_Function_glExtGetTexturesQCOM = 112,
- GLMessage_Function_glExtIsProgramBinaryQCOM = 113,
- GLMessage_Function_glExtTexObjectStateOverrideiQCOM = 114,
- GLMessage_Function_glFinishFenceNV = 115,
- GLMessage_Function_glFinish = 116,
- GLMessage_Function_glFlush = 117,
- GLMessage_Function_glFogf = 118,
- GLMessage_Function_glFogfv = 119,
- GLMessage_Function_glFogx = 120,
- GLMessage_Function_glFogxOES = 121,
- GLMessage_Function_glFogxv = 122,
- GLMessage_Function_glFogxvOES = 123,
- GLMessage_Function_glFramebufferRenderbuffer = 124,
- GLMessage_Function_glFramebufferRenderbufferOES = 125,
- GLMessage_Function_glFramebufferTexture2D = 126,
- GLMessage_Function_glFramebufferTexture2DMultisampleIMG = 127,
- GLMessage_Function_glFramebufferTexture2DOES = 128,
- GLMessage_Function_glFramebufferTexture3DOES = 129,
- GLMessage_Function_glFrontFace = 130,
- GLMessage_Function_glFrustumf = 131,
- GLMessage_Function_glFrustumfOES = 132,
- GLMessage_Function_glFrustumx = 133,
- GLMessage_Function_glFrustumxOES = 134,
- GLMessage_Function_glGenBuffers = 135,
- GLMessage_Function_glGenerateMipmap = 136,
- GLMessage_Function_glGenerateMipmapOES = 137,
- GLMessage_Function_glGenFencesNV = 138,
- GLMessage_Function_glGenFramebuffers = 139,
- GLMessage_Function_glGenFramebuffersOES = 140,
- GLMessage_Function_glGenPerfMonitorsAMD = 141,
- GLMessage_Function_glGenRenderbuffers = 142,
- GLMessage_Function_glGenRenderbuffersOES = 143,
- GLMessage_Function_glGenTextures = 144,
- GLMessage_Function_glGenVertexArraysOES = 145,
- GLMessage_Function_glGetActiveAttrib = 146,
- GLMessage_Function_glGetActiveUniform = 147,
- GLMessage_Function_glGetAttachedShaders = 148,
- GLMessage_Function_glGetAttribLocation = 149,
- GLMessage_Function_glGetBooleanv = 150,
- GLMessage_Function_glGetBufferParameteriv = 151,
- GLMessage_Function_glGetBufferPointervOES = 152,
- GLMessage_Function_glGetClipPlanef = 153,
- GLMessage_Function_glGetClipPlanefOES = 154,
- GLMessage_Function_glGetClipPlanex = 155,
- GLMessage_Function_glGetClipPlanexOES = 156,
- GLMessage_Function_glGetDriverControlsQCOM = 157,
- GLMessage_Function_glGetDriverControlStringQCOM = 158,
- GLMessage_Function_glGetError = 159,
- GLMessage_Function_glGetFenceivNV = 160,
- GLMessage_Function_glGetFixedv = 161,
- GLMessage_Function_glGetFixedvOES = 162,
- GLMessage_Function_glGetFloatv = 163,
- GLMessage_Function_glGetFramebufferAttachmentParameteriv = 164,
- GLMessage_Function_glGetFramebufferAttachmentParameterivOES = 165,
- GLMessage_Function_glGetIntegerv = 166,
- GLMessage_Function_glGetLightfv = 167,
- GLMessage_Function_glGetLightxv = 168,
- GLMessage_Function_glGetLightxvOES = 169,
- GLMessage_Function_glGetMaterialfv = 170,
- GLMessage_Function_glGetMaterialxv = 171,
- GLMessage_Function_glGetMaterialxvOES = 172,
- GLMessage_Function_glGetPerfMonitorCounterDataAMD = 173,
- GLMessage_Function_glGetPerfMonitorCounterInfoAMD = 174,
- GLMessage_Function_glGetPerfMonitorCountersAMD = 175,
- GLMessage_Function_glGetPerfMonitorCounterStringAMD = 176,
- GLMessage_Function_glGetPerfMonitorGroupsAMD = 177,
- GLMessage_Function_glGetPerfMonitorGroupStringAMD = 178,
- GLMessage_Function_glGetPointerv = 179,
- GLMessage_Function_glGetProgramBinaryOES = 180,
- GLMessage_Function_glGetProgramInfoLog = 181,
- GLMessage_Function_glGetProgramiv = 182,
- GLMessage_Function_glGetRenderbufferParameteriv = 183,
- GLMessage_Function_glGetRenderbufferParameterivOES = 184,
- GLMessage_Function_glGetShaderInfoLog = 185,
- GLMessage_Function_glGetShaderiv = 186,
- GLMessage_Function_glGetShaderPrecisionFormat = 187,
- GLMessage_Function_glGetShaderSource = 188,
- GLMessage_Function_glGetString = 189,
- GLMessage_Function_glGetTexEnvfv = 190,
- GLMessage_Function_glGetTexEnviv = 191,
- GLMessage_Function_glGetTexEnvxv = 192,
- GLMessage_Function_glGetTexEnvxvOES = 193,
- GLMessage_Function_glGetTexGenfvOES = 194,
- GLMessage_Function_glGetTexGenivOES = 195,
- GLMessage_Function_glGetTexGenxvOES = 196,
- GLMessage_Function_glGetTexParameterfv = 197,
- GLMessage_Function_glGetTexParameteriv = 198,
- GLMessage_Function_glGetTexParameterxv = 199,
- GLMessage_Function_glGetTexParameterxvOES = 200,
- GLMessage_Function_glGetUniformfv = 201,
- GLMessage_Function_glGetUniformiv = 202,
- GLMessage_Function_glGetUniformLocation = 203,
- GLMessage_Function_glGetVertexAttribfv = 204,
- GLMessage_Function_glGetVertexAttribiv = 205,
- GLMessage_Function_glGetVertexAttribPointerv = 206,
- GLMessage_Function_glHint = 207,
- GLMessage_Function_glIsBuffer = 208,
- GLMessage_Function_glIsEnabled = 209,
- GLMessage_Function_glIsFenceNV = 210,
- GLMessage_Function_glIsFramebuffer = 211,
- GLMessage_Function_glIsFramebufferOES = 212,
- GLMessage_Function_glIsProgram = 213,
- GLMessage_Function_glIsRenderbuffer = 214,
- GLMessage_Function_glIsRenderbufferOES = 215,
- GLMessage_Function_glIsShader = 216,
- GLMessage_Function_glIsTexture = 217,
- GLMessage_Function_glIsVertexArrayOES = 218,
- GLMessage_Function_glLightf = 219,
- GLMessage_Function_glLightfv = 220,
- GLMessage_Function_glLightModelf = 221,
- GLMessage_Function_glLightModelfv = 222,
- GLMessage_Function_glLightModelx = 223,
- GLMessage_Function_glLightModelxOES = 224,
- GLMessage_Function_glLightModelxv = 225,
- GLMessage_Function_glLightModelxvOES = 226,
- GLMessage_Function_glLightx = 227,
- GLMessage_Function_glLightxOES = 228,
- GLMessage_Function_glLightxv = 229,
- GLMessage_Function_glLightxvOES = 230,
- GLMessage_Function_glLineWidth = 231,
- GLMessage_Function_glLineWidthx = 232,
- GLMessage_Function_glLineWidthxOES = 233,
- GLMessage_Function_glLinkProgram = 234,
- GLMessage_Function_glLoadIdentity = 235,
- GLMessage_Function_glLoadMatrixf = 236,
- GLMessage_Function_glLoadMatrixx = 237,
- GLMessage_Function_glLoadMatrixxOES = 238,
- GLMessage_Function_glLoadPaletteFromModelViewMatrixOES = 239,
- GLMessage_Function_glLogicOp = 240,
- GLMessage_Function_glMapBufferOES = 241,
- GLMessage_Function_glMaterialf = 242,
- GLMessage_Function_glMaterialfv = 243,
- GLMessage_Function_glMaterialx = 244,
- GLMessage_Function_glMaterialxOES = 245,
- GLMessage_Function_glMaterialxv = 246,
- GLMessage_Function_glMaterialxvOES = 247,
- GLMessage_Function_glMatrixIndexPointerOES = 248,
- GLMessage_Function_glMatrixMode = 249,
- GLMessage_Function_glMultiDrawArraysEXT = 250,
- GLMessage_Function_glMultiDrawElementsEXT = 251,
- GLMessage_Function_glMultiTexCoord4f = 252,
- GLMessage_Function_glMultiTexCoord4x = 253,
- GLMessage_Function_glMultiTexCoord4xOES = 254,
- GLMessage_Function_glMultMatrixf = 255,
- GLMessage_Function_glMultMatrixx = 256,
- GLMessage_Function_glMultMatrixxOES = 257,
- GLMessage_Function_glNormal3f = 258,
- GLMessage_Function_glNormal3x = 259,
- GLMessage_Function_glNormal3xOES = 260,
- GLMessage_Function_glNormalPointer = 261,
- GLMessage_Function_glOrthof = 262,
- GLMessage_Function_glOrthofOES = 263,
- GLMessage_Function_glOrthox = 264,
- GLMessage_Function_glOrthoxOES = 265,
- GLMessage_Function_glPixelStorei = 266,
- GLMessage_Function_glPointParameterf = 267,
- GLMessage_Function_glPointParameterfv = 268,
- GLMessage_Function_glPointParameterx = 269,
- GLMessage_Function_glPointParameterxOES = 270,
- GLMessage_Function_glPointParameterxv = 271,
- GLMessage_Function_glPointParameterxvOES = 272,
- GLMessage_Function_glPointSize = 273,
- GLMessage_Function_glPointSizePointerOES = 274,
- GLMessage_Function_glPointSizex = 275,
- GLMessage_Function_glPointSizexOES = 276,
- GLMessage_Function_glPolygonOffset = 277,
- GLMessage_Function_glPolygonOffsetx = 278,
- GLMessage_Function_glPolygonOffsetxOES = 279,
- GLMessage_Function_glPopMatrix = 280,
- GLMessage_Function_glProgramBinaryOES = 281,
- GLMessage_Function_glPushMatrix = 282,
- GLMessage_Function_glQueryMatrixxOES = 283,
- GLMessage_Function_glReadPixels = 284,
- GLMessage_Function_glReleaseShaderCompiler = 285,
- GLMessage_Function_glRenderbufferStorage = 286,
- GLMessage_Function_glRenderbufferStorageMultisampleIMG = 287,
- GLMessage_Function_glRenderbufferStorageOES = 288,
- GLMessage_Function_glRotatef = 289,
- GLMessage_Function_glRotatex = 290,
- GLMessage_Function_glRotatexOES = 291,
- GLMessage_Function_glSampleCoverage = 292,
- GLMessage_Function_glSampleCoveragex = 293,
- GLMessage_Function_glSampleCoveragexOES = 294,
- GLMessage_Function_glScalef = 295,
- GLMessage_Function_glScalex = 296,
- GLMessage_Function_glScalexOES = 297,
- GLMessage_Function_glScissor = 298,
- GLMessage_Function_glSelectPerfMonitorCountersAMD = 299,
- GLMessage_Function_glSetFenceNV = 300,
- GLMessage_Function_glShadeModel = 301,
- GLMessage_Function_glShaderBinary = 302,
- GLMessage_Function_glShaderSource = 303,
- GLMessage_Function_glStartTilingQCOM = 304,
- GLMessage_Function_glStencilFunc = 305,
- GLMessage_Function_glStencilFuncSeparate = 306,
- GLMessage_Function_glStencilMask = 307,
- GLMessage_Function_glStencilMaskSeparate = 308,
- GLMessage_Function_glStencilOp = 309,
- GLMessage_Function_glStencilOpSeparate = 310,
- GLMessage_Function_glTestFenceNV = 311,
- GLMessage_Function_glTexCoordPointer = 312,
- GLMessage_Function_glTexEnvf = 313,
- GLMessage_Function_glTexEnvfv = 314,
- GLMessage_Function_glTexEnvi = 315,
- GLMessage_Function_glTexEnviv = 316,
- GLMessage_Function_glTexEnvx = 317,
- GLMessage_Function_glTexEnvxOES = 318,
- GLMessage_Function_glTexEnvxv = 319,
- GLMessage_Function_glTexEnvxvOES = 320,
- GLMessage_Function_glTexGenfOES = 321,
- GLMessage_Function_glTexGenfvOES = 322,
- GLMessage_Function_glTexGeniOES = 323,
- GLMessage_Function_glTexGenivOES = 324,
- GLMessage_Function_glTexGenxOES = 325,
- GLMessage_Function_glTexGenxvOES = 326,
- GLMessage_Function_glTexImage2D = 327,
- GLMessage_Function_glTexImage3DOES = 328,
- GLMessage_Function_glTexParameterf = 329,
- GLMessage_Function_glTexParameterfv = 330,
- GLMessage_Function_glTexParameteri = 331,
- GLMessage_Function_glTexParameteriv = 332,
- GLMessage_Function_glTexParameterx = 333,
- GLMessage_Function_glTexParameterxOES = 334,
- GLMessage_Function_glTexParameterxv = 335,
- GLMessage_Function_glTexParameterxvOES = 336,
- GLMessage_Function_glTexSubImage2D = 337,
- GLMessage_Function_glTexSubImage3DOES = 338,
- GLMessage_Function_glTranslatef = 339,
- GLMessage_Function_glTranslatex = 340,
- GLMessage_Function_glTranslatexOES = 341,
- GLMessage_Function_glUniform1f = 342,
- GLMessage_Function_glUniform1fv = 343,
- GLMessage_Function_glUniform1i = 344,
- GLMessage_Function_glUniform1iv = 345,
- GLMessage_Function_glUniform2f = 346,
- GLMessage_Function_glUniform2fv = 347,
- GLMessage_Function_glUniform2i = 348,
- GLMessage_Function_glUniform2iv = 349,
- GLMessage_Function_glUniform3f = 350,
- GLMessage_Function_glUniform3fv = 351,
- GLMessage_Function_glUniform3i = 352,
- GLMessage_Function_glUniform3iv = 353,
- GLMessage_Function_glUniform4f = 354,
- GLMessage_Function_glUniform4fv = 355,
- GLMessage_Function_glUniform4i = 356,
- GLMessage_Function_glUniform4iv = 357,
- GLMessage_Function_glUniformMatrix2fv = 358,
- GLMessage_Function_glUniformMatrix3fv = 359,
- GLMessage_Function_glUniformMatrix4fv = 360,
- GLMessage_Function_glUnmapBufferOES = 361,
- GLMessage_Function_glUseProgram = 362,
- GLMessage_Function_glValidateProgram = 363,
- GLMessage_Function_glVertexAttrib1f = 364,
- GLMessage_Function_glVertexAttrib1fv = 365,
- GLMessage_Function_glVertexAttrib2f = 366,
- GLMessage_Function_glVertexAttrib2fv = 367,
- GLMessage_Function_glVertexAttrib3f = 368,
- GLMessage_Function_glVertexAttrib3fv = 369,
- GLMessage_Function_glVertexAttrib4f = 370,
- GLMessage_Function_glVertexAttrib4fv = 371,
- GLMessage_Function_glVertexAttribPointer = 372,
- GLMessage_Function_glVertexPointer = 373,
- GLMessage_Function_glViewport = 374,
- GLMessage_Function_glWeightPointerOES = 375,
- GLMessage_Function_glReadBuffer = 376,
- GLMessage_Function_glDrawRangeElements = 377,
- GLMessage_Function_glTexImage3D = 378,
- GLMessage_Function_glTexSubImage3D = 379,
- GLMessage_Function_glCopyTexSubImage3D = 380,
- GLMessage_Function_glCompressedTexImage3D = 381,
- GLMessage_Function_glCompressedTexSubImage3D = 382,
- GLMessage_Function_glGenQueries = 383,
- GLMessage_Function_glDeleteQueries = 384,
- GLMessage_Function_glIsQuery = 385,
- GLMessage_Function_glBeginQuery = 386,
- GLMessage_Function_glEndQuery = 387,
- GLMessage_Function_glGetQueryiv = 388,
- GLMessage_Function_glGetQueryObjectuiv = 389,
- GLMessage_Function_glUnmapBuffer = 390,
- GLMessage_Function_glGetBufferPointerv = 391,
- GLMessage_Function_glDrawBuffers = 392,
- GLMessage_Function_glUniformMatrix2x3fv = 393,
- GLMessage_Function_glUniformMatrix3x2fv = 394,
- GLMessage_Function_glUniformMatrix2x4fv = 395,
- GLMessage_Function_glUniformMatrix4x2fv = 396,
- GLMessage_Function_glUniformMatrix3x4fv = 397,
- GLMessage_Function_glUniformMatrix4x3fv = 398,
- GLMessage_Function_glBlitFramebuffer = 399,
- GLMessage_Function_glRenderbufferStorageMultisample = 400,
- GLMessage_Function_glFramebufferTextureLayer = 401,
- GLMessage_Function_glMapBufferRange = 402,
- GLMessage_Function_glFlushMappedBufferRange = 403,
- GLMessage_Function_glBindVertexArray = 404,
- GLMessage_Function_glDeleteVertexArrays = 405,
- GLMessage_Function_glGenVertexArrays = 406,
- GLMessage_Function_glIsVertexArray = 407,
- GLMessage_Function_glGetIntegeri_v = 408,
- GLMessage_Function_glBeginTransformFeedback = 409,
- GLMessage_Function_glEndTransformFeedback = 410,
- GLMessage_Function_glBindBufferRange = 411,
- GLMessage_Function_glBindBufferBase = 412,
- GLMessage_Function_glTransformFeedbackVaryings = 413,
- GLMessage_Function_glGetTransformFeedbackVarying = 414,
- GLMessage_Function_glVertexAttribIPointer = 415,
- GLMessage_Function_glGetVertexAttribIiv = 416,
- GLMessage_Function_glGetVertexAttribIuiv = 417,
- GLMessage_Function_glVertexAttribI4i = 418,
- GLMessage_Function_glVertexAttribI4ui = 419,
- GLMessage_Function_glVertexAttribI4iv = 420,
- GLMessage_Function_glVertexAttribI4uiv = 421,
- GLMessage_Function_glGetUniformuiv = 422,
- GLMessage_Function_glGetFragDataLocation = 423,
- GLMessage_Function_glUniform1ui = 424,
- GLMessage_Function_glUniform2ui = 425,
- GLMessage_Function_glUniform3ui = 426,
- GLMessage_Function_glUniform4ui = 427,
- GLMessage_Function_glUniform1uiv = 428,
- GLMessage_Function_glUniform2uiv = 429,
- GLMessage_Function_glUniform3uiv = 430,
- GLMessage_Function_glUniform4uiv = 431,
- GLMessage_Function_glClearBufferiv = 432,
- GLMessage_Function_glClearBufferuiv = 433,
- GLMessage_Function_glClearBufferfv = 434,
- GLMessage_Function_glClearBufferfi = 435,
- GLMessage_Function_glGetStringi = 436,
- GLMessage_Function_glCopyBufferSubData = 437,
- GLMessage_Function_glGetUniformIndices = 438,
- GLMessage_Function_glGetActiveUniformsiv = 439,
- GLMessage_Function_glGetUniformBlockIndex = 440,
- GLMessage_Function_glGetActiveUniformBlockiv = 441,
- GLMessage_Function_glGetActiveUniformBlockName = 442,
- GLMessage_Function_glUniformBlockBinding = 443,
- GLMessage_Function_glDrawArraysInstanced = 444,
- GLMessage_Function_glDrawElementsInstanced = 445,
- GLMessage_Function_glFenceSync = 446,
- GLMessage_Function_glIsSync = 447,
- GLMessage_Function_glDeleteSync = 448,
- GLMessage_Function_glClientWaitSync = 449,
- GLMessage_Function_glWaitSync = 450,
- GLMessage_Function_glGetInteger64v = 451,
- GLMessage_Function_glGetSynciv = 452,
- GLMessage_Function_glGetInteger64i_v = 453,
- GLMessage_Function_glGetBufferParameteri64v = 454,
- GLMessage_Function_glGenSamplers = 455,
- GLMessage_Function_glDeleteSamplers = 456,
- GLMessage_Function_glIsSampler = 457,
- GLMessage_Function_glBindSampler = 458,
- GLMessage_Function_glSamplerParameteri = 459,
- GLMessage_Function_glSamplerParameteriv = 460,
- GLMessage_Function_glSamplerParameterf = 461,
- GLMessage_Function_glSamplerParameterfv = 462,
- GLMessage_Function_glGetSamplerParameteriv = 463,
- GLMessage_Function_glGetSamplerParameterfv = 464,
- GLMessage_Function_glVertexAttribDivisor = 465,
- GLMessage_Function_glBindTransformFeedback = 466,
- GLMessage_Function_glDeleteTransformFeedbacks = 467,
- GLMessage_Function_glGenTransformFeedbacks = 468,
- GLMessage_Function_glIsTransformFeedback = 469,
- GLMessage_Function_glPauseTransformFeedback = 470,
- GLMessage_Function_glResumeTransformFeedback = 471,
- GLMessage_Function_glGetProgramBinary = 472,
- GLMessage_Function_glProgramBinary = 473,
- GLMessage_Function_glProgramParameteri = 474,
- GLMessage_Function_glInvalidateFramebuffer = 475,
- GLMessage_Function_glInvalidateSubFramebuffer = 476,
- GLMessage_Function_glTexStorage2D = 477,
- GLMessage_Function_glTexStorage3D = 478,
- GLMessage_Function_glGetInternalformativ = 479,
- GLMessage_Function_glBeginPerfQueryINTEL = 480,
- GLMessage_Function_glCreatePerfQueryINTEL = 481,
- GLMessage_Function_glDeletePerfQueryINTEL = 482,
- GLMessage_Function_glEndPerfQueryINTEL = 483,
- GLMessage_Function_glGetFirstPerfQueryIdINTEL = 484,
- GLMessage_Function_glGetNextPerfQueryIdINTEL = 485,
- GLMessage_Function_glGetPerfCounterInfoINTEL = 486,
- GLMessage_Function_glGetPerfQueryDataINTEL = 487,
- GLMessage_Function_glGetPerfQueryIdByNameINTEL = 488,
- GLMessage_Function_glGetPerfQueryInfoINTEL = 489,
- GLMessage_Function_glBlendBarrierKHR = 490,
- GLMessage_Function_glBlendBarrierNV = 491,
- GLMessage_Function_glBlendParameteriNV = 492,
- GLMessage_Function_glBlitFramebufferNV = 493,
- GLMessage_Function_glFenceSyncAPPLE = 494,
- GLMessage_Function_glIsSyncAPPLE = 495,
- GLMessage_Function_glDeleteSyncAPPLE = 496,
- GLMessage_Function_glClientWaitSyncAPPLE = 497,
- GLMessage_Function_glWaitSyncAPPLE = 498,
- GLMessage_Function_glGetInteger64vAPPLE = 499,
- GLMessage_Function_glGetSyncivAPPLE = 500,
- GLMessage_Function_glCopyBufferSubDataNV = 501,
- GLMessage_Function_glActiveShaderProgramEXT = 502,
- GLMessage_Function_glAlphaFuncQCOM = 503,
- GLMessage_Function_glBeginQueryEXT = 504,
- GLMessage_Function_glBindProgramPipelineEXT = 505,
- GLMessage_Function_glBlitFramebufferANGLE = 506,
- GLMessage_Function_glCreateShaderProgramvEXT = 507,
- GLMessage_Function_glDeleteProgramPipelinesEXT = 508,
- GLMessage_Function_glDeleteQueriesEXT = 509,
- GLMessage_Function_glDrawBuffersNV = 510,
- GLMessage_Function_glEndQueryEXT = 511,
- GLMessage_Function_glFramebufferTexture2DMultisampleEXT = 512,
- GLMessage_Function_glGenProgramPipelinesEXT = 513,
- GLMessage_Function_glGenQueriesEXT = 514,
- GLMessage_Function_glGetGraphicsResetStatusEXT = 515,
- GLMessage_Function_glGetObjectLabelEXT = 516,
- GLMessage_Function_glGetProgramPipelineInfoLogEXT = 517,
- GLMessage_Function_glGetProgramPipelineivEXT = 518,
- GLMessage_Function_glGetQueryObjectuivEXT = 519,
- GLMessage_Function_glGetQueryivEXT = 520,
- GLMessage_Function_glGetnUniformfvEXT = 521,
- GLMessage_Function_glGetnUniformivEXT = 521,
- GLMessage_Function_glInsertEventMarkerEXT = 522,
- GLMessage_Function_glIsProgramPipelineEXT = 523,
- GLMessage_Function_glIsQueryEXT = 524,
- GLMessage_Function_glLabelObjectEXT = 525,
- GLMessage_Function_glPopGroupMarkerEXT = 526,
- GLMessage_Function_glProgramParameteriEXT = 527,
- GLMessage_Function_glProgramUniform1fEXT = 528,
- GLMessage_Function_glProgramUniform1fvEXT = 529,
- GLMessage_Function_glProgramUniform1iEXT = 530,
- GLMessage_Function_glProgramUniform1ivEXT = 531,
- GLMessage_Function_glProgramUniform2fEXT = 532,
- GLMessage_Function_glProgramUniform2fvEXT = 533,
- GLMessage_Function_glProgramUniform2iEXT = 534,
- GLMessage_Function_glProgramUniform2ivEXT = 535,
- GLMessage_Function_glProgramUniform3fEXT = 536,
- GLMessage_Function_glProgramUniform3fvEXT = 537,
- GLMessage_Function_glProgramUniform3iEXT = 538,
- GLMessage_Function_glProgramUniform3ivEXT = 539,
- GLMessage_Function_glProgramUniform4fEXT = 540,
- GLMessage_Function_glProgramUniform4fvEXT = 541,
- GLMessage_Function_glProgramUniform4iEXT = 542,
- GLMessage_Function_glProgramUniform4ivEXT = 543,
- GLMessage_Function_glProgramUniformMatrix2fvEXT = 544,
- GLMessage_Function_glProgramUniformMatrix3fvEXT = 545,
- GLMessage_Function_glProgramUniformMatrix4fvEXT = 546,
- GLMessage_Function_glPushGroupMarkerEXT = 547,
- GLMessage_Function_glReadBufferNV = 548,
- GLMessage_Function_glReadnPixelsEXT = 549,
- GLMessage_Function_glRenderbufferStorageMultisampleANGLE = 550,
- GLMessage_Function_glRenderbufferStorageMultisampleAPPLE = 551,
- GLMessage_Function_glRenderbufferStorageMultisampleEXT = 552,
- GLMessage_Function_glResolveMultisampleFramebufferAPPLE = 553,
- GLMessage_Function_glTexStorage1DEXT = 554,
- GLMessage_Function_glTexStorage2DEXT = 555,
- GLMessage_Function_glTexStorage3DEXT = 556,
- GLMessage_Function_glTextureStorage1DEXT = 557,
- GLMessage_Function_glTextureStorage2DEXT = 558,
- GLMessage_Function_glTextureStorage3DEXT = 559,
- GLMessage_Function_glUseProgramStagesEXT = 560,
- GLMessage_Function_glValidateProgramPipelineEXT = 561,
- GLMessage_Function_glCopyTextureLevelsAPPLE = 562,
- GLMessage_Function_glDebugMessageControlKHR = 563,
- GLMessage_Function_glDebugMessageInsertKHR = 564,
- GLMessage_Function_glDebugMessageCallbackKHR = 565,
- GLMessage_Function_glGetDebugMessageLogKHR = 566,
- GLMessage_Function_glPushDebugGroupKHR = 567,
- GLMessage_Function_glPopDebugGroupKHR = 568,
- GLMessage_Function_glObjectLabelKHR = 569,
- GLMessage_Function_glGetObjectLabelKHR = 570,
- GLMessage_Function_glObjectPtrLabelKHR = 571,
- GLMessage_Function_glGetObjectPtrLabelKHR = 572,
- GLMessage_Function_glGetPointervKHR = 573,
- GLMessage_Function_glDrawArraysInstancedANGLE = 574,
- GLMessage_Function_glDrawElementsInstancedANGLE = 575,
- GLMessage_Function_glVertexAttribDivisorANGLE = 576,
- GLMessage_Function_glDrawArraysInstancedEXT = 577,
- GLMessage_Function_glDrawElementsInstancedEXT = 578,
- GLMessage_Function_glVertexAttribDivisorEXT = 579,
- GLMessage_Function_glDrawArraysInstancedNV = 580,
- GLMessage_Function_glDrawElementsInstancedNV = 581,
- GLMessage_Function_glVertexAttribDivisorNV = 582,
- GLMessage_Function_glDrawBuffersEXT = 583,
- GLMessage_Function_glReadBufferIndexedEXT = 584,
- GLMessage_Function_glDrawBuffersIndexedEXT = 585,
- GLMessage_Function_glGetIntegeri_vEXT = 586,
- GLMessage_Function_glMapBufferRangeEXT = 587,
- GLMessage_Function_glFlushMappedBufferRangeEXT = 588,
- GLMessage_Function_glQueryCounterEXT = 589,
- GLMessage_Function_glGetQueryObjecti64vEXT = 590,
- GLMessage_Function_glGetQueryObjectivEXT = 591,
- GLMessage_Function_glGetQueryObjectui64vEXT = 592,
- GLMessage_Function_glGetTranslatedShaderSourceANGLE = 593,
- GLMessage_Function_glMinSampleShadingOES = 594,
- GLMessage_Function_glMultiTexCoord1bOES = 595,
- GLMessage_Function_glMultiTexCoord1bvOES = 596,
- GLMessage_Function_glMultiTexCoord2bOES = 597,
- GLMessage_Function_glMultiTexCoord2bvOES = 598,
- GLMessage_Function_glMultiTexCoord3bOES = 599,
- GLMessage_Function_glMultiTexCoord3bvOES = 600,
- GLMessage_Function_glMultiTexCoord4bOES = 601,
- GLMessage_Function_glMultiTexCoord4bvOES = 602,
- GLMessage_Function_glTexCoord1bOES = 603,
- GLMessage_Function_glTexCoord1bvOES = 604,
- GLMessage_Function_glTexCoord2bOES = 605,
- GLMessage_Function_glTexCoord2bvOES = 606,
- GLMessage_Function_glTexCoord3bOES = 607,
- GLMessage_Function_glTexCoord3bvOES = 608,
- GLMessage_Function_glTexCoord4bOES = 609,
- GLMessage_Function_glTexCoord4bvOES = 610,
- GLMessage_Function_glVertex2bOES = 611,
- GLMessage_Function_glVertex2bvOES = 612,
- GLMessage_Function_glVertex3bOES = 613,
- GLMessage_Function_glVertex3bvOES = 614,
- GLMessage_Function_glVertex4bOES = 615,
- GLMessage_Function_glVertex4bvOES = 616,
- GLMessage_Function_glProgramUniform1uiEXT = 617,
- GLMessage_Function_glProgramUniform2uiEXT = 618,
- GLMessage_Function_glProgramUniform3uiEXT = 619,
- GLMessage_Function_glProgramUniform4uiEXT = 620,
- GLMessage_Function_glProgramUniform1uivEXT = 621,
- GLMessage_Function_glProgramUniform2uivEXT = 622,
- GLMessage_Function_glProgramUniform3uivEXT = 623,
- GLMessage_Function_glProgramUniform4uivEXT = 624,
- GLMessage_Function_glProgramUniformMatrix2x3fvEXT = 625,
- GLMessage_Function_glProgramUniformMatrix3x2fvEXT = 626,
- GLMessage_Function_glProgramUniformMatrix2x4fvEXT = 627,
- GLMessage_Function_glProgramUniformMatrix4x2fvEXT = 628,
- GLMessage_Function_glProgramUniformMatrix3x4fvEXT = 629,
- GLMessage_Function_glProgramUniformMatrix4x3fvEXT = 630,
- GLMessage_Function_glRenderbufferStorageMultisampleNV = 631,
- GLMessage_Function_glSampleCoverageOES = 632,
- GLMessage_Function_glTexStorage3DMultisampleOES = 633,
- GLMessage_Function_glUniformMatrix2x3fvNV = 634,
- GLMessage_Function_glUniformMatrix3x2fvNV = 635,
- GLMessage_Function_glUniformMatrix2x4fvNV = 636,
- GLMessage_Function_glUniformMatrix4x2fvNV = 637,
- GLMessage_Function_glUniformMatrix3x4fvNV = 638,
- GLMessage_Function_glUniformMatrix4x3fvNV = 639,
- GLMessage_Function_glActiveShaderProgram = 640,
- GLMessage_Function_glBindImageTexture = 641,
- GLMessage_Function_glBindProgramPipeline = 642,
- GLMessage_Function_glBindVertexBuffer = 643,
- GLMessage_Function_glCreateShaderProgramv = 644,
- GLMessage_Function_glDeleteProgramPipelines = 645,
- GLMessage_Function_glDispatchCompute = 646,
- GLMessage_Function_glDispatchComputeIndirect = 647,
- GLMessage_Function_glDrawArraysIndirect = 648,
- GLMessage_Function_glDrawElementsIndirect = 649,
- GLMessage_Function_glFramebufferParameteri = 650,
- GLMessage_Function_glGenProgramPipelines = 651,
- GLMessage_Function_glGetBooleani_v = 652,
- GLMessage_Function_glGetFramebufferParameteriv = 653,
- GLMessage_Function_glGetMultisamplefv = 654,
- GLMessage_Function_glGetProgramInterfaceiv = 655,
- GLMessage_Function_glGetProgramPipelineInfoLog = 656,
- GLMessage_Function_glGetProgramPipelineiv = 657,
- GLMessage_Function_glGetProgramResourceIndex = 658,
- GLMessage_Function_glGetProgramResourceLocation = 659,
- GLMessage_Function_glGetProgramResourceName = 660,
- GLMessage_Function_glGetProgramResourceiv = 661,
- GLMessage_Function_glGetTexLevelParameterfv = 662,
- GLMessage_Function_glGetTexLevelParameteriv = 663,
- GLMessage_Function_glIsProgramPipeline = 664,
- GLMessage_Function_glMemoryBarrier = 665,
- GLMessage_Function_glMemoryBarrierByRegion = 666,
- GLMessage_Function_glProgramUniform1f = 667,
- GLMessage_Function_glProgramUniform1fv = 668,
- GLMessage_Function_glProgramUniform1i = 669,
- GLMessage_Function_glProgramUniform1iv = 670,
- GLMessage_Function_glProgramUniform1ui = 671,
- GLMessage_Function_glProgramUniform1uiv = 672,
- GLMessage_Function_glProgramUniform2f = 673,
- GLMessage_Function_glProgramUniform2fv = 674,
- GLMessage_Function_glProgramUniform2i = 675,
- GLMessage_Function_glProgramUniform2iv = 676,
- GLMessage_Function_glProgramUniform2ui = 677,
- GLMessage_Function_glProgramUniform2uiv = 678,
- GLMessage_Function_glProgramUniform3f = 679,
- GLMessage_Function_glProgramUniform3fv = 680,
- GLMessage_Function_glProgramUniform3i = 681,
- GLMessage_Function_glProgramUniform3iv = 682,
- GLMessage_Function_glProgramUniform3ui = 683,
- GLMessage_Function_glProgramUniform3uiv = 684,
- GLMessage_Function_glProgramUniform4f = 685,
- GLMessage_Function_glProgramUniform4fv = 686,
- GLMessage_Function_glProgramUniform4i = 687,
- GLMessage_Function_glProgramUniform4iv = 688,
- GLMessage_Function_glProgramUniform4ui = 689,
- GLMessage_Function_glProgramUniform4uiv = 690,
- GLMessage_Function_glProgramUniformMatrix2fv = 691,
- GLMessage_Function_glProgramUniformMatrix2x3fv = 692,
- GLMessage_Function_glProgramUniformMatrix2x4fv = 693,
- GLMessage_Function_glProgramUniformMatrix3fv = 694,
- GLMessage_Function_glProgramUniformMatrix3x2fv = 695,
- GLMessage_Function_glProgramUniformMatrix3x4fv = 696,
- GLMessage_Function_glProgramUniformMatrix4fv = 697,
- GLMessage_Function_glProgramUniformMatrix4x2fv = 698,
- GLMessage_Function_glProgramUniformMatrix4x3fv = 699,
- GLMessage_Function_glSampleMaski = 700,
- GLMessage_Function_glTexStorage2DMultisample = 701,
- GLMessage_Function_glUseProgramStages = 702,
- GLMessage_Function_glValidateProgramPipeline = 703,
- GLMessage_Function_glVertexAttribBinding = 704,
- GLMessage_Function_glVertexAttribFormat = 705,
- GLMessage_Function_glVertexAttribIFormat = 706,
- GLMessage_Function_glVertexBindingDivisor = 707,
- GLMessage_Function_glBlendEquationSeparateiEXT = 708,
- GLMessage_Function_glBlendEquationiEXT = 709,
- GLMessage_Function_glBlendFuncSeparateiEXT = 710,
- GLMessage_Function_glBlendFunciEXT = 711,
- GLMessage_Function_glColorMaskiEXT = 712,
- GLMessage_Function_glCopyImageSubDataEXT = 713,
- GLMessage_Function_glDisableiEXT = 714,
- GLMessage_Function_glEnableiEXT = 715,
- GLMessage_Function_glFramebufferTextureEXT = 716,
- GLMessage_Function_glGetSamplerParameterIivEXT = 717,
- GLMessage_Function_glGetSamplerParameterIuivEXT = 718,
- GLMessage_Function_glGetTexParameterIivEXT = 719,
- GLMessage_Function_glGetTexParameterIuivEXT = 720,
- GLMessage_Function_glIsEnablediEXT = 721,
- GLMessage_Function_glPatchParameteriEXT = 722,
- GLMessage_Function_glPrimitiveBoundingBoxEXT = 723,
- GLMessage_Function_glSamplerParameterIivEXT = 724,
- GLMessage_Function_glSamplerParameterIuivEXT = 725,
- GLMessage_Function_glTexBufferEXT = 726,
- GLMessage_Function_glTexBufferRangeEXT = 727,
- GLMessage_Function_glTexParameterIivEXT = 728,
- GLMessage_Function_glTexParameterIuivEXT = 729,
- GLMessage_Function_glTextureViewEXT = 730,
- GLMessage_Function_eglGetDisplay = 2000,
- GLMessage_Function_eglInitialize = 2001,
- GLMessage_Function_eglTerminate = 2002,
- GLMessage_Function_eglGetConfigs = 2003,
- GLMessage_Function_eglChooseConfig = 2004,
- GLMessage_Function_eglGetConfigAttrib = 2005,
- GLMessage_Function_eglCreateWindowSurface = 2006,
- GLMessage_Function_eglCreatePixmapSurface = 2007,
- GLMessage_Function_eglCreatePbufferSurface = 2008,
- GLMessage_Function_eglDestroySurface = 2009,
- GLMessage_Function_eglQuerySurface = 2010,
- GLMessage_Function_eglCreateContext = 2011,
- GLMessage_Function_eglDestroyContext = 2012,
- GLMessage_Function_eglMakeCurrent = 2013,
- GLMessage_Function_eglGetCurrentContext = 2014,
- GLMessage_Function_eglGetCurrentSurface = 2015,
- GLMessage_Function_eglGetCurrentDisplay = 2016,
- GLMessage_Function_eglQueryContext = 2017,
- GLMessage_Function_eglWaitGL = 2018,
- GLMessage_Function_eglWaitNative = 2019,
- GLMessage_Function_eglSwapBuffers = 2020,
- GLMessage_Function_eglCopyBuffers = 2021,
- GLMessage_Function_eglGetError = 2022,
- GLMessage_Function_eglQueryString = 2023,
- GLMessage_Function_eglGetProcAddress = 2024,
- GLMessage_Function_eglSurfaceAttrib = 2025,
- GLMessage_Function_eglBindTexImage = 2026,
- GLMessage_Function_eglReleaseTexImage = 2027,
- GLMessage_Function_eglSwapInterval = 2028,
- GLMessage_Function_eglBindAPI = 2029,
- GLMessage_Function_eglQueryAPI = 2030,
- GLMessage_Function_eglWaitClient = 2031,
- GLMessage_Function_eglReleaseThread = 2032,
- GLMessage_Function_eglCreatePbufferFromClientBuffer = 2033,
- GLMessage_Function_eglLockSurfaceKHR = 2034,
- GLMessage_Function_eglUnlockSurfaceKHR = 2035,
- GLMessage_Function_eglCreateImageKHR = 2036,
- GLMessage_Function_eglDestroyImageKHR = 2037,
- GLMessage_Function_eglCreateSyncKHR = 2038,
- GLMessage_Function_eglDestroySyncKHR = 2039,
- GLMessage_Function_eglClientWaitSyncKHR = 2040,
- GLMessage_Function_eglGetSyncAttribKHR = 2041,
- GLMessage_Function_eglSetSwapRectangleANDROID = 2042,
- GLMessage_Function_eglGetRenderBufferANDROID = 2043,
- GLMessage_Function_eglGetSystemTimeFrequencyNV = 2044,
- GLMessage_Function_eglGetSystemTimeNV = 2045,
- GLMessage_Function_invalid = 3000,
- GLMessage_Function_glVertexAttribPointerData = 3001
-};
-bool GLMessage_Function_IsValid(int value);
-const GLMessage_Function GLMessage_Function_Function_MIN = GLMessage_Function_glActiveTexture;
-const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_glVertexAttribPointerData;
-const int GLMessage_Function_Function_ARRAYSIZE = GLMessage_Function_Function_MAX + 1;
-
-// ===================================================================
-
-class GLMessage_DataType : public ::google::protobuf::MessageLite {
- public:
- GLMessage_DataType();
- virtual ~GLMessage_DataType();
-
- GLMessage_DataType(const GLMessage_DataType& from);
-
- inline GLMessage_DataType& operator=(const GLMessage_DataType& from) {
- CopyFrom(from);
- return *this;
- }
-
- static const GLMessage_DataType& default_instance();
-
- void Swap(GLMessage_DataType* other);
-
- // implements Message ----------------------------------------------
-
- GLMessage_DataType* New() const;
- void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
- void CopyFrom(const GLMessage_DataType& from);
- void MergeFrom(const GLMessage_DataType& from);
- void Clear();
- bool IsInitialized() const;
-
- int ByteSize() const;
- bool MergePartialFromCodedStream(
- ::google::protobuf::io::CodedInputStream* input);
- void SerializeWithCachedSizes(
- ::google::protobuf::io::CodedOutputStream* output) const;
- int GetCachedSize() const { return _cached_size_; }
- private:
- void SharedCtor();
- void SharedDtor();
- void SetCachedSize(int size) const;
- public:
-
- ::std::string GetTypeName() const;
-
- // nested types ----------------------------------------------------
-
- typedef GLMessage_DataType_Type Type;
- static const Type VOID = GLMessage_DataType_Type_VOID;
- static const Type CHAR = GLMessage_DataType_Type_CHAR;
- static const Type BYTE = GLMessage_DataType_Type_BYTE;
- static const Type INT = GLMessage_DataType_Type_INT;
- static const Type FLOAT = GLMessage_DataType_Type_FLOAT;
- static const Type BOOL = GLMessage_DataType_Type_BOOL;
- static const Type ENUM = GLMessage_DataType_Type_ENUM;
- static const Type INT64 = GLMessage_DataType_Type_INT64;
- static inline bool Type_IsValid(int value) {
- return GLMessage_DataType_Type_IsValid(value);
- }
- static const Type Type_MIN =
- GLMessage_DataType_Type_Type_MIN;
- static const Type Type_MAX =
- GLMessage_DataType_Type_Type_MAX;
- static const int Type_ARRAYSIZE =
- GLMessage_DataType_Type_Type_ARRAYSIZE;
-
- // accessors -------------------------------------------------------
-
- // required .android.gltrace.GLMessage.DataType.Type type = 1 [default = VOID];
- inline bool has_type() const;
- inline void clear_type();
- static const int kTypeFieldNumber = 1;
- inline ::android::gltrace::GLMessage_DataType_Type type() const;
- inline void set_type(::android::gltrace::GLMessage_DataType_Type value);
-
- // required bool isArray = 2 [default = false];
- inline bool has_isarray() const;
- inline void clear_isarray();
- static const int kIsArrayFieldNumber = 2;
- inline bool isarray() const;
- inline void set_isarray(bool value);
-
- // repeated int32 intValue = 3;
- inline int intvalue_size() const;
- inline void clear_intvalue();
- static const int kIntValueFieldNumber = 3;
- inline ::google::protobuf::int32 intvalue(int index) const;
- inline void set_intvalue(int index, ::google::protobuf::int32 value);
- inline void add_intvalue(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
- intvalue() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
- mutable_intvalue();
-
- // repeated float floatValue = 4;
- inline int floatvalue_size() const;
- inline void clear_floatvalue();
- static const int kFloatValueFieldNumber = 4;
- inline float floatvalue(int index) const;
- inline void set_floatvalue(int index, float value);
- inline void add_floatvalue(float value);
- inline const ::google::protobuf::RepeatedField< float >&
- floatvalue() const;
- inline ::google::protobuf::RepeatedField< float >*
- mutable_floatvalue();
-
- // repeated bytes charValue = 5;
- inline int charvalue_size() const;
- inline void clear_charvalue();
- static const int kCharValueFieldNumber = 5;
- inline const ::std::string& charvalue(int index) const;
- inline ::std::string* mutable_charvalue(int index);
- inline void set_charvalue(int index, const ::std::string& value);
- inline void set_charvalue(int index, const char* value);
- inline void set_charvalue(int index, const void* value, size_t size);
- inline ::std::string* add_charvalue();
- inline void add_charvalue(const ::std::string& value);
- inline void add_charvalue(const char* value);
- inline void add_charvalue(const void* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& charvalue() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_charvalue();
-
- // repeated bytes rawBytes = 6;
- inline int rawbytes_size() const;
- inline void clear_rawbytes();
- static const int kRawBytesFieldNumber = 6;
- inline const ::std::string& rawbytes(int index) const;
- inline ::std::string* mutable_rawbytes(int index);
- inline void set_rawbytes(int index, const ::std::string& value);
- inline void set_rawbytes(int index, const char* value);
- inline void set_rawbytes(int index, const void* value, size_t size);
- inline ::std::string* add_rawbytes();
- inline void add_rawbytes(const ::std::string& value);
- inline void add_rawbytes(const char* value);
- inline void add_rawbytes(const void* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& rawbytes() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_rawbytes();
-
- // repeated bool boolValue = 7;
- inline int boolvalue_size() const;
- inline void clear_boolvalue();
- static const int kBoolValueFieldNumber = 7;
- inline bool boolvalue(int index) const;
- inline void set_boolvalue(int index, bool value);
- inline void add_boolvalue(bool value);
- inline const ::google::protobuf::RepeatedField< bool >&
- boolvalue() const;
- inline ::google::protobuf::RepeatedField< bool >*
- mutable_boolvalue();
-
- // repeated int64 int64Value = 8;
- inline int int64value_size() const;
- inline void clear_int64value();
- static const int kInt64ValueFieldNumber = 8;
- inline ::google::protobuf::int64 int64value(int index) const;
- inline void set_int64value(int index, ::google::protobuf::int64 value);
- inline void add_int64value(::google::protobuf::int64 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int64 >&
- int64value() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int64 >*
- mutable_int64value();
-
- // @@protoc_insertion_point(class_scope:android.gltrace.GLMessage.DataType)
- private:
- mutable int _cached_size_;
-
- int type_;
- bool isarray_;
- ::google::protobuf::RepeatedField< ::google::protobuf::int32 > intvalue_;
- ::google::protobuf::RepeatedField< float > floatvalue_;
- ::google::protobuf::RepeatedPtrField< ::std::string> charvalue_;
- ::google::protobuf::RepeatedPtrField< ::std::string> rawbytes_;
- ::google::protobuf::RepeatedField< bool > boolvalue_;
- ::google::protobuf::RepeatedField< ::google::protobuf::int64 > int64value_;
- friend void protobuf_AddDesc_gltrace_2eproto();
- friend void protobuf_AssignDesc_gltrace_2eproto();
- friend void protobuf_ShutdownFile_gltrace_2eproto();
-
- ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-
- // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
- inline bool _has_bit(int index) const {
- return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
- }
- inline void _set_bit(int index) {
- _has_bits_[index / 32] |= (1u << (index % 32));
- }
- inline void _clear_bit(int index) {
- _has_bits_[index / 32] &= ~(1u << (index % 32));
- }
-
- void InitAsDefaultInstance();
- static GLMessage_DataType* default_instance_;
-};
-// -------------------------------------------------------------------
-
-class GLMessage_FrameBuffer : public ::google::protobuf::MessageLite {
- public:
- GLMessage_FrameBuffer();
- virtual ~GLMessage_FrameBuffer();
-
- GLMessage_FrameBuffer(const GLMessage_FrameBuffer& from);
-
- inline GLMessage_FrameBuffer& operator=(const GLMessage_FrameBuffer& from) {
- CopyFrom(from);
- return *this;
- }
-
- static const GLMessage_FrameBuffer& default_instance();
-
- void Swap(GLMessage_FrameBuffer* other);
-
- // implements Message ----------------------------------------------
-
- GLMessage_FrameBuffer* New() const;
- void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
- void CopyFrom(const GLMessage_FrameBuffer& from);
- void MergeFrom(const GLMessage_FrameBuffer& from);
- void Clear();
- bool IsInitialized() const;
-
- int ByteSize() const;
- bool MergePartialFromCodedStream(
- ::google::protobuf::io::CodedInputStream* input);
- void SerializeWithCachedSizes(
- ::google::protobuf::io::CodedOutputStream* output) const;
- int GetCachedSize() const { return _cached_size_; }
- private:
- void SharedCtor();
- void SharedDtor();
- void SetCachedSize(int size) const;
- public:
-
- ::std::string GetTypeName() const;
-
- // nested types ----------------------------------------------------
-
- // accessors -------------------------------------------------------
-
- // required int32 width = 1;
- inline bool has_width() const;
- inline void clear_width();
- static const int kWidthFieldNumber = 1;
- inline ::google::protobuf::int32 width() const;
- inline void set_width(::google::protobuf::int32 value);
-
- // required int32 height = 2;
- inline bool has_height() const;
- inline void clear_height();
- static const int kHeightFieldNumber = 2;
- inline ::google::protobuf::int32 height() const;
- inline void set_height(::google::protobuf::int32 value);
-
- // repeated bytes contents = 3;
- inline int contents_size() const;
- inline void clear_contents();
- static const int kContentsFieldNumber = 3;
- inline const ::std::string& contents(int index) const;
- inline ::std::string* mutable_contents(int index);
- inline void set_contents(int index, const ::std::string& value);
- inline void set_contents(int index, const char* value);
- inline void set_contents(int index, const void* value, size_t size);
- inline ::std::string* add_contents();
- inline void add_contents(const ::std::string& value);
- inline void add_contents(const char* value);
- inline void add_contents(const void* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& contents() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_contents();
-
- // @@protoc_insertion_point(class_scope:android.gltrace.GLMessage.FrameBuffer)
- private:
- mutable int _cached_size_;
-
- ::google::protobuf::int32 width_;
- ::google::protobuf::int32 height_;
- ::google::protobuf::RepeatedPtrField< ::std::string> contents_;
- friend void protobuf_AddDesc_gltrace_2eproto();
- friend void protobuf_AssignDesc_gltrace_2eproto();
- friend void protobuf_ShutdownFile_gltrace_2eproto();
-
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
- // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
- inline bool _has_bit(int index) const {
- return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
- }
- inline void _set_bit(int index) {
- _has_bits_[index / 32] |= (1u << (index % 32));
- }
- inline void _clear_bit(int index) {
- _has_bits_[index / 32] &= ~(1u << (index % 32));
- }
-
- void InitAsDefaultInstance();
- static GLMessage_FrameBuffer* default_instance_;
-};
-// -------------------------------------------------------------------
-
-class GLMessage : public ::google::protobuf::MessageLite {
- public:
- GLMessage();
- virtual ~GLMessage();
-
- GLMessage(const GLMessage& from);
-
- inline GLMessage& operator=(const GLMessage& from) {
- CopyFrom(from);
- return *this;
- }
-
- static const GLMessage& default_instance();
-
- void Swap(GLMessage* other);
-
- // implements Message ----------------------------------------------
-
- GLMessage* New() const;
- void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
- void CopyFrom(const GLMessage& from);
- void MergeFrom(const GLMessage& from);
- void Clear();
- bool IsInitialized() const;
-
- int ByteSize() const;
- bool MergePartialFromCodedStream(
- ::google::protobuf::io::CodedInputStream* input);
- void SerializeWithCachedSizes(
- ::google::protobuf::io::CodedOutputStream* output) const;
- int GetCachedSize() const { return _cached_size_; }
- private:
- void SharedCtor();
- void SharedDtor();
- void SetCachedSize(int size) const;
- public:
-
- ::std::string GetTypeName() const;
-
- // nested types ----------------------------------------------------
-
- typedef GLMessage_DataType DataType;
- typedef GLMessage_FrameBuffer FrameBuffer;
-
- typedef GLMessage_Function Function;
- static const Function glActiveTexture = GLMessage_Function_glActiveTexture;
- static const Function glAlphaFunc = GLMessage_Function_glAlphaFunc;
- static const Function glAlphaFuncx = GLMessage_Function_glAlphaFuncx;
- static const Function glAlphaFuncxOES = GLMessage_Function_glAlphaFuncxOES;
- static const Function glAttachShader = GLMessage_Function_glAttachShader;
- static const Function glBeginPerfMonitorAMD = GLMessage_Function_glBeginPerfMonitorAMD;
- static const Function glBindAttribLocation = GLMessage_Function_glBindAttribLocation;
- static const Function glBindBuffer = GLMessage_Function_glBindBuffer;
- static const Function glBindFramebuffer = GLMessage_Function_glBindFramebuffer;
- static const Function glBindFramebufferOES = GLMessage_Function_glBindFramebufferOES;
- static const Function glBindRenderbuffer = GLMessage_Function_glBindRenderbuffer;
- static const Function glBindRenderbufferOES = GLMessage_Function_glBindRenderbufferOES;
- static const Function glBindTexture = GLMessage_Function_glBindTexture;
- static const Function glBindVertexArrayOES = GLMessage_Function_glBindVertexArrayOES;
- static const Function glBlendColor = GLMessage_Function_glBlendColor;
- static const Function glBlendEquation = GLMessage_Function_glBlendEquation;
- static const Function glBlendEquationOES = GLMessage_Function_glBlendEquationOES;
- static const Function glBlendEquationSeparate = GLMessage_Function_glBlendEquationSeparate;
- static const Function glBlendEquationSeparateOES = GLMessage_Function_glBlendEquationSeparateOES;
- static const Function glBlendFunc = GLMessage_Function_glBlendFunc;
- static const Function glBlendFuncSeparate = GLMessage_Function_glBlendFuncSeparate;
- static const Function glBlendFuncSeparateOES = GLMessage_Function_glBlendFuncSeparateOES;
- static const Function glBufferData = GLMessage_Function_glBufferData;
- static const Function glBufferSubData = GLMessage_Function_glBufferSubData;
- static const Function glCheckFramebufferStatus = GLMessage_Function_glCheckFramebufferStatus;
- static const Function glCheckFramebufferStatusOES = GLMessage_Function_glCheckFramebufferStatusOES;
- static const Function glClearColor = GLMessage_Function_glClearColor;
- static const Function glClearColorx = GLMessage_Function_glClearColorx;
- static const Function glClearColorxOES = GLMessage_Function_glClearColorxOES;
- static const Function glClearDepthf = GLMessage_Function_glClearDepthf;
- static const Function glClearDepthfOES = GLMessage_Function_glClearDepthfOES;
- static const Function glClearDepthx = GLMessage_Function_glClearDepthx;
- static const Function glClearDepthxOES = GLMessage_Function_glClearDepthxOES;
- static const Function glClear = GLMessage_Function_glClear;
- static const Function glClearStencil = GLMessage_Function_glClearStencil;
- static const Function glClientActiveTexture = GLMessage_Function_glClientActiveTexture;
- static const Function glClipPlanef = GLMessage_Function_glClipPlanef;
- static const Function glClipPlanefIMG = GLMessage_Function_glClipPlanefIMG;
- static const Function glClipPlanefOES = GLMessage_Function_glClipPlanefOES;
- static const Function glClipPlanex = GLMessage_Function_glClipPlanex;
- static const Function glClipPlanexIMG = GLMessage_Function_glClipPlanexIMG;
- static const Function glClipPlanexOES = GLMessage_Function_glClipPlanexOES;
- static const Function glColor4f = GLMessage_Function_glColor4f;
- static const Function glColor4ub = GLMessage_Function_glColor4ub;
- static const Function glColor4x = GLMessage_Function_glColor4x;
- static const Function glColor4xOES = GLMessage_Function_glColor4xOES;
- static const Function glColorMask = GLMessage_Function_glColorMask;
- static const Function glColorPointer = GLMessage_Function_glColorPointer;
- static const Function glCompileShader = GLMessage_Function_glCompileShader;
- static const Function glCompressedTexImage2D = GLMessage_Function_glCompressedTexImage2D;
- static const Function glCompressedTexImage3DOES = GLMessage_Function_glCompressedTexImage3DOES;
- static const Function glCompressedTexSubImage2D = GLMessage_Function_glCompressedTexSubImage2D;
- static const Function glCompressedTexSubImage3DOES = GLMessage_Function_glCompressedTexSubImage3DOES;
- static const Function glCopyTexImage2D = GLMessage_Function_glCopyTexImage2D;
- static const Function glCopyTexSubImage2D = GLMessage_Function_glCopyTexSubImage2D;
- static const Function glCopyTexSubImage3DOES = GLMessage_Function_glCopyTexSubImage3DOES;
- static const Function glCoverageMaskNV = GLMessage_Function_glCoverageMaskNV;
- static const Function glCoverageOperationNV = GLMessage_Function_glCoverageOperationNV;
- static const Function glCreateProgram = GLMessage_Function_glCreateProgram;
- static const Function glCreateShader = GLMessage_Function_glCreateShader;
- static const Function glCullFace = GLMessage_Function_glCullFace;
- static const Function glCurrentPaletteMatrixOES = GLMessage_Function_glCurrentPaletteMatrixOES;
- static const Function glDeleteBuffers = GLMessage_Function_glDeleteBuffers;
- static const Function glDeleteFencesNV = GLMessage_Function_glDeleteFencesNV;
- static const Function glDeleteFramebuffers = GLMessage_Function_glDeleteFramebuffers;
- static const Function glDeleteFramebuffersOES = GLMessage_Function_glDeleteFramebuffersOES;
- static const Function glDeletePerfMonitorsAMD = GLMessage_Function_glDeletePerfMonitorsAMD;
- static const Function glDeleteProgram = GLMessage_Function_glDeleteProgram;
- static const Function glDeleteRenderbuffers = GLMessage_Function_glDeleteRenderbuffers;
- static const Function glDeleteRenderbuffersOES = GLMessage_Function_glDeleteRenderbuffersOES;
- static const Function glDeleteShader = GLMessage_Function_glDeleteShader;
- static const Function glDeleteTextures = GLMessage_Function_glDeleteTextures;
- static const Function glDeleteVertexArraysOES = GLMessage_Function_glDeleteVertexArraysOES;
- static const Function glDepthFunc = GLMessage_Function_glDepthFunc;
- static const Function glDepthMask = GLMessage_Function_glDepthMask;
- static const Function glDepthRangef = GLMessage_Function_glDepthRangef;
- static const Function glDepthRangefOES = GLMessage_Function_glDepthRangefOES;
- static const Function glDepthRangex = GLMessage_Function_glDepthRangex;
- static const Function glDepthRangexOES = GLMessage_Function_glDepthRangexOES;
- static const Function glDetachShader = GLMessage_Function_glDetachShader;
- static const Function glDisableClientState = GLMessage_Function_glDisableClientState;
- static const Function glDisableDriverControlQCOM = GLMessage_Function_glDisableDriverControlQCOM;
- static const Function glDisable = GLMessage_Function_glDisable;
- static const Function glDisableVertexAttribArray = GLMessage_Function_glDisableVertexAttribArray;
- static const Function glDiscardFramebufferEXT = GLMessage_Function_glDiscardFramebufferEXT;
- static const Function glDrawArrays = GLMessage_Function_glDrawArrays;
- static const Function glDrawElements = GLMessage_Function_glDrawElements;
- static const Function glDrawTexfOES = GLMessage_Function_glDrawTexfOES;
- static const Function glDrawTexfvOES = GLMessage_Function_glDrawTexfvOES;
- static const Function glDrawTexiOES = GLMessage_Function_glDrawTexiOES;
- static const Function glDrawTexivOES = GLMessage_Function_glDrawTexivOES;
- static const Function glDrawTexsOES = GLMessage_Function_glDrawTexsOES;
- static const Function glDrawTexsvOES = GLMessage_Function_glDrawTexsvOES;
- static const Function glDrawTexxOES = GLMessage_Function_glDrawTexxOES;
- static const Function glDrawTexxvOES = GLMessage_Function_glDrawTexxvOES;
- static const Function glEGLImageTargetRenderbufferStorageOES = GLMessage_Function_glEGLImageTargetRenderbufferStorageOES;
- static const Function glEGLImageTargetTexture2DOES = GLMessage_Function_glEGLImageTargetTexture2DOES;
- static const Function glEnableClientState = GLMessage_Function_glEnableClientState;
- static const Function glEnableDriverControlQCOM = GLMessage_Function_glEnableDriverControlQCOM;
- static const Function glEnable = GLMessage_Function_glEnable;
- static const Function glEnableVertexAttribArray = GLMessage_Function_glEnableVertexAttribArray;
- static const Function glEndPerfMonitorAMD = GLMessage_Function_glEndPerfMonitorAMD;
- static const Function glEndTilingQCOM = GLMessage_Function_glEndTilingQCOM;
- static const Function glExtGetBufferPointervQCOM = GLMessage_Function_glExtGetBufferPointervQCOM;
- static const Function glExtGetBuffersQCOM = GLMessage_Function_glExtGetBuffersQCOM;
- static const Function glExtGetFramebuffersQCOM = GLMessage_Function_glExtGetFramebuffersQCOM;
- static const Function glExtGetProgramBinarySourceQCOM = GLMessage_Function_glExtGetProgramBinarySourceQCOM;
- static const Function glExtGetProgramsQCOM = GLMessage_Function_glExtGetProgramsQCOM;
- static const Function glExtGetRenderbuffersQCOM = GLMessage_Function_glExtGetRenderbuffersQCOM;
- static const Function glExtGetShadersQCOM = GLMessage_Function_glExtGetShadersQCOM;
- static const Function glExtGetTexLevelParameterivQCOM = GLMessage_Function_glExtGetTexLevelParameterivQCOM;
- static const Function glExtGetTexSubImageQCOM = GLMessage_Function_glExtGetTexSubImageQCOM;
- static const Function glExtGetTexturesQCOM = GLMessage_Function_glExtGetTexturesQCOM;
- static const Function glExtIsProgramBinaryQCOM = GLMessage_Function_glExtIsProgramBinaryQCOM;
- static const Function glExtTexObjectStateOverrideiQCOM = GLMessage_Function_glExtTexObjectStateOverrideiQCOM;
- static const Function glFinishFenceNV = GLMessage_Function_glFinishFenceNV;
- static const Function glFinish = GLMessage_Function_glFinish;
- static const Function glFlush = GLMessage_Function_glFlush;
- static const Function glFogf = GLMessage_Function_glFogf;
- static const Function glFogfv = GLMessage_Function_glFogfv;
- static const Function glFogx = GLMessage_Function_glFogx;
- static const Function glFogxOES = GLMessage_Function_glFogxOES;
- static const Function glFogxv = GLMessage_Function_glFogxv;
- static const Function glFogxvOES = GLMessage_Function_glFogxvOES;
- static const Function glFramebufferRenderbuffer = GLMessage_Function_glFramebufferRenderbuffer;
- static const Function glFramebufferRenderbufferOES = GLMessage_Function_glFramebufferRenderbufferOES;
- static const Function glFramebufferTexture2D = GLMessage_Function_glFramebufferTexture2D;
- static const Function glFramebufferTexture2DMultisampleIMG = GLMessage_Function_glFramebufferTexture2DMultisampleIMG;
- static const Function glFramebufferTexture2DOES = GLMessage_Function_glFramebufferTexture2DOES;
- static const Function glFramebufferTexture3DOES = GLMessage_Function_glFramebufferTexture3DOES;
- static const Function glFrontFace = GLMessage_Function_glFrontFace;
- static const Function glFrustumf = GLMessage_Function_glFrustumf;
- static const Function glFrustumfOES = GLMessage_Function_glFrustumfOES;
- static const Function glFrustumx = GLMessage_Function_glFrustumx;
- static const Function glFrustumxOES = GLMessage_Function_glFrustumxOES;
- static const Function glGenBuffers = GLMessage_Function_glGenBuffers;
- static const Function glGenerateMipmap = GLMessage_Function_glGenerateMipmap;
- static const Function glGenerateMipmapOES = GLMessage_Function_glGenerateMipmapOES;
- static const Function glGenFencesNV = GLMessage_Function_glGenFencesNV;
- static const Function glGenFramebuffers = GLMessage_Function_glGenFramebuffers;
- static const Function glGenFramebuffersOES = GLMessage_Function_glGenFramebuffersOES;
- static const Function glGenPerfMonitorsAMD = GLMessage_Function_glGenPerfMonitorsAMD;
- static const Function glGenRenderbuffers = GLMessage_Function_glGenRenderbuffers;
- static const Function glGenRenderbuffersOES = GLMessage_Function_glGenRenderbuffersOES;
- static const Function glGenTextures = GLMessage_Function_glGenTextures;
- static const Function glGenVertexArraysOES = GLMessage_Function_glGenVertexArraysOES;
- static const Function glGetActiveAttrib = GLMessage_Function_glGetActiveAttrib;
- static const Function glGetActiveUniform = GLMessage_Function_glGetActiveUniform;
- static const Function glGetAttachedShaders = GLMessage_Function_glGetAttachedShaders;
- static const Function glGetAttribLocation = GLMessage_Function_glGetAttribLocation;
- static const Function glGetBooleanv = GLMessage_Function_glGetBooleanv;
- static const Function glGetBufferParameteriv = GLMessage_Function_glGetBufferParameteriv;
- static const Function glGetBufferPointervOES = GLMessage_Function_glGetBufferPointervOES;
- static const Function glGetClipPlanef = GLMessage_Function_glGetClipPlanef;
- static const Function glGetClipPlanefOES = GLMessage_Function_glGetClipPlanefOES;
- static const Function glGetClipPlanex = GLMessage_Function_glGetClipPlanex;
- static const Function glGetClipPlanexOES = GLMessage_Function_glGetClipPlanexOES;
- static const Function glGetDriverControlsQCOM = GLMessage_Function_glGetDriverControlsQCOM;
- static const Function glGetDriverControlStringQCOM = GLMessage_Function_glGetDriverControlStringQCOM;
- static const Function glGetError = GLMessage_Function_glGetError;
- static const Function glGetFenceivNV = GLMessage_Function_glGetFenceivNV;
- static const Function glGetFixedv = GLMessage_Function_glGetFixedv;
- static const Function glGetFixedvOES = GLMessage_Function_glGetFixedvOES;
- static const Function glGetFloatv = GLMessage_Function_glGetFloatv;
- static const Function glGetFramebufferAttachmentParameteriv = GLMessage_Function_glGetFramebufferAttachmentParameteriv;
- static const Function glGetFramebufferAttachmentParameterivOES = GLMessage_Function_glGetFramebufferAttachmentParameterivOES;
- static const Function glGetIntegerv = GLMessage_Function_glGetIntegerv;
- static const Function glGetLightfv = GLMessage_Function_glGetLightfv;
- static const Function glGetLightxv = GLMessage_Function_glGetLightxv;
- static const Function glGetLightxvOES = GLMessage_Function_glGetLightxvOES;
- static const Function glGetMaterialfv = GLMessage_Function_glGetMaterialfv;
- static const Function glGetMaterialxv = GLMessage_Function_glGetMaterialxv;
- static const Function glGetMaterialxvOES = GLMessage_Function_glGetMaterialxvOES;
- static const Function glGetPerfMonitorCounterDataAMD = GLMessage_Function_glGetPerfMonitorCounterDataAMD;
- static const Function glGetPerfMonitorCounterInfoAMD = GLMessage_Function_glGetPerfMonitorCounterInfoAMD;
- static const Function glGetPerfMonitorCountersAMD = GLMessage_Function_glGetPerfMonitorCountersAMD;
- static const Function glGetPerfMonitorCounterStringAMD = GLMessage_Function_glGetPerfMonitorCounterStringAMD;
- static const Function glGetPerfMonitorGroupsAMD = GLMessage_Function_glGetPerfMonitorGroupsAMD;
- static const Function glGetPerfMonitorGroupStringAMD = GLMessage_Function_glGetPerfMonitorGroupStringAMD;
- static const Function glGetPointerv = GLMessage_Function_glGetPointerv;
- static const Function glGetProgramBinaryOES = GLMessage_Function_glGetProgramBinaryOES;
- static const Function glGetProgramInfoLog = GLMessage_Function_glGetProgramInfoLog;
- static const Function glGetProgramiv = GLMessage_Function_glGetProgramiv;
- static const Function glGetRenderbufferParameteriv = GLMessage_Function_glGetRenderbufferParameteriv;
- static const Function glGetRenderbufferParameterivOES = GLMessage_Function_glGetRenderbufferParameterivOES;
- static const Function glGetShaderInfoLog = GLMessage_Function_glGetShaderInfoLog;
- static const Function glGetShaderiv = GLMessage_Function_glGetShaderiv;
- static const Function glGetShaderPrecisionFormat = GLMessage_Function_glGetShaderPrecisionFormat;
- static const Function glGetShaderSource = GLMessage_Function_glGetShaderSource;
- static const Function glGetString = GLMessage_Function_glGetString;
- static const Function glGetTexEnvfv = GLMessage_Function_glGetTexEnvfv;
- static const Function glGetTexEnviv = GLMessage_Function_glGetTexEnviv;
- static const Function glGetTexEnvxv = GLMessage_Function_glGetTexEnvxv;
- static const Function glGetTexEnvxvOES = GLMessage_Function_glGetTexEnvxvOES;
- static const Function glGetTexGenfvOES = GLMessage_Function_glGetTexGenfvOES;
- static const Function glGetTexGenivOES = GLMessage_Function_glGetTexGenivOES;
- static const Function glGetTexGenxvOES = GLMessage_Function_glGetTexGenxvOES;
- static const Function glGetTexParameterfv = GLMessage_Function_glGetTexParameterfv;
- static const Function glGetTexParameteriv = GLMessage_Function_glGetTexParameteriv;
- static const Function glGetTexParameterxv = GLMessage_Function_glGetTexParameterxv;
- static const Function glGetTexParameterxvOES = GLMessage_Function_glGetTexParameterxvOES;
- static const Function glGetUniformfv = GLMessage_Function_glGetUniformfv;
- static const Function glGetUniformiv = GLMessage_Function_glGetUniformiv;
- static const Function glGetUniformLocation = GLMessage_Function_glGetUniformLocation;
- static const Function glGetVertexAttribfv = GLMessage_Function_glGetVertexAttribfv;
- static const Function glGetVertexAttribiv = GLMessage_Function_glGetVertexAttribiv;
- static const Function glGetVertexAttribPointerv = GLMessage_Function_glGetVertexAttribPointerv;
- static const Function glHint = GLMessage_Function_glHint;
- static const Function glIsBuffer = GLMessage_Function_glIsBuffer;
- static const Function glIsEnabled = GLMessage_Function_glIsEnabled;
- static const Function glIsFenceNV = GLMessage_Function_glIsFenceNV;
- static const Function glIsFramebuffer = GLMessage_Function_glIsFramebuffer;
- static const Function glIsFramebufferOES = GLMessage_Function_glIsFramebufferOES;
- static const Function glIsProgram = GLMessage_Function_glIsProgram;
- static const Function glIsRenderbuffer = GLMessage_Function_glIsRenderbuffer;
- static const Function glIsRenderbufferOES = GLMessage_Function_glIsRenderbufferOES;
- static const Function glIsShader = GLMessage_Function_glIsShader;
- static const Function glIsTexture = GLMessage_Function_glIsTexture;
- static const Function glIsVertexArrayOES = GLMessage_Function_glIsVertexArrayOES;
- static const Function glLightf = GLMessage_Function_glLightf;
- static const Function glLightfv = GLMessage_Function_glLightfv;
- static const Function glLightModelf = GLMessage_Function_glLightModelf;
- static const Function glLightModelfv = GLMessage_Function_glLightModelfv;
- static const Function glLightModelx = GLMessage_Function_glLightModelx;
- static const Function glLightModelxOES = GLMessage_Function_glLightModelxOES;
- static const Function glLightModelxv = GLMessage_Function_glLightModelxv;
- static const Function glLightModelxvOES = GLMessage_Function_glLightModelxvOES;
- static const Function glLightx = GLMessage_Function_glLightx;
- static const Function glLightxOES = GLMessage_Function_glLightxOES;
- static const Function glLightxv = GLMessage_Function_glLightxv;
- static const Function glLightxvOES = GLMessage_Function_glLightxvOES;
- static const Function glLineWidth = GLMessage_Function_glLineWidth;
- static const Function glLineWidthx = GLMessage_Function_glLineWidthx;
- static const Function glLineWidthxOES = GLMessage_Function_glLineWidthxOES;
- static const Function glLinkProgram = GLMessage_Function_glLinkProgram;
- static const Function glLoadIdentity = GLMessage_Function_glLoadIdentity;
- static const Function glLoadMatrixf = GLMessage_Function_glLoadMatrixf;
- static const Function glLoadMatrixx = GLMessage_Function_glLoadMatrixx;
- static const Function glLoadMatrixxOES = GLMessage_Function_glLoadMatrixxOES;
- static const Function glLoadPaletteFromModelViewMatrixOES = GLMessage_Function_glLoadPaletteFromModelViewMatrixOES;
- static const Function glLogicOp = GLMessage_Function_glLogicOp;
- static const Function glMapBufferOES = GLMessage_Function_glMapBufferOES;
- static const Function glMaterialf = GLMessage_Function_glMaterialf;
- static const Function glMaterialfv = GLMessage_Function_glMaterialfv;
- static const Function glMaterialx = GLMessage_Function_glMaterialx;
- static const Function glMaterialxOES = GLMessage_Function_glMaterialxOES;
- static const Function glMaterialxv = GLMessage_Function_glMaterialxv;
- static const Function glMaterialxvOES = GLMessage_Function_glMaterialxvOES;
- static const Function glMatrixIndexPointerOES = GLMessage_Function_glMatrixIndexPointerOES;
- static const Function glMatrixMode = GLMessage_Function_glMatrixMode;
- static const Function glMultiDrawArraysEXT = GLMessage_Function_glMultiDrawArraysEXT;
- static const Function glMultiDrawElementsEXT = GLMessage_Function_glMultiDrawElementsEXT;
- static const Function glMultiTexCoord4f = GLMessage_Function_glMultiTexCoord4f;
- static const Function glMultiTexCoord4x = GLMessage_Function_glMultiTexCoord4x;
- static const Function glMultiTexCoord4xOES = GLMessage_Function_glMultiTexCoord4xOES;
- static const Function glMultMatrixf = GLMessage_Function_glMultMatrixf;
- static const Function glMultMatrixx = GLMessage_Function_glMultMatrixx;
- static const Function glMultMatrixxOES = GLMessage_Function_glMultMatrixxOES;
- static const Function glNormal3f = GLMessage_Function_glNormal3f;
- static const Function glNormal3x = GLMessage_Function_glNormal3x;
- static const Function glNormal3xOES = GLMessage_Function_glNormal3xOES;
- static const Function glNormalPointer = GLMessage_Function_glNormalPointer;
- static const Function glOrthof = GLMessage_Function_glOrthof;
- static const Function glOrthofOES = GLMessage_Function_glOrthofOES;
- static const Function glOrthox = GLMessage_Function_glOrthox;
- static const Function glOrthoxOES = GLMessage_Function_glOrthoxOES;
- static const Function glPixelStorei = GLMessage_Function_glPixelStorei;
- static const Function glPointParameterf = GLMessage_Function_glPointParameterf;
- static const Function glPointParameterfv = GLMessage_Function_glPointParameterfv;
- static const Function glPointParameterx = GLMessage_Function_glPointParameterx;
- static const Function glPointParameterxOES = GLMessage_Function_glPointParameterxOES;
- static const Function glPointParameterxv = GLMessage_Function_glPointParameterxv;
- static const Function glPointParameterxvOES = GLMessage_Function_glPointParameterxvOES;
- static const Function glPointSize = GLMessage_Function_glPointSize;
- static const Function glPointSizePointerOES = GLMessage_Function_glPointSizePointerOES;
- static const Function glPointSizex = GLMessage_Function_glPointSizex;
- static const Function glPointSizexOES = GLMessage_Function_glPointSizexOES;
- static const Function glPolygonOffset = GLMessage_Function_glPolygonOffset;
- static const Function glPolygonOffsetx = GLMessage_Function_glPolygonOffsetx;
- static const Function glPolygonOffsetxOES = GLMessage_Function_glPolygonOffsetxOES;
- static const Function glPopMatrix = GLMessage_Function_glPopMatrix;
- static const Function glProgramBinaryOES = GLMessage_Function_glProgramBinaryOES;
- static const Function glPushMatrix = GLMessage_Function_glPushMatrix;
- static const Function glQueryMatrixxOES = GLMessage_Function_glQueryMatrixxOES;
- static const Function glReadPixels = GLMessage_Function_glReadPixels;
- static const Function glReleaseShaderCompiler = GLMessage_Function_glReleaseShaderCompiler;
- static const Function glRenderbufferStorage = GLMessage_Function_glRenderbufferStorage;
- static const Function glRenderbufferStorageMultisampleIMG = GLMessage_Function_glRenderbufferStorageMultisampleIMG;
- static const Function glRenderbufferStorageOES = GLMessage_Function_glRenderbufferStorageOES;
- static const Function glRotatef = GLMessage_Function_glRotatef;
- static const Function glRotatex = GLMessage_Function_glRotatex;
- static const Function glRotatexOES = GLMessage_Function_glRotatexOES;
- static const Function glSampleCoverage = GLMessage_Function_glSampleCoverage;
- static const Function glSampleCoveragex = GLMessage_Function_glSampleCoveragex;
- static const Function glSampleCoveragexOES = GLMessage_Function_glSampleCoveragexOES;
- static const Function glScalef = GLMessage_Function_glScalef;
- static const Function glScalex = GLMessage_Function_glScalex;
- static const Function glScalexOES = GLMessage_Function_glScalexOES;
- static const Function glScissor = GLMessage_Function_glScissor;
- static const Function glSelectPerfMonitorCountersAMD = GLMessage_Function_glSelectPerfMonitorCountersAMD;
- static const Function glSetFenceNV = GLMessage_Function_glSetFenceNV;
- static const Function glShadeModel = GLMessage_Function_glShadeModel;
- static const Function glShaderBinary = GLMessage_Function_glShaderBinary;
- static const Function glShaderSource = GLMessage_Function_glShaderSource;
- static const Function glStartTilingQCOM = GLMessage_Function_glStartTilingQCOM;
- static const Function glStencilFunc = GLMessage_Function_glStencilFunc;
- static const Function glStencilFuncSeparate = GLMessage_Function_glStencilFuncSeparate;
- static const Function glStencilMask = GLMessage_Function_glStencilMask;
- static const Function glStencilMaskSeparate = GLMessage_Function_glStencilMaskSeparate;
- static const Function glStencilOp = GLMessage_Function_glStencilOp;
- static const Function glStencilOpSeparate = GLMessage_Function_glStencilOpSeparate;
- static const Function glTestFenceNV = GLMessage_Function_glTestFenceNV;
- static const Function glTexCoordPointer = GLMessage_Function_glTexCoordPointer;
- static const Function glTexEnvf = GLMessage_Function_glTexEnvf;
- static const Function glTexEnvfv = GLMessage_Function_glTexEnvfv;
- static const Function glTexEnvi = GLMessage_Function_glTexEnvi;
- static const Function glTexEnviv = GLMessage_Function_glTexEnviv;
- static const Function glTexEnvx = GLMessage_Function_glTexEnvx;
- static const Function glTexEnvxOES = GLMessage_Function_glTexEnvxOES;
- static const Function glTexEnvxv = GLMessage_Function_glTexEnvxv;
- static const Function glTexEnvxvOES = GLMessage_Function_glTexEnvxvOES;
- static const Function glTexGenfOES = GLMessage_Function_glTexGenfOES;
- static const Function glTexGenfvOES = GLMessage_Function_glTexGenfvOES;
- static const Function glTexGeniOES = GLMessage_Function_glTexGeniOES;
- static const Function glTexGenivOES = GLMessage_Function_glTexGenivOES;
- static const Function glTexGenxOES = GLMessage_Function_glTexGenxOES;
- static const Function glTexGenxvOES = GLMessage_Function_glTexGenxvOES;
- static const Function glTexImage2D = GLMessage_Function_glTexImage2D;
- static const Function glTexImage3DOES = GLMessage_Function_glTexImage3DOES;
- static const Function glTexParameterf = GLMessage_Function_glTexParameterf;
- static const Function glTexParameterfv = GLMessage_Function_glTexParameterfv;
- static const Function glTexParameteri = GLMessage_Function_glTexParameteri;
- static const Function glTexParameteriv = GLMessage_Function_glTexParameteriv;
- static const Function glTexParameterx = GLMessage_Function_glTexParameterx;
- static const Function glTexParameterxOES = GLMessage_Function_glTexParameterxOES;
- static const Function glTexParameterxv = GLMessage_Function_glTexParameterxv;
- static const Function glTexParameterxvOES = GLMessage_Function_glTexParameterxvOES;
- static const Function glTexSubImage2D = GLMessage_Function_glTexSubImage2D;
- static const Function glTexSubImage3DOES = GLMessage_Function_glTexSubImage3DOES;
- static const Function glTranslatef = GLMessage_Function_glTranslatef;
- static const Function glTranslatex = GLMessage_Function_glTranslatex;
- static const Function glTranslatexOES = GLMessage_Function_glTranslatexOES;
- static const Function glUniform1f = GLMessage_Function_glUniform1f;
- static const Function glUniform1fv = GLMessage_Function_glUniform1fv;
- static const Function glUniform1i = GLMessage_Function_glUniform1i;
- static const Function glUniform1iv = GLMessage_Function_glUniform1iv;
- static const Function glUniform2f = GLMessage_Function_glUniform2f;
- static const Function glUniform2fv = GLMessage_Function_glUniform2fv;
- static const Function glUniform2i = GLMessage_Function_glUniform2i;
- static const Function glUniform2iv = GLMessage_Function_glUniform2iv;
- static const Function glUniform3f = GLMessage_Function_glUniform3f;
- static const Function glUniform3fv = GLMessage_Function_glUniform3fv;
- static const Function glUniform3i = GLMessage_Function_glUniform3i;
- static const Function glUniform3iv = GLMessage_Function_glUniform3iv;
- static const Function glUniform4f = GLMessage_Function_glUniform4f;
- static const Function glUniform4fv = GLMessage_Function_glUniform4fv;
- static const Function glUniform4i = GLMessage_Function_glUniform4i;
- static const Function glUniform4iv = GLMessage_Function_glUniform4iv;
- static const Function glUniformMatrix2fv = GLMessage_Function_glUniformMatrix2fv;
- static const Function glUniformMatrix3fv = GLMessage_Function_glUniformMatrix3fv;
- static const Function glUniformMatrix4fv = GLMessage_Function_glUniformMatrix4fv;
- static const Function glUnmapBufferOES = GLMessage_Function_glUnmapBufferOES;
- static const Function glUseProgram = GLMessage_Function_glUseProgram;
- static const Function glValidateProgram = GLMessage_Function_glValidateProgram;
- static const Function glVertexAttrib1f = GLMessage_Function_glVertexAttrib1f;
- static const Function glVertexAttrib1fv = GLMessage_Function_glVertexAttrib1fv;
- static const Function glVertexAttrib2f = GLMessage_Function_glVertexAttrib2f;
- static const Function glVertexAttrib2fv = GLMessage_Function_glVertexAttrib2fv;
- static const Function glVertexAttrib3f = GLMessage_Function_glVertexAttrib3f;
- static const Function glVertexAttrib3fv = GLMessage_Function_glVertexAttrib3fv;
- static const Function glVertexAttrib4f = GLMessage_Function_glVertexAttrib4f;
- static const Function glVertexAttrib4fv = GLMessage_Function_glVertexAttrib4fv;
- static const Function glVertexAttribPointer = GLMessage_Function_glVertexAttribPointer;
- static const Function glVertexPointer = GLMessage_Function_glVertexPointer;
- static const Function glViewport = GLMessage_Function_glViewport;
- static const Function glWeightPointerOES = GLMessage_Function_glWeightPointerOES;
- static const Function glReadBuffer = GLMessage_Function_glReadBuffer;
- static const Function glDrawRangeElements = GLMessage_Function_glDrawRangeElements;
- static const Function glTexImage3D = GLMessage_Function_glTexImage3D;
- static const Function glTexSubImage3D = GLMessage_Function_glTexSubImage3D;
- static const Function glCopyTexSubImage3D = GLMessage_Function_glCopyTexSubImage3D;
- static const Function glCompressedTexImage3D = GLMessage_Function_glCompressedTexImage3D;
- static const Function glCompressedTexSubImage3D = GLMessage_Function_glCompressedTexSubImage3D;
- static const Function glGenQueries = GLMessage_Function_glGenQueries;
- static const Function glDeleteQueries = GLMessage_Function_glDeleteQueries;
- static const Function glIsQuery = GLMessage_Function_glIsQuery;
- static const Function glBeginQuery = GLMessage_Function_glBeginQuery;
- static const Function glEndQuery = GLMessage_Function_glEndQuery;
- static const Function glGetQueryiv = GLMessage_Function_glGetQueryiv;
- static const Function glGetQueryObjectuiv = GLMessage_Function_glGetQueryObjectuiv;
- static const Function glUnmapBuffer = GLMessage_Function_glUnmapBuffer;
- static const Function glGetBufferPointerv = GLMessage_Function_glGetBufferPointerv;
- static const Function glDrawBuffers = GLMessage_Function_glDrawBuffers;
- static const Function glUniformMatrix2x3fv = GLMessage_Function_glUniformMatrix2x3fv;
- static const Function glUniformMatrix3x2fv = GLMessage_Function_glUniformMatrix3x2fv;
- static const Function glUniformMatrix2x4fv = GLMessage_Function_glUniformMatrix2x4fv;
- static const Function glUniformMatrix4x2fv = GLMessage_Function_glUniformMatrix4x2fv;
- static const Function glUniformMatrix3x4fv = GLMessage_Function_glUniformMatrix3x4fv;
- static const Function glUniformMatrix4x3fv = GLMessage_Function_glUniformMatrix4x3fv;
- static const Function glBlitFramebuffer = GLMessage_Function_glBlitFramebuffer;
- static const Function glRenderbufferStorageMultisample = GLMessage_Function_glRenderbufferStorageMultisample;
- static const Function glFramebufferTextureLayer = GLMessage_Function_glFramebufferTextureLayer;
- static const Function glMapBufferRange = GLMessage_Function_glMapBufferRange;
- static const Function glFlushMappedBufferRange = GLMessage_Function_glFlushMappedBufferRange;
- static const Function glBindVertexArray = GLMessage_Function_glBindVertexArray;
- static const Function glDeleteVertexArrays = GLMessage_Function_glDeleteVertexArrays;
- static const Function glGenVertexArrays = GLMessage_Function_glGenVertexArrays;
- static const Function glIsVertexArray = GLMessage_Function_glIsVertexArray;
- static const Function glGetIntegeri_v = GLMessage_Function_glGetIntegeri_v;
- static const Function glBeginTransformFeedback = GLMessage_Function_glBeginTransformFeedback;
- static const Function glEndTransformFeedback = GLMessage_Function_glEndTransformFeedback;
- static const Function glBindBufferRange = GLMessage_Function_glBindBufferRange;
- static const Function glBindBufferBase = GLMessage_Function_glBindBufferBase;
- static const Function glTransformFeedbackVaryings = GLMessage_Function_glTransformFeedbackVaryings;
- static const Function glGetTransformFeedbackVarying = GLMessage_Function_glGetTransformFeedbackVarying;
- static const Function glVertexAttribIPointer = GLMessage_Function_glVertexAttribIPointer;
- static const Function glGetVertexAttribIiv = GLMessage_Function_glGetVertexAttribIiv;
- static const Function glGetVertexAttribIuiv = GLMessage_Function_glGetVertexAttribIuiv;
- static const Function glVertexAttribI4i = GLMessage_Function_glVertexAttribI4i;
- static const Function glVertexAttribI4ui = GLMessage_Function_glVertexAttribI4ui;
- static const Function glVertexAttribI4iv = GLMessage_Function_glVertexAttribI4iv;
- static const Function glVertexAttribI4uiv = GLMessage_Function_glVertexAttribI4uiv;
- static const Function glGetUniformuiv = GLMessage_Function_glGetUniformuiv;
- static const Function glGetFragDataLocation = GLMessage_Function_glGetFragDataLocation;
- static const Function glUniform1ui = GLMessage_Function_glUniform1ui;
- static const Function glUniform2ui = GLMessage_Function_glUniform2ui;
- static const Function glUniform3ui = GLMessage_Function_glUniform3ui;
- static const Function glUniform4ui = GLMessage_Function_glUniform4ui;
- static const Function glUniform1uiv = GLMessage_Function_glUniform1uiv;
- static const Function glUniform2uiv = GLMessage_Function_glUniform2uiv;
- static const Function glUniform3uiv = GLMessage_Function_glUniform3uiv;
- static const Function glUniform4uiv = GLMessage_Function_glUniform4uiv;
- static const Function glClearBufferiv = GLMessage_Function_glClearBufferiv;
- static const Function glClearBufferuiv = GLMessage_Function_glClearBufferuiv;
- static const Function glClearBufferfv = GLMessage_Function_glClearBufferfv;
- static const Function glClearBufferfi = GLMessage_Function_glClearBufferfi;
- static const Function glGetStringi = GLMessage_Function_glGetStringi;
- static const Function glCopyBufferSubData = GLMessage_Function_glCopyBufferSubData;
- static const Function glGetUniformIndices = GLMessage_Function_glGetUniformIndices;
- static const Function glGetActiveUniformsiv = GLMessage_Function_glGetActiveUniformsiv;
- static const Function glGetUniformBlockIndex = GLMessage_Function_glGetUniformBlockIndex;
- static const Function glGetActiveUniformBlockiv = GLMessage_Function_glGetActiveUniformBlockiv;
- static const Function glGetActiveUniformBlockName = GLMessage_Function_glGetActiveUniformBlockName;
- static const Function glUniformBlockBinding = GLMessage_Function_glUniformBlockBinding;
- static const Function glDrawArraysInstanced = GLMessage_Function_glDrawArraysInstanced;
- static const Function glDrawElementsInstanced = GLMessage_Function_glDrawElementsInstanced;
- static const Function glFenceSync = GLMessage_Function_glFenceSync;
- static const Function glIsSync = GLMessage_Function_glIsSync;
- static const Function glDeleteSync = GLMessage_Function_glDeleteSync;
- static const Function glClientWaitSync = GLMessage_Function_glClientWaitSync;
- static const Function glWaitSync = GLMessage_Function_glWaitSync;
- static const Function glGetInteger64v = GLMessage_Function_glGetInteger64v;
- static const Function glGetSynciv = GLMessage_Function_glGetSynciv;
- static const Function glGetInteger64i_v = GLMessage_Function_glGetInteger64i_v;
- static const Function glGetBufferParameteri64v = GLMessage_Function_glGetBufferParameteri64v;
- static const Function glGenSamplers = GLMessage_Function_glGenSamplers;
- static const Function glDeleteSamplers = GLMessage_Function_glDeleteSamplers;
- static const Function glIsSampler = GLMessage_Function_glIsSampler;
- static const Function glBindSampler = GLMessage_Function_glBindSampler;
- static const Function glSamplerParameteri = GLMessage_Function_glSamplerParameteri;
- static const Function glSamplerParameteriv = GLMessage_Function_glSamplerParameteriv;
- static const Function glSamplerParameterf = GLMessage_Function_glSamplerParameterf;
- static const Function glSamplerParameterfv = GLMessage_Function_glSamplerParameterfv;
- static const Function glGetSamplerParameteriv = GLMessage_Function_glGetSamplerParameteriv;
- static const Function glGetSamplerParameterfv = GLMessage_Function_glGetSamplerParameterfv;
- static const Function glVertexAttribDivisor = GLMessage_Function_glVertexAttribDivisor;
- static const Function glBindTransformFeedback = GLMessage_Function_glBindTransformFeedback;
- static const Function glDeleteTransformFeedbacks = GLMessage_Function_glDeleteTransformFeedbacks;
- static const Function glGenTransformFeedbacks = GLMessage_Function_glGenTransformFeedbacks;
- static const Function glIsTransformFeedback = GLMessage_Function_glIsTransformFeedback;
- static const Function glPauseTransformFeedback = GLMessage_Function_glPauseTransformFeedback;
- static const Function glResumeTransformFeedback = GLMessage_Function_glResumeTransformFeedback;
- static const Function glGetProgramBinary = GLMessage_Function_glGetProgramBinary;
- static const Function glProgramBinary = GLMessage_Function_glProgramBinary;
- static const Function glProgramParameteri = GLMessage_Function_glProgramParameteri;
- static const Function glInvalidateFramebuffer = GLMessage_Function_glInvalidateFramebuffer;
- static const Function glInvalidateSubFramebuffer = GLMessage_Function_glInvalidateSubFramebuffer;
- static const Function glTexStorage2D = GLMessage_Function_glTexStorage2D;
- static const Function glTexStorage3D = GLMessage_Function_glTexStorage3D;
- static const Function glGetInternalformativ = GLMessage_Function_glGetInternalformativ;
- static const Function glBeginPerfQueryINTEL = GLMessage_Function_glBeginPerfQueryINTEL;
- static const Function glCreatePerfQueryINTEL = GLMessage_Function_glCreatePerfQueryINTEL;
- static const Function glDeletePerfQueryINTEL = GLMessage_Function_glDeletePerfQueryINTEL;
- static const Function glEndPerfQueryINTEL = GLMessage_Function_glEndPerfQueryINTEL;
- static const Function glGetFirstPerfQueryIdINTEL = GLMessage_Function_glGetFirstPerfQueryIdINTEL;
- static const Function glGetNextPerfQueryIdINTEL = GLMessage_Function_glGetNextPerfQueryIdINTEL;
- static const Function glGetPerfCounterInfoINTEL = GLMessage_Function_glGetPerfCounterInfoINTEL;
- static const Function glGetPerfQueryDataINTEL = GLMessage_Function_glGetPerfQueryDataINTEL;
- static const Function glGetPerfQueryIdByNameINTEL = GLMessage_Function_glGetPerfQueryIdByNameINTEL;
- static const Function glGetPerfQueryInfoINTEL = GLMessage_Function_glGetPerfQueryInfoINTEL;
- static const Function glBlendBarrierKHR = GLMessage_Function_glBlendBarrierKHR;
- static const Function glBlendBarrierNV = GLMessage_Function_glBlendBarrierNV;
- static const Function glBlendParameteriNV = GLMessage_Function_glBlendParameteriNV;
- static const Function glBlitFramebufferNV = GLMessage_Function_glBlitFramebufferNV;
- static const Function glFenceSyncAPPLE = GLMessage_Function_glFenceSyncAPPLE;
- static const Function glIsSyncAPPLE = GLMessage_Function_glIsSyncAPPLE;
- static const Function glDeleteSyncAPPLE = GLMessage_Function_glDeleteSyncAPPLE;
- static const Function glClientWaitSyncAPPLE = GLMessage_Function_glClientWaitSyncAPPLE;
- static const Function glWaitSyncAPPLE = GLMessage_Function_glWaitSyncAPPLE;
- static const Function glGetInteger64vAPPLE = GLMessage_Function_glGetInteger64vAPPLE;
- static const Function glGetSyncivAPPLE = GLMessage_Function_glGetSyncivAPPLE;
- static const Function glCopyBufferSubDataNV = GLMessage_Function_glCopyBufferSubDataNV;
- static const Function glActiveShaderProgramEXT = GLMessage_Function_glActiveShaderProgramEXT;
- static const Function glAlphaFuncQCOM = GLMessage_Function_glAlphaFuncQCOM;
- static const Function glBeginQueryEXT = GLMessage_Function_glBeginQueryEXT;
- static const Function glBindProgramPipelineEXT = GLMessage_Function_glBindProgramPipelineEXT;
- static const Function glBlitFramebufferANGLE = GLMessage_Function_glBlitFramebufferANGLE;
- static const Function glCreateShaderProgramvEXT = GLMessage_Function_glCreateShaderProgramvEXT;
- static const Function glDeleteProgramPipelinesEXT = GLMessage_Function_glDeleteProgramPipelinesEXT;
- static const Function glDeleteQueriesEXT = GLMessage_Function_glDeleteQueriesEXT;
- static const Function glDrawBuffersNV = GLMessage_Function_glDrawBuffersNV;
- static const Function glEndQueryEXT = GLMessage_Function_glEndQueryEXT;
- static const Function glFramebufferTexture2DMultisampleEXT = GLMessage_Function_glFramebufferTexture2DMultisampleEXT;
- static const Function glGenProgramPipelinesEXT = GLMessage_Function_glGenProgramPipelinesEXT;
- static const Function glGenQueriesEXT = GLMessage_Function_glGenQueriesEXT;
- static const Function glGetGraphicsResetStatusEXT = GLMessage_Function_glGetGraphicsResetStatusEXT;
- static const Function glGetObjectLabelEXT = GLMessage_Function_glGetObjectLabelEXT;
- static const Function glGetProgramPipelineInfoLogEXT = GLMessage_Function_glGetProgramPipelineInfoLogEXT;
- static const Function glGetProgramPipelineivEXT = GLMessage_Function_glGetProgramPipelineivEXT;
- static const Function glGetQueryObjectuivEXT = GLMessage_Function_glGetQueryObjectuivEXT;
- static const Function glGetQueryivEXT = GLMessage_Function_glGetQueryivEXT;
- static const Function glGetnUniformfvEXT = GLMessage_Function_glGetnUniformfvEXT;
- static const Function glGetnUniformivEXT = GLMessage_Function_glGetnUniformivEXT;
- static const Function glInsertEventMarkerEXT = GLMessage_Function_glInsertEventMarkerEXT;
- static const Function glIsProgramPipelineEXT = GLMessage_Function_glIsProgramPipelineEXT;
- static const Function glIsQueryEXT = GLMessage_Function_glIsQueryEXT;
- static const Function glLabelObjectEXT = GLMessage_Function_glLabelObjectEXT;
- static const Function glPopGroupMarkerEXT = GLMessage_Function_glPopGroupMarkerEXT;
- static const Function glProgramParameteriEXT = GLMessage_Function_glProgramParameteriEXT;
- static const Function glProgramUniform1fEXT = GLMessage_Function_glProgramUniform1fEXT;
- static const Function glProgramUniform1fvEXT = GLMessage_Function_glProgramUniform1fvEXT;
- static const Function glProgramUniform1iEXT = GLMessage_Function_glProgramUniform1iEXT;
- static const Function glProgramUniform1ivEXT = GLMessage_Function_glProgramUniform1ivEXT;
- static const Function glProgramUniform2fEXT = GLMessage_Function_glProgramUniform2fEXT;
- static const Function glProgramUniform2fvEXT = GLMessage_Function_glProgramUniform2fvEXT;
- static const Function glProgramUniform2iEXT = GLMessage_Function_glProgramUniform2iEXT;
- static const Function glProgramUniform2ivEXT = GLMessage_Function_glProgramUniform2ivEXT;
- static const Function glProgramUniform3fEXT = GLMessage_Function_glProgramUniform3fEXT;
- static const Function glProgramUniform3fvEXT = GLMessage_Function_glProgramUniform3fvEXT;
- static const Function glProgramUniform3iEXT = GLMessage_Function_glProgramUniform3iEXT;
- static const Function glProgramUniform3ivEXT = GLMessage_Function_glProgramUniform3ivEXT;
- static const Function glProgramUniform4fEXT = GLMessage_Function_glProgramUniform4fEXT;
- static const Function glProgramUniform4fvEXT = GLMessage_Function_glProgramUniform4fvEXT;
- static const Function glProgramUniform4iEXT = GLMessage_Function_glProgramUniform4iEXT;
- static const Function glProgramUniform4ivEXT = GLMessage_Function_glProgramUniform4ivEXT;
- static const Function glProgramUniformMatrix2fvEXT = GLMessage_Function_glProgramUniformMatrix2fvEXT;
- static const Function glProgramUniformMatrix3fvEXT = GLMessage_Function_glProgramUniformMatrix3fvEXT;
- static const Function glProgramUniformMatrix4fvEXT = GLMessage_Function_glProgramUniformMatrix4fvEXT;
- static const Function glPushGroupMarkerEXT = GLMessage_Function_glPushGroupMarkerEXT;
- static const Function glReadBufferNV = GLMessage_Function_glReadBufferNV;
- static const Function glReadnPixelsEXT = GLMessage_Function_glReadnPixelsEXT;
- static const Function glRenderbufferStorageMultisampleANGLE = GLMessage_Function_glRenderbufferStorageMultisampleANGLE;
- static const Function glRenderbufferStorageMultisampleAPPLE = GLMessage_Function_glRenderbufferStorageMultisampleAPPLE;
- static const Function glRenderbufferStorageMultisampleEXT = GLMessage_Function_glRenderbufferStorageMultisampleEXT;
- static const Function glResolveMultisampleFramebufferAPPLE = GLMessage_Function_glResolveMultisampleFramebufferAPPLE;
- static const Function glTexStorage1DEXT = GLMessage_Function_glTexStorage1DEXT;
- static const Function glTexStorage2DEXT = GLMessage_Function_glTexStorage2DEXT;
- static const Function glTexStorage3DEXT = GLMessage_Function_glTexStorage3DEXT;
- static const Function glTextureStorage1DEXT = GLMessage_Function_glTextureStorage1DEXT;
- static const Function glTextureStorage2DEXT = GLMessage_Function_glTextureStorage2DEXT;
- static const Function glTextureStorage3DEXT = GLMessage_Function_glTextureStorage3DEXT;
- static const Function glUseProgramStagesEXT = GLMessage_Function_glUseProgramStagesEXT;
- static const Function glValidateProgramPipelineEXT = GLMessage_Function_glValidateProgramPipelineEXT;
- static const Function glCopyTextureLevelsAPPLE = GLMessage_Function_glCopyTextureLevelsAPPLE;
- static const Function glDebugMessageControlKHR = GLMessage_Function_glDebugMessageControlKHR;
- static const Function glDebugMessageInsertKHR = GLMessage_Function_glDebugMessageInsertKHR;
- static const Function glDebugMessageCallbackKHR = GLMessage_Function_glDebugMessageCallbackKHR;
- static const Function glGetDebugMessageLogKHR = GLMessage_Function_glGetDebugMessageLogKHR;
- static const Function glPushDebugGroupKHR = GLMessage_Function_glPushDebugGroupKHR;
- static const Function glPopDebugGroupKHR = GLMessage_Function_glPopDebugGroupKHR;
- static const Function glObjectLabelKHR = GLMessage_Function_glObjectLabelKHR;
- static const Function glGetObjectLabelKHR = GLMessage_Function_glGetObjectLabelKHR;
- static const Function glObjectPtrLabelKHR = GLMessage_Function_glObjectPtrLabelKHR;
- static const Function glGetObjectPtrLabelKHR = GLMessage_Function_glGetObjectPtrLabelKHR;
- static const Function glGetPointervKHR = GLMessage_Function_glGetPointervKHR;
- static const Function glDrawArraysInstancedANGLE = GLMessage_Function_glDrawArraysInstancedANGLE;
- static const Function glDrawElementsInstancedANGLE = GLMessage_Function_glDrawElementsInstancedANGLE;
- static const Function glVertexAttribDivisorANGLE = GLMessage_Function_glVertexAttribDivisorANGLE;
- static const Function glDrawArraysInstancedEXT = GLMessage_Function_glDrawArraysInstancedEXT;
- static const Function glDrawElementsInstancedEXT = GLMessage_Function_glDrawElementsInstancedEXT;
- static const Function glVertexAttribDivisorEXT = GLMessage_Function_glVertexAttribDivisorEXT;
- static const Function glDrawArraysInstancedNV = GLMessage_Function_glDrawArraysInstancedNV;
- static const Function glDrawElementsInstancedNV = GLMessage_Function_glDrawElementsInstancedNV;
- static const Function glVertexAttribDivisorNV = GLMessage_Function_glVertexAttribDivisorNV;
- static const Function glDrawBuffersEXT = GLMessage_Function_glDrawBuffersEXT;
- static const Function glReadBufferIndexedEXT = GLMessage_Function_glReadBufferIndexedEXT;
- static const Function glDrawBuffersIndexedEXT = GLMessage_Function_glDrawBuffersIndexedEXT;
- static const Function glGetIntegeri_vEXT = GLMessage_Function_glGetIntegeri_vEXT;
- static const Function glMapBufferRangeEXT = GLMessage_Function_glMapBufferRangeEXT;
- static const Function glFlushMappedBufferRangeEXT = GLMessage_Function_glFlushMappedBufferRangeEXT;
- static const Function glQueryCounterEXT = GLMessage_Function_glQueryCounterEXT;
- static const Function glGetQueryObjecti64vEXT = GLMessage_Function_glGetQueryObjecti64vEXT;
- static const Function glGetQueryObjectivEXT = GLMessage_Function_glGetQueryObjectivEXT;
- static const Function glGetQueryObjectui64vEXT = GLMessage_Function_glGetQueryObjectui64vEXT;
- static const Function glGetTranslatedShaderSourceANGLE = GLMessage_Function_glGetTranslatedShaderSourceANGLE;
- static const Function glMinSampleShadingOES = GLMessage_Function_glMinSampleShadingOES;
- static const Function glMultiTexCoord1bOES = GLMessage_Function_glMultiTexCoord1bOES;
- static const Function glMultiTexCoord1bvOES = GLMessage_Function_glMultiTexCoord1bvOES;
- static const Function glMultiTexCoord2bOES = GLMessage_Function_glMultiTexCoord2bOES;
- static const Function glMultiTexCoord2bvOES = GLMessage_Function_glMultiTexCoord2bvOES;
- static const Function glMultiTexCoord3bOES = GLMessage_Function_glMultiTexCoord3bOES;
- static const Function glMultiTexCoord3bvOES = GLMessage_Function_glMultiTexCoord3bvOES;
- static const Function glMultiTexCoord4bOES = GLMessage_Function_glMultiTexCoord4bOES;
- static const Function glMultiTexCoord4bvOES = GLMessage_Function_glMultiTexCoord4bvOES;
- static const Function glTexCoord1bOES = GLMessage_Function_glTexCoord1bOES;
- static const Function glTexCoord1bvOES = GLMessage_Function_glTexCoord1bvOES;
- static const Function glTexCoord2bOES = GLMessage_Function_glTexCoord2bOES;
- static const Function glTexCoord2bvOES = GLMessage_Function_glTexCoord2bvOES;
- static const Function glTexCoord3bOES = GLMessage_Function_glTexCoord3bOES;
- static const Function glTexCoord3bvOES = GLMessage_Function_glTexCoord3bvOES;
- static const Function glTexCoord4bOES = GLMessage_Function_glTexCoord4bOES;
- static const Function glTexCoord4bvOES = GLMessage_Function_glTexCoord4bvOES;
- static const Function glVertex2bOES = GLMessage_Function_glVertex2bOES;
- static const Function glVertex2bvOES = GLMessage_Function_glVertex2bvOES;
- static const Function glVertex3bOES = GLMessage_Function_glVertex3bOES;
- static const Function glVertex3bvOES = GLMessage_Function_glVertex3bvOES;
- static const Function glVertex4bOES = GLMessage_Function_glVertex4bOES;
- static const Function glVertex4bvOES = GLMessage_Function_glVertex4bvOES;
- static const Function glProgramUniform1uiEXT = GLMessage_Function_glProgramUniform1uiEXT;
- static const Function glProgramUniform2uiEXT = GLMessage_Function_glProgramUniform2uiEXT;
- static const Function glProgramUniform3uiEXT = GLMessage_Function_glProgramUniform3uiEXT;
- static const Function glProgramUniform4uiEXT = GLMessage_Function_glProgramUniform4uiEXT;
- static const Function glProgramUniform1uivEXT = GLMessage_Function_glProgramUniform1uivEXT;
- static const Function glProgramUniform2uivEXT = GLMessage_Function_glProgramUniform2uivEXT;
- static const Function glProgramUniform3uivEXT = GLMessage_Function_glProgramUniform3uivEXT;
- static const Function glProgramUniform4uivEXT = GLMessage_Function_glProgramUniform4uivEXT;
- static const Function glProgramUniformMatrix2x3fvEXT = GLMessage_Function_glProgramUniformMatrix2x3fvEXT;
- static const Function glProgramUniformMatrix3x2fvEXT = GLMessage_Function_glProgramUniformMatrix3x2fvEXT;
- static const Function glProgramUniformMatrix2x4fvEXT = GLMessage_Function_glProgramUniformMatrix2x4fvEXT;
- static const Function glProgramUniformMatrix4x2fvEXT = GLMessage_Function_glProgramUniformMatrix4x2fvEXT;
- static const Function glProgramUniformMatrix3x4fvEXT = GLMessage_Function_glProgramUniformMatrix3x4fvEXT;
- static const Function glProgramUniformMatrix4x3fvEXT = GLMessage_Function_glProgramUniformMatrix4x3fvEXT;
- static const Function glRenderbufferStorageMultisampleNV = GLMessage_Function_glRenderbufferStorageMultisampleNV;
- static const Function glSampleCoverageOES = GLMessage_Function_glSampleCoverageOES;
- static const Function glTexStorage3DMultisampleOES = GLMessage_Function_glTexStorage3DMultisampleOES;
- static const Function glUniformMatrix2x3fvNV = GLMessage_Function_glUniformMatrix2x3fvNV;
- static const Function glUniformMatrix3x2fvNV = GLMessage_Function_glUniformMatrix3x2fvNV;
- static const Function glUniformMatrix2x4fvNV = GLMessage_Function_glUniformMatrix2x4fvNV;
- static const Function glUniformMatrix4x2fvNV = GLMessage_Function_glUniformMatrix4x2fvNV;
- static const Function glUniformMatrix3x4fvNV = GLMessage_Function_glUniformMatrix3x4fvNV;
- static const Function glUniformMatrix4x3fvNV = GLMessage_Function_glUniformMatrix4x3fvNV;
- static const Function glActiveShaderProgram = GLMessage_Function_glActiveShaderProgram;
- static const Function glBindImageTexture = GLMessage_Function_glBindImageTexture;
- static const Function glBindProgramPipeline = GLMessage_Function_glBindProgramPipeline;
- static const Function glBindVertexBuffer = GLMessage_Function_glBindVertexBuffer;
- static const Function glCreateShaderProgramv = GLMessage_Function_glCreateShaderProgramv;
- static const Function glDeleteProgramPipelines = GLMessage_Function_glDeleteProgramPipelines;
- static const Function glDispatchCompute = GLMessage_Function_glDispatchCompute;
- static const Function glDispatchComputeIndirect = GLMessage_Function_glDispatchComputeIndirect;
- static const Function glDrawArraysIndirect = GLMessage_Function_glDrawArraysIndirect;
- static const Function glDrawElementsIndirect = GLMessage_Function_glDrawElementsIndirect;
- static const Function glFramebufferParameteri = GLMessage_Function_glFramebufferParameteri;
- static const Function glGenProgramPipelines = GLMessage_Function_glGenProgramPipelines;
- static const Function glGetBooleani_v = GLMessage_Function_glGetBooleani_v;
- static const Function glGetFramebufferParameteriv = GLMessage_Function_glGetFramebufferParameteriv;
- static const Function glGetMultisamplefv = GLMessage_Function_glGetMultisamplefv;
- static const Function glGetProgramInterfaceiv = GLMessage_Function_glGetProgramInterfaceiv;
- static const Function glGetProgramPipelineInfoLog = GLMessage_Function_glGetProgramPipelineInfoLog;
- static const Function glGetProgramPipelineiv = GLMessage_Function_glGetProgramPipelineiv;
- static const Function glGetProgramResourceIndex = GLMessage_Function_glGetProgramResourceIndex;
- static const Function glGetProgramResourceLocation = GLMessage_Function_glGetProgramResourceLocation;
- static const Function glGetProgramResourceName = GLMessage_Function_glGetProgramResourceName;
- static const Function glGetProgramResourceiv = GLMessage_Function_glGetProgramResourceiv;
- static const Function glGetTexLevelParameterfv = GLMessage_Function_glGetTexLevelParameterfv;
- static const Function glGetTexLevelParameteriv = GLMessage_Function_glGetTexLevelParameteriv;
- static const Function glIsProgramPipeline = GLMessage_Function_glIsProgramPipeline;
- static const Function glMemoryBarrier = GLMessage_Function_glMemoryBarrier;
- static const Function glMemoryBarrierByRegion = GLMessage_Function_glMemoryBarrierByRegion;
- static const Function glProgramUniform1f = GLMessage_Function_glProgramUniform1f;
- static const Function glProgramUniform1fv = GLMessage_Function_glProgramUniform1fv;
- static const Function glProgramUniform1i = GLMessage_Function_glProgramUniform1i;
- static const Function glProgramUniform1iv = GLMessage_Function_glProgramUniform1iv;
- static const Function glProgramUniform1ui = GLMessage_Function_glProgramUniform1ui;
- static const Function glProgramUniform1uiv = GLMessage_Function_glProgramUniform1uiv;
- static const Function glProgramUniform2f = GLMessage_Function_glProgramUniform2f;
- static const Function glProgramUniform2fv = GLMessage_Function_glProgramUniform2fv;
- static const Function glProgramUniform2i = GLMessage_Function_glProgramUniform2i;
- static const Function glProgramUniform2iv = GLMessage_Function_glProgramUniform2iv;
- static const Function glProgramUniform2ui = GLMessage_Function_glProgramUniform2ui;
- static const Function glProgramUniform2uiv = GLMessage_Function_glProgramUniform2uiv;
- static const Function glProgramUniform3f = GLMessage_Function_glProgramUniform3f;
- static const Function glProgramUniform3fv = GLMessage_Function_glProgramUniform3fv;
- static const Function glProgramUniform3i = GLMessage_Function_glProgramUniform3i;
- static const Function glProgramUniform3iv = GLMessage_Function_glProgramUniform3iv;
- static const Function glProgramUniform3ui = GLMessage_Function_glProgramUniform3ui;
- static const Function glProgramUniform3uiv = GLMessage_Function_glProgramUniform3uiv;
- static const Function glProgramUniform4f = GLMessage_Function_glProgramUniform4f;
- static const Function glProgramUniform4fv = GLMessage_Function_glProgramUniform4fv;
- static const Function glProgramUniform4i = GLMessage_Function_glProgramUniform4i;
- static const Function glProgramUniform4iv = GLMessage_Function_glProgramUniform4iv;
- static const Function glProgramUniform4ui = GLMessage_Function_glProgramUniform4ui;
- static const Function glProgramUniform4uiv = GLMessage_Function_glProgramUniform4uiv;
- static const Function glProgramUniformMatrix2fv = GLMessage_Function_glProgramUniformMatrix2fv;
- static const Function glProgramUniformMatrix2x3fv = GLMessage_Function_glProgramUniformMatrix2x3fv;
- static const Function glProgramUniformMatrix2x4fv = GLMessage_Function_glProgramUniformMatrix2x4fv;
- static const Function glProgramUniformMatrix3fv = GLMessage_Function_glProgramUniformMatrix3fv;
- static const Function glProgramUniformMatrix3x2fv = GLMessage_Function_glProgramUniformMatrix3x2fv;
- static const Function glProgramUniformMatrix3x4fv = GLMessage_Function_glProgramUniformMatrix3x4fv;
- static const Function glProgramUniformMatrix4fv = GLMessage_Function_glProgramUniformMatrix4fv;
- static const Function glProgramUniformMatrix4x2fv = GLMessage_Function_glProgramUniformMatrix4x2fv;
- static const Function glProgramUniformMatrix4x3fv = GLMessage_Function_glProgramUniformMatrix4x3fv;
- static const Function glSampleMaski = GLMessage_Function_glSampleMaski;
- static const Function glTexStorage2DMultisample = GLMessage_Function_glTexStorage2DMultisample;
- static const Function glUseProgramStages = GLMessage_Function_glUseProgramStages;
- static const Function glValidateProgramPipeline = GLMessage_Function_glValidateProgramPipeline;
- static const Function glVertexAttribBinding = GLMessage_Function_glVertexAttribBinding;
- static const Function glVertexAttribFormat = GLMessage_Function_glVertexAttribFormat;
- static const Function glVertexAttribIFormat = GLMessage_Function_glVertexAttribIFormat;
- static const Function glVertexBindingDivisor = GLMessage_Function_glVertexBindingDivisor;
- static const Function glBlendEquationSeparateiEXT = GLMessage_Function_glBlendEquationSeparateiEXT;
- static const Function glBlendEquationiEXT = GLMessage_Function_glBlendEquationiEXT;
- static const Function glBlendFuncSeparateiEXT = GLMessage_Function_glBlendFuncSeparateiEXT;
- static const Function glBlendFunciEXT = GLMessage_Function_glBlendFunciEXT;
- static const Function glColorMaskiEXT = GLMessage_Function_glColorMaskiEXT;
- static const Function glCopyImageSubDataEXT = GLMessage_Function_glCopyImageSubDataEXT;
- static const Function glDisableiEXT = GLMessage_Function_glDisableiEXT;
- static const Function glEnableiEXT = GLMessage_Function_glEnableiEXT;
- static const Function glFramebufferTextureEXT = GLMessage_Function_glFramebufferTextureEXT;
- static const Function glGetSamplerParameterIivEXT = GLMessage_Function_glGetSamplerParameterIivEXT;
- static const Function glGetSamplerParameterIuivEXT = GLMessage_Function_glGetSamplerParameterIuivEXT;
- static const Function glGetTexParameterIivEXT = GLMessage_Function_glGetTexParameterIivEXT;
- static const Function glGetTexParameterIuivEXT = GLMessage_Function_glGetTexParameterIuivEXT;
- static const Function glIsEnablediEXT = GLMessage_Function_glIsEnablediEXT;
- static const Function glPatchParameteriEXT = GLMessage_Function_glPatchParameteriEXT;
- static const Function glPrimitiveBoundingBoxEXT = GLMessage_Function_glPrimitiveBoundingBoxEXT;
- static const Function glSamplerParameterIivEXT = GLMessage_Function_glSamplerParameterIivEXT;
- static const Function glSamplerParameterIuivEXT = GLMessage_Function_glSamplerParameterIuivEXT;
- static const Function glTexBufferEXT = GLMessage_Function_glTexBufferEXT;
- static const Function glTexBufferRangeEXT = GLMessage_Function_glTexBufferRangeEXT;
- static const Function glTexParameterIivEXT = GLMessage_Function_glTexParameterIivEXT;
- static const Function glTexParameterIuivEXT = GLMessage_Function_glTexParameterIuivEXT;
- static const Function glTextureViewEXT = GLMessage_Function_glTextureViewEXT;
- static const Function eglGetDisplay = GLMessage_Function_eglGetDisplay;
- static const Function eglInitialize = GLMessage_Function_eglInitialize;
- static const Function eglTerminate = GLMessage_Function_eglTerminate;
- static const Function eglGetConfigs = GLMessage_Function_eglGetConfigs;
- static const Function eglChooseConfig = GLMessage_Function_eglChooseConfig;
- static const Function eglGetConfigAttrib = GLMessage_Function_eglGetConfigAttrib;
- static const Function eglCreateWindowSurface = GLMessage_Function_eglCreateWindowSurface;
- static const Function eglCreatePixmapSurface = GLMessage_Function_eglCreatePixmapSurface;
- static const Function eglCreatePbufferSurface = GLMessage_Function_eglCreatePbufferSurface;
- static const Function eglDestroySurface = GLMessage_Function_eglDestroySurface;
- static const Function eglQuerySurface = GLMessage_Function_eglQuerySurface;
- static const Function eglCreateContext = GLMessage_Function_eglCreateContext;
- static const Function eglDestroyContext = GLMessage_Function_eglDestroyContext;
- static const Function eglMakeCurrent = GLMessage_Function_eglMakeCurrent;
- static const Function eglGetCurrentContext = GLMessage_Function_eglGetCurrentContext;
- static const Function eglGetCurrentSurface = GLMessage_Function_eglGetCurrentSurface;
- static const Function eglGetCurrentDisplay = GLMessage_Function_eglGetCurrentDisplay;
- static const Function eglQueryContext = GLMessage_Function_eglQueryContext;
- static const Function eglWaitGL = GLMessage_Function_eglWaitGL;
- static const Function eglWaitNative = GLMessage_Function_eglWaitNative;
- static const Function eglSwapBuffers = GLMessage_Function_eglSwapBuffers;
- static const Function eglCopyBuffers = GLMessage_Function_eglCopyBuffers;
- static const Function eglGetError = GLMessage_Function_eglGetError;
- static const Function eglQueryString = GLMessage_Function_eglQueryString;
- static const Function eglGetProcAddress = GLMessage_Function_eglGetProcAddress;
- static const Function eglSurfaceAttrib = GLMessage_Function_eglSurfaceAttrib;
- static const Function eglBindTexImage = GLMessage_Function_eglBindTexImage;
- static const Function eglReleaseTexImage = GLMessage_Function_eglReleaseTexImage;
- static const Function eglSwapInterval = GLMessage_Function_eglSwapInterval;
- static const Function eglBindAPI = GLMessage_Function_eglBindAPI;
- static const Function eglQueryAPI = GLMessage_Function_eglQueryAPI;
- static const Function eglWaitClient = GLMessage_Function_eglWaitClient;
- static const Function eglReleaseThread = GLMessage_Function_eglReleaseThread;
- static const Function eglCreatePbufferFromClientBuffer = GLMessage_Function_eglCreatePbufferFromClientBuffer;
- static const Function eglLockSurfaceKHR = GLMessage_Function_eglLockSurfaceKHR;
- static const Function eglUnlockSurfaceKHR = GLMessage_Function_eglUnlockSurfaceKHR;
- static const Function eglCreateImageKHR = GLMessage_Function_eglCreateImageKHR;
- static const Function eglDestroyImageKHR = GLMessage_Function_eglDestroyImageKHR;
- static const Function eglCreateSyncKHR = GLMessage_Function_eglCreateSyncKHR;
- static const Function eglDestroySyncKHR = GLMessage_Function_eglDestroySyncKHR;
- static const Function eglClientWaitSyncKHR = GLMessage_Function_eglClientWaitSyncKHR;
- static const Function eglGetSyncAttribKHR = GLMessage_Function_eglGetSyncAttribKHR;
- static const Function eglSetSwapRectangleANDROID = GLMessage_Function_eglSetSwapRectangleANDROID;
- static const Function eglGetRenderBufferANDROID = GLMessage_Function_eglGetRenderBufferANDROID;
- static const Function eglGetSystemTimeFrequencyNV = GLMessage_Function_eglGetSystemTimeFrequencyNV;
- static const Function eglGetSystemTimeNV = GLMessage_Function_eglGetSystemTimeNV;
- static const Function invalid = GLMessage_Function_invalid;
- static const Function glVertexAttribPointerData = GLMessage_Function_glVertexAttribPointerData;
- static inline bool Function_IsValid(int value) {
- return GLMessage_Function_IsValid(value);
- }
- static const Function Function_MIN =
- GLMessage_Function_Function_MIN;
- static const Function Function_MAX =
- GLMessage_Function_Function_MAX;
- static const int Function_ARRAYSIZE =
- GLMessage_Function_Function_ARRAYSIZE;
-
- // accessors -------------------------------------------------------
-
- // required int32 context_id = 1;
- inline bool has_context_id() const;
- inline void clear_context_id();
- static const int kContextIdFieldNumber = 1;
- inline ::google::protobuf::int32 context_id() const;
- inline void set_context_id(::google::protobuf::int32 value);
-
- // required int64 start_time = 2;
- inline bool has_start_time() const;
- inline void clear_start_time();
- static const int kStartTimeFieldNumber = 2;
- inline ::google::protobuf::int64 start_time() const;
- inline void set_start_time(::google::protobuf::int64 value);
-
- // required int32 duration = 3;
- inline bool has_duration() const;
- inline void clear_duration();
- static const int kDurationFieldNumber = 3;
- inline ::google::protobuf::int32 duration() const;
- inline void set_duration(::google::protobuf::int32 value);
-
- // required .android.gltrace.GLMessage.Function function = 4 [default = invalid];
- inline bool has_function() const;
- inline void clear_function();
- static const int kFunctionFieldNumber = 4;
- inline ::android::gltrace::GLMessage_Function function() const;
- inline void set_function(::android::gltrace::GLMessage_Function value);
-
- // repeated .android.gltrace.GLMessage.DataType args = 5;
- inline int args_size() const;
- inline void clear_args();
- static const int kArgsFieldNumber = 5;
- inline const ::android::gltrace::GLMessage_DataType& args(int index) const;
- inline ::android::gltrace::GLMessage_DataType* mutable_args(int index);
- inline ::android::gltrace::GLMessage_DataType* add_args();
- inline const ::google::protobuf::RepeatedPtrField< ::android::gltrace::GLMessage_DataType >&
- args() const;
- inline ::google::protobuf::RepeatedPtrField< ::android::gltrace::GLMessage_DataType >*
- mutable_args();
-
- // optional .android.gltrace.GLMessage.DataType returnValue = 6;
- inline bool has_returnvalue() const;
- inline void clear_returnvalue();
- static const int kReturnValueFieldNumber = 6;
- inline const ::android::gltrace::GLMessage_DataType& returnvalue() const;
- inline ::android::gltrace::GLMessage_DataType* mutable_returnvalue();
-
- // optional .android.gltrace.GLMessage.FrameBuffer fb = 7;
- inline bool has_fb() const;
- inline void clear_fb();
- static const int kFbFieldNumber = 7;
- inline const ::android::gltrace::GLMessage_FrameBuffer& fb() const;
- inline ::android::gltrace::GLMessage_FrameBuffer* mutable_fb();
-
- // optional int32 threadtime = 8;
- inline bool has_threadtime() const;
- inline void clear_threadtime();
- static const int kThreadtimeFieldNumber = 8;
- inline ::google::protobuf::int32 threadtime() const;
- inline void set_threadtime(::google::protobuf::int32 value);
-
- // @@protoc_insertion_point(class_scope:android.gltrace.GLMessage)
- private:
- mutable int _cached_size_;
-
- ::google::protobuf::int32 context_id_;
- ::google::protobuf::int64 start_time_;
- ::google::protobuf::int32 duration_;
- int function_;
- ::google::protobuf::RepeatedPtrField< ::android::gltrace::GLMessage_DataType > args_;
- ::android::gltrace::GLMessage_DataType* returnvalue_;
- ::android::gltrace::GLMessage_FrameBuffer* fb_;
- ::google::protobuf::int32 threadtime_;
- friend void protobuf_AddDesc_gltrace_2eproto();
- friend void protobuf_AssignDesc_gltrace_2eproto();
- friend void protobuf_ShutdownFile_gltrace_2eproto();
-
- ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-
- // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
- inline bool _has_bit(int index) const {
- return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
- }
- inline void _set_bit(int index) {
- _has_bits_[index / 32] |= (1u << (index % 32));
- }
- inline void _clear_bit(int index) {
- _has_bits_[index / 32] &= ~(1u << (index % 32));
- }
-
- void InitAsDefaultInstance();
- static GLMessage* default_instance_;
-};
-// ===================================================================
-
-
-// ===================================================================
-
-// GLMessage_DataType
-
-// required .android.gltrace.GLMessage.DataType.Type type = 1 [default = VOID];
-inline bool GLMessage_DataType::has_type() const {
- return _has_bit(0);
-}
-inline void GLMessage_DataType::clear_type() {
- type_ = 1;
- _clear_bit(0);
-}
-inline ::android::gltrace::GLMessage_DataType_Type GLMessage_DataType::type() const {
- return static_cast< ::android::gltrace::GLMessage_DataType_Type >(type_);
-}
-inline void GLMessage_DataType::set_type(::android::gltrace::GLMessage_DataType_Type value) {
- GOOGLE_DCHECK(::android::gltrace::GLMessage_DataType_Type_IsValid(value));
- _set_bit(0);
- type_ = value;
-}
-
-// required bool isArray = 2 [default = false];
-inline bool GLMessage_DataType::has_isarray() const {
- return _has_bit(1);
-}
-inline void GLMessage_DataType::clear_isarray() {
- isarray_ = false;
- _clear_bit(1);
-}
-inline bool GLMessage_DataType::isarray() const {
- return isarray_;
-}
-inline void GLMessage_DataType::set_isarray(bool value) {
- _set_bit(1);
- isarray_ = value;
-}
-
-// repeated int32 intValue = 3;
-inline int GLMessage_DataType::intvalue_size() const {
- return intvalue_.size();
-}
-inline void GLMessage_DataType::clear_intvalue() {
- intvalue_.Clear();
-}
-inline ::google::protobuf::int32 GLMessage_DataType::intvalue(int index) const {
- return intvalue_.Get(index);
-}
-inline void GLMessage_DataType::set_intvalue(int index, ::google::protobuf::int32 value) {
- intvalue_.Set(index, value);
-}
-inline void GLMessage_DataType::add_intvalue(::google::protobuf::int32 value) {
- intvalue_.Add(value);
-}
-inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
-GLMessage_DataType::intvalue() const {
- return intvalue_;
-}
-inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
-GLMessage_DataType::mutable_intvalue() {
- return &intvalue_;
-}
-
-// repeated float floatValue = 4;
-inline int GLMessage_DataType::floatvalue_size() const {
- return floatvalue_.size();
-}
-inline void GLMessage_DataType::clear_floatvalue() {
- floatvalue_.Clear();
-}
-inline float GLMessage_DataType::floatvalue(int index) const {
- return floatvalue_.Get(index);
-}
-inline void GLMessage_DataType::set_floatvalue(int index, float value) {
- floatvalue_.Set(index, value);
-}
-inline void GLMessage_DataType::add_floatvalue(float value) {
- floatvalue_.Add(value);
-}
-inline const ::google::protobuf::RepeatedField< float >&
-GLMessage_DataType::floatvalue() const {
- return floatvalue_;
-}
-inline ::google::protobuf::RepeatedField< float >*
-GLMessage_DataType::mutable_floatvalue() {
- return &floatvalue_;
-}
-
-// repeated bytes charValue = 5;
-inline int GLMessage_DataType::charvalue_size() const {
- return charvalue_.size();
-}
-inline void GLMessage_DataType::clear_charvalue() {
- charvalue_.Clear();
-}
-inline const ::std::string& GLMessage_DataType::charvalue(int index) const {
- return charvalue_.Get(index);
-}
-inline ::std::string* GLMessage_DataType::mutable_charvalue(int index) {
- return charvalue_.Mutable(index);
-}
-inline void GLMessage_DataType::set_charvalue(int index, const ::std::string& value) {
- charvalue_.Mutable(index)->assign(value);
-}
-inline void GLMessage_DataType::set_charvalue(int index, const char* value) {
- charvalue_.Mutable(index)->assign(value);
-}
-inline void GLMessage_DataType::set_charvalue(int index, const void* value, size_t size) {
- charvalue_.Mutable(index)->assign(
- reinterpret_cast<const char*>(value), size);
-}
-inline ::std::string* GLMessage_DataType::add_charvalue() {
- return charvalue_.Add();
-}
-inline void GLMessage_DataType::add_charvalue(const ::std::string& value) {
- charvalue_.Add()->assign(value);
-}
-inline void GLMessage_DataType::add_charvalue(const char* value) {
- charvalue_.Add()->assign(value);
-}
-inline void GLMessage_DataType::add_charvalue(const void* value, size_t size) {
- charvalue_.Add()->assign(reinterpret_cast<const char*>(value), size);
-}
-inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
-GLMessage_DataType::charvalue() const {
- return charvalue_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::std::string>*
-GLMessage_DataType::mutable_charvalue() {
- return &charvalue_;
-}
-
-// repeated bytes rawBytes = 6;
-inline int GLMessage_DataType::rawbytes_size() const {
- return rawbytes_.size();
-}
-inline void GLMessage_DataType::clear_rawbytes() {
- rawbytes_.Clear();
-}
-inline const ::std::string& GLMessage_DataType::rawbytes(int index) const {
- return rawbytes_.Get(index);
-}
-inline ::std::string* GLMessage_DataType::mutable_rawbytes(int index) {
- return rawbytes_.Mutable(index);
-}
-inline void GLMessage_DataType::set_rawbytes(int index, const ::std::string& value) {
- rawbytes_.Mutable(index)->assign(value);
-}
-inline void GLMessage_DataType::set_rawbytes(int index, const char* value) {
- rawbytes_.Mutable(index)->assign(value);
-}
-inline void GLMessage_DataType::set_rawbytes(int index, const void* value, size_t size) {
- rawbytes_.Mutable(index)->assign(
- reinterpret_cast<const char*>(value), size);
-}
-inline ::std::string* GLMessage_DataType::add_rawbytes() {
- return rawbytes_.Add();
-}
-inline void GLMessage_DataType::add_rawbytes(const ::std::string& value) {
- rawbytes_.Add()->assign(value);
-}
-inline void GLMessage_DataType::add_rawbytes(const char* value) {
- rawbytes_.Add()->assign(value);
-}
-inline void GLMessage_DataType::add_rawbytes(const void* value, size_t size) {
- rawbytes_.Add()->assign(reinterpret_cast<const char*>(value), size);
-}
-inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
-GLMessage_DataType::rawbytes() const {
- return rawbytes_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::std::string>*
-GLMessage_DataType::mutable_rawbytes() {
- return &rawbytes_;
-}
-
-// repeated bool boolValue = 7;
-inline int GLMessage_DataType::boolvalue_size() const {
- return boolvalue_.size();
-}
-inline void GLMessage_DataType::clear_boolvalue() {
- boolvalue_.Clear();
-}
-inline bool GLMessage_DataType::boolvalue(int index) const {
- return boolvalue_.Get(index);
-}
-inline void GLMessage_DataType::set_boolvalue(int index, bool value) {
- boolvalue_.Set(index, value);
-}
-inline void GLMessage_DataType::add_boolvalue(bool value) {
- boolvalue_.Add(value);
-}
-inline const ::google::protobuf::RepeatedField< bool >&
-GLMessage_DataType::boolvalue() const {
- return boolvalue_;
-}
-inline ::google::protobuf::RepeatedField< bool >*
-GLMessage_DataType::mutable_boolvalue() {
- return &boolvalue_;
-}
-
-// repeated int64 int64Value = 8;
-inline int GLMessage_DataType::int64value_size() const {
- return int64value_.size();
-}
-inline void GLMessage_DataType::clear_int64value() {
- int64value_.Clear();
-}
-inline ::google::protobuf::int64 GLMessage_DataType::int64value(int index) const {
- return int64value_.Get(index);
-}
-inline void GLMessage_DataType::set_int64value(int index, ::google::protobuf::int64 value) {
- int64value_.Set(index, value);
-}
-inline void GLMessage_DataType::add_int64value(::google::protobuf::int64 value) {
- int64value_.Add(value);
-}
-inline const ::google::protobuf::RepeatedField< ::google::protobuf::int64 >&
-GLMessage_DataType::int64value() const {
- return int64value_;
-}
-inline ::google::protobuf::RepeatedField< ::google::protobuf::int64 >*
-GLMessage_DataType::mutable_int64value() {
- return &int64value_;
-}
-
-// -------------------------------------------------------------------
-
-// GLMessage_FrameBuffer
-
-// required int32 width = 1;
-inline bool GLMessage_FrameBuffer::has_width() const {
- return _has_bit(0);
-}
-inline void GLMessage_FrameBuffer::clear_width() {
- width_ = 0;
- _clear_bit(0);
-}
-inline ::google::protobuf::int32 GLMessage_FrameBuffer::width() const {
- return width_;
-}
-inline void GLMessage_FrameBuffer::set_width(::google::protobuf::int32 value) {
- _set_bit(0);
- width_ = value;
-}
-
-// required int32 height = 2;
-inline bool GLMessage_FrameBuffer::has_height() const {
- return _has_bit(1);
-}
-inline void GLMessage_FrameBuffer::clear_height() {
- height_ = 0;
- _clear_bit(1);
-}
-inline ::google::protobuf::int32 GLMessage_FrameBuffer::height() const {
- return height_;
-}
-inline void GLMessage_FrameBuffer::set_height(::google::protobuf::int32 value) {
- _set_bit(1);
- height_ = value;
-}
-
-// repeated bytes contents = 3;
-inline int GLMessage_FrameBuffer::contents_size() const {
- return contents_.size();
-}
-inline void GLMessage_FrameBuffer::clear_contents() {
- contents_.Clear();
-}
-inline const ::std::string& GLMessage_FrameBuffer::contents(int index) const {
- return contents_.Get(index);
-}
-inline ::std::string* GLMessage_FrameBuffer::mutable_contents(int index) {
- return contents_.Mutable(index);
-}
-inline void GLMessage_FrameBuffer::set_contents(int index, const ::std::string& value) {
- contents_.Mutable(index)->assign(value);
-}
-inline void GLMessage_FrameBuffer::set_contents(int index, const char* value) {
- contents_.Mutable(index)->assign(value);
-}
-inline void GLMessage_FrameBuffer::set_contents(int index, const void* value, size_t size) {
- contents_.Mutable(index)->assign(
- reinterpret_cast<const char*>(value), size);
-}
-inline ::std::string* GLMessage_FrameBuffer::add_contents() {
- return contents_.Add();
-}
-inline void GLMessage_FrameBuffer::add_contents(const ::std::string& value) {
- contents_.Add()->assign(value);
-}
-inline void GLMessage_FrameBuffer::add_contents(const char* value) {
- contents_.Add()->assign(value);
-}
-inline void GLMessage_FrameBuffer::add_contents(const void* value, size_t size) {
- contents_.Add()->assign(reinterpret_cast<const char*>(value), size);
-}
-inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
-GLMessage_FrameBuffer::contents() const {
- return contents_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::std::string>*
-GLMessage_FrameBuffer::mutable_contents() {
- return &contents_;
-}
-
-// -------------------------------------------------------------------
-
-// GLMessage
-
-// required int32 context_id = 1;
-inline bool GLMessage::has_context_id() const {
- return _has_bit(0);
-}
-inline void GLMessage::clear_context_id() {
- context_id_ = 0;
- _clear_bit(0);
-}
-inline ::google::protobuf::int32 GLMessage::context_id() const {
- return context_id_;
-}
-inline void GLMessage::set_context_id(::google::protobuf::int32 value) {
- _set_bit(0);
- context_id_ = value;
-}
-
-// required int64 start_time = 2;
-inline bool GLMessage::has_start_time() const {
- return _has_bit(1);
-}
-inline void GLMessage::clear_start_time() {
- start_time_ = GOOGLE_LONGLONG(0);
- _clear_bit(1);
-}
-inline ::google::protobuf::int64 GLMessage::start_time() const {
- return start_time_;
-}
-inline void GLMessage::set_start_time(::google::protobuf::int64 value) {
- _set_bit(1);
- start_time_ = value;
-}
-
-// required int32 duration = 3;
-inline bool GLMessage::has_duration() const {
- return _has_bit(2);
-}
-inline void GLMessage::clear_duration() {
- duration_ = 0;
- _clear_bit(2);
-}
-inline ::google::protobuf::int32 GLMessage::duration() const {
- return duration_;
-}
-inline void GLMessage::set_duration(::google::protobuf::int32 value) {
- _set_bit(2);
- duration_ = value;
-}
-
-// required .android.gltrace.GLMessage.Function function = 4 [default = invalid];
-inline bool GLMessage::has_function() const {
- return _has_bit(3);
-}
-inline void GLMessage::clear_function() {
- function_ = 3000;
- _clear_bit(3);
-}
-inline ::android::gltrace::GLMessage_Function GLMessage::function() const {
- return static_cast< ::android::gltrace::GLMessage_Function >(function_);
-}
-inline void GLMessage::set_function(::android::gltrace::GLMessage_Function value) {
- GOOGLE_DCHECK(::android::gltrace::GLMessage_Function_IsValid(value));
- _set_bit(3);
- function_ = value;
-}
-
-// repeated .android.gltrace.GLMessage.DataType args = 5;
-inline int GLMessage::args_size() const {
- return args_.size();
-}
-inline void GLMessage::clear_args() {
- args_.Clear();
-}
-inline const ::android::gltrace::GLMessage_DataType& GLMessage::args(int index) const {
- return args_.Get(index);
-}
-inline ::android::gltrace::GLMessage_DataType* GLMessage::mutable_args(int index) {
- return args_.Mutable(index);
-}
-inline ::android::gltrace::GLMessage_DataType* GLMessage::add_args() {
- return args_.Add();
-}
-inline const ::google::protobuf::RepeatedPtrField< ::android::gltrace::GLMessage_DataType >&
-GLMessage::args() const {
- return args_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::android::gltrace::GLMessage_DataType >*
-GLMessage::mutable_args() {
- return &args_;
-}
-
-// optional .android.gltrace.GLMessage.DataType returnValue = 6;
-inline bool GLMessage::has_returnvalue() const {
- return _has_bit(5);
-}
-inline void GLMessage::clear_returnvalue() {
- if (returnvalue_ != NULL) returnvalue_->::android::gltrace::GLMessage_DataType::Clear();
- _clear_bit(5);
-}
-inline const ::android::gltrace::GLMessage_DataType& GLMessage::returnvalue() const {
- return returnvalue_ != NULL ? *returnvalue_ : *default_instance_->returnvalue_;
-}
-inline ::android::gltrace::GLMessage_DataType* GLMessage::mutable_returnvalue() {
- _set_bit(5);
- if (returnvalue_ == NULL) returnvalue_ = new ::android::gltrace::GLMessage_DataType;
- return returnvalue_;
-}
-
-// optional .android.gltrace.GLMessage.FrameBuffer fb = 7;
-inline bool GLMessage::has_fb() const {
- return _has_bit(6);
-}
-inline void GLMessage::clear_fb() {
- if (fb_ != NULL) fb_->::android::gltrace::GLMessage_FrameBuffer::Clear();
- _clear_bit(6);
-}
-inline const ::android::gltrace::GLMessage_FrameBuffer& GLMessage::fb() const {
- return fb_ != NULL ? *fb_ : *default_instance_->fb_;
-}
-inline ::android::gltrace::GLMessage_FrameBuffer* GLMessage::mutable_fb() {
- _set_bit(6);
- if (fb_ == NULL) fb_ = new ::android::gltrace::GLMessage_FrameBuffer;
- return fb_;
-}
-
-// optional int32 threadtime = 8;
-inline bool GLMessage::has_threadtime() const {
- return _has_bit(7);
-}
-inline void GLMessage::clear_threadtime() {
- threadtime_ = 0;
- _clear_bit(7);
-}
-inline ::google::protobuf::int32 GLMessage::threadtime() const {
- return threadtime_;
-}
-inline void GLMessage::set_threadtime(::google::protobuf::int32 value) {
- _set_bit(7);
- threadtime_ = value;
-}
-
-
-// @@protoc_insertion_point(namespace_scope)
-
-} // namespace gltrace
-} // namespace android
-
-// @@protoc_insertion_point(global_scope)
-
-#endif // PROTOBUF_gltrace_2eproto__INCLUDED
diff --git a/opengl/libs/GLES_trace/src/gltrace_api.cpp b/opengl/libs/GLES_trace/src/gltrace_api.cpp
index eed3ccf..d83b9b4 100644
--- a/opengl/libs/GLES_trace/src/gltrace_api.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_api.cpp
@@ -19,7 +19,7 @@
#include <cutils/log.h>
#include <utils/Timers.h>
-#include "gltrace.pb.h"
+#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
#include "gltrace_context.h"
#include "gltrace_fixup.h"
#include "gltrace_transport.h"
diff --git a/opengl/libs/GLES_trace/src/gltrace_egl.cpp b/opengl/libs/GLES_trace/src/gltrace_egl.cpp
index 4f9b006..a7878f2 100644
--- a/opengl/libs/GLES_trace/src/gltrace_egl.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_egl.cpp
@@ -17,7 +17,7 @@
#include <cutils/log.h>
#include <utils/Timers.h>
-#include "gltrace.pb.h"
+#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
#include "gltrace_context.h"
#include "gltrace_fixup.h"
#include "gltrace_transport.h"
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index be729c7..a4a187a 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -21,7 +21,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
-#include "gltrace.pb.h"
+#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
#include "gltrace_api.h"
#include "gltrace_context.h"
#include "gltrace_fixup.h"
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.h b/opengl/libs/GLES_trace/src/gltrace_fixup.h
index fe30125..c90dbeb 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.h
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.h
@@ -19,7 +19,7 @@
#include <utils/Timers.h>
-#include "gltrace.pb.h"
+#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
#include "gltrace_context.h"
namespace android {
diff --git a/opengl/libs/GLES_trace/src/gltrace_transport.h b/opengl/libs/GLES_trace/src/gltrace_transport.h
index 9cf5b45..fd6cb8c 100644
--- a/opengl/libs/GLES_trace/src/gltrace_transport.h
+++ b/opengl/libs/GLES_trace/src/gltrace_transport.h
@@ -19,7 +19,7 @@
#include <pthread.h>
-#include "gltrace.pb.h"
+#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
namespace android {
namespace gltrace {
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index cb0e908..c0990ec 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -30,6 +30,9 @@
// ----------------------------------------------------------------------------
EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name);
+EGLAPI const GLubyte * egl_get_string_for_current_context(GLenum name,
+ GLuint index);
+EGLAPI GLint egl_get_num_extensions_for_current_context();
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
index f37efec..80e4867 100644
--- a/opengl/tests/EGLTest/Android.mk
+++ b/opengl/tests/EGLTest/Android.mk
@@ -1,6 +1,7 @@
# Build the unit tests.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := EGL_test
@@ -14,27 +15,18 @@
libEGL \
libcutils \
libbinder \
- libstlport \
libutils \
libgui \
-LOCAL_STATIC_LIBRARIES := \
- libgtest \
- libgtest_main \
-
LOCAL_C_INCLUDES := \
- bionic \
bionic/libc/private \
- bionic/libstdc++/include \
- external/gtest/include \
- external/stlport/stlport \
frameworks/native/opengl/libs \
frameworks/native/opengl/libs/EGL \
# gold in binutils 2.22 will warn about the usage of mktemp
LOCAL_LDFLAGS += -Wl,--no-fatal-warnings
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_TEST)
# Include subdirectory makefiles
# ============================================================
diff --git a/opengl/tests/EGLTest/egl_cache_test.cpp b/opengl/tests/EGLTest/egl_cache_test.cpp
index c7d9e3e..c5bf296 100644
--- a/opengl/tests/EGLTest/egl_cache_test.cpp
+++ b/opengl/tests/EGLTest/egl_cache_test.cpp
@@ -41,7 +41,7 @@
};
TEST_F(EGLCacheTest, UninitializedCacheAlwaysMisses) {
- char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ uint8_t buf[4] = { 0xee, 0xee, 0xee, 0xee };
mCache->setBlob("abcd", 4, "efgh", 4);
ASSERT_EQ(0, mCache->getBlob("abcd", 4, buf, 4));
ASSERT_EQ(0xee, buf[0]);
@@ -51,7 +51,7 @@
}
TEST_F(EGLCacheTest, InitializedCacheAlwaysHits) {
- char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ uint8_t buf[4] = { 0xee, 0xee, 0xee, 0xee };
mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
mCache->setBlob("abcd", 4, "efgh", 4);
ASSERT_EQ(4, mCache->getBlob("abcd", 4, buf, 4));
@@ -62,7 +62,7 @@
}
TEST_F(EGLCacheTest, TerminatedCacheAlwaysMisses) {
- char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ uint8_t buf[4] = { 0xee, 0xee, 0xee, 0xee };
mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
mCache->setBlob("abcd", 4, "efgh", 4);
mCache->terminate();
@@ -94,7 +94,7 @@
};
TEST_F(EGLCacheSerializationTest, ReinitializedCacheContainsValues) {
- char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ uint8_t buf[4] = { 0xee, 0xee, 0xee, 0xee };
mCache->setCacheFilename(mFilename);
mCache->initialize(egl_display_t::get(EGL_DEFAULT_DISPLAY));
mCache->setBlob("abcd", 4, "efgh", 4);
diff --git a/opengl/tests/angeles/app-linux.cpp b/opengl/tests/angeles/app-linux.cpp
index e490351..ced8786 100644
--- a/opengl/tests/angeles/app-linux.cpp
+++ b/opengl/tests/angeles/app-linux.cpp
@@ -118,7 +118,7 @@
fprintf(stderr, "EGL Error: 0x%04x\n", (int)error);
}
-static int initGraphics(unsigned samples, const WindowSurface& windowSurface)
+static int initGraphics(EGLint samples, const WindowSurface& windowSurface)
{
EGLint configAttribs[] = {
EGL_DEPTH_SIZE, 16,
diff --git a/opengl/tests/fillrate/fillrate.cpp b/opengl/tests/fillrate/fillrate.cpp
index 1d9b026..2db63d7 100644
--- a/opengl/tests/fillrate/fillrate.cpp
+++ b/opengl/tests/fillrate/fillrate.cpp
@@ -91,11 +91,13 @@
}
}
+ const GLfloat fh = h;
+ const GLfloat fw = w;
const GLfloat vertices[4][2] = {
- { 0, 0 },
- { 0, h },
- { w, h },
- { w, 0 }
+ { 0, 0 },
+ { 0, fh },
+ { fw, fh },
+ { fw, 0 }
};
const GLfloat texCoords[4][2] = {
diff --git a/opengl/tests/filter/filter.cpp b/opengl/tests/filter/filter.cpp
index 289e6cc..287ee93 100644
--- a/opengl/tests/filter/filter.cpp
+++ b/opengl/tests/filter/filter.cpp
@@ -140,11 +140,12 @@
//glDrawTexiOES(0, 0, 0, dim, dim);
+ const GLfloat fdim = dim;
const GLfloat vertices[4][2] = {
- { 0, 0 },
- { 0, dim },
- { dim, dim },
- { dim, 0 }
+ { 0, 0 },
+ { 0, fdim },
+ { fdim, fdim },
+ { fdim, 0 }
};
const GLfloat texCoords[4][2] = {
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 86e1d46..f83846b 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -15,24 +15,25 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE:= libhwcTest
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcTestLib.cpp
LOCAL_C_INCLUDES += system/extras/tests/include \
- bionic \
- bionic/libstdc++/include \
- external/stlport/stlport \
- $(call include-path-for, opengl-tests-includes)
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
-LOCAL_STATIC_LIBRARIES += libglTest
-
+ $(call include-path-for, opengl-tests-includes) \
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE:= hwcStress
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcStress.cpp
LOCAL_SHARED_LIBRARIES := \
@@ -52,19 +53,17 @@
LOCAL_C_INCLUDES += \
system/extras/tests/include \
hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes)
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_MODULE:= hwcStress
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+ $(call include-path-for, opengl-tests-includes) \
include $(BUILD_NATIVE_TEST)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE:= hwcRects
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcRects.cpp
LOCAL_SHARED_LIBRARIES := \
@@ -84,17 +83,17 @@
LOCAL_C_INCLUDES += \
system/extras/tests/include \
hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= hwcRects
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+ $(call include-path-for, opengl-tests-includes) \
include $(BUILD_NATIVE_TEST)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE:= hwcColorEquiv
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcColorEquiv.cpp
LOCAL_SHARED_LIBRARIES := \
@@ -114,17 +113,17 @@
LOCAL_C_INCLUDES += \
system/extras/tests/include \
hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= hwcColorEquiv
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+ $(call include-path-for, opengl-tests-includes) \
include $(BUILD_NATIVE_TEST)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE:= hwcCommit
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CXX_STL := libc++
LOCAL_SRC_FILES:= hwcCommit.cpp
LOCAL_SHARED_LIBRARIES := \
@@ -144,12 +143,6 @@
LOCAL_C_INCLUDES += \
system/extras/tests/include \
hardware/libhardware/include \
- $(call include-path-for, opengl-tests-includes)
-
-LOCAL_MODULE:= hwcCommit
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+ $(call include-path-for, opengl-tests-includes) \
include $(BUILD_NATIVE_TEST)
diff --git a/opengl/tests/hwc/hwcColorEquiv.cpp b/opengl/tests/hwc/hwcColorEquiv.cpp
index c4624d2..06a0191 100644
--- a/opengl/tests/hwc/hwcColorEquiv.cpp
+++ b/opengl/tests/hwc/hwcColorEquiv.cpp
@@ -166,7 +166,6 @@
int rv, opt;
bool error;
char *chptr;
- unsigned int pass;
char cmd[MAXCMD];
string str;
@@ -293,14 +292,12 @@
// Use the upper third of the display for the reference frame and
// the middle third for the equivalence frame.
unsigned int refHeight = height / 3;
- unsigned int refPosY = 0; // Reference frame Y position
unsigned int refPosX = 0; // Reference frame X position
unsigned int refWidth = width - refPosX;
if ((refWidth & refFormat->wMod) != 0) {
refWidth += refFormat->wMod - (refWidth % refFormat->wMod);
}
unsigned int equivHeight = height / 3;
- unsigned int equivPosY = refHeight; // Equivalence frame Y position
unsigned int equivPosX = 0; // Equivalence frame X position
unsigned int equivWidth = width - equivPosX;
if ((equivWidth & equivFormat->wMod) != 0) {
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 1bd5fdf..1bcb860 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -338,7 +338,6 @@
main(int argc, char *argv[])
{
int rv, opt;
- char *chptr;
bool error;
string str;
char cmd[MAXCMD];
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
index 9b57623..56c1a2a 100644
--- a/opengl/tests/hwc/hwcRects.cpp
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -204,7 +204,6 @@
{
int rv, opt;
char *chptr;
- bool error;
string str;
char cmd[MAXCMD];
@@ -367,7 +366,6 @@
istringstream in(rectStr);
const struct hwcTestGraphicFormat *format;
Rectangle rect;
- struct hwc_rect hwcRect;
// Graphic Format
in >> str;
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
index 7fae5e5..3b0ca74 100644
--- a/opengl/tests/hwc/hwcTestLib.cpp
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -20,22 +20,22 @@
* Utility library functions for use by the Hardware Composer test cases
*/
+#include <arpa/inet.h> // For ntohl() and htonl()
+
+#include <cmath>
#include <sstream>
#include <string>
-#include <arpa/inet.h> // For ntohl() and htonl()
-
#include "hwcTestLib.h"
#include "EGLUtils.h"
// Defines
-#define NUMA(a) (sizeof(a) / sizeof(a [0]))
+#define NUMA(a) (sizeof(a) / sizeof((a)[0]))
// Function Prototypes
static void printGLString(const char *name, GLenum s);
static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
-static void checkGlError(const char* op);
static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
using namespace std;
@@ -51,8 +51,6 @@
{
static EGLContext context;
- int rv;
-
EGLBoolean returnValue;
EGLConfig myConfig = {0};
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
@@ -668,7 +666,6 @@
for (unsigned int x = 0; x < gBuf->getStride(); x++) {
for (unsigned int y = 0; y < gBuf->getHeight(); y++) {
- uint32_t val = pixel;
hwcTestSetPixel(gBuf, buf, x, y, (x < gBuf->getWidth())
? pixel : testRand());
}
@@ -965,14 +962,6 @@
}
}
-static void checkGlError(const char* op)
-{
- for (GLint error = glGetError(); error; error
- = glGetError()) {
- testPrintE("after %s() glError (0x%x)", op, error);
- }
-}
-
static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config)
{
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
index a2752cd..e5124ad 100644
--- a/opengl/tests/lib/Android.mk
+++ b/opengl/tests/lib/Android.mk
@@ -15,18 +15,13 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE:= libglTest
LOCAL_SRC_FILES:= glTestLib.cpp WindowSurface.cpp
LOCAL_C_INCLUDES += system/extras/tests/include \
- bionic \
- bionic/libstdc++/include \
- external/stlport/stlport \
$(call include-path-for, opengl-tests-includes)
LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
-
-
include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/linetex/linetex.cpp b/opengl/tests/linetex/linetex.cpp
index 7921f80..5ad695b 100644
--- a/opengl/tests/linetex/linetex.cpp
+++ b/opengl/tests/linetex/linetex.cpp
@@ -80,9 +80,11 @@
// default pack-alignment is 4
const uint16_t t16[64] = { 0xFFFF, 0, 0xF800, 0, 0x07E0, 0, 0x001F, 0 };
+ const GLfloat fh = h;
+ const GLfloat fw2 = w/2;
const GLfloat vertices[4][2] = {
- { w/2, 0 },
- { w/2, h }
+ { fw2, 0 },
+ { fw2, fh }
};
const GLfloat texCoords[4][2] = {
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index c6e227e..5803a44 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -191,6 +191,84 @@
(baseType.indexOf("Buffer") != -1);
}
+ public JType getArrayTypeForTypedBuffer() {
+ if (!isTypedBuffer()) {
+ throw new RuntimeException("Not typed buffer type " + this);
+ }
+ switch (baseType) {
+ case "java.nio.ByteBuffer":
+ return new JType("byte", false, true);
+ case "java.nio.BooleanBuffer":
+ return new JType("boolean", false, true);
+ case "java.nio.ShortBuffer":
+ return new JType("short", false, true);
+ case "java.nio.CharBuffer":
+ return new JType("char", false, true);
+ case "java.nio.IntBuffer":
+ return new JType("int", false, true);
+ case "java.nio.LongBuffer":
+ return new JType("long", false, true);
+ case "java.nio.FloatBuffer":
+ return new JType("float", false, true);
+ case "java.nio.DoubleBuffer":
+ return new JType("double", false, true);
+ default:
+ throw new RuntimeException("Unknown typed buffer type " + this);
+ }
+ }
+
+ public String getArrayGetterForPrimitiveArray() {
+ if (!isArray() || isClass()) {
+ throw new RuntimeException("Not array type " + this);
+ }
+ switch (baseType) {
+ case "byte":
+ return "GetByteArrayElements";
+ case "boolean":
+ return "GetBooleanArrayElements";
+ case "short":
+ return "GetShortArrayElements";
+ case "char":
+ return "GetCharArrayElements";
+ case "int":
+ return "GetIntArrayElements";
+ case "long":
+ return "GetLongArrayElements";
+ case "float":
+ return "GetFloatArrayElements";
+ case "double":
+ return "GetDoubleArrayElements";
+ default:
+ throw new RuntimeException("Unknown array type " + this);
+ }
+ }
+
+ public String getArrayReleaserForPrimitiveArray() {
+ if (!isArray() || isClass()) {
+ throw new RuntimeException("Not array type " + this);
+ }
+ switch (baseType) {
+ case "byte":
+ return "ReleaseByteArrayElements";
+ case "boolean":
+ return "ReleaseBooleanArrayElements";
+ case "short":
+ return "ReleaseShortArrayElements";
+ case "char":
+ return "ReleaseCharArrayElements";
+ case "int":
+ return "ReleaseIntArrayElements";
+ case "long":
+ return "ReleaseLongArrayElements";
+ case "float":
+ return "ReleaseFloatArrayElements";
+ case "double":
+ return "ReleaseDoubleArrayElements";
+ default:
+ throw new RuntimeException("Unknown array type " + this);
+ }
+ }
+
public boolean isEGLHandle() {
return !isPrimitive() &&
(baseType.startsWith("EGL"));
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index e51b7a2..1bed05b 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -812,6 +812,7 @@
List<Integer> stringArgs = new ArrayList<Integer>();
int numBufferArgs = 0;
List<String> bufferArgNames = new ArrayList<String>();
+ List<JType> bufferArgTypes = new ArrayList<JType>();
// Emit JNI signature (arguments)
//
@@ -835,6 +836,7 @@
int cIndex = jfunc.getArgCIndex(i);
String cname = cfunc.getArgName(cIndex);
bufferArgNames.add(cname);
+ bufferArgTypes.add(jfunc.getArgType(i));
numBufferArgs++;
}
}
@@ -948,12 +950,25 @@
// Emit a single _array or multiple _XXXArray variables
if (numBufferArgs == 1) {
+ JType bufferType = bufferArgTypes.get(0);
+ if (bufferType.isTypedBuffer()) {
+ String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
+ out.println(indent + typedArrayType + " _array = (" + typedArrayType + ") 0;");
+ } else {
out.println(indent + "jarray _array = (jarray) 0;");
- out.println(indent + "jint _bufferOffset = (jint) 0;");
+ }
+ out.println(indent + "jint _bufferOffset = (jint) 0;");
} else {
for (int i = 0; i < numBufferArgs; i++) {
- out.println(indent + "jarray _" + bufferArgNames.get(i) +
- "Array = (jarray) 0;");
+ JType bufferType = bufferArgTypes.get(0);
+ if (bufferType.isTypedBuffer()) {
+ String typedArrayType = getJniType(bufferType.getArrayTypeForTypedBuffer());
+ out.println(indent + typedArrayType + " _" + bufferArgNames.get(i) +
+ "Array = (" + typedArrayType + ") 0;");
+ } else {
+ out.println(indent + "jarray _" + bufferArgNames.get(i) +
+ "Array = (jarray) 0;");
+ }
out.println(indent + "jint _" + bufferArgNames.get(i) +
"BufferOffset = (jint) 0;");
}
@@ -1135,9 +1150,10 @@
"_base = (" +
cfunc.getArgType(cIndex).getDeclaration() +
")");
+ String arrayGetter = jfunc.getArgType(idx).getArrayGetterForPrimitiveArray();
out.println(indent + " " +
(mUseCPlusPlus ? "_env" : "(*_env)") +
- "->GetPrimitiveArrayCritical(" +
+ "->" + arrayGetter + "(" +
(mUseCPlusPlus ? "" : "_env, ") +
jfunc.getArgName(idx) +
"_ref, (jboolean *)0);");
@@ -1209,7 +1225,7 @@
cfunc.getArgType(cIndex).getDeclaration() +
")getPointer(_env, " +
cname +
- "_buf, &" + array + ", &" + remaining + ", &" + bufferOffset +
+ "_buf, (jarray*)&" + array + ", &" + remaining + ", &" + bufferOffset +
");");
}
@@ -1244,9 +1260,17 @@
} else {
out.println(indent + "if (" + cname +" == NULL) {");
}
- out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->GetPrimitiveArrayCritical(" + array + ", (jboolean *) 0);");
- out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
- out.println(indent + "}");
+ JType argType = jfunc.getArgType(idx);
+ if (argType.isTypedBuffer()) {
+ String arrayGetter = argType.getArrayTypeForTypedBuffer().getArrayGetterForPrimitiveArray();
+ out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->" + arrayGetter + "(" + array + ", (jboolean *) 0);");
+ out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
+ out.println(indent + "}");
+ } else {
+ out.println(indent + indent + "char * _" + cname + "Base = (char *)_env->GetPrimitiveArrayCritical(" + array + ", (jboolean *) 0);");
+ out.println(indent + indent + cname + " = (" +cfunc.getArgType(cIndex).getDeclaration() +") (_" + cname + "Base + " + bufferOffset + ");");
+ out.println(indent + "}");
+ }
}
}
@@ -1336,12 +1360,13 @@
// the need to write back to the Java array
out.println(indent +
"if (" + jfunc.getArgName(idx) + "_base) {");
+ String arrayReleaser = jfunc.getArgType(idx).getArrayReleaserForPrimitiveArray();
out.println(indent + indent +
(mUseCPlusPlus ? "_env" : "(*_env)") +
- "->ReleasePrimitiveArrayCritical(" +
+ "->" + arrayReleaser + "(" +
(mUseCPlusPlus ? "" : "_env, ") +
jfunc.getArgName(idx) + "_ref, " +
- cfunc.getArgName(cIndex) +
+ "(j" + jfunc.getArgType(idx).getBaseType() + "*)" + cfunc.getArgName(cIndex) +
"_base,");
out.println(indent + indent + indent +
(cfunc.getArgType(cIndex).isConst() ?
@@ -1350,17 +1375,32 @@
out.println(indent + "}");
} else if (jfunc.getArgType(idx).isBuffer()) {
if (! isPointerFunc) {
+ JType argType = jfunc.getArgType(idx);
String array = numBufferArgs <= 1 ? "_array" :
"_" + cfunc.getArgName(cIndex) + "Array";
out.println(indent + "if (" + array + ") {");
- out.println(indent + indent +
- "releasePointer(_env, " + array + ", " +
- cfunc.getArgName(cIndex) +
- ", " +
- (cfunc.getArgType(cIndex).isConst() ?
- "JNI_FALSE" : (emitExceptionCheck ?
- "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
- ");");
+ if (argType.isTypedBuffer()) {
+ String arrayReleaser =
+ argType.getArrayTypeForTypedBuffer().getArrayReleaserForPrimitiveArray();
+ out.println(indent + indent +
+ "_env->" + arrayReleaser + "(" + array + ", " +
+ "(j" + argType.getArrayTypeForTypedBuffer().getBaseType() + "*)" +
+ cfunc.getArgName(cIndex) +
+ ", " +
+ (cfunc.getArgType(cIndex).isConst() ?
+ "JNI_ABORT" : (emitExceptionCheck ?
+ "_exception ? JNI_ABORT : 0" : "0")) +
+ ");");
+ } else {
+ out.println(indent + indent +
+ "releasePointer(_env, " + array + ", " +
+ cfunc.getArgName(cIndex) +
+ ", " +
+ (cfunc.getArgType(cIndex).isConst() ?
+ "JNI_FALSE" : (emitExceptionCheck ?
+ "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
+ ");");
+ }
out.println(indent + "}");
}
}
diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
index a372362..f6813fd 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
@@ -16,6 +16,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include "jni.h"
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
index b5c19df..4df61d3 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
@@ -16,6 +16,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include "jni.h"
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
@@ -81,23 +85,19 @@
eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
- jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
- eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
- jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
- eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
- jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
- eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
-
jclass eglClass = _env->FindClass("android/opengl/EGL14");
jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
- _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject);
+ jobject localeglNoContextObject = _env->GetStaticObjectField(eglClass, noContextFieldID);
+ eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
- _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject);
+ jobject localeglNoDisplayObject = _env->GetStaticObjectField(eglClass, noDisplayFieldID);
+ eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
- _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject);
+ jobject localeglNoSurfaceObject = _env->GetStaticObjectField(eglClass, noSurfaceFieldID);
+ eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
}
static void *
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp
index f09c171..6199637 100755
--- a/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp
@@ -27,7 +27,7 @@
}
_remaining = _env->GetArrayLength(attrib_list_ref) - offset;
attrib_list_base = (EGLint *)
- _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+ _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
attrib_list = attrib_list_base + offset;
attrib_list_sentinel = false;
for (int i = _remaining - 1; i >= 0; i--) {
@@ -53,7 +53,7 @@
exit:
if (attrib_list_base) {
- _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+ _env->ReleaseIntArrayElements(attrib_list_ref, attrib_list_base,
JNI_ABORT);
}
if (_exception) {
@@ -71,4 +71,3 @@
}
return android_eglCreatePbufferFromClientBuffer(_env, _this, dpy, buftype, buffer, config, attrib_list_ref, offset);
}
-
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
index 0b6bf58..cc7b85d 100644
--- a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
@@ -41,7 +41,7 @@
_remaining = _env->GetArrayLength(attrib_list_ref) - offset;
attrib_list_base = (EGLint *)
- _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+ _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
attrib_list = attrib_list_base + offset;
attrib_list_sentinel = 0;
for (int i = _remaining - 1; i >= 0; i--) {
@@ -66,7 +66,7 @@
exit:
if (attrib_list_base) {
- _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+ _env->ReleaseIntArrayElements(attrib_list_ref, attrib_list_base,
JNI_ABORT);
}
if (_exception) {
@@ -123,7 +123,7 @@
_remaining = _env->GetArrayLength(attrib_list_ref) - offset;
attrib_list_base = (EGLint *)
- _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+ _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
attrib_list = attrib_list_base + offset;
attrib_list_sentinel = 0;
for (int i = _remaining - 1; i >= 0; i--) {
@@ -148,7 +148,7 @@
exit:
if (attrib_list_base) {
- _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+ _env->ReleaseIntArrayElements(attrib_list_ref, attrib_list_base,
JNI_ABORT);
}
if (_exception) {
diff --git a/opengl/tools/glgen/stubs/egl/eglGetDisplay.cpp b/opengl/tools/glgen/stubs/egl/eglGetDisplay.cpp
index 003efd3..2abc916 100755
--- a/opengl/tools/glgen/stubs/egl/eglGetDisplay.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglGetDisplay.cpp
@@ -14,7 +14,8 @@
android_eglGetDisplayInt
(JNIEnv *_env, jobject _this, jint display_id) {
- if ((EGLNativeDisplayType)display_id != EGL_DEFAULT_DISPLAY) {
+ if (static_cast<uintptr_t>(display_id) !=
+ reinterpret_cast<uintptr_t>(EGL_DEFAULT_DISPLAY)) {
jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglGetDisplay");
return 0;
}
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index 8a1d5ed..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -17,6 +17,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES/gl.h>
#include <GLES/glext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index 8a1d5ed..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -17,6 +17,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES/gl.h>
#include <GLES/glext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index 8a1d5ed..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -17,6 +17,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES/gl.h>
#include <GLES/glext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index 8a1d5ed..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -17,6 +17,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES/gl.h>
#include <GLES/glext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
index 2389563..4004a7d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
@@ -17,6 +17,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
index f5ec455..c5bdf32 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
@@ -17,6 +17,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
index e7e3561..2260a80 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
@@ -16,6 +16,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <GLES3/gl31.h>
#include <GLES2/gl2ext.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
index c48ec7c..130612d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
@@ -16,5 +16,9 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include <stdint.h>
#include <GLES3/gl31.h>
diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp
index f7bcb9d..18ec5e3 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -100,6 +100,116 @@
return NULL;
}
+class ByteArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jbyteArray array, jboolean* is_copy) {
+ return _env->GetByteArrayElements(array, is_copy);
+ }
+};
+class BooleanArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jbooleanArray array, jboolean* is_copy) {
+ return _env->GetBooleanArrayElements(array, is_copy);
+ }
+};
+class CharArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jcharArray array, jboolean* is_copy) {
+ return _env->GetCharArrayElements(array, is_copy);
+ }
+};
+class ShortArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jshortArray array, jboolean* is_copy) {
+ return _env->GetShortArrayElements(array, is_copy);
+ }
+};
+class IntArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jintArray array, jboolean* is_copy) {
+ return _env->GetIntArrayElements(array, is_copy);
+ }
+};
+class LongArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jlongArray array, jboolean* is_copy) {
+ return _env->GetLongArrayElements(array, is_copy);
+ }
+};
+class FloatArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jfloatArray array, jboolean* is_copy) {
+ return _env->GetFloatArrayElements(array, is_copy);
+ }
+};
+class DoubleArrayGetter {
+public:
+ static void* Get(JNIEnv* _env, jdoubleArray array, jboolean* is_copy) {
+ return _env->GetDoubleArrayElements(array, is_copy);
+ }
+};
+
+template<typename JTYPEARRAY, typename ARRAYGETTER>
+static void*
+getArrayPointer(JNIEnv *_env, JTYPEARRAY array, jboolean* is_copy) {
+ return ARRAYGETTER::Get(_env, array, is_copy);
+}
+
+class ByteArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jbyteArray array, jbyte* data, jboolean commit) {
+ _env->ReleaseByteArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class BooleanArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jbooleanArray array, jboolean* data, jboolean commit) {
+ _env->ReleaseBooleanArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class CharArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jcharArray array, jchar* data, jboolean commit) {
+ _env->ReleaseCharArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class ShortArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jshortArray array, jshort* data, jboolean commit) {
+ _env->ReleaseShortArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class IntArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jintArray array, jint* data, jboolean commit) {
+ _env->ReleaseIntArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class LongArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jlongArray array, jlong* data, jboolean commit) {
+ _env->ReleaseLongArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class FloatArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jfloatArray array, jfloat* data, jboolean commit) {
+ _env->ReleaseFloatArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+class DoubleArrayReleaser {
+public:
+ static void Release(JNIEnv* _env, jdoubleArray array, jdouble* data, jboolean commit) {
+ _env->ReleaseDoubleArrayElements(array, data, commit ? 0 : JNI_ABORT);
+ }
+};
+
+template<typename JTYPEARRAY, typename NTYPEARRAY, typename ARRAYRELEASER>
+static void
+releaseArrayPointer(JNIEnv *_env, JTYPEARRAY array, NTYPEARRAY data, jboolean commit) {
+ ARRAYRELEASER::Release(_env, array, data, commit);
+}
+
static void
releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
{
@@ -203,7 +313,8 @@
return needed;
}
-template <typename JTYPEARRAY, typename CTYPE, void GET(GLenum, CTYPE*)>
+template <typename JTYPEARRAY, typename ARRAYGETTER, typename NTYPEARRAY,
+ typename ARRAYRELEASER, typename CTYPE, void GET(GLenum, CTYPE*)>
static void
get
(JNIEnv *_env, jobject _this, jint pname, JTYPEARRAY params_ref, jint offset) {
@@ -238,8 +349,8 @@
_exceptionMessage = "length - offset < needed";
goto exit;
}
- params_base = (CTYPE *)
- _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params_base = (CTYPE *) getArrayPointer<JTYPEARRAY, ARRAYGETTER>(
+ _env, params_ref, (jboolean *)0);
params = params_base + offset;
GET(
@@ -249,8 +360,8 @@
exit:
if (params_base) {
- _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
- _exception ? JNI_ABORT: 0);
+ releaseArrayPointer<JTYPEARRAY, NTYPEARRAY, ARRAYRELEASER>(
+ _env, params_ref, params_base, !_exception);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -258,20 +369,21 @@
}
-template <typename CTYPE, void GET(GLenum, CTYPE*)>
+template <typename CTYPE, typename JTYPEARRAY, typename ARRAYGETTER, typename NTYPEARRAY,
+ typename ARRAYRELEASER, void GET(GLenum, CTYPE*)>
static void
getarray
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
jint _exception = 0;
const char * _exceptionType;
const char * _exceptionMessage;
- jarray _array = (jarray) 0;
+ JTYPEARRAY _array = (JTYPEARRAY) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
CTYPE *params = (CTYPE *) 0;
int _needed = 0;
- params = (CTYPE *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+ params = (CTYPE *)getPointer(_env, params_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
_remaining /= sizeof(CTYPE); // convert from bytes to item count
_needed = getNeededCount(pname);
// if we didn't find this pname, we just assume the user passed
@@ -284,7 +396,8 @@
goto exit;
}
if (params == NULL) {
- char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+ char * _paramsBase = (char *) getArrayPointer<JTYPEARRAY, ARRAYGETTER>(
+ _env, _array, (jboolean *) 0);
params = (CTYPE *) (_paramsBase + _bufferOffset);
}
GET(
@@ -294,7 +407,8 @@
exit:
if (_array) {
- releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ releaseArrayPointer<JTYPEARRAY, NTYPEARRAY, ARRAYRELEASER>(
+ _env, _array, (NTYPEARRAY)params, _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/opengl/tools/glgen/stubs/gles11/glDrawArraysIndirect.cpp b/opengl/tools/glgen/stubs/gles11/glDrawArraysIndirect.cpp
index ce3bc8f..eda2e46 100644
--- a/opengl/tools/glgen/stubs/gles11/glDrawArraysIndirect.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glDrawArraysIndirect.cpp
@@ -3,7 +3,7 @@
// In OpenGL ES, 'indirect' is a byte offset into a buffer, not a raw pointer.
// GL checks for too-large values. Here we only need to check for successful signed 64-bit
// to unsigned 32-bit conversion.
- if (sizeof(void*) != sizeof(jlong) && indirect > UINTPTR_MAX) {
+ if (sizeof(void*) != sizeof(jlong) && indirect > static_cast<jlong>(UINT32_MAX)) {
jniThrowException(_env, "java/lang/IllegalArgumentException", "indirect offset too large");
return;
}
diff --git a/opengl/tools/glgen/stubs/gles11/glDrawElementsIndirect.cpp b/opengl/tools/glgen/stubs/gles11/glDrawElementsIndirect.cpp
index 1833ee9..a091dc9 100644
--- a/opengl/tools/glgen/stubs/gles11/glDrawElementsIndirect.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glDrawElementsIndirect.cpp
@@ -3,7 +3,7 @@
// In OpenGL ES, 'indirect' is a byte offset into a buffer, not a raw pointer.
// GL checks for too-large values. Here we only need to check for successful signed 64-bit
// to unsigned 32-bit conversion.
- if (sizeof(void*) != sizeof(jlong) && indirect > UINTPTR_MAX) {
+ if (sizeof(void*) != sizeof(jlong) && indirect > static_cast<jlong>(UINT32_MAX)) {
jniThrowException(_env, "java/lang/IllegalArgumentException", "indirect offset too large");
return;
}
diff --git a/opengl/tools/glgen/stubs/gles11/glDrawElementsInstanced.cpp b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstanced.cpp
index 41df486..86decfb 100644
--- a/opengl/tools/glgen/stubs/gles11/glDrawElementsInstanced.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstanced.cpp
@@ -32,8 +32,7 @@
(GLenum)mode,
(GLsizei)count,
(GLenum)type,
- (GLvoid *)indicesOffset,
+ (GLvoid *)static_cast<uintptr_t>(indicesOffset),
(GLsizei)instanceCount
);
}
-
diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp b/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp
index 7d414d8..a8d63d9 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp
@@ -32,7 +32,7 @@
}
_lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
length_base = (GLsizei *)
- _env->GetPrimitiveArrayCritical(length_ref, (jboolean *)0);
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
length = length_base + lengthOffset;
if (!size_ref) {
@@ -49,7 +49,7 @@
}
_sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
size_base = (GLint *)
- _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+ _env->GetIntArrayElements(size_ref, (jboolean *)0);
size = size_base + sizeOffset;
if (!type_ref) {
@@ -66,7 +66,7 @@
}
_typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
type_base = (GLenum *)
- _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+ _env->GetIntArrayElements(type_ref, (jboolean *)0);
type = type_base + typeOffset;
if (!name_ref) {
@@ -83,7 +83,7 @@
}
_nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
name_base = (char *)
- _env->GetPrimitiveArrayCritical(name_ref, (jboolean *)0);
+ _env->GetByteArrayElements(name_ref, (jboolean *)0);
name = name_base + nameOffset;
glGetActiveAttrib(
@@ -98,19 +98,19 @@
exit:
if (name_base) {
- _env->ReleasePrimitiveArrayCritical(name_ref, name_base,
+ _env->ReleaseByteArrayElements(name_ref, (jbyte*)name_base,
_exception ? JNI_ABORT: 0);
}
if (type_base) {
- _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+ _env->ReleaseIntArrayElements(type_ref, (jint*)type_base,
_exception ? JNI_ABORT: 0);
}
if (size_base) {
- _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+ _env->ReleaseIntArrayElements(size_ref, (jint*)size_base,
_exception ? JNI_ABORT: 0);
}
if (length_base) {
- _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
+ _env->ReleaseIntArrayElements(length_ref, (jint*)length_base,
_exception ? JNI_ABORT: 0);
}
if (_exception) {
@@ -122,11 +122,11 @@
static void
android_glGetActiveAttrib__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
(JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
- jarray _lengthArray = (jarray) 0;
+ jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
- jarray _sizeArray = (jarray) 0;
+ jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
- jarray _typeArray = (jarray) 0;
+ jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
@@ -135,19 +135,19 @@
jint _typeRemaining;
GLenum *type = (GLenum *) 0;
- length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
- size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
- type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+ type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
if (length == NULL) {
- char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+ char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
}
if (size == NULL) {
- char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+ char * _sizeBase = (char *)_env->GetIntArrayElements(_sizeArray, (jboolean *) 0);
size = (GLint *) (_sizeBase + _sizeBufferOffset);
}
if (type == NULL) {
- char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+ char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
glGetActiveAttrib(
@@ -160,13 +160,13 @@
reinterpret_cast<char *>(name)
);
if (_typeArray) {
- releasePointer(_env, _typeArray, type, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
}
if (_sizeArray) {
- releasePointer(_env, _sizeArray, size, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _sizeArray, (jint*)size, JNI_TRUE);
}
if (_lengthArray) {
- releasePointer(_env, _lengthArray, length, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
}
}
@@ -211,7 +211,7 @@
}
_sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
size_base = (GLint *)
- _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+ _env->GetIntArrayElements(size_ref, (jboolean *)0);
size = size_base + sizeOffset;
if (!type_ref) {
@@ -228,7 +228,7 @@
}
_typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
type_base = (GLenum *)
- _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+ _env->GetIntArrayElements(type_ref, (jboolean *)0);
type = type_base + typeOffset;
glGetActiveAttrib(
@@ -242,11 +242,11 @@
);
exit:
if (type_base) {
- _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+ _env->ReleaseIntArrayElements(type_ref, (jint*)type_base,
_exception ? JNI_ABORT: 0);
}
if (size_base) {
- _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+ _env->ReleaseIntArrayElements(size_ref, (jint*)size_base,
_exception ? JNI_ABORT: 0);
}
if (_exception != 1) {
@@ -269,9 +269,9 @@
static jstring
android_glGetActiveAttrib2
(JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
- jarray _sizeArray = (jarray) 0;
+ jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
- jarray _typeArray = (jarray) 0;
+ jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
@@ -294,14 +294,14 @@
return NULL;
}
- size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
- type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+ size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+ type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
if (size == NULL) {
- char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+ char * _sizeBase = (char *)_env->GetIntArrayElements(_sizeArray, (jboolean *) 0);
size = (GLint *) (_sizeBase + _sizeBufferOffset);
}
if (type == NULL) {
- char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+ char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
glGetActiveAttrib(
@@ -315,10 +315,10 @@
);
if (_typeArray) {
- releasePointer(_env, _typeArray, type, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
}
if (_sizeArray) {
- releasePointer(_env, _sizeArray, size, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _sizeArray, (jint*)size, JNI_TRUE);
}
result = _env->NewStringUTF(buf);
if (buf) {
diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp b/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp
index a7376ba..68e8389 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp
@@ -32,7 +32,7 @@
}
_lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
length_base = (GLsizei *)
- _env->GetPrimitiveArrayCritical(length_ref, (jboolean *)0);
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
length = length_base + lengthOffset;
if (!size_ref) {
@@ -49,7 +49,7 @@
}
_sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
size_base = (GLint *)
- _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+ _env->GetIntArrayElements(size_ref, (jboolean *)0);
size = size_base + sizeOffset;
if (!type_ref) {
@@ -66,7 +66,7 @@
}
_typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
type_base = (GLenum *)
- _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+ _env->GetIntArrayElements(type_ref, (jboolean *)0);
type = type_base + typeOffset;
if (!name_ref) {
@@ -83,7 +83,7 @@
}
_nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
name_base = (char *)
- _env->GetPrimitiveArrayCritical(name_ref, (jboolean *)0);
+ _env->GetByteArrayElements(name_ref, (jboolean *)0);
name = name_base + nameOffset;
glGetActiveUniform(
@@ -98,19 +98,19 @@
exit:
if (name_base) {
- _env->ReleasePrimitiveArrayCritical(name_ref, name_base,
+ _env->ReleaseByteArrayElements(name_ref, (jbyte*)name_base,
_exception ? JNI_ABORT: 0);
}
if (type_base) {
- _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+ _env->ReleaseIntArrayElements(type_ref, (jint*)type_base,
_exception ? JNI_ABORT: 0);
}
if (size_base) {
- _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+ _env->ReleaseIntArrayElements(size_ref, (jint*)size_base,
_exception ? JNI_ABORT: 0);
}
if (length_base) {
- _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
+ _env->ReleaseIntArrayElements(length_ref, (jint*)length_base,
_exception ? JNI_ABORT: 0);
}
if (_exception) {
@@ -122,11 +122,11 @@
static void
android_glGetActiveUniform__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
(JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
- jarray _lengthArray = (jarray) 0;
+ jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
- jarray _sizeArray = (jarray) 0;
+ jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
- jarray _typeArray = (jarray) 0;
+ jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
@@ -135,19 +135,19 @@
jint _typeRemaining;
GLenum *type = (GLenum *) 0;
- length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
- size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
- type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+ type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
if (length == NULL) {
- char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+ char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
}
if (size == NULL) {
- char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+ char * _sizeBase = (char *)_env->GetIntArrayElements(_sizeArray, (jboolean *) 0);
size = (GLint *) (_sizeBase + _sizeBufferOffset);
}
if (type == NULL) {
- char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+ char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
glGetActiveUniform(
@@ -160,13 +160,13 @@
reinterpret_cast<char *>(name)
);
if (_typeArray) {
- releasePointer(_env, _typeArray, type, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
}
if (_sizeArray) {
- releasePointer(_env, _sizeArray, size, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _sizeArray, (jint*)size, JNI_TRUE);
}
if (_lengthArray) {
- releasePointer(_env, _lengthArray, length, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
}
}
@@ -214,7 +214,7 @@
}
_sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
size_base = (GLint *)
- _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+ _env->GetIntArrayElements(size_ref, (jboolean *)0);
size = size_base + sizeOffset;
if (!type_ref) {
@@ -231,7 +231,7 @@
}
_typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
type_base = (GLenum *)
- _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+ _env->GetIntArrayElements(type_ref, (jboolean *)0);
type = type_base + typeOffset;
glGetActiveUniform(
@@ -246,11 +246,11 @@
exit:
if (type_base) {
- _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+ _env->ReleaseIntArrayElements(type_ref, (jint*)type_base,
_exception ? JNI_ABORT: 0);
}
if (size_base) {
- _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+ _env->ReleaseIntArrayElements(size_ref, (jint*)size_base,
_exception ? JNI_ABORT: 0);
}
if (_exception != 1) {
@@ -272,9 +272,9 @@
static jstring
android_glGetActiveUniform2
(JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
- jarray _sizeArray = (jarray) 0;
+ jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
- jarray _typeArray = (jarray) 0;
+ jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
jint _sizeRemaining;
GLint *size = (GLint *) 0;
@@ -294,15 +294,15 @@
return NULL;
}
- size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
- type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+ size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+ type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
if (size == NULL) {
- char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+ char * _sizeBase = (char *)_env->GetIntArrayElements(_sizeArray, (jboolean *) 0);
size = (GLint *) (_sizeBase + _sizeBufferOffset);
}
if (type == NULL) {
- char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+ char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
glGetActiveUniform(
@@ -316,10 +316,10 @@
);
if (_typeArray) {
- releasePointer(_env, _typeArray, type, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
}
if (_sizeArray) {
- releasePointer(_env, _sizeArray, size, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _sizeArray, (jint*)size, JNI_TRUE);
}
result = _env->NewStringUTF(buf);
if (buf) {
diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp b/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp
index bb6ae7c..6104c84 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp
@@ -25,7 +25,7 @@
goto exit;
}
_lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
- _length_base = (GLsizei*)_env->GetPrimitiveArrayCritical(
+ _length_base = (GLsizei*)_env->GetIntArrayElements(
length_ref, (jboolean*)0);
_length = _length_base + lengthOffset;
@@ -42,7 +42,7 @@
goto exit;
}
_nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
- _name_base = (GLchar*)_env->GetPrimitiveArrayCritical(
+ _name_base = (GLchar*)_env->GetByteArrayElements(
name_ref, (jboolean*)0);
_name = _name_base + nameOffset;
@@ -56,11 +56,11 @@
exit:
if (_name_base) {
- _env->ReleasePrimitiveArrayCritical(name_ref, _name_base,
+ _env->ReleaseByteArrayElements(name_ref, (jbyte*)_name_base,
_exception ? JNI_ABORT: 0);
}
if (_length_base) {
- _env->ReleasePrimitiveArrayCritical(length_ref, _length_base,
+ _env->ReleaseIntArrayElements(length_ref, (jint*)_length_base,
_exception ? JNI_ABORT: 0);
}
if (_exception) {
@@ -124,4 +124,3 @@
free(name);
return result;
}
-
diff --git a/opengl/tools/glgen/stubs/gles11/glGetBooleanv.cpp b/opengl/tools/glgen/stubs/gles11/glGetBooleanv.cpp
index 00c52af..7874bd8 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetBooleanv.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetBooleanv.cpp
@@ -2,12 +2,14 @@
static void
android_glGetBooleanv__I_3ZI
(JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
- get<jbooleanArray, GLboolean, glGetBooleanv>(_env, _this, pname, params_ref, offset);
+ get<jbooleanArray, BooleanArrayGetter, jboolean*, BooleanArrayReleaser, GLboolean, glGetBooleanv>(
+ _env, _this, pname, params_ref, offset);
}
/* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
static void
android_glGetBooleanv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
- getarray<GLboolean, glGetBooleanv>(_env, _this, pname, params_buf);
+ getarray<GLboolean, jintArray, IntArrayGetter, jint*, IntArrayReleaser, glGetBooleanv>(
+ _env, _this, pname, params_buf);
}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetFloatv.cpp b/opengl/tools/glgen/stubs/gles11/glGetFloatv.cpp
index 71c399d..2f41fd1 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetFloatv.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetFloatv.cpp
@@ -2,12 +2,14 @@
static void
android_glGetFloatv__I_3FI
(JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
- get<jfloatArray, GLfloat, glGetFloatv>(_env, _this, pname, params_ref, offset);
+ get<jfloatArray, FloatArrayGetter, jfloat*, FloatArrayReleaser, GLfloat, glGetFloatv>(
+ _env, _this, pname, params_ref, offset);
}
/* void glGetFloatv ( GLenum pname, GLfloat *params ) */
static void
android_glGetFloatv__ILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
- getarray<GLfloat, glGetFloatv>(_env, _this, pname, params_buf);
+ getarray<GLfloat, jfloatArray, FloatArrayGetter, jfloat*, FloatArrayReleaser, glGetFloatv>(
+ _env, _this, pname, params_buf);
}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetIntegerv.cpp b/opengl/tools/glgen/stubs/gles11/glGetIntegerv.cpp
index 9000ece..c960f31a 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetIntegerv.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetIntegerv.cpp
@@ -2,13 +2,14 @@
static void
android_glGetIntegerv__I_3II
(JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
- get<jintArray, GLint, glGetIntegerv>(_env, _this, pname, params_ref, offset);
+ get<jintArray, IntArrayGetter, jint*, IntArrayReleaser, GLint, glGetIntegerv>(
+ _env, _this, pname, params_ref, offset);
}
/* void glGetIntegerv ( GLenum pname, GLint *params ) */
static void
android_glGetIntegerv__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
- getarray<GLint, glGetIntegerv>(_env, _this, pname, params_buf);
+ getarray<GLint, jintArray, IntArrayGetter, jint*, IntArrayReleaser, glGetIntegerv>(
+ _env, _this, pname, params_buf);
}
-
diff --git a/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp b/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp
index c995d9c..d9808ef 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp
@@ -26,7 +26,7 @@
}
_lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
length_base = (GLsizei *)
- _env->GetPrimitiveArrayCritical(length_ref, (jboolean *)0);
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
length = length_base + lengthOffset;
if (!source_ref) {
@@ -43,7 +43,7 @@
}
_sourceRemaining = _env->GetArrayLength(source_ref) - sourceOffset;
source_base = (char *)
- _env->GetPrimitiveArrayCritical(source_ref, (jboolean *)0);
+ _env->GetByteArrayElements(source_ref, (jboolean *)0);
source = source_base + sourceOffset;
glGetShaderSource(
@@ -55,11 +55,11 @@
exit:
if (source_base) {
- _env->ReleasePrimitiveArrayCritical(source_ref, source_base,
+ _env->ReleaseByteArrayElements(source_ref, (jbyte*)source_base,
_exception ? JNI_ABORT: 0);
}
if (length_base) {
- _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
+ _env->ReleaseIntArrayElements(length_ref, (jint*)length_base,
_exception ? JNI_ABORT: 0);
}
if (_exception) {
@@ -71,14 +71,14 @@
static void
android_glGetShaderSource__IILjava_nio_IntBuffer_2B
(JNIEnv *_env, jobject _this, jint shader, jint bufsize, jobject length_buf, jbyte source) {
- jarray _array = (jarray) 0;
+ jintArray _array = (jintArray) 0;
jint _bufferOffset = (jint) 0;
jint _remaining;
GLsizei *length = (GLsizei *) 0;
- length = (GLsizei *)getPointer(_env, length_buf, &_array, &_remaining, &_bufferOffset);
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_array, &_remaining, &_bufferOffset);
if (length == NULL) {
- char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+ char * _lengthBase = (char *)_env->GetIntArrayElements(_array, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _bufferOffset);
}
glGetShaderSource(
@@ -88,7 +88,7 @@
reinterpret_cast<char *>(source)
);
if (_array) {
- releasePointer(_env, _array, length, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _array, (jint*)length, JNI_TRUE);
}
}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
index 0514fe9..cb656c8 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
@@ -32,7 +32,7 @@
}
_lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
length_base = (GLsizei *)
- _env->GetPrimitiveArrayCritical(length_ref, (jboolean *)0);
+ _env->GetIntArrayElements(length_ref, (jboolean *)0);
length = length_base + lengthOffset;
if (!size_ref) {
@@ -49,7 +49,7 @@
}
_sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
size_base = (GLint *)
- _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+ _env->GetIntArrayElements(size_ref, (jboolean *)0);
size = size_base + sizeOffset;
if (!type_ref) {
@@ -66,7 +66,7 @@
}
_typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
type_base = (GLenum *)
- _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+ _env->GetIntArrayElements(type_ref, (jboolean *)0);
type = type_base + typeOffset;
if (!name_ref) {
@@ -83,7 +83,7 @@
}
_nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
name_base = (char *)
- _env->GetPrimitiveArrayCritical(name_ref, (jboolean *)0);
+ _env->GetByteArrayElements(name_ref, (jboolean *)0);
name = name_base + nameOffset;
glGetTransformFeedbackVarying(
@@ -98,19 +98,19 @@
exit:
if (name_base) {
- _env->ReleasePrimitiveArrayCritical(name_ref, name_base,
+ _env->ReleaseByteArrayElements(name_ref, (jbyte*)name_base,
_exception ? JNI_ABORT: 0);
}
if (type_base) {
- _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+ _env->ReleaseIntArrayElements(type_ref, (jint*)type_base,
_exception ? JNI_ABORT: 0);
}
if (size_base) {
- _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+ _env->ReleaseIntArrayElements(size_ref, (jint*)size_base,
_exception ? JNI_ABORT: 0);
}
if (length_base) {
- _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
+ _env->ReleaseIntArrayElements(length_ref, (jint*)length_base,
_exception ? JNI_ABORT: 0);
}
if (_exception) {
@@ -122,11 +122,11 @@
static void
android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
(JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
- jarray _lengthArray = (jarray) 0;
+ jintArray _lengthArray = (jintArray) 0;
jint _lengthBufferOffset = (jint) 0;
- jarray _sizeArray = (jarray) 0;
+ jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
- jarray _typeArray = (jarray) 0;
+ jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
@@ -135,19 +135,19 @@
jint _typeRemaining;
GLenum *type = (GLenum *) 0;
- length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
- size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
- type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+ length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+ size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+ type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
if (length == NULL) {
- char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+ char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
}
if (size == NULL) {
- char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+ char * _sizeBase = (char *)_env->GetIntArrayElements(_sizeArray, (jboolean *) 0);
size = (GLint *) (_sizeBase + _sizeBufferOffset);
}
if (type == NULL) {
- char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+ char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
glGetTransformFeedbackVarying(
@@ -157,16 +157,20 @@
(GLsizei *)length,
(GLint *)size,
(GLenum *)type,
- (char *)name
+ // The cast below is incorrect. The driver will end up writing to the
+ // address specified by name, which will always crash the process since
+ // it is guaranteed to be in low memory. The additional static_cast
+ // suppresses the warning for now. http://b/19478262
+ (char *)static_cast<uintptr_t>(name)
);
if (_typeArray) {
- releasePointer(_env, _typeArray, type, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
}
if (_sizeArray) {
- releasePointer(_env, _sizeArray, size, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _sizeArray, (jint*)size, JNI_TRUE);
}
if (_lengthArray) {
- releasePointer(_env, _lengthArray, length, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
}
}
@@ -211,7 +215,7 @@
}
_sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
size_base = (GLint *)
- _env->GetPrimitiveArrayCritical(size_ref, (jboolean *)0);
+ _env->GetIntArrayElements(size_ref, (jboolean *)0);
size = size_base + sizeOffset;
if (!type_ref) {
@@ -228,7 +232,7 @@
}
_typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
type_base = (GLenum *)
- _env->GetPrimitiveArrayCritical(type_ref, (jboolean *)0);
+ _env->GetIntArrayElements(type_ref, (jboolean *)0);
type = type_base + typeOffset;
glGetTransformFeedbackVarying(
@@ -242,11 +246,11 @@
);
exit:
if (type_base) {
- _env->ReleasePrimitiveArrayCritical(type_ref, type_base,
+ _env->ReleaseIntArrayElements(type_ref, (jint*)type_base,
_exception ? JNI_ABORT: 0);
}
if (size_base) {
- _env->ReleasePrimitiveArrayCritical(size_ref, size_base,
+ _env->ReleaseIntArrayElements(size_ref, (jint*)size_base,
_exception ? JNI_ABORT: 0);
}
if (_exception != 1) {
@@ -269,9 +273,9 @@
static jstring
android_glGetTransformFeedbackVarying2
(JNIEnv *_env, jobject _this, jint program, jint index, jobject size_buf, jobject type_buf) {
- jarray _sizeArray = (jarray) 0;
+ jintArray _sizeArray = (jintArray) 0;
jint _sizeBufferOffset = (jint) 0;
- jarray _typeArray = (jarray) 0;
+ jintArray _typeArray = (jintArray) 0;
jint _typeBufferOffset = (jint) 0;
jint _lengthRemaining;
GLsizei *length = (GLsizei *) 0;
@@ -294,14 +298,14 @@
return NULL;
}
- size = (GLint *)getPointer(_env, size_buf, &_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
- type = (GLenum *)getPointer(_env, type_buf, &_typeArray, &_typeRemaining, &_typeBufferOffset);
+ size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
+ type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
if (size == NULL) {
- char * _sizeBase = (char *)_env->GetPrimitiveArrayCritical(_sizeArray, (jboolean *) 0);
+ char * _sizeBase = (char *)_env->GetIntArrayElements(_sizeArray, (jboolean *) 0);
size = (GLint *) (_sizeBase + _sizeBufferOffset);
}
if (type == NULL) {
- char * _typeBase = (char *)_env->GetPrimitiveArrayCritical(_typeArray, (jboolean *) 0);
+ char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
type = (GLenum *) (_typeBase + _typeBufferOffset);
}
glGetTransformFeedbackVarying(
@@ -315,10 +319,10 @@
);
if (_typeArray) {
- releasePointer(_env, _typeArray, type, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
}
if (_sizeArray) {
- releasePointer(_env, _sizeArray, size, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _sizeArray, (jint*)size, JNI_TRUE);
}
result = _env->NewStringUTF(buf);
if (buf) {
diff --git a/opengl/tools/glgen/stubs/gles11/glGetUniformIndices.cpp b/opengl/tools/glgen/stubs/gles11/glGetUniformIndices.cpp
index fb137ab..13ef01e 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetUniformIndices.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetUniformIndices.cpp
@@ -49,7 +49,7 @@
_exceptionMessage = "not enough space in uniformIndices";
goto exit;
}
- _indices_base = (GLuint*)_env->GetPrimitiveArrayCritical(
+ _indices_base = (GLuint*)_env->GetIntArrayElements(
uniformIndices_ref, 0);
_indices = _indices_base + uniformIndicesOffset;
@@ -57,8 +57,8 @@
exit:
if (_indices_base) {
- _env->ReleasePrimitiveArrayCritical(uniformIndices_ref, _indices_base,
- _exception ? JNI_ABORT : 0);
+ _env->ReleaseIntArrayElements(uniformIndices_ref, (jint*)_indices_base,
+ _exception ? JNI_ABORT : 0);
}
for (_i = _count - 1; _i >= 0; _i--) {
if (_names[_i]) {
@@ -85,7 +85,7 @@
jint _count = 0;
jint _i;
const char** _names = NULL;
- jarray _uniformIndicesArray = (jarray)0;
+ jintArray _uniformIndicesArray = (jintArray)0;
jint _uniformIndicesRemaining;
jint _uniformIndicesOffset = 0;
GLuint* _indices = NULL;
@@ -118,11 +118,11 @@
}
_indices = (GLuint*)getPointer(_env, uniformIndices_buf,
- &_uniformIndicesArray, &_uniformIndicesRemaining,
+ (jarray*)&_uniformIndicesArray, &_uniformIndicesRemaining,
&_uniformIndicesOffset);
if (!_indices) {
- _indicesBase = (char*)_env->GetPrimitiveArrayCritical(
- _uniformIndicesArray, 0);
+ _indicesBase = (char*)_env->GetIntArrayElements(
+ _uniformIndicesArray, 0);
_indices = (GLuint*)(_indicesBase + _uniformIndicesOffset);
}
if (_uniformIndicesRemaining < _count) {
@@ -136,7 +136,8 @@
exit:
if (_uniformIndicesArray) {
- releasePointer(_env, _uniformIndicesArray, _indicesBase, JNI_TRUE);
+ releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(
+ _env, _uniformIndicesArray, (jint*)_indicesBase, JNI_TRUE);
}
for (_i = _count - 1; _i >= 0; _i--) {
if (_names[_i]) {
@@ -151,4 +152,3 @@
jniThrowException(_env, _exceptionType, _exceptionMessage);
}
}
-
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index df11c53..f5506ba 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -16,6 +16,10 @@
// This source file is automatically generated
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
#include "jni.h"
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
diff --git a/opengl/tools/glgen2/glgen.py b/opengl/tools/glgen2/glgen.py
index ed6b451..9b30fd1 100755
--- a/opengl/tools/glgen2/glgen.py
+++ b/opengl/tools/glgen2/glgen.py
@@ -86,11 +86,25 @@
return ', '.join(['"%s", %s' % (p[0], p[1]) for p in params])
-def overrideSymbolName(sym):
- # The wrapper intercepts glGetString and (sometimes) calls the generated
- # __glGetString thunk which dispatches to the driver's glGetString
- if sym == 'glGetString':
- return '__glGetString'
+def overrideSymbolName(sym, apiname):
+ # The wrapper intercepts various glGet and glGetString functions and
+ # (sometimes) calls the generated thunk which dispatches to the
+ # driver's implementation
+ wrapped_get_syms = {
+ 'gles1' : [
+ 'glGetString'
+ ],
+ 'gles2' : [
+ 'glGetString',
+ 'glGetStringi',
+ 'glGetBooleanv',
+ 'glGetFloatv',
+ 'glGetIntegerv',
+ 'glGetInteger64v',
+ ],
+ }
+ if sym in wrapped_get_syms.get(apiname):
+ return '__' + sym
else:
return sym
@@ -115,8 +129,8 @@
print('%s API_ENTRY(%s)(%s) {\n'
' %s(%s%s%s);\n'
'}'
- % (rtype, overrideSymbolName(fname), fmtParams(params),
- call, fname,
+ % (rtype, overrideSymbolName(fname, self.genOpts.apiname),
+ fmtParams(params), call, fname,
', ' if len(params) > 0 else '',
fmtArgs(params)),
file=self.outFile)
diff --git a/services/batteryservice/Android.mk b/services/batteryservice/Android.mk
index 9354b99..e4097d7 100644
--- a/services/batteryservice/Android.mk
+++ b/services/batteryservice/Android.mk
@@ -2,17 +2,19 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- BatteryProperties.cpp \
- BatteryProperty.cpp \
- IBatteryPropertiesListener.cpp \
- IBatteryPropertiesRegistrar.cpp
+ BatteryProperties.cpp \
+ BatteryProperty.cpp \
+ IBatteryPropertiesListener.cpp \
+ IBatteryPropertiesRegistrar.cpp
LOCAL_STATIC_LIBRARIES := \
- libutils \
- libbinder
+ libutils \
+ libbinder
LOCAL_MODULE:= libbatteryservice
LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+
include $(BUILD_STATIC_LIBRARY)
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
index ab636a9..f13d6e8 100644
--- a/services/batteryservice/BatteryProperties.cpp
+++ b/services/batteryservice/BatteryProperties.cpp
@@ -33,6 +33,7 @@
chargerAcOnline = p->readInt32() == 1 ? true : false;
chargerUsbOnline = p->readInt32() == 1 ? true : false;
chargerWirelessOnline = p->readInt32() == 1 ? true : false;
+ maxChargingCurrent = p->readInt32();
batteryStatus = p->readInt32();
batteryHealth = p->readInt32();
batteryPresent = p->readInt32() == 1 ? true : false;
@@ -47,6 +48,7 @@
p->writeInt32(chargerAcOnline ? 1 : 0);
p->writeInt32(chargerUsbOnline ? 1 : 0);
p->writeInt32(chargerWirelessOnline ? 1 : 0);
+ p->writeInt32(maxChargingCurrent);
p->writeInt32(batteryStatus);
p->writeInt32(batteryHealth);
p->writeInt32(batteryPresent ? 1 : 0);
diff --git a/services/batteryservice/IBatteryPropertiesListener.cpp b/services/batteryservice/IBatteryPropertiesListener.cpp
index 19ac7f0..8aff26c 100644
--- a/services/batteryservice/IBatteryPropertiesListener.cpp
+++ b/services/batteryservice/IBatteryPropertiesListener.cpp
@@ -35,7 +35,7 @@
data.writeInterfaceToken(IBatteryPropertiesListener::getInterfaceDescriptor());
data.writeInt32(1);
props.writeToParcel(&data);
- status_t err = remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
index 296bfab..46934e0 100644
--- a/services/batteryservice/IBatteryPropertiesRegistrar.cpp
+++ b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
@@ -34,14 +34,14 @@
void registerListener(const sp<IBatteryPropertiesListener>& listener) {
Parcel data;
data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeStrongBinder(listener->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(listener));
remote()->transact(REGISTER_LISTENER, data, NULL);
}
void unregisterListener(const sp<IBatteryPropertiesListener>& listener) {
Parcel data;
data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeStrongBinder(listener->asBinder());
+ data.writeStrongBinder(IInterface::asBinder(listener));
remote()->transact(UNREGISTER_LISTENER, data, NULL);
}
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
index 85edbe5..ed867d8 100644
--- a/services/inputflinger/Android.mk
+++ b/services/inputflinger/Android.mk
@@ -31,16 +31,13 @@
libinput \
liblog \
libutils \
- libui \
- libhardware_legacy
+ libui \
+ libhardware_legacy
# TODO: Move inputflinger to its own process and mark it hidden
#LOCAL_CFLAGS += -fvisibility=hidden
-LOCAL_C_INCLUDES := \
- external/openssl/include \
-
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
@@ -48,3 +45,5 @@
LOCAL_MODULE := libinputflinger
include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index dfe5d3d..6b60c7c 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -131,6 +131,13 @@
}
}
+ // External stylus gets the pressure axis
+ if (deviceClasses & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ if (axis == ABS_PRESSURE) {
+ return INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+ }
+ }
+
// Joystick devices get the rest.
return deviceClasses & INPUT_DEVICE_CLASS_JOYSTICK;
}
@@ -858,7 +865,6 @@
int(iev.time.tv_sec), int(iev.time.tv_usec));
}
-#ifdef HAVE_POSIX_CLOCKS
// Use the time specified in the event instead of the current time
// so that downstream code can get more accurate estimates of
// event dispatch latency from the time the event is enqueued onto
@@ -909,9 +915,6 @@
event->when, time, now);
}
}
-#else
- event->when = now;
-#endif
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
@@ -1189,6 +1192,16 @@
&& test_bit(ABS_X, device->absBitmask)
&& test_bit(ABS_Y, device->absBitmask)) {
device->classes |= INPUT_DEVICE_CLASS_TOUCH;
+ // Is this a BT stylus?
+ } else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
+ test_bit(BTN_TOUCH, device->keyBitmask))
+ && !test_bit(ABS_X, device->absBitmask)
+ && !test_bit(ABS_Y, device->absBitmask)) {
+ device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
+ // Keyboard will try to claim some of the buttons but we really want to reserve those so we
+ // can fuse it with the touch screen data, so just take them back. Note this means an
+ // external stylus cannot also be a keyboard device.
+ device->classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
}
// See if this device is a joystick.
@@ -1283,6 +1296,11 @@
return -1;
}
+ // Determine whether the device has a mic.
+ if (deviceHasMicLocked(device)) {
+ device->classes |= INPUT_DEVICE_CLASS_MIC;
+ }
+
// Determine whether the device is external or internal.
if (isExternalDeviceLocked(device)) {
device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
@@ -1297,7 +1315,10 @@
// Register with epoll.
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = mUsingEpollWakeup ? EPOLLIN : EPOLLIN | EPOLLWAKEUP;
+ eventItem.events = EPOLLIN;
+ if (mUsingEpollWakeup) {
+ eventItem.events |= EPOLLWAKEUP;
+ }
eventItem.data.u32 = deviceId;
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
@@ -1416,6 +1437,16 @@
return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
}
+bool EventHub::deviceHasMicLocked(Device* device) {
+ if (device->configuration) {
+ bool value;
+ if (device->configuration->tryGetProperty(String8("audio.mic"), value)) {
+ return value;
+ }
+ }
+ return false;
+}
+
int32_t EventHub::getNextControllerNumberLocked(Device* device) {
if (mControllerNumbers.isFull()) {
ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
@@ -1443,7 +1474,7 @@
}
bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
- if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
+ if (!device->keyMap.haveKeyLayout()) {
return false;
}
@@ -1461,7 +1492,7 @@
}
status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) const {
- if (!device->keyMap.haveKeyLayout() || !device->ledBitmask) {
+ if (!device->keyMap.haveKeyLayout()) {
return NAME_NOT_FOUND;
}
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 20179ae..3ec4910 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -131,6 +131,12 @@
/* The input device has a vibrator (supports FF_RUMBLE). */
INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
+ /* The input device has a microphone. */
+ INPUT_DEVICE_CLASS_MIC = 0x00000400,
+
+ /* The input device is an external stylus (has data we want to fuse with touch data). */
+ INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
+
/* The input device is virtual (not a real device, not part of UI configuration). */
INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
@@ -394,6 +400,7 @@
status_t loadKeyMapLocked(Device* device);
bool isExternalDeviceLocked(Device* device);
+ bool deviceHasMicLocked(Device* device);
int32_t getNextControllerNumberLocked(Device* device);
void releaseControllerNumberLocked(Device* device);
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 603836a..0fba1bf 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -119,7 +119,7 @@
return true;
}
-static bool isValidMotionAction(int32_t action, size_t pointerCount) {
+static bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
switch (action & AMOTION_EVENT_ACTION_MASK) {
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_UP:
@@ -136,14 +136,17 @@
int32_t index = getMotionEventActionPointerIndex(action);
return index >= 0 && size_t(index) < pointerCount;
}
+ case AMOTION_EVENT_ACTION_BUTTON_PRESS:
+ case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
+ return actionButton != 0;
default:
return false;
}
}
-static bool validateMotionEvent(int32_t action, size_t pointerCount,
+static bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCount,
const PointerProperties* pointerProperties) {
- if (! isValidMotionAction(action, pointerCount)) {
+ if (! isValidMotionAction(action, actionButton, pointerCount)) {
ALOGE("Motion event has invalid action code 0x%x", action);
return false;
}
@@ -198,7 +201,8 @@
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy),
- mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+ mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
+ mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(NULL),
mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
@@ -394,6 +398,7 @@
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason);
}
+ mLastDropReason = dropReason;
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
@@ -503,7 +508,9 @@
reason = "inbound event was dropped because the policy consumed it";
break;
case DROP_REASON_DISABLED:
- ALOGI("Dropped event because input dispatch is disabled.");
+ if (mLastDropReason != DROP_REASON_DISABLED) {
+ ALOGI("Dropped event because input dispatch is disabled.");
+ }
reason = "inbound event was dropped because input dispatch is disabled";
break;
case DROP_REASON_APP_SWITCH:
@@ -852,6 +859,13 @@
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
+ if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
+ CancelationOptions::Mode mode(isPointerEvent ?
+ CancelationOptions::CANCEL_POINTER_EVENTS :
+ CancelationOptions::CANCEL_NON_POINTER_EVENTS);
+ CancelationOptions options(mode, "input event injection failed");
+ synthesizeCancelationEventsForMonitorsLocked(options);
+ }
return true;
}
@@ -874,12 +888,12 @@
void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, "
- "metaState=0x%x, buttonState=0x%x, "
+ "action=0x%x, actionButton=0x%x, flags=0x%x, "
+ "metaState=0x%x, buttonState=0x%x,"
"edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
- entry->action, entry->flags,
+ entry->action, entry->actionButton, entry->flags,
entry->metaState, entry->buttonState,
entry->edgeFlags, entry->xPrecision, entry->yPrecision,
entry->downTime);
@@ -1981,10 +1995,10 @@
// Publish the motion event.
status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
motionEntry->deviceId, motionEntry->source,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
- motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
- xOffset, yOffset,
- motionEntry->xPrecision, motionEntry->yPrecision,
+ dispatchEntry->resolvedAction, motionEntry->actionButton,
+ dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
+ motionEntry->metaState, motionEntry->buttonState,
+ xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount, motionEntry->pointerProperties,
usingCoords);
@@ -2160,6 +2174,13 @@
}
}
+void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
+ const CancelationOptions& options) {
+ for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+ synthesizeCancelationEventsForInputChannelLocked(mMonitoringChannels[i], options);
+ }
+}
+
void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
const sp<InputChannel>& channel, const CancelationOptions& options) {
ssize_t index = getConnectionIndexLocked(channel);
@@ -2298,6 +2319,7 @@
originalMotionEntry->source,
originalMotionEntry->policyFlags,
action,
+ originalMotionEntry->actionButton,
originalMotionEntry->flags,
originalMotionEntry->metaState,
originalMotionEntry->buttonState,
@@ -2432,10 +2454,10 @@
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, "
- "xPrecision=%f, yPrecision=%f, downTime=%lld",
+ "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
args->eventTime, args->deviceId, args->source, args->policyFlags,
- args->action, args->flags, args->metaState, args->buttonState,
+ args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
for (uint32_t i = 0; i < args->pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%d, "
@@ -2455,7 +2477,8 @@
args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
}
#endif
- if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {
+ if (!validateMotionEvent(args->action, args->actionButton,
+ args->pointerCount, args->pointerProperties)) {
return;
}
@@ -2471,9 +2494,9 @@
mLock.unlock();
MotionEvent event;
- event.initialize(args->deviceId, args->source, args->action, args->flags,
- args->edgeFlags, args->metaState, args->buttonState, 0, 0,
- args->xPrecision, args->yPrecision,
+ event.initialize(args->deviceId, args->source, args->action, args->actionButton,
+ args->flags, args->edgeFlags, args->metaState, args->buttonState,
+ 0, 0, args->xPrecision, args->yPrecision,
args->downTime, args->eventTime,
args->pointerCount, args->pointerProperties, args->pointerCoords);
@@ -2488,7 +2511,8 @@
// Just enqueue a new motion event.
MotionEntry* newEntry = new MotionEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
- args->action, args->flags, args->metaState, args->buttonState,
+ args->action, args->actionButton, args->flags,
+ args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
@@ -2589,7 +2613,8 @@
int32_t action = motionEvent->getAction();
size_t pointerCount = motionEvent->getPointerCount();
const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
- if (! validateMotionEvent(action, pointerCount, pointerProperties)) {
+ int32_t actionButton = motionEvent->getActionButton();
+ if (! validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
return INPUT_EVENT_INJECTION_FAILED;
}
@@ -2603,7 +2628,7 @@
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
firstInjectedEntry = new MotionEntry(*sampleEventTimes,
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
+ action, actionButton, motionEvent->getFlags(),
motionEvent->getMetaState(), motionEvent->getButtonState(),
motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
@@ -2616,7 +2641,7 @@
samplePointerCoords += pointerCount;
MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes,
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
+ action, actionButton, motionEvent->getFlags(),
motionEvent->getMetaState(), motionEvent->getButtonState(),
motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
@@ -3789,18 +3814,6 @@
}
-// --- InputDispatcher::Queue ---
-
-template <typename T>
-uint32_t InputDispatcher::Queue<T>::count() const {
- uint32_t result = 0;
- for (const T* entry = head; entry; entry = entry->next) {
- result += 1;
- }
- return result;
-}
-
-
// --- InputDispatcher::InjectionState ---
InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) :
@@ -3919,18 +3932,18 @@
// --- InputDispatcher::MotionEntry ---
-InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, float xPrecision, float yPrecision,
- nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
+InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId,
+ uint32_t source, uint32_t policyFlags, int32_t action, int32_t actionButton,
+ int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ float xPrecision, float yPrecision, nsecs_t downTime,
+ int32_t displayId, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xOffset, float yOffset) :
EventEntry(TYPE_MOTION, eventTime, policyFlags),
eventTime(eventTime),
- deviceId(deviceId), source(source), action(action), flags(flags),
- metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags),
- xPrecision(xPrecision), yPrecision(yPrecision),
+ deviceId(deviceId), source(source), action(action), actionButton(actionButton),
+ flags(flags), metaState(metaState), buttonState(buttonState),
+ edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision),
downTime(downTime), displayId(displayId), pointerCount(pointerCount) {
for (uint32_t i = 0; i < pointerCount; i++) {
this->pointerProperties[i].copyFrom(pointerProperties[i]);
@@ -3945,10 +3958,10 @@
}
void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
- msg.appendFormat("MotionEvent(deviceId=%d, source=0x%08x, action=%d, "
- "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, edgeFlags=0x%08x, "
- "xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
- deviceId, source, action, flags, metaState, buttonState, edgeFlags,
+ msg.appendFormat("MotionEvent(deviceId=%d, source=0x%08x, action=%d, actionButton=0x%08x, "
+ "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
+ "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
+ deviceId, source, action, actionButton, flags, metaState, buttonState, edgeFlags,
xPrecision, yPrecision, displayId);
for (uint32_t i = 0; i < pointerCount; i++) {
if (i) {
@@ -4249,7 +4262,7 @@
memento.hovering
? AMOTION_EVENT_ACTION_HOVER_EXIT
: AMOTION_EVENT_ACTION_CANCEL,
- memento.flags, 0, 0, 0,
+ memento.flags, 0, 0, 0, 0,
memento.xPrecision, memento.yPrecision, memento.downTime,
memento.displayId,
memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 70b0a34..98355c6 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -504,6 +504,7 @@
int32_t deviceId;
uint32_t source;
int32_t action;
+ int32_t actionButton;
int32_t flags;
int32_t metaState;
int32_t buttonState;
@@ -518,10 +519,10 @@
MotionEntry(nsecs_t eventTime,
int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags,
+ int32_t action, int32_t actionButton, int32_t flags,
int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- float xPrecision, float yPrecision,
- nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
+ float xPrecision, float yPrecision, nsecs_t downTime,
+ int32_t displayId, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xOffset, float yOffset);
virtual void appendDescription(String8& msg) const;
@@ -606,8 +607,9 @@
struct Queue {
T* head;
T* tail;
+ uint32_t entryCount;
- inline Queue() : head(NULL), tail(NULL) {
+ inline Queue() : head(NULL), tail(NULL), entryCount(0) {
}
inline bool isEmpty() const {
@@ -615,6 +617,7 @@
}
inline void enqueueAtTail(T* entry) {
+ entryCount++;
entry->prev = tail;
if (tail) {
tail->next = entry;
@@ -626,6 +629,7 @@
}
inline void enqueueAtHead(T* entry) {
+ entryCount++;
entry->next = head;
if (head) {
head->prev = entry;
@@ -637,6 +641,7 @@
}
inline void dequeue(T* entry) {
+ entryCount--;
if (entry->prev) {
entry->prev->next = entry->next;
} else {
@@ -650,6 +655,7 @@
}
inline T* dequeueAtHead() {
+ entryCount--;
T* entry = head;
head = entry->next;
if (head) {
@@ -660,7 +666,9 @@
return entry;
}
- uint32_t count() const;
+ uint32_t count() const {
+ return entryCount;
+ }
};
/* Specifies which events are to be canceled and why. */
@@ -849,6 +857,8 @@
Queue<EventEntry> mRecentQueue;
Queue<CommandEntry> mCommandQueue;
+ DropReason mLastDropReason;
+
void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime);
// Enqueues an inbound event. Returns true if mLooper->wake() should be called.
@@ -1066,6 +1076,7 @@
void synthesizeCancelationEventsForAllConnectionsLocked(
const CancelationOptions& options);
+ void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options);
void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
const CancelationOptions& options);
void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 85bb0ed..dded47d 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -68,12 +68,13 @@
NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
+ int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
+ int32_t buttonState, int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) :
eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
- action(action), flags(flags), metaState(metaState), buttonState(buttonState),
+ action(action), actionButton(actionButton),
+ flags(flags), metaState(metaState), buttonState(buttonState),
edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount),
xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) {
for (uint32_t i = 0; i < pointerCount; i++) {
@@ -85,10 +86,9 @@
NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
policyFlags(other.policyFlags),
- action(other.action), flags(other.flags),
+ action(other.action), actionButton(other.actionButton), flags(other.flags),
metaState(other.metaState), buttonState(other.buttonState),
- edgeFlags(other.edgeFlags), displayId(other.displayId),
- pointerCount(other.pointerCount),
+ edgeFlags(other.edgeFlags), displayId(other.displayId), pointerCount(other.pointerCount),
xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) {
for (uint32_t i = 0; i < pointerCount; i++) {
pointerProperties[i].copyFrom(other.pointerProperties[i]);
diff --git a/services/inputflinger/InputListener.h b/services/inputflinger/InputListener.h
index 78ae10f..1ec09ce 100644
--- a/services/inputflinger/InputListener.h
+++ b/services/inputflinger/InputListener.h
@@ -84,6 +84,7 @@
uint32_t source;
uint32_t policyFlags;
int32_t action;
+ int32_t actionButton;
int32_t flags;
int32_t metaState;
int32_t buttonState;
@@ -99,7 +100,8 @@
inline NotifyMotionArgs() { }
NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
+ int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState,
int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 006ec6b..36095bf 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -39,12 +39,16 @@
// Log debug messages about the vibrator.
#define DEBUG_VIBRATOR 0
+// Log debug messages about fusing stylus data.
+#define DEBUG_STYLUS_FUSION 0
+
#include "InputReader.h"
#include <cutils/log.h>
#include <input/Keyboard.h>
#include <input/VirtualKeyMap.h>
+#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
@@ -65,6 +69,17 @@
// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
static const size_t MAX_SLOTS = 32;
+// Maximum amount of latency to add to touch events while waiting for data from an
+// external stylus.
+static const nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
+
+// Maximum amount of time to wait on touch data before pushing out new pressure data.
+static const nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
+
+// Artificial latency on synthetic events created from stylus data without corresponding touch
+// data.
+static const nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
+
// --- Static Functions ---
template<typename T>
@@ -381,6 +396,10 @@
mDevices.add(deviceId, device);
bumpGenerationLocked();
+
+ if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ notifyExternalStylusPresenceChanged();
+ }
}
void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
@@ -403,6 +422,10 @@
device->getId(), device->getName().string(), device->getSources());
}
+ if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ notifyExternalStylusPresenceChanged();
+ }
+
device->reset(when);
delete device;
}
@@ -417,6 +440,11 @@
device->setExternal(true);
}
+ // Devices with mics.
+ if (classes & INPUT_DEVICE_CLASS_MIC) {
+ device->setMic(true);
+ }
+
// Switch-like devices.
if (classes & INPUT_DEVICE_CLASS_SWITCH) {
device->addMapper(new SwitchInputMapper(device));
@@ -464,6 +492,11 @@
device->addMapper(new JoystickInputMapper(device));
}
+ // External stylus-like devices.
+ if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
+ device->addMapper(new ExternalStylusInputMapper(device));
+ }
+
return device;
}
@@ -534,6 +567,27 @@
return mGlobalMetaState;
}
+void InputReader::notifyExternalStylusPresenceChanged() {
+ refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
+}
+
+void InputReader::getExternalStylusDevicesLocked(Vector<InputDeviceInfo>& outDevices) {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
+ outDevices.push();
+ device->getDeviceInfo(&outDevices.editTop());
+ }
+ }
+}
+
+void InputReader::dispatchExternalStylusState(const StylusState& state) {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ device->updateExternalStylusState(state);
+ }
+}
+
void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
mDisableVirtualKeysTimeout = time;
}
@@ -824,6 +878,15 @@
return mReader->bumpGenerationLocked();
}
+void InputReader::ContextImpl::getExternalStylusDevices(Vector<InputDeviceInfo>& outDevices) {
+ // lock is already held by whatever called refreshConfigurationLocked
+ mReader->getExternalStylusDevicesLocked(outDevices);
+}
+
+void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
+ mReader->dispatchExternalStylusState(state);
+}
+
InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
return mReader->mPolicy.get();
}
@@ -858,7 +921,7 @@
int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
mIdentifier(identifier), mClasses(classes),
- mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
+ mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
}
InputDevice::~InputDevice() {
@@ -877,6 +940,7 @@
deviceInfo.getDisplayName().string());
dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
+ dump.appendFormat(INDENT2 "HasMic: %s\n", toString(mHasMic));
dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
@@ -1006,10 +1070,17 @@
}
}
+void InputDevice::updateExternalStylusState(const StylusState& state) {
+ size_t numMappers = mMappers.size();
+ for (size_t i = 0; i < numMappers; i++) {
+ InputMapper* mapper = mMappers[i];
+ mapper->updateExternalStylusState(state);
+ }
+}
+
void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
- mIsExternal);
-
+ mIsExternal, mHasMic);
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
@@ -1285,7 +1356,9 @@
void TouchButtonAccumulator::reset(InputDevice* device) {
mBtnTouch = device->isKeyPressed(BTN_TOUCH);
mBtnStylus = device->isKeyPressed(BTN_STYLUS);
- mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
+ // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
+ mBtnStylus2 =
+ device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
@@ -1326,6 +1399,7 @@
mBtnStylus = rawEvent->value;
break;
case BTN_STYLUS2:
+ case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
mBtnStylus2 = rawEvent->value;
break;
case BTN_TOOL_FINGER:
@@ -1368,10 +1442,10 @@
uint32_t TouchButtonAccumulator::getButtonState() const {
uint32_t result = 0;
if (mBtnStylus) {
- result |= AMOTION_EVENT_BUTTON_SECONDARY;
+ result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
}
if (mBtnStylus2) {
- result |= AMOTION_EVENT_BUTTON_TERTIARY;
+ result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
}
return result;
}
@@ -1801,6 +1875,10 @@
return 0;
}
+void InputMapper::updateExternalStylusState(const StylusState& state) {
+
+}
+
void InputMapper::fadePointer() {
}
@@ -1822,6 +1900,12 @@
}
}
+void InputMapper::dumpStylusState(String8& dump, const StylusState& state) {
+ dump.appendFormat(INDENT4 "When: %" PRId64 "\n", state.when);
+ dump.appendFormat(INDENT4 "Pressure: %f\n", state.pressure);
+ dump.appendFormat(INDENT4 "Button State: 0x%08x\n", state.buttons);
+ dump.appendFormat(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
+}
// --- SwitchInputMapper ---
@@ -2463,7 +2547,8 @@
}
nsecs_t downTime = mDownTime;
bool buttonsChanged = currentButtonState != lastButtonState;
- bool buttonsPressed = currentButtonState & ~lastButtonState;
+ int32_t buttonsPressed = currentButtonState & ~lastButtonState;
+ int32_t buttonsReleased = lastButtonState & ~currentButtonState;
float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
@@ -2539,6 +2624,7 @@
// Send motion event.
if (downChanged || moved || scrolled || buttonsChanged) {
int32_t metaState = mContext->getGlobalMetaState();
+ int32_t buttonState = lastButtonState;
int32_t motionEventAction;
if (downChanged) {
motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
@@ -2548,17 +2634,48 @@
motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
}
+ if (buttonsReleased) {
+ BitSet32 released(buttonsReleased);
+ while (!released.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
+ buttonState &= ~actionButton;
+ NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ displayId, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime);
+ getListener()->notifyMotion(&releaseArgs);
+ }
+ }
+
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- motionEventAction, 0, metaState, currentButtonState, 0,
+ motionEventAction, 0, 0, metaState, currentButtonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
displayId, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&args);
+ if (buttonsPressed) {
+ BitSet32 pressed(buttonsPressed);
+ while (!pressed.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
+ buttonState |= actionButton;
+ NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, policyFlags,
+ AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ displayId, 1, &pointerProperties, &pointerCoords,
+ mXPrecision, mYPrecision, downTime);
+ getListener()->notifyMotion(&pressArgs);
+ }
+ }
+
+ ALOG_ASSERT(buttonState == currentButtonState);
+
// Send hover move after UP to tell the application that the mouse is hovering now.
if (motionEventAction == AMOTION_EVENT_ACTION_UP
&& mPointerController != NULL) {
NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
displayId, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
@@ -2571,7 +2688,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
displayId, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
@@ -2703,12 +2820,11 @@
dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
- dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
-
+ dump.appendFormat(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
- mLastRawPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
- const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
+ mLastRawState.rawPointerData.pointerCount);
+ for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
+ const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
"touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
"orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
@@ -2720,11 +2836,13 @@
pointer.toolType, toString(pointer.isHovering));
}
+ dump.appendFormat(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState);
dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
- mLastCookedPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
- const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
- const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
+ mLastCookedState.cookedPointerData.pointerCount);
+ for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
+ const PointerProperties& pointerProperties =
+ mLastCookedState.cookedPointerData.pointerProperties[i];
+ const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
"touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
"orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
@@ -2741,9 +2859,18 @@
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
pointerProperties.toolType,
- toString(mLastCookedPointerData.isHovering(i)));
+ toString(mLastCookedState.cookedPointerData.isHovering(i)));
}
+ dump.append(INDENT3 "Stylus Fusion:\n");
+ dump.appendFormat(INDENT4 "ExternalStylusConnected: %s\n",
+ toString(mExternalStylusConnected));
+ dump.appendFormat(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
+ dump.appendFormat(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
+ mExternalStylusFusionTimeout);
+ dump.append(INDENT3 "External Stylus State:\n");
+ dumpStylusState(dump, mExternalStylusState);
+
if (mDeviceMode == DEVICE_MODE_POINTER) {
dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
@@ -2781,7 +2908,7 @@
resolveCalibration();
}
- if (!changes || (changes & InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION)) {
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
// Update location calibration to reflect current settings
updateAffineTransformation();
}
@@ -2796,7 +2923,8 @@
bool resetNeeded = false;
if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
| InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
- | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
+ | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
+ | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
// Configure device sources, surface dimensions, orientation and
// scaling factors.
configureSurface(when, &resetNeeded);
@@ -2809,6 +2937,16 @@
}
}
+void TouchInputMapper::resolveExternalStylusPresence() {
+ Vector<InputDeviceInfo> devices;
+ mContext->getExternalStylusDevices(devices);
+ mExternalStylusConnected = !devices.isEmpty();
+
+ if (!mExternalStylusConnected) {
+ resetExternalStylus();
+ }
+}
+
void TouchInputMapper::configureParameters() {
// Use the pointer presentation mode for devices that do not support distinct
// multitouch. The spot-based presentation relies on being able to accurately
@@ -2945,9 +3083,15 @@
dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
}
+bool TouchInputMapper::hasExternalStylus() const {
+ return mExternalStylusConnected;
+}
+
void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
int32_t oldDeviceMode = mDeviceMode;
+ resolveExternalStylusPresence();
+
// Determine device mode.
if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
&& mConfig.pointerGesturesEnabled) {
@@ -2963,6 +3107,9 @@
if (hasStylus()) {
mSource |= AINPUT_SOURCE_STYLUS;
}
+ if (hasExternalStylus()) {
+ mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
+ }
} else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
mDeviceMode = DEVICE_MODE_NAVIGATION;
@@ -3705,22 +3852,14 @@
mWheelXVelocityControl.reset();
mWheelYVelocityControl.reset();
- mCurrentRawPointerData.clear();
- mLastRawPointerData.clear();
- mCurrentCookedPointerData.clear();
- mLastCookedPointerData.clear();
- mCurrentButtonState = 0;
- mLastButtonState = 0;
- mCurrentRawVScroll = 0;
- mCurrentRawHScroll = 0;
- mCurrentFingerIdBits.clear();
- mLastFingerIdBits.clear();
- mCurrentStylusIdBits.clear();
- mLastStylusIdBits.clear();
- mCurrentMouseIdBits.clear();
- mLastMouseIdBits.clear();
+ mRawStatesPending.clear();
+ mCurrentRawState.clear();
+ mCurrentCookedState.clear();
+ mLastRawState.clear();
+ mLastCookedState.clear();
mPointerUsage = POINTER_USAGE_NONE;
mSentHoverEnter = false;
+ mHavePointerIds = false;
mCurrentMotionAborted = false;
mDownTime = 0;
@@ -3728,6 +3867,7 @@
mPointerGesture.reset();
mPointerSimple.reset();
+ resetExternalStylus();
if (mPointerController != NULL) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
@@ -3737,6 +3877,18 @@
InputMapper::reset(when);
}
+void TouchInputMapper::resetExternalStylus() {
+ mExternalStylusState.clear();
+ mExternalStylusId = -1;
+ mExternalStylusFusionTimeout = LLONG_MAX;
+ mExternalStylusDataPending = false;
+}
+
+void TouchInputMapper::clearStylusDataPendingFlags() {
+ mExternalStylusDataPending = false;
+ mExternalStylusFusionTimeout = LLONG_MAX;
+}
+
void TouchInputMapper::process(const RawEvent* rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
@@ -3748,160 +3900,288 @@
}
void TouchInputMapper::sync(nsecs_t when) {
+ const RawState* last = mRawStatesPending.isEmpty() ?
+ &mCurrentRawState : &mRawStatesPending.top();
+
+ // Push a new state.
+ mRawStatesPending.push();
+ RawState* next = &mRawStatesPending.editTop();
+ next->clear();
+ next->when = when;
+
// Sync button state.
- mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
+ next->buttonState = mTouchButtonAccumulator.getButtonState()
| mCursorButtonAccumulator.getButtonState();
- // Sync scroll state.
- mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
- mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
+ // Sync scroll
+ next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
+ next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
mCursorScrollAccumulator.finishSync();
- // Sync touch state.
- bool havePointerIds = true;
- mCurrentRawPointerData.clear();
- syncTouch(when, &havePointerIds);
+ // Sync touch
+ syncTouch(when, next);
+
+ // Assign pointer ids.
+ if (!mHavePointerIds) {
+ assignPointerIds(last, next);
+ }
#if DEBUG_RAW_EVENTS
- if (!havePointerIds) {
- ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
- mLastRawPointerData.pointerCount,
- mCurrentRawPointerData.pointerCount);
- } else {
- ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
- "hovering ids 0x%08x -> 0x%08x",
- mLastRawPointerData.pointerCount,
- mCurrentRawPointerData.pointerCount,
- mLastRawPointerData.touchingIdBits.value,
- mCurrentRawPointerData.touchingIdBits.value,
- mLastRawPointerData.hoveringIdBits.value,
- mCurrentRawPointerData.hoveringIdBits.value);
- }
+ ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
+ "hovering ids 0x%08x -> 0x%08x",
+ last->rawPointerData.pointerCount,
+ next->rawPointerData.pointerCount,
+ last->rawPointerData.touchingIdBits.value,
+ next->rawPointerData.touchingIdBits.value,
+ last->rawPointerData.hoveringIdBits.value,
+ next->rawPointerData.hoveringIdBits.value);
#endif
- // Reset state that we will compute below.
- mCurrentFingerIdBits.clear();
- mCurrentStylusIdBits.clear();
- mCurrentMouseIdBits.clear();
- mCurrentCookedPointerData.clear();
+ processRawTouches(false /*timeout*/);
+}
+void TouchInputMapper::processRawTouches(bool timeout) {
if (mDeviceMode == DEVICE_MODE_DISABLED) {
// Drop all input if the device is disabled.
- mCurrentRawPointerData.clear();
- mCurrentButtonState = 0;
- } else {
- // Preprocess pointer data.
- if (!havePointerIds) {
- assignPointerIds();
- }
-
- // Handle policy on initial down or hover events.
- uint32_t policyFlags = 0;
- bool initialDown = mLastRawPointerData.pointerCount == 0
- && mCurrentRawPointerData.pointerCount != 0;
- bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
- if (initialDown || buttonsPressed) {
- // If this is a touch screen, hide the pointer on an initial down.
- if (mDeviceMode == DEVICE_MODE_DIRECT) {
- getContext()->fadePointer();
- }
-
- if (mParameters.wake) {
- policyFlags |= POLICY_FLAG_WAKE;
- }
- }
-
- // Synthesize key down from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
-
- // Consume raw off-screen touches before cooking pointer data.
- // If touches are consumed, subsequent code will not receive any pointer data.
- if (consumeRawTouches(when, policyFlags)) {
- mCurrentRawPointerData.clear();
- }
-
- // Cook pointer data. This call populates the mCurrentCookedPointerData structure
- // with cooked pointer data that has the same ids and indices as the raw data.
- // The following code can use either the raw or cooked data, as needed.
- cookPointerData();
-
- // Dispatch the touches either directly or by translation through a pointer on screen.
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentStylusIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- mCurrentFingerIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
- mCurrentMouseIdBits.markBit(id);
- }
- }
- for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentStylusIdBits.markBit(id);
- }
- }
-
- // Stylus takes precedence over all tools, then mouse, then finger.
- PointerUsage pointerUsage = mPointerUsage;
- if (!mCurrentStylusIdBits.isEmpty()) {
- mCurrentMouseIdBits.clear();
- mCurrentFingerIdBits.clear();
- pointerUsage = POINTER_USAGE_STYLUS;
- } else if (!mCurrentMouseIdBits.isEmpty()) {
- mCurrentFingerIdBits.clear();
- pointerUsage = POINTER_USAGE_MOUSE;
- } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
- pointerUsage = POINTER_USAGE_GESTURES;
- }
-
- dispatchPointerUsage(when, policyFlags, pointerUsage);
- } else {
- if (mDeviceMode == DEVICE_MODE_DIRECT
- && mConfig.showTouches && mPointerController != NULL) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-
- mPointerController->setButtonState(mCurrentButtonState);
- mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.touchingIdBits);
- }
- if (!mCurrentMotionAborted) {
- dispatchHoverExit(when, policyFlags);
- dispatchTouches(when, policyFlags);
- dispatchHoverEnterAndMove(when, policyFlags);
- }
-
- if (mCurrentCookedPointerData.pointerCount == 0) {
- mCurrentMotionAborted = false;
- }
- }
-
- // Synthesize key up from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
+ mCurrentRawState.clear();
+ mRawStatesPending.clear();
+ return;
}
- // Copy current touch to last touch in preparation for the next cycle.
- mLastRawPointerData.copyFrom(mCurrentRawPointerData);
- mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
- mLastButtonState = mCurrentButtonState;
- mLastFingerIdBits = mCurrentFingerIdBits;
- mLastStylusIdBits = mCurrentStylusIdBits;
- mLastMouseIdBits = mCurrentMouseIdBits;
+ // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
+ // valid and must go through the full cook and dispatch cycle. This ensures that anything
+ // touching the current state will only observe the events that have been dispatched to the
+ // rest of the pipeline.
+ const size_t N = mRawStatesPending.size();
+ size_t count;
+ for(count = 0; count < N; count++) {
+ const RawState& next = mRawStatesPending[count];
+
+ // A failure to assign the stylus id means that we're waiting on stylus data
+ // and so should defer the rest of the pipeline.
+ if (assignExternalStylusId(next, timeout)) {
+ break;
+ }
+
+ // All ready to go.
+ clearStylusDataPendingFlags();
+ mCurrentRawState.copyFrom(next);
+ if (mCurrentRawState.when < mLastRawState.when) {
+ mCurrentRawState.when = mLastRawState.when;
+ }
+ cookAndDispatch(mCurrentRawState.when);
+ }
+ if (count != 0) {
+ mRawStatesPending.removeItemsAt(0, count);
+ }
+
+ if (mExternalStylusDataPending) {
+ if (timeout) {
+ nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
+ clearStylusDataPendingFlags();
+ mCurrentRawState.copyFrom(mLastRawState);
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Timeout expired, synthesizing event with new stylus data");
+#endif
+ cookAndDispatch(when);
+ } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
+ mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ }
+ }
+}
+
+void TouchInputMapper::cookAndDispatch(nsecs_t when) {
+ // Always start with a clean state.
+ mCurrentCookedState.clear();
+
+ // Apply stylus buttons to current raw state.
+ applyExternalStylusButtonState(when);
+
+ // Handle policy on initial down or hover events.
+ bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
+ && mCurrentRawState.rawPointerData.pointerCount != 0;
+
+ uint32_t policyFlags = 0;
+ bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
+ if (initialDown || buttonsPressed) {
+ // If this is a touch screen, hide the pointer on an initial down.
+ if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ getContext()->fadePointer();
+ }
+
+ if (mParameters.wake) {
+ policyFlags |= POLICY_FLAG_WAKE;
+ }
+ }
+
+ // Consume raw off-screen touches before cooking pointer data.
+ // If touches are consumed, subsequent code will not receive any pointer data.
+ if (consumeRawTouches(when, policyFlags)) {
+ mCurrentRawState.rawPointerData.clear();
+ }
+
+ // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
+ // with cooked pointer data that has the same ids and indices as the raw data.
+ // The following code can use either the raw or cooked data, as needed.
+ cookPointerData();
+
+ // Apply stylus pressure to current cooked state.
+ applyExternalStylusTouchState(when);
+
+ // Synthesize key down from raw buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
+ policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
+
+ // Dispatch the touches either directly or by translation through a pointer on screen.
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
+ !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
+ if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ mCurrentCookedState.stylusIdBits.markBit(id);
+ } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ mCurrentCookedState.fingerIdBits.markBit(id);
+ } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
+ mCurrentCookedState.mouseIdBits.markBit(id);
+ }
+ }
+ for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
+ !idBits.isEmpty(); ) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
+ if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
+ || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ mCurrentCookedState.stylusIdBits.markBit(id);
+ }
+ }
+
+ // Stylus takes precedence over all tools, then mouse, then finger.
+ PointerUsage pointerUsage = mPointerUsage;
+ if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
+ mCurrentCookedState.mouseIdBits.clear();
+ mCurrentCookedState.fingerIdBits.clear();
+ pointerUsage = POINTER_USAGE_STYLUS;
+ } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
+ mCurrentCookedState.fingerIdBits.clear();
+ pointerUsage = POINTER_USAGE_MOUSE;
+ } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
+ isPointerDown(mCurrentRawState.buttonState)) {
+ pointerUsage = POINTER_USAGE_GESTURES;
+ }
+
+ dispatchPointerUsage(when, policyFlags, pointerUsage);
+ } else {
+ if (mDeviceMode == DEVICE_MODE_DIRECT
+ && mConfig.showTouches && mPointerController != NULL) {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+ mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
+
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
+ mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.touchingIdBits);
+ }
+
+ if (!mCurrentMotionAborted) {
+ dispatchButtonRelease(when, policyFlags);
+ dispatchHoverExit(when, policyFlags);
+ dispatchTouches(when, policyFlags);
+ dispatchHoverEnterAndMove(when, policyFlags);
+ dispatchButtonPress(when, policyFlags);
+ }
+
+ if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+ mCurrentMotionAborted = false;
+ }
+ }
+
+ // Synthesize key up from raw buttons if needed.
+ synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
+ policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);
// Clear some transient state.
- mCurrentRawVScroll = 0;
- mCurrentRawHScroll = 0;
+ mCurrentRawState.rawVScroll = 0;
+ mCurrentRawState.rawHScroll = 0;
+
+ // Copy current touch to last touch in preparation for the next cycle.
+ mLastRawState.copyFrom(mCurrentRawState);
+ mLastCookedState.copyFrom(mCurrentCookedState);
+}
+
+void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
+ if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
+ mCurrentRawState.buttonState |= mExternalStylusState.buttons;
+ }
+}
+
+void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
+ CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
+ const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
+
+ if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
+ float pressure = mExternalStylusState.pressure;
+ if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
+ const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
+ pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+ }
+ PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
+ coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+
+ PointerProperties& properties =
+ currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
+ if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ properties.toolType = mExternalStylusState.toolType;
+ }
+ }
+}
+
+bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
+ if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
+ return false;
+ }
+
+ const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
+ && state.rawPointerData.pointerCount != 0;
+ if (initialDown) {
+ if (mExternalStylusState.pressure != 0.0f) {
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Have both stylus and touch data, beginning fusion");
+#endif
+ mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
+ } else if (timeout) {
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Timeout expired, assuming touch is not a stylus.");
+#endif
+ resetExternalStylus();
+ } else {
+ if (mExternalStylusFusionTimeout == LLONG_MAX) {
+ mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
+ }
+#if DEBUG_STYLUS_FUSION
+ ALOGD("No stylus data but stylus is connected, requesting timeout "
+ "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
+#endif
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ return true;
+ }
+ }
+
+ // Check if the stylus pointer has gone up.
+ if (mExternalStylusId != -1 &&
+ !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
+#if DEBUG_STYLUS_FUSION
+ ALOGD("Stylus pointer is going up");
+#endif
+ mExternalStylusId = -1;
+ }
+
+ return false;
}
void TouchInputMapper::timeoutExpired(nsecs_t when) {
@@ -3909,13 +4189,30 @@
if (mPointerUsage == POINTER_USAGE_GESTURES) {
dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
}
+ } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
+ if (mExternalStylusFusionTimeout < when) {
+ processRawTouches(true /*timeout*/);
+ } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
+ getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
+ }
+ }
+}
+
+void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
+ mExternalStylusState.copyFrom(state);
+ if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
+ // We're either in the middle of a fused stream of data or we're waiting on data before
+ // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
+ // data.
+ mExternalStylusDataPending = true;
+ processRawTouches(false /*timeout*/);
}
}
bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
// Check for release of a virtual key.
if (mCurrentVirtualKey.down) {
- if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
+ if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
// Pointer went up while virtual key was down.
mCurrentVirtualKey.down = false;
if (!mCurrentVirtualKey.ignored) {
@@ -3930,9 +4227,10 @@
return true;
}
- if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
- uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
+ if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
+ uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
// Pointer is still within the space of the virtual key.
@@ -3957,15 +4255,15 @@
}
}
- if (mLastRawPointerData.touchingIdBits.isEmpty()
- && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
+ if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
+ && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
// Pointer just went down. Check for virtual key press or off-screen touches.
- uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
+ uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
+ const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
if (!isPointInsideSurface(pointer.x, pointer.y)) {
// If exactly one pointer went down, check for virtual key hit.
// Otherwise we will drop the entire stroke.
- if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
+ if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
if (virtualKey) {
mCurrentVirtualKey.down = true;
@@ -4005,7 +4303,8 @@
// area and accidentally triggers a virtual key. This often happens when virtual keys
// are layed out below the screen near to where the on screen keyboard's space bar
// is displayed.
- if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
+ if (mConfig.virtualKeyQuietTime > 0 &&
+ !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
}
return false;
@@ -4025,15 +4324,15 @@
}
void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
- BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
+ BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
if (!currentIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
- dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0,
+ int32_t buttonState = mCurrentCookedState.buttonState;
+ dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
currentIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
mCurrentMotionAborted = true;
@@ -4041,21 +4340,21 @@
}
void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
- BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
- BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
+ BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
+ BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
+ int32_t buttonState = mCurrentCookedState.buttonState;
if (currentIdBits == lastIdBits) {
if (!currentIdBits.isEmpty()) {
// No pointer id changes so this is a move event.
// The listener takes care of batching moves so we don't have to deal with that here.
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
currentIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
@@ -4070,14 +4369,14 @@
// Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up.
bool moveNeeded = updateMovedPointers(
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mLastCookedState.cookedPointerData.pointerProperties,
+ mLastCookedState.cookedPointerData.pointerCoords,
+ mLastCookedState.cookedPointerData.idToIndex,
moveIdBits);
- if (buttonState != mLastButtonState) {
+ if (buttonState != mLastCookedState.buttonState) {
moveNeeded = true;
}
@@ -4086,27 +4385,25 @@
uint32_t upId = upIdBits.clearFirstMarkedBit();
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- dispatchedIdBits, upId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
+ mLastCookedState.cookedPointerData.pointerProperties,
+ mLastCookedState.cookedPointerData.pointerCoords,
+ mLastCookedState.cookedPointerData.idToIndex,
+ dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
dispatchedIdBits.clearBit(upId);
}
// Dispatch move events if any of the remaining pointers moved from their old locations.
// Although applications receive new locations as part of individual pointer up
// events, they do not generally handle them except when presented in a move event.
- if (moveNeeded) {
+ if (moveNeeded && !moveIdBits.isEmpty()) {
ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- dispatchedIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
// Dispatch pointer down events using the new pointer locations.
@@ -4120,69 +4417,119 @@
}
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- dispatchedIdBits, downId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
}
}
void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
if (mSentHoverEnter &&
- (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
- || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
+ (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
+ || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
int32_t metaState = getContext()->getGlobalMetaState();
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- mLastCookedPointerData.hoveringIdBits, -1,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
+ mLastCookedState.cookedPointerData.pointerProperties,
+ mLastCookedState.cookedPointerData.pointerCoords,
+ mLastCookedState.cookedPointerData.idToIndex,
+ mLastCookedState.cookedPointerData.hoveringIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
mSentHoverEnter = false;
}
}
void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
- if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
- && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
+ if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
+ && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
if (!mSentHoverEnter) {
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.hoveringIdBits, -1,
+ dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
+ 0, 0, metaState, mCurrentRawState.buttonState, 0,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
mSentHoverEnter = true;
}
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.hoveringIdBits, -1,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, 0,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
}
-void TouchInputMapper::cookPointerData() {
- uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
+void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
+ BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
+ const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
+ const int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mLastCookedState.buttonState;
+ while (!releasedButtons.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
+ buttonState &= ~actionButton;
+ dispatchMotion(when, policyFlags, mSource,
+ AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
+ 0, metaState, buttonState, 0,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+}
- mCurrentCookedPointerData.clear();
- mCurrentCookedPointerData.pointerCount = currentPointerCount;
- mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
- mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
+void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
+ BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
+ const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
+ const int32_t metaState = getContext()->getGlobalMetaState();
+ int32_t buttonState = mLastCookedState.buttonState;
+ while (!pressedButtons.isEmpty()) {
+ int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
+ buttonState |= actionButton;
+ dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
+ 0, metaState, buttonState, 0,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ }
+}
+
+const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
+ if (!cookedPointerData.touchingIdBits.isEmpty()) {
+ return cookedPointerData.touchingIdBits;
+ }
+ return cookedPointerData.hoveringIdBits;
+}
+
+void TouchInputMapper::cookPointerData() {
+ uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
+
+ mCurrentCookedState.cookedPointerData.clear();
+ mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
+ mCurrentCookedState.cookedPointerData.hoveringIdBits =
+ mCurrentRawState.rawPointerData.hoveringIdBits;
+ mCurrentCookedState.cookedPointerData.touchingIdBits =
+ mCurrentRawState.rawPointerData.touchingIdBits;
+
+ if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+ mCurrentCookedState.buttonState = 0;
+ } else {
+ mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
+ }
// Walk through the the active pointers and map device coordinates onto
// surface coordinates and adjust for display orientation.
for (uint32_t i = 0; i < currentPointerCount; i++) {
- const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
+ const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
// Size
float touchMajor, touchMinor, toolMajor, toolMinor, size;
@@ -4221,7 +4568,8 @@
}
if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
- uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
+ uint32_t touchingCount =
+ mCurrentRawState.rawPointerData.touchingIdBits.count();
if (touchingCount > 1) {
touchMajor /= touchingCount;
touchMinor /= touchingCount;
@@ -4351,7 +4699,7 @@
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
orientation -= M_PI_2;
- if (orientation < mOrientedRanges.orientation.min) {
+ if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
@@ -4363,7 +4711,7 @@
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
orientation -= M_PI;
- if (orientation < mOrientedRanges.orientation.min) {
+ if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
@@ -4375,7 +4723,7 @@
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
orientation += M_PI_2;
- if (orientation > mOrientedRanges.orientation.max) {
+ if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
@@ -4390,7 +4738,7 @@
}
// Write output coords.
- PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
+ PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
out.clear();
out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -4412,14 +4760,15 @@
}
// Write output properties.
- PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
+ PointerProperties& properties =
+ mCurrentCookedState.cookedPointerData.pointerProperties[i];
uint32_t id = in.id;
properties.clear();
properties.id = id;
properties.toolType = in.toolType;
// Write id index.
- mCurrentCookedPointerData.idToIndex[id] = i;
+ mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
}
}
@@ -4523,7 +4872,7 @@
// Send events!
int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
+ int32_t buttonState = mCurrentCookedState.buttonState;
// Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up.
@@ -4544,7 +4893,7 @@
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
movedGestureIdBits);
- if (buttonState != mLastButtonState) {
+ if (buttonState != mLastCookedState.buttonState) {
moveNeeded = true;
}
}
@@ -4554,12 +4903,12 @@
if (!dispatchedGestureIdBits.isEmpty()) {
if (cancelPreviousGesture) {
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
+ AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
- dispatchedGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
+ dispatchedGestureIdBits, -1, 0,
+ 0, mPointerGesture.downTime);
dispatchedGestureIdBits.clear();
} else {
@@ -4574,7 +4923,7 @@
uint32_t id = upGestureIdBits.clearFirstMarkedBit();
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0,
+ AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
@@ -4589,7 +4938,8 @@
// Send motion events for all pointers that moved.
if (moveNeeded) {
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
dispatchedGestureIdBits, -1,
@@ -4609,7 +4959,7 @@
}
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
+ AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
dispatchedGestureIdBits, id,
@@ -4620,7 +4970,7 @@
// Send motion events for hover.
if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
@@ -4646,7 +4996,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mViewport.displayId, 1, &pointerProperties, &pointerCoords,
0, 0, mPointerGesture.downTime);
@@ -4675,9 +5025,9 @@
// Cancel previously dispatches pointers.
if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
+ int32_t buttonState = mCurrentRawState.buttonState;
dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
+ AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
@@ -4732,21 +5082,22 @@
return false;
}
- const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
- const uint32_t lastFingerCount = mLastFingerIdBits.count();
+ const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
+ const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
// Update the velocity tracker.
{
VelocityTracker::Position positions[MAX_POINTERS];
uint32_t count = 0;
- for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
+ for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
+ const RawPointerData::Pointer& pointer =
+ mCurrentRawState.rawPointerData.pointerForId(id);
positions[count].x = pointer.x * mPointerXMovementScale;
positions[count].y = pointer.y * mPointerYMovementScale;
}
mPointerGesture.velocityTracker.addMovement(when,
- mCurrentFingerIdBits, positions);
+ mCurrentCookedState.fingerIdBits, positions);
}
// If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
@@ -4766,17 +5117,17 @@
int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
int32_t activeTouchId = lastActiveTouchId;
if (activeTouchId < 0) {
- if (!mCurrentFingerIdBits.isEmpty()) {
+ if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
activeTouchChanged = true;
activeTouchId = mPointerGesture.activeTouchId =
- mCurrentFingerIdBits.firstMarkedBit();
+ mCurrentCookedState.fingerIdBits.firstMarkedBit();
mPointerGesture.firstTouchTime = when;
}
- } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
+ } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
activeTouchChanged = true;
- if (!mCurrentFingerIdBits.isEmpty()) {
+ if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
activeTouchId = mPointerGesture.activeTouchId =
- mCurrentFingerIdBits.firstMarkedBit();
+ mCurrentCookedState.fingerIdBits.firstMarkedBit();
} else {
activeTouchId = mPointerGesture.activeTouchId = -1;
}
@@ -4799,7 +5150,7 @@
isQuietTime = true;
} else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
&& currentFingerCount >= 2
- && !isPointerDown(mCurrentButtonState)) {
+ && !isPointerDown(mCurrentRawState.buttonState)) {
// Enter quiet time when releasing the button and there are still two or more
// fingers down. This may indicate that one finger was used to press the button
// but it has not gone up yet.
@@ -4827,7 +5178,7 @@
mPointerGesture.currentGestureIdBits.clear();
mPointerVelocityControl.reset();
- } else if (isPointerDown(mCurrentButtonState)) {
+ } else if (isPointerDown(mCurrentRawState.buttonState)) {
// Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
// The pointer follows the active touch point.
// Emit DOWN, MOVE, UP events at the pointer location.
@@ -4856,7 +5207,7 @@
if (activeTouchId >= 0 && currentFingerCount > 1) {
int32_t bestId = -1;
float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
- for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
+ for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
float vx, vy;
if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
@@ -4877,11 +5228,11 @@
}
}
- if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
+ if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointerForId(activeTouchId);
+ mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointerForId(activeTouchId);
+ mLastRawState.rawPointerData.pointerForId(activeTouchId);
float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
@@ -5017,11 +5368,11 @@
mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
}
- if (mLastFingerIdBits.hasBit(activeTouchId)) {
+ if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointerForId(activeTouchId);
+ mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointerForId(activeTouchId);
+ mLastRawState.rawPointerData.pointerForId(activeTouchId);
float deltaX = (currentPointer.x - lastPointer.x)
* mPointerXMovementScale;
float deltaY = (currentPointer.y - lastPointer.y)
@@ -5126,7 +5477,7 @@
+ mConfig.pointerGestureMultitouchSettleInterval - when)
* 0.000001f);
#endif
- mCurrentRawPointerData.getCentroidOfTouchingPointers(
+ mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
&mPointerGesture.referenceTouchX,
&mPointerGesture.referenceTouchY);
mPointerController->getPosition(&mPointerGesture.referenceGestureX,
@@ -5134,23 +5485,23 @@
}
// Clear the reference deltas for fingers not yet included in the reference calculation.
- for (BitSet32 idBits(mCurrentFingerIdBits.value
+ for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
& ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
uint32_t id = idBits.clearFirstMarkedBit();
mPointerGesture.referenceDeltas[id].dx = 0;
mPointerGesture.referenceDeltas[id].dy = 0;
}
- mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
+ mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
// Add delta for all fingers and calculate a common movement delta.
float commonDeltaX = 0, commonDeltaY = 0;
- BitSet32 commonIdBits(mLastFingerIdBits.value
- & mCurrentFingerIdBits.value);
+ BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
+ & mCurrentCookedState.fingerIdBits.value);
for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
bool first = (idBits == commonIdBits);
uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
- const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
+ const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
+ const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
delta.dx += cpd.x - lpd.x;
delta.dy += cpd.y - lpd.y;
@@ -5191,11 +5542,13 @@
mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
} else {
// There are exactly two pointers.
- BitSet32 idBits(mCurrentFingerIdBits);
+ BitSet32 idBits(mCurrentCookedState.fingerIdBits);
uint32_t id1 = idBits.clearFirstMarkedBit();
uint32_t id2 = idBits.firstMarkedBit();
- const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
- const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
+ const RawPointerData::Pointer& p1 =
+ mCurrentRawState.rawPointerData.pointerForId(id1);
+ const RawPointerData::Pointer& p2 =
+ mCurrentRawState.rawPointerData.pointerForId(id2);
float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
if (mutualDistance > mPointerGestureMaxSwipeWidth) {
// There are two pointers but they are too far apart for a SWIPE,
@@ -5341,14 +5694,14 @@
} else {
// Otherwise, assume we mapped all touches from the previous frame.
// Reuse all mappings that are still applicable.
- mappedTouchIdBits.value = mLastFingerIdBits.value
- & mCurrentFingerIdBits.value;
+ mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
+ & mCurrentCookedState.fingerIdBits.value;
usedGestureIdBits = mPointerGesture.lastGestureIdBits;
// Check whether we need to choose a new active gesture id because the
// current went went up.
- for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
- & ~mCurrentFingerIdBits.value);
+ for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
+ & ~mCurrentCookedState.fingerIdBits.value);
!upTouchIdBits.isEmpty(); ) {
uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
@@ -5367,7 +5720,7 @@
mPointerGesture.activeGestureId);
#endif
- BitSet32 idBits(mCurrentFingerIdBits);
+ BitSet32 idBits(mCurrentCookedState.fingerIdBits);
for (uint32_t i = 0; i < currentFingerCount; i++) {
uint32_t touchId = idBits.clearFirstMarkedBit();
uint32_t gestureId;
@@ -5391,7 +5744,7 @@
mPointerGesture.currentGestureIdToIndex[gestureId] = i;
const RawPointerData::Pointer& pointer =
- mCurrentRawPointerData.pointerForId(touchId);
+ mCurrentRawState.rawPointerData.pointerForId(touchId);
float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
* mPointerXZoomScale;
float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
@@ -5422,7 +5775,7 @@
}
}
- mPointerController->setButtonState(mCurrentButtonState);
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
#if DEBUG_GESTURES
ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
@@ -5464,23 +5817,24 @@
mPointerSimple.currentProperties.clear();
bool down, hovering;
- if (!mCurrentStylusIdBits.isEmpty()) {
- uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
- uint32_t index = mCurrentCookedPointerData.idToIndex[id];
- float x = mCurrentCookedPointerData.pointerCoords[index].getX();
- float y = mCurrentCookedPointerData.pointerCoords[index].getY();
+ if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
+ uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
+ uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
+ float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
+ float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
mPointerController->setPosition(x, y);
- hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
+ hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
down = !hovering;
mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
+ mPointerSimple.currentCoords.copyFrom(
+ mCurrentCookedState.cookedPointerData.pointerCoords[index]);
mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerSimple.currentProperties.id = 0;
mPointerSimple.currentProperties.toolType =
- mCurrentCookedPointerData.pointerProperties[index].toolType;
+ mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
} else {
down = false;
hovering = false;
@@ -5498,16 +5852,16 @@
mPointerSimple.currentProperties.clear();
bool down, hovering;
- if (!mCurrentMouseIdBits.isEmpty()) {
- uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
- uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
- if (mLastMouseIdBits.hasBit(id)) {
- uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
- float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
- - mLastRawPointerData.pointers[lastIndex].x)
+ if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
+ uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
+ uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+ if (mLastCookedState.mouseIdBits.hasBit(id)) {
+ uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+ float deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
+ - mLastRawState.rawPointerData.pointers[lastIndex].x)
* mPointerXMovementScale;
- float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
- - mLastRawPointerData.pointers[lastIndex].y)
+ float deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
+ - mLastRawState.rawPointerData.pointers[lastIndex].y)
* mPointerYMovementScale;
rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
@@ -5518,20 +5872,20 @@
mPointerVelocityControl.reset();
}
- down = isPointerDown(mCurrentButtonState);
+ down = isPointerDown(mCurrentRawState.buttonState);
hovering = !down;
float x, y;
mPointerController->getPosition(&x, &y);
mPointerSimple.currentCoords.copyFrom(
- mCurrentCookedPointerData.pointerCoords[currentIndex]);
+ mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
hovering ? 0.0f : 1.0f);
mPointerSimple.currentProperties.id = 0;
mPointerSimple.currentProperties.toolType =
- mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
+ mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
} else {
mPointerVelocityControl.reset();
@@ -5556,7 +5910,7 @@
if (down || hovering) {
mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
mPointerController->clearSpots();
- mPointerController->setButtonState(mCurrentButtonState);
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
} else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
@@ -5568,7 +5922,7 @@
// Send up.
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
+ AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5581,7 +5935,7 @@
// Send hover exit.
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
+ AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5596,7 +5950,7 @@
// Send down.
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5606,7 +5960,7 @@
// Send move.
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5620,7 +5974,8 @@
// Send hover enter.
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
+ AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
+ mCurrentRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5630,7 +5985,8 @@
// Send hover move.
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5638,9 +5994,9 @@
getListener()->notifyMotion(&args);
}
- if (mCurrentRawVScroll || mCurrentRawHScroll) {
- float vscroll = mCurrentRawVScroll;
- float hscroll = mCurrentRawHScroll;
+ if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
+ float vscroll = mCurrentRawState.rawVScroll;
+ float hscroll = mCurrentRawState.rawHScroll;
mWheelYVelocityControl.move(when, NULL, &vscroll);
mWheelXVelocityControl.move(when, &hscroll, NULL);
@@ -5651,7 +6007,7 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
+ AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
mViewport.displayId,
1, &mPointerSimple.currentProperties, &pointerCoords,
mOrientedXPrecision, mOrientedYPrecision,
@@ -5676,10 +6032,11 @@
}
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
const PointerProperties* properties, const PointerCoords* coords,
- const uint32_t* idToIndex, BitSet32 idBits,
- int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
+ const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
+ float xPrecision, float yPrecision, nsecs_t downTime) {
PointerCoords pointerCoords[MAX_POINTERS];
PointerProperties pointerProperties[MAX_POINTERS];
uint32_t pointerCount = 0;
@@ -5713,7 +6070,7 @@
}
NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
- action, flags, metaState, buttonState, edgeFlags,
+ action, actionButton, flags, metaState, buttonState, edgeFlags,
mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
getListener()->notifyMotion(&args);
@@ -5786,11 +6143,11 @@
return NULL;
}
-void TouchInputMapper::assignPointerIds() {
- uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
- uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
+void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
+ uint32_t currentPointerCount = current->rawPointerData.pointerCount;
+ uint32_t lastPointerCount = last->rawPointerData.pointerCount;
- mCurrentRawPointerData.clearIdBits();
+ current->rawPointerData.clearIdBits();
if (currentPointerCount == 0) {
// No pointers to assign.
@@ -5801,21 +6158,21 @@
// All pointers are new.
for (uint32_t i = 0; i < currentPointerCount; i++) {
uint32_t id = i;
- mCurrentRawPointerData.pointers[i].id = id;
- mCurrentRawPointerData.idToIndex[id] = i;
- mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
+ current->rawPointerData.pointers[i].id = id;
+ current->rawPointerData.idToIndex[id] = i;
+ current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
}
return;
}
if (currentPointerCount == 1 && lastPointerCount == 1
- && mCurrentRawPointerData.pointers[0].toolType
- == mLastRawPointerData.pointers[0].toolType) {
+ && current->rawPointerData.pointers[0].toolType
+ == last->rawPointerData.pointers[0].toolType) {
// Only one pointer and no change in count so it must have the same id as before.
- uint32_t id = mLastRawPointerData.pointers[0].id;
- mCurrentRawPointerData.pointers[0].id = id;
- mCurrentRawPointerData.idToIndex[id] = 0;
- mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
+ uint32_t id = last->rawPointerData.pointers[0].id;
+ current->rawPointerData.pointers[0].id = id;
+ current->rawPointerData.idToIndex[id] = 0;
+ current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
return;
}
@@ -5833,9 +6190,9 @@
for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
lastPointerIndex++) {
const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointers[currentPointerIndex];
+ current->rawPointerData.pointers[currentPointerIndex];
const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointers[lastPointerIndex];
+ last->rawPointerData.pointers[lastPointerIndex];
if (currentPointer.toolType == lastPointer.toolType) {
int64_t deltaX = currentPointer.x - lastPointer.x;
int64_t deltaY = currentPointer.y - lastPointer.y;
@@ -5941,11 +6298,11 @@
matchedCurrentBits.markBit(currentPointerIndex);
matchedLastBits.markBit(lastPointerIndex);
- uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
- mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
- mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
- mCurrentRawPointerData.markIdBit(id,
- mCurrentRawPointerData.isHovering(currentPointerIndex));
+ uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
+ current->rawPointerData.pointers[currentPointerIndex].id = id;
+ current->rawPointerData.idToIndex[id] = currentPointerIndex;
+ current->rawPointerData.markIdBit(id,
+ current->rawPointerData.isHovering(currentPointerIndex));
usedIdBits.markBit(id);
#if DEBUG_POINTER_ASSIGNMENT
@@ -5961,10 +6318,10 @@
uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
uint32_t id = usedIdBits.markFirstUnmarkedBit();
- mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
- mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
- mCurrentRawPointerData.markIdBit(id,
- mCurrentRawPointerData.isHovering(currentPointerIndex));
+ current->rawPointerData.pointers[currentPointerIndex].id = id;
+ current->rawPointerData.idToIndex[id] = currentPointerIndex;
+ current->rawPointerData.markIdBit(id,
+ current->rawPointerData.isHovering(currentPointerIndex));
#if DEBUG_POINTER_ASSIGNMENT
ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
@@ -6043,18 +6400,18 @@
mSingleTouchMotionAccumulator.process(rawEvent);
}
-void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
+void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
if (mTouchButtonAccumulator.isToolActive()) {
- mCurrentRawPointerData.pointerCount = 1;
- mCurrentRawPointerData.idToIndex[0] = 0;
+ outState->rawPointerData.pointerCount = 1;
+ outState->rawPointerData.idToIndex[0] = 0;
bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
&& (mTouchButtonAccumulator.isHovering()
|| (mRawPointerAxes.pressure.valid
&& mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
- mCurrentRawPointerData.markIdBit(0, isHovering);
+ outState->rawPointerData.markIdBit(0, isHovering);
- RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
+ RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
outPointer.id = 0;
outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
@@ -6115,7 +6472,7 @@
mMultiTouchMotionAccumulator.process(rawEvent);
}
-void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
+void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
size_t outCount = 0;
BitSet32 newPointerIdBits;
@@ -6136,7 +6493,7 @@
break; // too many fingers!
}
- RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
+ RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
outPointer.x = inSlot->getX();
outPointer.y = inSlot->getY();
outPointer.pressure = inSlot->getPressure();
@@ -6163,38 +6520,37 @@
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
- if (*outHavePointerIds) {
- int32_t trackingId = inSlot->getTrackingId();
- int32_t id = -1;
- if (trackingId >= 0) {
- for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
- uint32_t n = idBits.clearFirstMarkedBit();
- if (mPointerTrackingIdMap[n] == trackingId) {
- id = n;
- }
+ mHavePointerIds = true;
+ int32_t trackingId = inSlot->getTrackingId();
+ int32_t id = -1;
+ if (trackingId >= 0) {
+ for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
+ uint32_t n = idBits.clearFirstMarkedBit();
+ if (mPointerTrackingIdMap[n] == trackingId) {
+ id = n;
}
+ }
- if (id < 0 && !mPointerIdBits.isFull()) {
- id = mPointerIdBits.markFirstUnmarkedBit();
- mPointerTrackingIdMap[id] = trackingId;
- }
+ if (id < 0 && !mPointerIdBits.isFull()) {
+ id = mPointerIdBits.markFirstUnmarkedBit();
+ mPointerTrackingIdMap[id] = trackingId;
}
- if (id < 0) {
- *outHavePointerIds = false;
- mCurrentRawPointerData.clearIdBits();
- newPointerIdBits.clear();
- } else {
- outPointer.id = id;
- mCurrentRawPointerData.idToIndex[id] = outCount;
- mCurrentRawPointerData.markIdBit(id, isHovering);
- newPointerIdBits.markBit(id);
- }
+ }
+ if (id < 0) {
+ mHavePointerIds = false;
+ outState->rawPointerData.clearIdBits();
+ newPointerIdBits.clear();
+ } else {
+ outPointer.id = id;
+ outState->rawPointerData.idToIndex[id] = outCount;
+ outState->rawPointerData.markIdBit(id, isHovering);
+ newPointerIdBits.markBit(id);
}
outCount += 1;
}
- mCurrentRawPointerData.pointerCount = outCount;
+ outState->rawPointerData.pointerCount = outCount;
mPointerIdBits = newPointerIdBits;
mMultiTouchMotionAccumulator.finishSync();
@@ -6238,6 +6594,77 @@
|| mTouchButtonAccumulator.hasStylus();
}
+// --- ExternalStylusInputMapper
+
+ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
+ InputMapper(device) {
+
+}
+
+uint32_t ExternalStylusInputMapper::getSources() {
+ return AINPUT_SOURCE_STYLUS;
+}
+
+void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+ info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+}
+
+void ExternalStylusInputMapper::dump(String8& dump) {
+ dump.append(INDENT2 "External Stylus Input Mapper:\n");
+ dump.append(INDENT3 "Raw Stylus Axes:\n");
+ dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
+ dump.append(INDENT3 "Stylus State:\n");
+ dumpStylusState(dump, mStylusState);
+}
+
+void ExternalStylusInputMapper::configure(nsecs_t when,
+ const InputReaderConfiguration* config, uint32_t changes) {
+ getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
+ mTouchButtonAccumulator.configure(getDevice());
+}
+
+void ExternalStylusInputMapper::reset(nsecs_t when) {
+ InputDevice* device = getDevice();
+ mSingleTouchMotionAccumulator.reset(device);
+ mTouchButtonAccumulator.reset(device);
+ InputMapper::reset(when);
+}
+
+void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
+ mSingleTouchMotionAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+}
+
+void ExternalStylusInputMapper::sync(nsecs_t when) {
+ mStylusState.clear();
+
+ mStylusState.when = when;
+
+ mStylusState.toolType = mTouchButtonAccumulator.getToolType();
+ if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+
+ int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+ if (mRawPressureAxis.valid) {
+ mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
+ } else if (mTouchButtonAccumulator.isToolActive()) {
+ mStylusState.pressure = 1.0f;
+ } else {
+ mStylusState.pressure = 0.0f;
+ }
+
+ mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
+
+ mContext->dispatchExternalStylusState(mStylusState);
+}
+
// --- JoystickInputMapper ---
@@ -6561,7 +6988,7 @@
uint32_t policyFlags = 0;
NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
getListener()->notifyMotion(&args);
}
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 62cd36a..7cb4680 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -139,7 +139,10 @@
CHANGE_DEVICE_ALIAS = 1 << 5,
// The location calibration matrix changed.
- TOUCH_AFFINE_TRANSFORMATION = 1 << 6,
+ CHANGE_TOUCH_AFFINE_TRANSFORMATION = 1 << 6,
+
+ // The presence of an external stylus has changed.
+ CHANGE_EXTERNAL_STYLUS_PRESENCE = 1 << 7,
// All devices must be reopened.
CHANGE_MUST_REOPEN = 1 << 31,
@@ -371,6 +374,31 @@
virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;
};
+struct StylusState {
+ /* Time the stylus event was received. */
+ nsecs_t when;
+ /* Pressure as reported by the stylus, normalized to the range [0, 1.0]. */
+ float pressure;
+ /* The state of the stylus buttons as a bitfield (e.g. AMOTION_EVENT_BUTTON_SECONDARY). */
+ uint32_t buttons;
+ /* Which tool type the stylus is currently using (e.g. AMOTION_EVENT_TOOL_TYPE_ERASER). */
+ int32_t toolType;
+
+ void copyFrom(const StylusState& other) {
+ when = other.when;
+ pressure = other.pressure;
+ buttons = other.buttons;
+ toolType = other.toolType;
+ }
+
+ void clear() {
+ when = LLONG_MAX;
+ pressure = 0.f;
+ buttons = 0;
+ toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+ }
+};
+
/* Internal interface used by individual input devices to access global input device state
* and parameters maintained by the input reader.
@@ -392,6 +420,9 @@
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
virtual int32_t bumpGeneration() = 0;
+ virtual void getExternalStylusDevices(Vector<InputDeviceInfo>& outDevices) = 0;
+ virtual void dispatchExternalStylusState(const StylusState& outState) = 0;
+
virtual InputReaderPolicyInterface* getPolicy() = 0;
virtual InputListenerInterface* getListener() = 0;
virtual EventHubInterface* getEventHub() = 0;
@@ -458,6 +489,8 @@
virtual void fadePointer();
virtual void requestTimeoutAtTime(nsecs_t when);
virtual int32_t bumpGeneration();
+ virtual void getExternalStylusDevices(Vector<InputDeviceInfo>& outDevices);
+ virtual void dispatchExternalStylusState(const StylusState& outState);
virtual InputReaderPolicyInterface* getPolicy();
virtual InputListenerInterface* getListener();
virtual EventHubInterface* getEventHub();
@@ -496,6 +529,10 @@
void updateGlobalMetaStateLocked();
int32_t getGlobalMetaStateLocked();
+ void notifyExternalStylusPresenceChanged();
+ void getExternalStylusDevicesLocked(Vector<InputDeviceInfo>& outDevices);
+ void dispatchExternalStylusState(const StylusState& state);
+
void fadePointerLocked();
int32_t mGeneration;
@@ -555,6 +592,9 @@
inline bool isExternal() { return mIsExternal; }
inline void setExternal(bool external) { mIsExternal = external; }
+ inline void setMic(bool hasMic) { mHasMic = hasMic; }
+ inline bool hasMic() const { return mHasMic; }
+
inline bool isIgnored() { return mMappers.isEmpty(); }
void dump(String8& dump);
@@ -563,6 +603,7 @@
void reset(nsecs_t when);
void process(const RawEvent* rawEvents, size_t count);
void timeoutExpired(nsecs_t when);
+ void updateExternalStylusState(const StylusState& state);
void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
@@ -618,6 +659,7 @@
uint32_t mSources;
bool mIsExternal;
+ bool mHasMic;
bool mDropUntilNextSync;
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
@@ -831,9 +873,21 @@
return pointerCoords[idToIndex[id]];
}
- inline bool isHovering(uint32_t pointerIndex) {
+ inline PointerCoords& editPointerCoordsWithId(uint32_t id) {
+ return pointerCoords[idToIndex[id]];
+ }
+
+ inline PointerProperties& editPointerPropertiesWithId(uint32_t id) {
+ return pointerProperties[idToIndex[id]];
+ }
+
+ inline bool isHovering(uint32_t pointerIndex) const {
return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
}
+
+ inline bool isTouching(uint32_t pointerIndex) const {
+ return touchingIdBits.hasBit(pointerProperties[pointerIndex].id);
+ }
};
@@ -978,6 +1032,8 @@
virtual int32_t getMetaState();
+ virtual void updateExternalStylusState(const StylusState& state);
+
virtual void fadePointer();
protected:
@@ -989,6 +1045,7 @@
static void dumpRawAbsoluteAxisInfo(String8& dump,
const RawAbsoluteAxisInfo& axis, const char* name);
+ static void dumpStylusState(String8& dump, const StylusState& state);
};
@@ -1195,6 +1252,7 @@
virtual void fadePointer();
virtual void cancelTouch(nsecs_t when);
virtual void timeoutExpired(nsecs_t when);
+ virtual void updateExternalStylusState(const StylusState& state);
protected:
CursorButtonAccumulator mCursorButtonAccumulator;
@@ -1334,36 +1392,83 @@
// Affine location transformation/calibration
struct TouchAffineTransformation mAffineTransform;
- // Raw pointer axis information from the driver.
RawPointerAxes mRawPointerAxes;
- // Raw pointer sample data.
- RawPointerData mCurrentRawPointerData;
- RawPointerData mLastRawPointerData;
+ struct RawState {
+ nsecs_t when;
- // Cooked pointer sample data.
- CookedPointerData mCurrentCookedPointerData;
- CookedPointerData mLastCookedPointerData;
+ // Raw pointer sample data.
+ RawPointerData rawPointerData;
- // Button state.
- int32_t mCurrentButtonState;
- int32_t mLastButtonState;
+ int32_t buttonState;
- // Scroll state.
- int32_t mCurrentRawVScroll;
- int32_t mCurrentRawHScroll;
+ // Scroll state.
+ int32_t rawVScroll;
+ int32_t rawHScroll;
- // Id bits used to differentiate fingers, stylus and mouse tools.
- BitSet32 mCurrentFingerIdBits; // finger or unknown
- BitSet32 mLastFingerIdBits;
- BitSet32 mCurrentStylusIdBits; // stylus or eraser
- BitSet32 mLastStylusIdBits;
- BitSet32 mCurrentMouseIdBits; // mouse or lens
- BitSet32 mLastMouseIdBits;
+ void copyFrom(const RawState& other) {
+ when = other.when;
+ rawPointerData.copyFrom(other.rawPointerData);
+ buttonState = other.buttonState;
+ rawVScroll = other.rawVScroll;
+ rawHScroll = other.rawHScroll;
+ }
+
+ void clear() {
+ when = 0;
+ rawPointerData.clear();
+ buttonState = 0;
+ rawVScroll = 0;
+ rawHScroll = 0;
+ }
+ };
+
+ struct CookedState {
+ // Cooked pointer sample data.
+ CookedPointerData cookedPointerData;
+
+ // Id bits used to differentiate fingers, stylus and mouse tools.
+ BitSet32 fingerIdBits;
+ BitSet32 stylusIdBits;
+ BitSet32 mouseIdBits;
+
+ int32_t buttonState;
+
+ void copyFrom(const CookedState& other) {
+ cookedPointerData.copyFrom(other.cookedPointerData);
+ fingerIdBits = other.fingerIdBits;
+ stylusIdBits = other.stylusIdBits;
+ mouseIdBits = other.mouseIdBits;
+ buttonState = other.buttonState;
+ }
+
+ void clear() {
+ cookedPointerData.clear();
+ fingerIdBits.clear();
+ stylusIdBits.clear();
+ mouseIdBits.clear();
+ buttonState = 0;
+ }
+ };
+
+ Vector<RawState> mRawStatesPending;
+ RawState mCurrentRawState;
+ CookedState mCurrentCookedState;
+ RawState mLastRawState;
+ CookedState mLastCookedState;
+
+ // State provided by an external stylus
+ StylusState mExternalStylusState;
+ int64_t mExternalStylusId;
+ nsecs_t mExternalStylusFusionTimeout;
+ bool mExternalStylusDataPending;
// True if we sent a HOVER_ENTER event.
bool mSentHoverEnter;
+ // Have we assigned pointer IDs for this stream
+ bool mHavePointerIds;
+
// Is the current stream of direct touch events aborted
bool mCurrentMotionAborted;
@@ -1386,11 +1491,13 @@
virtual void parseCalibration();
virtual void resolveCalibration();
virtual void dumpCalibration(String8& dump);
- virtual void dumpAffineTransformation(String8& dump);
- virtual bool hasStylus() const = 0;
virtual void updateAffineTransformation();
+ virtual void dumpAffineTransformation(String8& dump);
+ virtual void resolveExternalStylusPresence();
+ virtual bool hasStylus() const = 0;
+ virtual bool hasExternalStylus() const;
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0;
+ virtual void syncTouch(nsecs_t when, RawState* outState) = 0;
private:
// The current viewport.
@@ -1436,6 +1543,8 @@
float mTiltYCenter;
float mTiltYScale;
+ bool mExternalStylusConnected;
+
// Oriented motion ranges for input device info.
struct OrientedRanges {
InputDeviceInfo::MotionRange x;
@@ -1678,20 +1787,28 @@
VelocityControl mWheelXVelocityControl;
VelocityControl mWheelYVelocityControl;
+ void resetExternalStylus();
+ void clearStylusDataPendingFlags();
+
void sync(nsecs_t when);
bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
+ void processRawTouches(bool timeout);
+ void cookAndDispatch(nsecs_t when);
void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
int32_t keyEventAction, int32_t keyEventFlags);
void dispatchTouches(nsecs_t when, uint32_t policyFlags);
void dispatchHoverExit(nsecs_t when, uint32_t policyFlags);
void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
+ void dispatchButtonRelease(nsecs_t when, uint32_t policyFlags);
+ void dispatchButtonPress(nsecs_t when, uint32_t policyFlags);
+ const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
void cookPointerData();
+ void abortTouches(nsecs_t when, uint32_t policyFlags);
void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
- void abortTouches(nsecs_t when, uint32_t policyFlags);
void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
@@ -1709,13 +1826,17 @@
bool down, bool hovering);
void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
+ bool assignExternalStylusId(const RawState& state, bool timeout);
+ void applyExternalStylusButtonState(nsecs_t when);
+ void applyExternalStylusTouchState(nsecs_t when);
+
// Dispatches a motion event.
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
// method will take care of setting the index and transmuting the action to DOWN or UP
// it is the first / last pointer to go down / up.
void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags,
+ int32_t action, int32_t actionButton,
+ int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
const PointerProperties* properties, const PointerCoords* coords,
const uint32_t* idToIndex, BitSet32 idBits,
int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
@@ -1730,7 +1851,7 @@
bool isPointInsideSurface(int32_t x, int32_t y);
const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
- void assignPointerIds();
+ static void assignPointerIds(const RawState* last, RawState* current);
};
@@ -1743,7 +1864,7 @@
virtual void process(const RawEvent* rawEvent);
protected:
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
+ virtual void syncTouch(nsecs_t when, RawState* outState);
virtual void configureRawPointerAxes();
virtual bool hasStylus() const;
@@ -1761,7 +1882,7 @@
virtual void process(const RawEvent* rawEvent);
protected:
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
+ virtual void syncTouch(nsecs_t when, RawState* outState);
virtual void configureRawPointerAxes();
virtual bool hasStylus() const;
@@ -1773,6 +1894,27 @@
int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
};
+class ExternalStylusInputMapper : public InputMapper {
+public:
+ ExternalStylusInputMapper(InputDevice* device);
+ virtual ~ExternalStylusInputMapper() = default;
+
+ virtual uint32_t getSources();
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+ virtual void dump(String8& dump);
+ virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+ virtual void reset(nsecs_t when);
+ virtual void process(const RawEvent* rawEvent);
+ virtual void sync(nsecs_t when);
+
+private:
+ SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
+ RawAbsoluteAxisInfo mRawPressureAxis;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+
+ StylusState mStylusState;
+};
+
class JoystickInputMapper : public InputMapper {
public:
diff --git a/services/inputflinger/host/Android.mk b/services/inputflinger/host/Android.mk
new file mode 100644
index 0000000..b828175
--- /dev/null
+++ b/services/inputflinger/host/Android.mk
@@ -0,0 +1,62 @@
+# Copyright (C) 2015 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+
+LOCAL_SRC_FILES:= \
+ InputFlinger.cpp \
+ InputDriver.cpp \
+ InputHost.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libcrypto \
+ libcutils \
+ libinput \
+ liblog \
+ libutils \
+ libhardware
+
+
+# TODO: Move inputflinger to its own process and mark it hidden
+#LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_CFLAGS += -Wno-unused-parameter
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+LOCAL_MODULE := libinputflingerhost
+
+include $(BUILD_SHARED_LIBRARY)
+
+########################################################################
+# build input flinger executable
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+
+LOCAL_SRC_FILES:= \
+ main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libinputflingerhost \
+ libutils
+
+LOCAL_MODULE := inputflinger
+
+include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
new file mode 100644
index 0000000..cb4ccbe
--- /dev/null
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015 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 <functional>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unordered_map>
+#include <vector>
+
+#define LOG_TAG "InputDriver"
+
+#define LOG_NDEBUG 0
+
+#include "InputDriver.h"
+#include "InputHost.h"
+
+#include <hardware/input.h>
+#include <input/InputDevice.h>
+#include <utils/Log.h>
+#include <utils/PropertyMap.h>
+#include <utils/String8.h>
+
+#define INDENT2 " "
+
+namespace android {
+
+static input_host_callbacks_t kCallbacks = {
+ .create_device_identifier = create_device_identifier,
+ .create_device_definition = create_device_definition,
+ .create_input_report_definition = create_input_report_definition,
+ .create_output_report_definition = create_output_report_definition,
+ .free_report_definition = free_report_definition,
+ .input_device_definition_add_report = input_device_definition_add_report,
+ .input_report_definition_add_collection = input_report_definition_add_collection,
+ .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
+ .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
+ .register_device = register_device,
+ .input_allocate_report = input_allocate_report,
+ .input_report_set_usage_int = input_report_set_usage_int,
+ .input_report_set_usage_bool = input_report_set_usage_bool,
+ .report_event = report_event,
+ .input_get_device_property_map = input_get_device_property_map,
+ .input_get_device_property = input_get_device_property,
+ .input_get_property_key = input_get_property_key,
+ .input_get_property_value = input_get_property_value,
+ .input_free_device_property = input_free_device_property,
+ .input_free_device_property_map = input_free_device_property_map,
+};
+
+InputDriver::InputDriver(const char* name) : mName(String8(name)) {
+ const hw_module_t* module;
+ int err = input_open(&module, name);
+ LOG_ALWAYS_FATAL_IF(err != 0, "Input module %s not found", name);
+ mHal = reinterpret_cast<const input_module_t*>(module);
+}
+
+void InputDriver::init(InputHostInterface* host) {
+ mHal->init(mHal, static_cast<input_host_t*>(host), kCallbacks);
+}
+
+void InputDriver::dump(String8& result) {
+ result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
+}
+
+} // namespace android
+
+struct input_property_map {
+ android::PropertyMap* propertyMap;
+};
+
+struct input_property {
+ android::String8 key;
+ android::String8 value;
+};
+
+struct input_device_identifier {
+ const char* name;
+ const char* uniqueId;
+ input_bus_t bus;
+ int32_t vendorId;
+ int32_t productId;
+ int32_t version;
+};
+
+struct input_device_definition {
+ std::vector<input_report_definition*> reportDefs;
+};
+
+struct input_device_handle {
+ input_device_identifier_t* id;
+ input_device_definition_t* def;
+};
+
+struct input_int_usage {
+ input_usage_t usage;
+ int32_t min;
+ int32_t max;
+ float resolution;
+};
+
+struct input_collection {
+ int32_t arity;
+ std::vector<input_int_usage> intUsages;
+ std::vector<input_usage_t> boolUsages;
+};
+
+struct InputCollectionIdHasher {
+ std::size_t operator()(const input_collection_id& id) const {
+ return std::hash<int>()(static_cast<int>(id));
+ }
+};
+
+struct input_report_definition {
+ std::unordered_map<input_collection_id_t, input_collection, InputCollectionIdHasher> collections;
+};
+
+// HAL wrapper functions
+
+namespace android {
+
+::input_device_identifier_t* create_device_identifier(input_host_t* host,
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id) {
+ auto identifier = new ::input_device_identifier {
+ .name = name,
+ .productId = product_id,
+ .vendorId = vendor_id,
+ //.bus = bus,
+ .uniqueId = unique_id,
+ };
+ // store this identifier somewhere? in the host?
+ return identifier;
+}
+
+input_device_definition_t* create_device_definition(input_host_t* host) {
+ return new ::input_device_definition;
+}
+
+input_report_definition_t* create_input_report_definition(input_host_t* host) {
+ return new ::input_report_definition;
+}
+
+input_report_definition_t* create_output_report_definition(input_host_t* host) {
+ return new ::input_report_definition;
+}
+
+void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
+ delete report_def;
+}
+
+void input_device_definition_add_report(input_host_t* host,
+ input_device_definition_t* d, input_report_definition_t* r) {
+ d->reportDefs.push_back(r);
+}
+
+void input_report_definition_add_collection(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
+ report->collections[id] = {.arity = arity};
+}
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t usage, int32_t min, int32_t max, float resolution) {
+ if (report->collections.find(id) != report->collections.end()) {
+ report->collections[id].intUsages.push_back({
+ .usage = usage, .min = min, .max = max, .resolution = resolution});
+ }
+}
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t* usage, size_t usage_count) {
+ if (report->collections.find(id) != report->collections.end()) {
+ for (size_t i = 0; i < usage_count; ++i) {
+ report->collections[id].boolUsages.push_back(usage[i]);
+ }
+ }
+}
+
+input_device_handle_t* register_device(input_host_t* host,
+ input_device_identifier_t* id, input_device_definition_t* d) {
+ ALOGD("Registering device %s with %d input reports", id->name, d->reportDefs.size());
+ return new input_device_handle{ .id = id, .def = d };
+}
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+ ALOGD("Allocating input report for definition %p", r);
+ return nullptr;
+}
+
+void input_report_set_usage_int(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
+
+void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
+
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
+ ALOGD("report_event %p for handle %p", report, d);
+}
+
+input_property_map_t* input_get_device_property_map(input_host_t* host,
+ input_device_identifier_t* id) {
+ InputDeviceIdentifier idi;
+ idi.name = id->name;
+ idi.uniqueId = id->uniqueId;
+ idi.bus = id->bus;
+ idi.vendor = id->vendorId;
+ idi.product = id->productId;
+ idi.version = id->version;
+
+ String8 configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
+ idi, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
+ if (configFile.isEmpty()) {
+ ALOGD("No input device configuration file found for device '%s'.",
+ idi.name.string());
+ } else {
+ auto propMap = new input_property_map_t();
+ status_t status = PropertyMap::load(configFile, &propMap->propertyMap);
+ if (status) {
+ ALOGE("Error loading input device configuration file for device '%s'. "
+ "Using default configuration.",
+ idi.name.string());
+ delete propMap;
+ return nullptr;
+ }
+ return propMap;
+ }
+ return nullptr;
+}
+
+input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+ const char* key) {
+ String8 keyString(key);
+ if (map != nullptr) {
+ if (map->propertyMap->hasProperty(keyString)) {
+ auto prop = new input_property_t();
+ if (!map->propertyMap->tryGetProperty(keyString, prop->value)) {
+ delete prop;
+ return nullptr;
+ }
+ prop->key = keyString;
+ return prop;
+ }
+ }
+ return nullptr;
+}
+
+const char* input_get_property_key(input_host_t* host, input_property_t* property) {
+ if (property != nullptr) {
+ return property->key.string();
+ }
+ return nullptr;
+}
+
+const char* input_get_property_value(input_host_t* host, input_property_t* property) {
+ if (property != nullptr) {
+ return property->value.string();
+ }
+ return nullptr;
+}
+
+void input_free_device_property(input_host_t* host, input_property_t* property) {
+ if (property != nullptr) {
+ delete property;
+ }
+}
+
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+ if (map != nullptr) {
+ delete map->propertyMap;
+ delete map;
+ }
+}
+
+} // namespace android
diff --git a/services/inputflinger/host/InputDriver.h b/services/inputflinger/host/InputDriver.h
new file mode 100644
index 0000000..9bc14a7
--- /dev/null
+++ b/services/inputflinger/host/InputDriver.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_INPUT_DRIVER_H
+#define ANDROID_INPUT_DRIVER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "InputHost.h"
+
+#include <hardware/input.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class InputHostInterface;
+
+class InputDriverInterface : public virtual RefBase {
+protected:
+ InputDriverInterface() = default;
+ virtual ~InputDriverInterface() = default;
+
+public:
+ virtual void init(InputHostInterface* host) = 0;
+
+ virtual void dump(String8& result) = 0;
+};
+
+class InputDriver : public InputDriverInterface {
+public:
+ InputDriver(const char* name);
+ virtual ~InputDriver() = default;
+
+ virtual void init(InputHostInterface* host) override;
+
+ virtual void dump(String8& result) override;
+
+private:
+ String8 mName;
+ const input_module_t* mHal;
+};
+
+
+extern "C" {
+
+input_device_identifier_t* create_device_identifier(input_host_t* host,
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id);
+
+input_device_definition_t* create_device_definition(input_host_t* host);
+
+input_report_definition_t* create_input_report_definition(input_host_t* host);
+
+input_report_definition_t* create_output_report_definition(input_host_t* host);
+
+void free_report_definition(input_host_t* host, input_report_definition_t* report_def);
+
+void input_device_definition_add_report(input_host_t* host,
+ input_device_definition_t* d, input_report_definition_t* r);
+
+void input_report_definition_add_collection(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id, int32_t arity);
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t usage, int32_t min, int32_t max, float resolution);
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t* usage, size_t usage_count);
+
+
+input_device_handle_t* register_device(input_host_t* host,
+ input_device_identifier_t* id, input_device_definition_t* d);
+
+void unregister_device(input_host_t* host, input_device_handle_t* handle);
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r);
+
+void input_report_set_usage_int(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index);
+
+void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index);
+
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report);
+
+input_property_map_t* input_get_device_property_map(input_host_t* host,
+ input_device_identifier_t* id);
+
+input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+ const char* key);
+
+const char* input_get_property_key(input_host_t* host, input_property_t* property);
+
+const char* input_get_property_value(input_host_t* host, input_property_t* property);
+
+void input_free_device_property(input_host_t* host, input_property_t* property);
+
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map);
+}
+
+} // namespace android
+#endif // ANDROID_INPUT_DRIVER_H
diff --git a/services/inputflinger/host/InputFlinger.cpp b/services/inputflinger/host/InputFlinger.cpp
new file mode 100644
index 0000000..859c3b8
--- /dev/null
+++ b/services/inputflinger/host/InputFlinger.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "InputFlinger"
+
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+
+#include "InputFlinger.h"
+#include "InputDriver.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
+#include <hardware/input.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+namespace android {
+
+const String16 sAccessInputFlingerPermission("android.permission.ACCESS_INPUT_FLINGER");
+const String16 sDumpPermission("android.permission.DUMP");
+
+
+InputFlinger::InputFlinger() :
+ BnInputFlinger() {
+ ALOGI("InputFlinger is starting");
+ mHost = new InputHost();
+ mHost->registerInputDriver(new InputDriver(INPUT_INSTANCE_EVDEV));
+}
+
+InputFlinger::~InputFlinger() {
+}
+
+status_t InputFlinger::dump(int fd, const Vector<String16>& args) {
+ String8 result;
+ const IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_SHELL)
+ && !PermissionCache::checkPermission(sDumpPermission, pid, uid)) {
+ result.appendFormat("Permission Denial: "
+ "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
+ } else {
+ dumpInternal(result);
+ }
+ write(fd, result.string(), result.size());
+ return OK;
+}
+
+void InputFlinger::dumpInternal(String8& result) {
+ result.append("INPUT FLINGER (dumpsys inputflinger)\n");
+ mHost->dump(result);
+}
+
+}; // namespace android
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
new file mode 100644
index 0000000..39e69e5
--- /dev/null
+++ b/services/inputflinger/host/InputFlinger.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ANDROID_INPUT_FLINGER_H
+#define ANDROID_INPUT_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "InputHost.h"
+
+#include <cutils/compiler.h>
+#include <input/IInputFlinger.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class InputFlinger : public BnInputFlinger {
+public:
+ static char const* getServiceName() ANDROID_API {
+ return "inputflinger";
+ }
+
+ InputFlinger() ANDROID_API;
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+private:
+ virtual ~InputFlinger();
+
+ void dumpInternal(String8& result);
+
+ sp<InputHostInterface> mHost;
+};
+
+} // namespace android
+
+#endif // ANDROID_INPUT_FLINGER_H
diff --git a/services/inputflinger/host/InputHost.cpp b/services/inputflinger/host/InputHost.cpp
new file mode 100644
index 0000000..51d3e6b
--- /dev/null
+++ b/services/inputflinger/host/InputHost.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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 <vector>
+
+#include "InputDriver.h"
+#include "InputHost.h"
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#define INDENT " "
+
+namespace android {
+
+void InputHost::registerInputDriver(InputDriverInterface* driver) {
+ LOG_ALWAYS_FATAL_IF(driver == nullptr, "Cannot register a nullptr as an InputDriver!");
+ driver->init(this);
+ mDrivers.push_back(driver);
+}
+
+void InputHost::dump(String8& result) {
+ result.append(INDENT "Input Drivers:\n");
+ for (size_t i = 0; i < mDrivers.size(); i++) {
+ mDrivers[i]->dump(result);
+ }
+}
+
+} // namespace android
diff --git a/services/inputflinger/host/InputHost.h b/services/inputflinger/host/InputHost.h
new file mode 100644
index 0000000..42a66e0
--- /dev/null
+++ b/services/inputflinger/host/InputHost.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_INPUT_HOST_H
+#define ANDROID_INPUT_HOST_H
+
+#include <vector>
+
+#include <hardware/input.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/StrongPointer.h>
+
+#include "InputDriver.h"
+
+// Declare a concrete type for the HAL
+struct input_host {
+};
+
+namespace android {
+
+class InputDriverInterface;
+
+class InputHostInterface : public input_host_t, public virtual RefBase {
+protected:
+ InputHostInterface() = default;
+ virtual ~InputHostInterface() = default;
+
+public:
+
+ virtual void registerInputDriver(InputDriverInterface* driver) = 0;
+
+ virtual void dump(String8& result) = 0;
+};
+
+class InputHost : public InputHostInterface {
+public:
+ InputHost() = default;
+
+ virtual void registerInputDriver(InputDriverInterface* driver) override;
+
+ virtual void dump(String8& result) override;
+
+private:
+ std::vector<sp<InputDriverInterface>> mDrivers;
+};
+
+} // namespace android
+#endif // ANDRIOD_INPUT_HOST_H
diff --git a/services/inputflinger/host/main.cpp b/services/inputflinger/host/main.cpp
new file mode 100644
index 0000000..0a517cc
--- /dev/null
+++ b/services/inputflinger/host/main.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 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 <binder/BinderService.h>
+#include "InputFlinger.h"
+
+using namespace android;
+
+int main(int, char**) {
+ ProcessState::self()->setThreadPoolMaxThreadCount(4);
+ BinderService<InputFlinger>::publishAndJoinThreadPool(true);
+ return 0;
+}
diff --git a/services/inputflinger/tests/Android.mk b/services/inputflinger/tests/Android.mk
index 6dae82f..4c43392 100644
--- a/services/inputflinger/tests/Android.mk
+++ b/services/inputflinger/tests/Android.mk
@@ -10,37 +10,26 @@
shared_libraries := \
libcutils \
liblog \
- libandroidfw \
libutils \
libhardware \
libhardware_legacy \
libui \
libskia \
- libstlport \
libinput \
libinputflinger \
libinputservice
-static_libraries := \
- libgtest \
- libgtest_main
-
c_includes := \
- bionic \
- bionic/libstdc++/include \
- external/gtest/include \
- external/stlport/stlport \
external/skia/include/core
-module_tags := eng tests
+module_tags := tests
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
$(eval LOCAL_C_INCLUDES := $(c_includes)) \
- $(eval LOCAL_CFLAGS += -Wno-unused-parameter) \
+ $(eval LOCAL_CFLAGS += -Wno-unused-parameter) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
$(eval LOCAL_MODULE_TAGS := $(module_tags)) \
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 7aac6ed..2d8eaef 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -49,51 +49,49 @@
}
private:
- virtual void notifyConfigurationChanged(nsecs_t when) {
+ virtual void notifyConfigurationChanged(nsecs_t) {
}
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle,
- const String8& reason) {
+ virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
+ const sp<InputWindowHandle>&,
+ const String8&) {
return 0;
}
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
+ virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) {
}
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
*outConfig = mConfig;
}
- virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
+ virtual bool filterInputEvent(const InputEvent*, uint32_t) {
return true;
}
- virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
+ virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
}
- virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+ virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
}
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
- const KeyEvent* keyEvent, uint32_t policyFlags) {
+ virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&,
+ const KeyEvent*, uint32_t) {
return 0;
}
- virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
- const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
+ virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&,
+ const KeyEvent*, uint32_t, KeyEvent*) {
return false;
}
- virtual void notifySwitch(nsecs_t when,
- uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
+ virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
}
- virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
+ virtual void pokeUserActivity(nsecs_t, int32_t) {
}
- virtual bool checkInjectEventsPermissionNonReentrant(
- int32_t injectorPid, int32_t injectorUid) {
+ virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
return false;
}
};
@@ -152,7 +150,7 @@
// Rejects undefined motion actions.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -163,7 +161,7 @@
// Rejects pointer down with invalid index.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -173,7 +171,7 @@
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -184,7 +182,7 @@
// Rejects pointer up with invalid index.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -194,7 +192,7 @@
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -204,7 +202,7 @@
// Rejects motion events with invalid number of pointers.
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -213,7 +211,7 @@
<< "Should reject motion events with 0 pointers.";
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -224,7 +222,7 @@
// Rejects motion events with invalid pointer ids.
pointerProperties[0].id = -1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -234,7 +232,7 @@
pointerProperties[0].id = MAX_POINTER_ID + 1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -246,7 +244,7 @@
pointerProperties[0].id = 1;
pointerProperties[1].id = 1;
event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index c6eb1fd..f34b810 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -104,17 +104,16 @@
if (mY > mMaxY) mY = mMaxY;
}
- virtual void fade(Transition transition) {
+ virtual void fade(Transition) {
}
- virtual void unfade(Transition transition) {
+ virtual void unfade(Transition) {
}
- virtual void setPresentation(Presentation presentation) {
+ virtual void setPresentation(Presentation) {
}
- virtual void setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
+ virtual void setSpots(const PointerCoords*, const uint32_t*, BitSet32) {
}
virtual void clearSpots() {
@@ -196,11 +195,11 @@
mInputDevices = inputDevices;
}
- virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) {
+ virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier&) {
return NULL;
}
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) {
+ virtual String8 getDeviceAlias(const InputDeviceIdentifier&) {
return String8::empty();
}
};
@@ -482,7 +481,7 @@
return device ? device->identifier : InputDeviceIdentifier();
}
- virtual int32_t getDeviceControllerNumber(int32_t deviceId) const {
+ virtual int32_t getDeviceControllerNumber(int32_t) const {
return 0;
}
@@ -515,7 +514,7 @@
return false;
}
- virtual bool hasInputProperty(int32_t deviceId, int property) const {
+ virtual bool hasInputProperty(int32_t, int) const {
return false;
}
@@ -553,8 +552,7 @@
return NULL;
}
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
- AxisInfo* outAxisInfo) const {
+ virtual status_t mapAxis(int32_t, int32_t, AxisInfo*) const {
return NAME_NOT_FOUND;
}
@@ -562,7 +560,7 @@
mExcludedDevices = devices;
}
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
+ virtual size_t getEvents(int, RawEvent* buffer, size_t) {
if (mEvents.empty()) {
return 0;
}
@@ -680,25 +678,25 @@
}
}
- virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const {
+ virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t) const {
return NULL;
}
- virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) {
+ virtual bool setKeyboardLayoutOverlay(int32_t, const sp<KeyCharacterMap>&) {
return false;
}
- virtual void vibrate(int32_t deviceId, nsecs_t duration) {
+ virtual void vibrate(int32_t, nsecs_t) {
}
- virtual void cancelVibrate(int32_t deviceId) {
+ virtual void cancelVibrate(int32_t) {
}
- virtual bool isExternal(int32_t deviceId) const {
+ virtual bool isExternal(int32_t) const {
return false;
}
- virtual void dump(String8& dump) {
+ virtual void dump(String8&) {
}
virtual void monitor() {
@@ -763,23 +761,30 @@
return mListener.get();
}
- virtual void disableVirtualKeysUntil(nsecs_t time) {
+ virtual void disableVirtualKeysUntil(nsecs_t) {
}
- virtual bool shouldDropVirtualKey(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode) {
+ virtual bool shouldDropVirtualKey(nsecs_t, InputDevice*, int32_t, int32_t) {
return false;
}
virtual void fadePointer() {
}
- virtual void requestTimeoutAtTime(nsecs_t when) {
+ virtual void requestTimeoutAtTime(nsecs_t) {
}
virtual int32_t bumpGeneration() {
return ++mGeneration;
}
+
+ virtual void getExternalStylusDevices(Vector<InputDeviceInfo>& outDevices) {
+
+ }
+
+ virtual void dispatchExternalStylusState(const StylusState&) {
+
+ }
};
@@ -867,12 +872,11 @@
}
}
- virtual void configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
+ virtual void configure(nsecs_t, const InputReaderConfiguration*, uint32_t) {
mConfigureWasCalled = true;
}
- virtual void reset(nsecs_t when) {
+ virtual void reset(nsecs_t) {
mResetWasCalled = true;
}
@@ -881,22 +885,22 @@
mProcessWasCalled = true;
}
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+ virtual int32_t getKeyCodeState(uint32_t, int32_t keyCode) {
ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
}
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ virtual int32_t getScanCodeState(uint32_t, int32_t scanCode) {
ssize_t index = mScanCodeStates.indexOfKey(scanCode);
return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
}
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+ virtual int32_t getSwitchState(uint32_t, int32_t switchCode) {
ssize_t index = mSwitchStates.indexOfKey(switchCode);
return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
}
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ virtual bool markSupportedKeyCodes(uint32_t, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) {
bool result = false;
for (size_t i = 0; i < numCodes; i++) {
@@ -1536,7 +1540,7 @@
};
void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
- int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
+ int32_t originalScanCode, int32_t, int32_t rotatedKeyCode) {
NotifyKeyArgs args;
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 1);
diff --git a/services/powermanager/Android.mk b/services/powermanager/Android.mk
index d98b2da..7b24c65 100644
--- a/services/powermanager/Android.mk
+++ b/services/powermanager/Android.mk
@@ -2,14 +2,16 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- IPowerManager.cpp
+ IPowerManager.cpp
LOCAL_SHARED_LIBRARIES := \
- libutils \
- libbinder
+ libutils \
+ libbinder
LOCAL_MODULE:= libpowermanager
LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 80845a2..dd1bccf 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -79,16 +79,17 @@
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
- result.appendFormat("halVersion %d\n", getHalDeviceVersion());
+ result.appendFormat("halVersion 0x%08x\n", getHalDeviceVersion());
result.appendFormat("%d h/w sensors:\n", int(count));
Mutex::Autolock _l(mLock);
for (size_t i=0 ; i<size_t(count) ; i++) {
const Info& info = mActivationCount.valueFor(list[i].handle);
+ if (info.batchParams.isEmpty()) continue;
result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
info.batchParams.size());
for (size_t j = 0; j < info.batchParams.size(); j++) {
- BatchParams params = info.batchParams.valueAt(j);
+ const BatchParams& params = info.batchParams.valueAt(j);
result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
j < info.batchParams.size() - 1 ? ", " : "");
}
@@ -147,8 +148,12 @@
if (enabled) {
ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
+ if (isClientDisabledLocked(ident)) {
+ return INVALID_OPERATION;
+ }
+
if (info.batchParams.indexOfKey(ident) >= 0) {
- if (info.batchParams.size() == 1) {
+ if (info.numActiveClients() == 1) {
// This is the first connection, we need to activate the underlying h/w sensor.
actuateHardware = true;
}
@@ -160,7 +165,7 @@
ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
if (info.removeBatchParamsForIdent(ident) >= 0) {
- if (info.batchParams.size() == 0) {
+ if (info.numActiveClients() == 0) {
// This is the last connection, we need to de-activate the underlying h/w sensor.
actuateHardware = true;
} else {
@@ -181,10 +186,15 @@
} else {
// sensor wasn't enabled for this ident
}
+
+ if (isClientDisabledLocked(ident)) {
+ return NO_ERROR;
+ }
}
if (actuateHardware) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, enabled);
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
+ enabled);
err = mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
@@ -197,7 +207,7 @@
}
// On older devices which do not support batch, call setDelay().
- if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.batchParams.size() > 0) {
+ if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
info.bestBatchParams.batchDelay);
mSensorDevice->setDelay(
@@ -279,6 +289,7 @@
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
}
Mutex::Autolock _l(mLock);
+ if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
Info& info( mActivationCount.editValueFor(handle) );
// If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
// Calling setDelay() in batch mode is an invalid operation.
@@ -298,7 +309,6 @@
int SensorDevice::getHalDeviceVersion() const {
if (!mSensorDevice) return -1;
-
return mSensorDevice->common.version;
}
@@ -306,12 +316,110 @@
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
return INVALID_OPERATION;
}
+ if (isClientDisabled(ident)) return INVALID_OPERATION;
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
return mSensorDevice->flush(mSensorDevice, handle);
}
+bool SensorDevice::isClientDisabled(void* ident) {
+ Mutex::Autolock _l(mLock);
+ return isClientDisabledLocked(ident);
+}
+
+bool SensorDevice::isClientDisabledLocked(void* ident) {
+ return mDisabledClients.indexOf(ident) >= 0;
+}
+
+void SensorDevice::enableAllSensors() {
+ Mutex::Autolock _l(mLock);
+ mDisabledClients.clear();
+ const int halVersion = getHalDeviceVersion();
+ for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ Info& info = mActivationCount.editValueAt(i);
+ if (info.batchParams.isEmpty()) continue;
+ info.selectBatchParams();
+ const int sensor_handle = mActivationCount.keyAt(i);
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
+ sensor_handle);
+ status_t err(NO_ERROR);
+ if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
+ err = mSensorDevice->batch(mSensorDevice, sensor_handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
+ }
+
+ if (err == NO_ERROR) {
+ err = mSensorDevice->activate(
+ reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
+ sensor_handle, 1);
+ ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
+ }
+
+ if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) {
+ err = mSensorDevice->setDelay(
+ reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
+ sensor_handle, info.bestBatchParams.batchDelay);
+ ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err));
+ }
+ }
+}
+
+void SensorDevice::disableAllSensors() {
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i< mActivationCount.size(); ++i) {
+ const Info& info = mActivationCount.valueAt(i);
+ // Check if this sensor has been activated previously and disable it.
+ if (info.batchParams.size() > 0) {
+ const int sensor_handle = mActivationCount.keyAt(i);
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
+ sensor_handle);
+ mSensorDevice->activate(
+ reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
+ sensor_handle, 0);
+ // Add all the connections that were registered for this sensor to the disabled
+ // clients list.
+ for (size_t j = 0; j < info.batchParams.size(); ++j) {
+ mDisabledClients.add(info.batchParams.keyAt(j));
+ }
+ }
+ }
+}
+
+status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) {
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "sensor_event handle=%d ts=%lld data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
+ injected_sensor_event->sensor,
+ injected_sensor_event->timestamp, injected_sensor_event->data[0],
+ injected_sensor_event->data[1], injected_sensor_event->data[2],
+ injected_sensor_event->data[3], injected_sensor_event->data[4],
+ injected_sensor_event->data[5]);
+ if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
+ return INVALID_OPERATION;
+ }
+ return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event);
+}
+
+status_t SensorDevice::setMode(uint32_t mode) {
+ if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
+ return INVALID_OPERATION;
+ }
+ return mSensorModule->set_operation_mode(mode);
+}
+
// ---------------------------------------------------------------------------
+int SensorDevice::Info::numActiveClients() {
+ SensorDevice& device(SensorDevice::getInstance());
+ int num = 0;
+ for (size_t i = 0; i < batchParams.size(); ++i) {
+ if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
+ ++num;
+ }
+ }
+ return num;
+}
+
status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs) {
@@ -329,19 +437,16 @@
}
void SensorDevice::Info::selectBatchParams() {
- BatchParams bestParams(-1, -1, -1);
+ BatchParams bestParams(0, -1, -1);
+ SensorDevice& device(SensorDevice::getInstance());
- if (batchParams.size() > 0) {
- BatchParams params = batchParams.valueAt(0);
- bestParams = params;
- }
-
- for (size_t i = 1; i < batchParams.size(); ++i) {
+ for (size_t i = 0; i < batchParams.size(); ++i) {
+ if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
BatchParams params = batchParams.valueAt(i);
- if (params.batchDelay < bestParams.batchDelay) {
+ if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
bestParams.batchDelay = params.batchDelay;
}
- if (params.batchTimeout < bestParams.batchTimeout) {
+ if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
bestParams.batchTimeout = params.batchTimeout;
}
}
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 761b48c..c484849 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -42,6 +42,7 @@
// Struct to store all the parameters(samplingPeriod, maxBatchReportLatency and flags) from
// batch call. For continous mode clients, maxBatchReportLatency is set to zero.
struct BatchParams {
+ // TODO: Get rid of flags parameter everywhere.
int flags;
nsecs_t batchDelay, batchTimeout;
BatchParams() : flags(0), batchDelay(0), batchTimeout(0) {}
@@ -65,7 +66,7 @@
// requested by the client.
KeyedVector<void*, BatchParams> batchParams;
- Info() : bestBatchParams(-1, -1, -1) {}
+ Info() : bestBatchParams(0, -1, -1) {}
// Sets batch parameters for this ident. Returns error if this ident is not already present
// in the KeyedVector above.
status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs,
@@ -75,10 +76,17 @@
// Removes batchParams for an ident and re-computes bestBatchParams. Returns the index of
// the removed ident. If index >=0, ident is present and successfully removed.
ssize_t removeBatchParamsForIdent(void* ident);
+
+ int numActiveClients();
};
DefaultKeyedVector<int, Info> mActivationCount;
+ // Use this vector to determine which client is activated or deactivated.
+ SortedVector<void *> mDisabledClients;
SensorDevice();
+
+ bool isClientDisabled(void* ident);
+ bool isClientDisabledLocked(void* ident);
public:
ssize_t getSensorList(sensor_t const** list);
status_t initCheck() const;
@@ -90,7 +98,11 @@
// Call batch with timeout zero instead of calling setDelay() for newer devices.
status_t setDelay(void* ident, int handle, int64_t ns);
status_t flush(void* ident, int handle);
+ status_t setMode(uint32_t mode);
+ void disableAllSensors();
+ void enableAllSensors();
void autoDisable(void *ident, int handle);
+ status_t injectSensorData(const sensors_event_t *event);
void dump(String8& result);
};
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 30ec458..bb2d4f3 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -31,6 +31,7 @@
#include <utils/Singleton.h>
#include <utils/String16.h>
+#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
@@ -63,7 +64,9 @@
*
*/
-const char* SensorService::WAKE_LOCK_NAME = "SensorService";
+const char* SensorService::WAKE_LOCK_NAME = "SensorService_wakelock";
+// Permissions.
+static const String16 sDump("android.permission.DUMP");
SensorService::SensorService()
: mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
@@ -74,7 +77,6 @@
void SensorService::onFirstRef()
{
ALOGD("nuSensorService starting...");
-
SensorDevice& dev(SensorDevice::getInstance());
if (dev.initCheck() == NO_ERROR) {
@@ -82,7 +84,7 @@
ssize_t count = dev.getSensorList(&list);
if (count > 0) {
ssize_t orientationIndex = -1;
- bool hasGyro = false, hasAccel = false, hasMag = false;
+ bool hasGyro = false;
uint32_t virtualSensorsNeeds =
(1<<SENSOR_TYPE_GRAVITY) |
(1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
@@ -92,12 +94,6 @@
for (ssize_t i=0 ; i<count ; i++) {
registerSensor( new HardwareSensor(list[i]) );
switch (list[i].type) {
- case SENSOR_TYPE_ACCELEROMETER:
- hasAccel = true;
- break;
- case SENSOR_TYPE_MAGNETIC_FIELD:
- hasMag = true;
- break;
case SENSOR_TYPE_ORIENTATION:
orientationIndex = i;
break;
@@ -121,7 +117,7 @@
// build the sensor list returned to users
mUserSensorList = mSensorList;
- if (hasGyro && hasAccel && hasMag) {
+ if (hasGyro) {
Sensor aSensor;
// Add Android virtual sensors if they're not already
@@ -160,7 +156,7 @@
// Check if the device really supports batching by looking at the FIFO event
// counts for each sensor.
bool batchingSupported = false;
- for (int i = 0; i < mSensorList.size(); ++i) {
+ for (size_t i = 0; i < mSensorList.size(); ++i) {
if (mSensorList[i].getFifoMaxEventCount() > 0) {
batchingSupported = true;
break;
@@ -196,10 +192,16 @@
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
+ mCurrentOperatingMode = NORMAL;
+ mNextSensorRegIndex = 0;
+ for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
+ mLastNSensorRegistrations.push();
+ }
+
+ mInitCheck = NO_ERROR;
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
- mInitCheck = NO_ERROR;
run("SensorService", PRIORITY_URGENT_DISPLAY);
}
}
@@ -216,7 +218,7 @@
// add to our handle->SensorInterface mapping
mSensorMap.add(sensor.getHandle(), s);
// create an entry in the mLastEventSeen array
- mLastEventSeen.add(sensor.getHandle(), event);
+ mLastEventSeen.add(sensor.getHandle(), NULL);
return sensor;
}
@@ -234,9 +236,7 @@
delete mSensorMap.valueAt(i);
}
-static const String16 sDump("android.permission.DUMP");
-
-status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
+status_t SensorService::dump(int fd, const Vector<String16>& args)
{
String8 result;
if (!PermissionCache::checkCallingPermission(sDump)) {
@@ -245,116 +245,188 @@
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
} else {
+ if (args.size() > 2) {
+ return INVALID_OPERATION;
+ }
Mutex::Autolock _l(mLock);
- result.append("Sensor List:\n");
- for (size_t i=0 ; i<mSensorList.size() ; i++) {
- const Sensor& s(mSensorList[i]);
- const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
- result.appendFormat(
- "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
- s.getName().string(),
- s.getVendor().string(),
- s.getVersion(),
- s.getStringType().string(),
- s.getHandle(),
- s.getRequiredPermission().string(),
- s.getType());
-
- const int reportingMode = s.getReportingMode();
- if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
- result.append(" continuous | ");
- } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
- result.append(" on-change | ");
- } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
- result.append(" one-shot | ");
+ SensorDevice& dev(SensorDevice::getInstance());
+ if (args.size() == 2 && args[0] == String16("restrict")) {
+ // If already in restricted mode. Ignore.
+ if (mCurrentOperatingMode == RESTRICTED) {
+ return status_t(NO_ERROR);
+ }
+ // If in any mode other than normal, ignore.
+ if (mCurrentOperatingMode != NORMAL) {
+ return INVALID_OPERATION;
+ }
+ mCurrentOperatingMode = RESTRICTED;
+ dev.disableAllSensors();
+ // Clear all pending flush connections for all active sensors. If one of the active
+ // connections has called flush() and the underlying sensor has been disabled before a
+ // flush complete event is returned, we need to remove the connection from this queue.
+ for (size_t i=0 ; i< mActiveSensors.size(); ++i) {
+ mActiveSensors.valueAt(i)->clearAllPendingFlushConnections();
+ }
+ mWhiteListedPackage.setTo(String8(args[1]));
+ return status_t(NO_ERROR);
+ } else if (args.size() == 1 && args[0] == String16("enable")) {
+ // If currently in restricted mode, reset back to NORMAL mode else ignore.
+ if (mCurrentOperatingMode == RESTRICTED) {
+ mCurrentOperatingMode = NORMAL;
+ dev.enableAllSensors();
+ }
+ if (mCurrentOperatingMode == DATA_INJECTION) {
+ resetToNormalModeLocked();
+ }
+ mWhiteListedPackage.clear();
+ return status_t(NO_ERROR);
+ } else if (args.size() == 2 && args[0] == String16("data_injection")) {
+ if (mCurrentOperatingMode == NORMAL) {
+ dev.disableAllSensors();
+ status_t err = dev.setMode(DATA_INJECTION);
+ if (err == NO_ERROR) {
+ mCurrentOperatingMode = DATA_INJECTION;
+ } else {
+ // Re-enable sensors.
+ dev.enableAllSensors();
+ }
+ mWhiteListedPackage.setTo(String8(args[1]));
+ return NO_ERROR;
+ } else if (mCurrentOperatingMode == DATA_INJECTION) {
+ // Already in DATA_INJECTION mode. Treat this as a no_op.
+ return NO_ERROR;
} else {
- result.append(" special-trigger | ");
+ // Transition to data injection mode supported only from NORMAL mode.
+ return INVALID_OPERATION;
+ }
+ } else if (mSensorList.size() == 0) {
+ result.append("No Sensors on the device\n");
+ } else {
+ // Default dump the sensor list and debugging information.
+ result.append("Sensor List:\n");
+ for (size_t i=0 ; i<mSensorList.size() ; i++) {
+ const Sensor& s(mSensorList[i]);
+ result.appendFormat(
+ "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
+ s.getName().string(),
+ s.getVendor().string(),
+ s.getVersion(),
+ s.getStringType().string(),
+ s.getHandle(),
+ s.getRequiredPermission().string(),
+ s.getType());
+
+ const int reportingMode = s.getReportingMode();
+ if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
+ result.append(" continuous | ");
+ } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
+ result.append(" on-change | ");
+ } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
+ result.append(" one-shot | ");
+ } else {
+ result.append(" special-trigger | ");
+ }
+
+ if (s.getMaxDelay() > 0) {
+ result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+ } else {
+ result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
+ }
+
+ if (s.getMinDelay() > 0) {
+ result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
+ } else {
+ result.appendFormat("minDelay=%dus |", s.getMinDelay());
+ }
+
+ if (s.getFifoMaxEventCount() > 0) {
+ result.appendFormat("FifoMax=%d events | ",
+ s.getFifoMaxEventCount());
+ } else {
+ result.append("no batching | ");
+ }
+
+ if (s.isWakeUpSensor()) {
+ result.appendFormat("wakeUp | ");
+ } else {
+ result.appendFormat("non-wakeUp | ");
+ }
+
+ int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
+ if (bufIndex >= 0) {
+ const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex);
+ if (buf != NULL && s.getRequiredPermission().isEmpty()) {
+ buf->printBuffer(result);
+ } else {
+ result.append("last=<> \n");
+ }
+ }
+ result.append("\n");
+ }
+ SensorFusion::getInstance().dump(result);
+ SensorDevice::getInstance().dump(result);
+
+ result.append("Active sensors:\n");
+ for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
+ int handle = mActiveSensors.keyAt(i);
+ result.appendFormat("%s (handle=0x%08x, connections=%zu)\n",
+ getSensorName(handle).string(),
+ handle,
+ mActiveSensors.valueAt(i)->getNumConnections());
}
- if (s.getMaxDelay() > 0) {
- result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
- } else {
- result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
+ result.appendFormat("Socket Buffer size = %d events\n",
+ mSocketBufferSize/sizeof(sensors_event_t));
+ result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" :
+ "not held");
+ result.appendFormat("Mode :");
+ switch(mCurrentOperatingMode) {
+ case NORMAL:
+ result.appendFormat(" NORMAL\n");
+ break;
+ case RESTRICTED:
+ result.appendFormat(" RESTRICTED : %s\n", mWhiteListedPackage.string());
+ break;
+ case DATA_INJECTION:
+ result.appendFormat(" DATA_INJECTION : %s\n", mWhiteListedPackage.string());
+ }
+ result.appendFormat("%zd active connections\n", mActiveConnections.size());
+
+ for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
+ sp<SensorEventConnection> connection(mActiveConnections[i].promote());
+ if (connection != 0) {
+ result.appendFormat("Connection Number: %zu \n", i);
+ connection->dump(result);
+ }
}
- if (s.getMinDelay() > 0) {
- result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
- } else {
- result.appendFormat("minDelay=%dus |", s.getMinDelay());
- }
-
- if (s.getFifoMaxEventCount() > 0) {
- result.appendFormat("FifoMax=%d events | ",
- s.getFifoMaxEventCount());
- } else {
- result.append("no batching | ");
- }
-
- if (s.isWakeUpSensor()) {
- result.appendFormat("wakeUp | ");
- } else {
- result.appendFormat("non-wakeUp | ");
- }
-
- switch (s.getType()) {
- case SENSOR_TYPE_ROTATION_VECTOR:
- case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
- result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
- e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.timestamp);
- break;
- case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
- case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
- result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
- e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5],
- e.timestamp);
- break;
- case SENSOR_TYPE_GAME_ROTATION_VECTOR:
- result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
- e.data[0], e.data[1], e.data[2], e.data[3], e.timestamp);
- break;
- case SENSOR_TYPE_SIGNIFICANT_MOTION:
- case SENSOR_TYPE_STEP_DETECTOR:
- result.appendFormat( "last=<%f %" PRId64 ">\n", e.data[0], e.timestamp);
- break;
- case SENSOR_TYPE_STEP_COUNTER:
- result.appendFormat( "last=<%" PRIu64 ", %" PRId64 ">\n", e.u64.step_counter,
- e.timestamp);
- break;
- default:
- // default to 3 values
- result.appendFormat(
- "last=<%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
- e.data[0], e.data[1], e.data[2], e.timestamp);
- break;
- }
- result.append("\n");
- }
- SensorFusion::getInstance().dump(result);
- SensorDevice::getInstance().dump(result);
-
- result.append("Active sensors:\n");
- for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
- int handle = mActiveSensors.keyAt(i);
- result.appendFormat("%s (handle=0x%08x, connections=%zu)\n",
- getSensorName(handle).string(),
- handle,
- mActiveSensors.valueAt(i)->getNumConnections());
- }
-
- result.appendFormat("Socket Buffer size = %d events\n",
- mSocketBufferSize/sizeof(sensors_event_t));
- result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
- result.appendFormat("%zd active connections\n", mActiveConnections.size());
-
- for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != 0) {
- result.appendFormat("Connection Number: %zu \n", i);
- connection->dump(result);
- }
+ result.appendFormat("Previous Registrations:\n");
+ // Log in the reverse chronological order.
+ int currentIndex = (mNextSensorRegIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+ SENSOR_REGISTRATIONS_BUF_SIZE;
+ const int startIndex = currentIndex;
+ do {
+ const SensorRegistrationInfo& reg_info = mLastNSensorRegistrations[currentIndex];
+ if (SensorRegistrationInfo::isSentinel(reg_info)) {
+ // Ignore sentinel, proceed to next item.
+ currentIndex = (currentIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+ SENSOR_REGISTRATIONS_BUF_SIZE;
+ continue;
+ }
+ if (reg_info.mActivated) {
+ result.appendFormat("%02d:%02d:%02d activated package=%s handle=0x%08x "
+ "samplingRate=%dus maxReportLatency=%dus\n",
+ reg_info.mHour, reg_info.mMin, reg_info.mSec,
+ reg_info.mPackageName.string(), reg_info.mSensorHandle,
+ reg_info.mSamplingRateUs, reg_info.mMaxReportLatencyUs);
+ } else {
+ result.appendFormat("%02d:%02d:%02d de-activated package=%s handle=0x%08x\n",
+ reg_info.mHour, reg_info.mMin, reg_info.mSec,
+ reg_info.mPackageName.string(), reg_info.mSensorHandle);
+ }
+ currentIndex = (currentIndex - 1 + SENSOR_REGISTRATIONS_BUF_SIZE) %
+ SENSOR_REGISTRATIONS_BUF_SIZE;
+ } while(startIndex != currentIndex);
}
}
write(fd, result.string(), result.size());
@@ -377,8 +449,9 @@
sensor->autoDisable(connection.get(), handle);
cleanupWithoutDisableLocked(connection, handle);
}
+
}
- }
+ }
}
bool SensorService::threadLoop()
@@ -560,7 +633,6 @@
}
}
-
bool SensorService::isWakeLockAcquired() {
Mutex::Autolock _l(mLock);
return mWakeLockAcquired;
@@ -583,19 +655,15 @@
void SensorService::recordLastValueLocked(
const sensors_event_t* buffer, size_t count) {
- const sensors_event_t* last = NULL;
for (size_t i = 0; i < count; i++) {
- const sensors_event_t* event = &buffer[i];
- if (event->type != SENSOR_TYPE_META_DATA) {
- if (last && event->sensor != last->sensor) {
- mLastEventSeen.editValueFor(last->sensor) = *last;
+ if (buffer[i].type != SENSOR_TYPE_META_DATA) {
+ CircularBuffer* &circular_buf = mLastEventSeen.editValueFor(buffer[i].sensor);
+ if (circular_buf == NULL) {
+ circular_buf = new CircularBuffer(buffer[i].type);
}
- last = event;
+ circular_buf->addEvent(buffer[i]);
}
}
- if (last) {
- mLastEventSeen.editValueFor(last->sensor) = *last;
- }
}
void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
@@ -636,12 +704,11 @@
return sensor != NULL && sensor->getSensor().isWakeUpSensor();
}
-
SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
return mActiveSensors.valueFor(handle);
}
-Vector<Sensor> SensorService::getSensorList()
+Vector<Sensor> SensorService::getSensorList(const String16& opPackageName)
{
char value[PROPERTY_VALUE_MAX];
property_get("debug.sensors", value, "0");
@@ -650,27 +717,65 @@
Vector<Sensor> accessibleSensorList;
for (size_t i = 0; i < initialSensorList.size(); i++) {
Sensor sensor = initialSensorList[i];
- if (canAccessSensor(sensor)) {
+ if (canAccessSensor(sensor, "getSensorList", opPackageName)) {
accessibleSensorList.add(sensor);
} else {
- String8 infoMessage;
- infoMessage.appendFormat(
- "Skipped sensor %s because it requires permission %s",
- sensor.getName().string(),
- sensor.getRequiredPermission().string());
- ALOGI(infoMessage.string());
+ ALOGI("Skipped sensor %s because it requires permission %s and app op %d",
+ sensor.getName().string(),
+ sensor.getRequiredPermission().string(),
+ sensor.getRequiredAppOp());
}
}
return accessibleSensorList;
}
-sp<ISensorEventConnection> SensorService::createSensorEventConnection()
-{
+sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,
+ int requestedMode, const String16& opPackageName) {
+ // Only 2 modes supported for a SensorEventConnection ... NORMAL and DATA_INJECTION.
+ if (requestedMode != NORMAL && requestedMode != DATA_INJECTION) {
+ return NULL;
+ }
+
+ Mutex::Autolock _l(mLock);
+ // To create a client in DATA_INJECTION mode to inject data, SensorService should already be
+ // operating in DI mode.
+ if (requestedMode == DATA_INJECTION) {
+ if (mCurrentOperatingMode != DATA_INJECTION) return NULL;
+ if (!isWhiteListedPackage(packageName)) return NULL;
+ }
+
uid_t uid = IPCThreadState::self()->getCallingUid();
- sp<SensorEventConnection> result(new SensorEventConnection(this, uid));
+ sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName,
+ requestedMode == DATA_INJECTION, opPackageName));
+ if (requestedMode == DATA_INJECTION) {
+ if (mActiveConnections.indexOf(result) < 0) {
+ mActiveConnections.add(result);
+ }
+ // Add the associated file descriptor to the Looper for polling whenever there is data to
+ // be injected.
+ result->updateLooperRegistration(mLooper);
+ }
return result;
}
+int SensorService::isDataInjectionEnabled() {
+ Mutex::Autolock _l(mLock);
+ return (mCurrentOperatingMode == DATA_INJECTION);
+}
+
+status_t SensorService::resetToNormalMode() {
+ Mutex::Autolock _l(mLock);
+ return resetToNormalModeLocked();
+}
+
+status_t SensorService::resetToNormalModeLocked() {
+ SensorDevice& dev(SensorDevice::getInstance());
+ dev.enableAllSensors();
+ status_t err = dev.setMode(NORMAL);
+ mCurrentOperatingMode = NORMAL;
+ return err;
+}
+
void SensorService::cleanupConnection(SensorEventConnection* c)
{
Mutex::Autolock _l(mLock);
@@ -717,7 +822,8 @@
}
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
- int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags)
+ int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
+ const String16& opPackageName)
{
if (mInitCheck != NO_ERROR)
return mInitCheck;
@@ -727,11 +833,16 @@
return BAD_VALUE;
}
- if (!verifyCanAccessSensor(sensor->getSensor(), "Tried enabling")) {
+ if (!canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ if ((mCurrentOperatingMode == RESTRICTED || mCurrentOperatingMode == DATA_INJECTION)
+ && !isWhiteListedPackage(connection->getPackageName())) {
+ return INVALID_OPERATION;
+ }
+
SensorRecord* rec = mActiveSensors.valueFor(handle);
if (rec == 0) {
rec = new SensorRecord(connection);
@@ -747,14 +858,24 @@
if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
// NOTE: The wake_up flag of this event may get set to
// WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
- sensors_event_t& event(mLastEventSeen.editValueFor(handle));
- if (event.version == sizeof(sensors_event_t)) {
- if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
- setWakeLockAcquiredLocked(true);
- }
- connection->sendEvents(&event, 1, NULL);
- if (!connection->needsWakeLock() && mWakeLockAcquired) {
- checkWakeLockStateLocked();
+ CircularBuffer *circular_buf = mLastEventSeen.valueFor(handle);
+ if (circular_buf) {
+ sensors_event_t event;
+ memset(&event, 0, sizeof(event));
+ // It is unlikely that this buffer is empty as the sensor is already active.
+ // One possible corner case may be two applications activating an on-change
+ // sensor at the same time.
+ if(circular_buf->populateLastEvent(&event)) {
+ event.sensor = handle;
+ if (event.version == sizeof(sensors_event_t)) {
+ if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
+ setWakeLockAcquiredLocked(true);
+ }
+ connection->sendEvents(&event, 1, NULL);
+ if (!connection->needsWakeLock() && mWakeLockAcquired) {
+ checkWakeLockStateLocked();
+ }
+ }
}
}
}
@@ -782,7 +903,7 @@
"rate=%" PRId64 " timeout== %" PRId64"",
handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);
- status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
+ status_t err = sensor->batch(connection.get(), handle, 0, samplingPeriodNs,
maxBatchReportLatencyNs);
// Call flush() before calling activate() on the sensor. Wait for a first flush complete
@@ -807,6 +928,19 @@
if (err == NO_ERROR) {
connection->updateLooperRegistration(mLooper);
+ SensorRegistrationInfo ®_info =
+ mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
+ reg_info.mSensorHandle = handle;
+ reg_info.mSamplingRateUs = samplingPeriodNs/1000;
+ reg_info.mMaxReportLatencyUs = maxBatchReportLatencyNs/1000;
+ reg_info.mActivated = true;
+ reg_info.mPackageName = connection->getPackageName();
+ time_t rawtime = time(NULL);
+ struct tm * timeinfo = localtime(&rawtime);
+ reg_info.mHour = timeinfo->tm_hour;
+ reg_info.mMin = timeinfo->tm_min;
+ reg_info.mSec = timeinfo->tm_sec;
+ mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;
}
if (err != NO_ERROR) {
@@ -827,6 +961,20 @@
if (err == NO_ERROR) {
SensorInterface* sensor = mSensorMap.valueFor(handle);
err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+
+ }
+ if (err == NO_ERROR) {
+ SensorRegistrationInfo ®_info =
+ mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
+ reg_info.mActivated = false;
+ reg_info.mPackageName= connection->getPackageName();
+ reg_info.mSensorHandle = handle;
+ time_t rawtime = time(NULL);
+ struct tm * timeinfo = localtime(&rawtime);
+ reg_info.mHour = timeinfo->tm_hour;
+ reg_info.mMin = timeinfo->tm_min;
+ reg_info.mSec = timeinfo->tm_sec;
+ mNextSensorRegIndex = (mNextSensorRegIndex + 1) % SENSOR_REGISTRATIONS_BUF_SIZE;
}
return err;
}
@@ -861,7 +1009,7 @@
}
status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
- int handle, nsecs_t ns)
+ int handle, nsecs_t ns, const String16& opPackageName)
{
if (mInitCheck != NO_ERROR)
return mInitCheck;
@@ -870,7 +1018,7 @@
if (!sensor)
return BAD_VALUE;
- if (!verifyCanAccessSensor(sensor->getSensor(), "Tried configuring")) {
+ if (!canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
return BAD_VALUE;
}
@@ -885,7 +1033,8 @@
return sensor->setDelay(connection.get(), handle, ns);
}
-status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection) {
+status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection,
+ const String16& opPackageName) {
if (mInitCheck != NO_ERROR) return mInitCheck;
SensorDevice& dev(SensorDevice::getInstance());
const int halVersion = dev.getHalDeviceVersion();
@@ -905,6 +1054,10 @@
// flush complete event.
connection->incrementPendingFlushCount(handle);
} else {
+ if (!canAccessSensor(sensor->getSensor(), "Tried flushing", opPackageName)) {
+ err = INVALID_OPERATION;
+ continue;
+ }
status_t err_flush = sensor->flush(connection.get(), handle);
if (err_flush == NO_ERROR) {
SensorRecord* rec = mActiveSensors.valueFor(handle);
@@ -916,23 +1069,42 @@
return err;
}
-bool SensorService::canAccessSensor(const Sensor& sensor) {
- return (sensor.getRequiredPermission().isEmpty()) ||
- PermissionCache::checkCallingPermission(String16(sensor.getRequiredPermission()));
-}
+bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
+ const String16& opPackageName) {
+ const String8& requiredPermission = sensor.getRequiredPermission();
-bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* operation) {
- if (canAccessSensor(sensor)) {
+ if (requiredPermission.length() <= 0) {
return true;
+ }
+
+ bool hasPermission = false;
+
+ // Runtime permissions can't use the cache as they may change.
+ if (sensor.isRequiredPermissionRuntime()) {
+ hasPermission = checkPermission(String16(requiredPermission),
+ IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
} else {
- String8 errorMessage;
- errorMessage.appendFormat(
- "%s a sensor (%s) without holding its required permission: %s",
- operation,
- sensor.getName().string(),
- sensor.getRequiredPermission().string());
+ hasPermission = PermissionCache::checkCallingPermission(String16(requiredPermission));
+ }
+
+ if (!hasPermission) {
+ ALOGE("%s a sensor (%s) without holding its required permission: %s",
+ operation, sensor.getName().string(), sensor.getRequiredPermission().string());
return false;
}
+
+ const int32_t opCode = sensor.getRequiredAppOp();
+ if (opCode >= 0) {
+ AppOpsManager appOps;
+ if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName)
+ != AppOpsManager::MODE_ALLOWED) {
+ ALOGE("%s a sensor (%s) without enabled required app op: %D",
+ operation, sensor.getName().string(), opCode);
+ return false;
+ }
+ }
+
+ return true;
}
void SensorService::checkWakeLockState() {
@@ -978,6 +1150,33 @@
}
}
+bool SensorService::isWhiteListedPackage(const String8& packageName) {
+ return (packageName.contains(mWhiteListedPackage.string()));
+}
+
+int SensorService::getNumEventsForSensorType(int sensor_event_type) {
+ switch (sensor_event_type) {
+ case SENSOR_TYPE_ROTATION_VECTOR:
+ case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ return 5;
+
+ case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+ return 6;
+
+ case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+ return 4;
+
+ case SENSOR_TYPE_SIGNIFICANT_MOTION:
+ case SENSOR_TYPE_STEP_DETECTOR:
+ case SENSOR_TYPE_STEP_COUNTER:
+ return 1;
+
+ default:
+ return 3;
+ }
+}
+
// ---------------------------------------------------------------------------
SensorService::SensorRecord::SensorRecord(
const sp<SensorEventConnection>& connection)
@@ -1034,12 +1233,121 @@
return NULL;
}
+void SensorService::SensorRecord::clearAllPendingFlushConnections() {
+ mPendingFlushConnections.clear();
+}
+
+
+// ---------------------------------------------------------------------------
+SensorService::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
+ mTimestamp = -1;
+ const int numData = SensorService::getNumEventsForSensorType(sensorType);
+ if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
+ mStepCounter = 0;
+ } else {
+ mData = new float[numData];
+ for (int i = 0; i < numData; ++i) {
+ mData[i] = -1.0;
+ }
+ }
+ mHour = mMin = mSec = INT32_MIN;
+}
+
+bool SensorService::TrimmedSensorEvent::isSentinel(const TrimmedSensorEvent& event) {
+ return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
+}
+// --------------------------------------------------------------------------
+SensorService::CircularBuffer::CircularBuffer(int sensor_event_type) {
+ mNextInd = 0;
+ mBufSize = CIRCULAR_BUF_SIZE;
+ if (sensor_event_type == SENSOR_TYPE_STEP_COUNTER ||
+ sensor_event_type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+ sensor_event_type == SENSOR_TYPE_ACCELEROMETER) {
+ mBufSize = CIRCULAR_BUF_SIZE * 5;
+ }
+ mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
+ mSensorType = sensor_event_type;
+ for (int i = 0; i < mBufSize; ++i) {
+ mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
+ }
+}
+
+void SensorService::CircularBuffer::addEvent(const sensors_event_t& sensor_event) {
+ TrimmedSensorEvent *curr_event = mTrimmedSensorEventArr[mNextInd];
+ curr_event->mTimestamp = sensor_event.timestamp;
+ if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+ curr_event->mStepCounter = sensor_event.u64.step_counter;
+ } else {
+ memcpy(curr_event->mData, sensor_event.data,
+ sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
+ }
+ time_t rawtime = time(NULL);
+ struct tm * timeinfo = localtime(&rawtime);
+ curr_event->mHour = timeinfo->tm_hour;
+ curr_event->mMin = timeinfo->tm_min;
+ curr_event->mSec = timeinfo->tm_sec;
+ mNextInd = (mNextInd + 1) % mBufSize;
+}
+
+void SensorService::CircularBuffer::printBuffer(String8& result) const {
+ const int numData = SensorService::getNumEventsForSensorType(mSensorType);
+ int i = mNextInd, eventNum = 1;
+ result.appendFormat("last %d events = < ", mBufSize);
+ do {
+ if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
+ // Sentinel, ignore.
+ i = (i + 1) % mBufSize;
+ continue;
+ }
+ result.appendFormat("%d) ", eventNum++);
+ if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+ result.appendFormat("%llu,", mTrimmedSensorEventArr[i]->mStepCounter);
+ } else {
+ for (int j = 0; j < numData; ++j) {
+ result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]);
+ }
+ }
+ result.appendFormat("%lld %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
+ mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
+ mTrimmedSensorEventArr[i]->mSec);
+ i = (i + 1) % mBufSize;
+ } while (i != mNextInd);
+ result.appendFormat(">\n");
+}
+
+bool SensorService::CircularBuffer::populateLastEvent(sensors_event_t *event) {
+ int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
+ // Check if the buffer is empty.
+ if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
+ return false;
+ }
+ event->version = sizeof(sensors_event_t);
+ event->type = mSensorType;
+ event->timestamp = mTrimmedSensorEventArr[lastEventInd]->mTimestamp;
+ if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+ event->u64.step_counter = mTrimmedSensorEventArr[lastEventInd]->mStepCounter;
+ } else {
+ memcpy(event->data, mTrimmedSensorEventArr[lastEventInd]->mData,
+ sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
+ }
+ return true;
+}
+
+SensorService::CircularBuffer::~CircularBuffer() {
+ for (int i = 0; i < mBufSize; ++i) {
+ delete mTrimmedSensorEventArr[i];
+ }
+ delete [] mTrimmedSensorEventArr;
+}
+
// ---------------------------------------------------------------------------
SensorService::SensorEventConnection::SensorEventConnection(
- const sp<SensorService>& service, uid_t uid)
+ const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
+ const String16& opPackageName)
: mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
- mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0) {
+ mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
+ mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName) {
mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -1071,8 +1379,10 @@
void SensorService::SensorEventConnection::dump(String8& result) {
Mutex::Autolock _l(mConnectionLock);
- result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
- mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
+ result.appendFormat("\tOperating Mode: %s\n",mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
+ result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
+ "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
+ mMaxCacheSize);
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
@@ -1096,7 +1406,8 @@
bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
Mutex::Autolock _l(mConnectionLock);
- if (!verifyCanAccessSensor(mService->getSensorFromHandle(handle), "Tried adding")) {
+ if (!canAccessSensor(mService->getSensorFromHandle(handle),
+ "Tried adding", mOpPackageName)) {
return false;
}
if (mSensorInfo.indexOfKey(handle) < 0) {
@@ -1135,6 +1446,10 @@
return false;
}
+String8 SensorService::SensorEventConnection::getPackageName() const {
+ return mPackageName;
+}
+
void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
bool value) {
Mutex::Autolock _l(mConnectionLock);
@@ -1152,7 +1467,8 @@
void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
const sp<Looper>& looper) {
- bool isConnectionActive = mSensorInfo.size() > 0;
+ bool isConnectionActive = (mSensorInfo.size() > 0 && !mDataInjectionMode) ||
+ mDataInjectionMode;
// If all sensors are unregistered OR Looper has encountered an error, we
// can remove the Fd from the Looper if it has been previously added.
if (!isConnectionActive || mDead) {
@@ -1166,6 +1482,7 @@
int looper_flags = 0;
if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
+ if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i);
if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
@@ -1209,7 +1526,7 @@
sensors_event_t* scratch,
SensorEventConnection const * const * mapFlushEventsToConnections) {
// filter out events not for this connection
- size_t count = 0;
+ int count = 0;
Mutex::Autolock _l(mConnectionLock);
if (scratch) {
size_t i=0;
@@ -1501,7 +1818,7 @@
status_t err;
if (enabled) {
err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
- reservedFlags);
+ reservedFlags, mOpPackageName);
} else {
err = mService->disable(this, handle);
@@ -1512,11 +1829,11 @@
status_t SensorService::SensorEventConnection::setEventRate(
int handle, nsecs_t samplingPeriodNs)
{
- return mService->setEventRate(this, handle, samplingPeriodNs);
+ return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
}
status_t SensorService::SensorEventConnection::flush() {
- return mService->flushSensor(this);
+ return mService->flushSensor(this, mOpPackageName);
}
int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* /*data*/) {
@@ -1532,26 +1849,55 @@
updateLooperRegistrationLocked(mService->getLooper());
}
mService->checkWakeLockState();
+ if (mDataInjectionMode) {
+ // If the Looper has encountered some error in data injection mode, reset SensorService
+ // back to normal mode.
+ mService->resetToNormalMode();
+ mDataInjectionMode = false;
+ }
return 1;
}
if (events & ALOOPER_EVENT_INPUT) {
- uint32_t numAcks = 0;
- ssize_t ret = ::recv(fd, &numAcks, sizeof(numAcks), MSG_DONTWAIT);
+ unsigned char buf[sizeof(sensors_event_t)];
+ ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
{
Mutex::Autolock _l(mConnectionLock);
- // Sanity check to ensure there are no read errors in recv, numAcks is always
- // within the range and not zero. If any of the above don't hold reset mWakeLockRefCount
- // to zero.
- if (ret != sizeof(numAcks) || numAcks > mWakeLockRefCount || numAcks == 0) {
- ALOGE("Looper read error ret=%d numAcks=%d", ret, numAcks);
- mWakeLockRefCount = 0;
- } else {
- mWakeLockRefCount -= numAcks;
- }
+ if (numBytesRead == sizeof(sensors_event_t)) {
+ if (!mDataInjectionMode) {
+ ALOGE("Data injected in normal mode, dropping event"
+ "package=%s uid=%d", mPackageName.string(), mUid);
+ // Unregister call backs.
+ return 0;
+ }
+ SensorDevice& dev(SensorDevice::getInstance());
+ sensors_event_t sensor_event;
+ memset(&sensor_event, 0, sizeof(sensor_event));
+ memcpy(&sensor_event, buf, sizeof(sensors_event_t));
+ Sensor sensor = mService->getSensorFromHandle(sensor_event.sensor);
+ sensor_event.type = sensor.getType();
+ dev.injectSensorData(&sensor_event);
#if DEBUG_CONNECTIONS
- mTotalAcksReceived += numAcks;
+ ++mEventsReceived;
#endif
+ } else if (numBytesRead == sizeof(uint32_t)) {
+ uint32_t numAcks = 0;
+ memcpy(&numAcks, buf, numBytesRead);
+ // Sanity check to ensure there are no read errors in recv, numAcks is always
+ // within the range and not zero. If any of the above don't hold reset
+ // mWakeLockRefCount to zero.
+ if (numAcks > 0 && numAcks < mWakeLockRefCount) {
+ mWakeLockRefCount -= numAcks;
+ } else {
+ mWakeLockRefCount = 0;
+ }
+#if DEBUG_CONNECTIONS
+ mTotalAcksReceived += numAcks;
+#endif
+ } else {
+ // Read error, reset wakelock refcount.
+ mWakeLockRefCount = 0;
+ }
}
// Check if wakelock can be released by sensorservice. mConnectionLock needs to be released
// here as checkWakeLockState() will need it.
@@ -1570,8 +1916,8 @@
}
int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const {
- int fifoWakeUpSensors = 0;
- int fifoNonWakeUpSensors = 0;
+ size_t fifoWakeUpSensors = 0;
+ size_t fifoNonWakeUpSensors = 0;
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const Sensor& sensor = mService->getSensorFromHandle(mSensorInfo.keyAt(i));
if (sensor.getFifoReservedEventCount() == sensor.getFifoMaxEventCount()) {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 8719487..9a573ae 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -27,6 +27,7 @@
#include <utils/AndroidThreads.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
+#include <utils/String8.h>
#include <binder/BinderService.h>
@@ -37,6 +38,13 @@
#include "SensorInterface.h"
+#if __clang__
+// Clang warns about SensorEventConnection::dump hiding BBinder::dump
+// The cause isn't fixable without changing the API, so let's tell clang
+// this is indeed intentional.
+#pragma clang diagnostic ignored "-Woverloaded-virtual"
+#endif
+
// ---------------------------------------------------------------------------
#define DEBUG_CONNECTIONS false
@@ -45,6 +53,9 @@
// For older HALs which don't support batching, use a smaller socket buffer size.
#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
+#define CIRCULAR_BUF_SIZE 10
+#define SENSOR_REGISTRATIONS_BUF_SIZE 20
+
struct sensors_poll_device_t;
struct sensors_module_t;
@@ -58,6 +69,51 @@
{
friend class BinderService<SensorService>;
+ enum Mode {
+ // The regular operating mode where any application can register/unregister/call flush on
+ // sensors.
+ NORMAL = 0,
+ // This mode is only used for testing purposes. Not all HALs support this mode. In this
+ // mode, the HAL ignores the sensor data provided by physical sensors and accepts the data
+ // that is injected from the SensorService as if it were the real sensor data. This mode
+ // is primarily used for testing various algorithms like vendor provided SensorFusion,
+ // Step Counter and Step Detector etc. Typically in this mode, there will be a client
+ // (a SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps
+ // can unregister and register for any sensor that supports injection. Registering to sensors
+ // that do not support injection will give an error.
+ // TODO(aakella) : Allow exactly one client to inject sensor data at a time.
+ DATA_INJECTION = 1,
+ // This mode is used only for testing sensors. Each sensor can be tested in isolation with
+ // the required sampling_rate and maxReportLatency parameters without having to think about
+ // the data rates requested by other applications. End user devices are always expected to be
+ // in NORMAL mode. When this mode is first activated, all active sensors from all connections
+ // are disabled. Calling flush() will return an error. In this mode, only the requests from
+ // selected apps whose package names are whitelisted are allowed (typically CTS apps). Only
+ // these apps can register/unregister/call flush() on sensors. If SensorService switches to
+ // NORMAL mode again, all sensors that were previously registered to are activated with the
+ // corresponding paramaters if the application hasn't unregistered for sensors in the mean
+ // time.
+ // NOTE: Non whitelisted app whose sensors were previously deactivated may still receive
+ // events if a whitelisted app requests data from the same sensor.
+ RESTRICTED = 2
+
+ // State Transitions supported.
+ // RESTRICTED <--- NORMAL ---> DATA_INJECTION
+ // ---> <---
+
+ // Shell commands to switch modes in SensorService.
+ // 1) Put SensorService in RESTRICTED mode with packageName .cts. If it is already in
+ // restricted mode it is treated as a NO_OP (and packageName is NOT changed).
+ // $ adb shell dumpsys sensorservice restrict .cts.
+ //
+ // 2) Put SensorService in DATA_INJECTION mode with packageName .xts. If it is already in
+ // data_injection mode it is treated as a NO_OP (and packageName is NOT changed).
+ // $ adb shell dumpsys sensorservice data_injection .xts.
+ //
+ // 3) Reset sensorservice back to NORMAL mode.
+ // $ adb shell dumpsys sensorservice enable
+ };
+
static const char* WAKE_LOCK_NAME;
static char const* getServiceName() ANDROID_API { return "sensorservice"; }
@@ -70,8 +126,10 @@
virtual bool threadLoop();
// ISensorServer interface
- virtual Vector<Sensor> getSensorList();
- virtual sp<ISensorEventConnection> createSensorEventConnection();
+ virtual Vector<Sensor> getSensorList(const String16& opPackageName);
+ virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
+ int requestedMode, const String16& opPackageName);
+ virtual int isDataInjectionEnabled();
virtual status_t dump(int fd, const Vector<String16>& args);
class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
@@ -126,7 +184,6 @@
// connection FD may be added to the Looper. The flags to set are determined by the internal
// state of the connection. FDs are added to the looper when wake-up sensors are registered
// (to poll for acknowledgements) and when write fails on the socket when there are too many
- // events (to poll when the FD is available for writing). FDs are removed when there is an
// error and the other end hangs up or when this client unregisters for this connection.
void updateLooperRegistration(const sp<Looper>& looper);
void updateLooperRegistrationLocked(const sp<Looper>& looper);
@@ -149,6 +206,8 @@
// mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if
// this flag is set.
bool mDead;
+
+ bool mDataInjectionMode;
struct FlushInfo {
// The number of flush complete events dropped for this sensor is stored here.
// They are sent separately before the next batch of events.
@@ -162,14 +221,16 @@
KeyedVector<int, FlushInfo> mSensorInfo;
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
-
+ String8 mPackageName;
+ const String16 mOpPackageName;
#if DEBUG_CONNECTIONS
int mEventsReceived, mEventsSent, mEventsSentFromCache;
int mTotalAcksNeeded, mTotalAcksReceived;
#endif
public:
- SensorEventConnection(const sp<SensorService>& service, uid_t uid);
+ SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
+ bool isDataInjectionMode, const String16& opPackageName);
status_t sendEvents(sensors_event_t const* buffer, size_t count,
sensors_event_t* scratch,
@@ -183,6 +244,7 @@
void dump(String8& result);
bool needsWakeLock();
void resetWakeLockRefCount();
+ String8 getPackageName() const;
uid_t getUid() const { return mUid; }
};
@@ -201,6 +263,7 @@
void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
void removeFirstPendingFlushConnection();
SensorEventConnection * getFirstPendingFlushConnection();
+ void clearAllPendingFlushConnections();
};
class SensorEventAckReceiver : public Thread {
@@ -210,6 +273,63 @@
SensorEventAckReceiver(const sp<SensorService>& service): mService(service) {}
};
+ // sensor_event_t with only the data and the timestamp.
+ struct TrimmedSensorEvent {
+ union {
+ float *mData;
+ uint64_t mStepCounter;
+ };
+ // Timestamp from the sensor_event.
+ int64_t mTimestamp;
+ // HH:MM:SS local time at which this sensor event is read at SensorService. Useful
+ // for debugging.
+ int32_t mHour, mMin, mSec;
+
+ TrimmedSensorEvent(int sensorType);
+ static bool isSentinel(const TrimmedSensorEvent& event);
+
+ ~TrimmedSensorEvent() {
+ delete [] mData;
+ }
+ };
+
+ // A circular buffer of TrimmedSensorEvents. The size of this buffer is typically 10. The
+ // last N events generated from the sensor are stored in this buffer. The buffer is NOT
+ // cleared when the sensor unregisters and as a result one may see very old data in the
+ // dumpsys output but this is WAI.
+ class CircularBuffer {
+ int mNextInd;
+ int mSensorType;
+ int mBufSize;
+ TrimmedSensorEvent ** mTrimmedSensorEventArr;
+ public:
+ CircularBuffer(int sensor_event_type);
+ void addEvent(const sensors_event_t& sensor_event);
+ void printBuffer(String8& buffer) const;
+ bool populateLastEvent(sensors_event_t *event);
+ ~CircularBuffer();
+ };
+
+ struct SensorRegistrationInfo {
+ int32_t mSensorHandle;
+ String8 mPackageName;
+ bool mActivated;
+ int32_t mSamplingRateUs;
+ int32_t mMaxReportLatencyUs;
+ int32_t mHour, mMin, mSec;
+
+ SensorRegistrationInfo() : mPackageName() {
+ mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
+ mHour = mMin = mSec = INT32_MIN;
+ mActivated = false;
+ }
+
+ static bool isSentinel(const SensorRegistrationInfo& info) {
+ return (info.mHour == INT32_MIN && info.mMin == INT32_MIN && info.mSec == INT32_MIN);
+ }
+ };
+
+ static int getNumEventsForSensorType(int sensor_event_type);
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
Sensor getSensorFromHandle(int handle) const;
@@ -224,8 +344,8 @@
const sp<SensorEventConnection>& connection, int handle);
void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count);
- static bool canAccessSensor(const Sensor& sensor);
- static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation);
+ static bool canAccessSensor(const Sensor& sensor, const char* operation,
+ const String16& opPackageName);
// SensorService acquires a partial wakelock for delivering events from wake up sensors. This
// method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released.
@@ -254,6 +374,15 @@
// to the output vector.
void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections);
+ // If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
+ // allowed to register for or call flush on sensors. Typically only cts test packages are
+ // allowed.
+ bool isWhiteListedPackage(const String8& packageName);
+
+ // Reset the state of SensorService to NORMAL mode.
+ status_t resetToNormalMode();
+ status_t resetToNormalModeLocked();
+
// constants
Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug;
@@ -275,17 +404,28 @@
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
+ Mode mCurrentOperatingMode;
+ // This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
+ // applications with this packageName are allowed to activate/deactivate or call flush on
+ // sensors. To run CTS this is can be set to ".cts." and only CTS tests will get access to
+ // sensors.
+ String8 mWhiteListedPackage;
// The size of this vector is constant, only the items are mutable
- KeyedVector<int32_t, sensors_event_t> mLastEventSeen;
+ KeyedVector<int32_t, CircularBuffer *> mLastEventSeen;
+ int mNextSensorRegIndex;
+ Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
public:
void cleanupConnection(SensorEventConnection* connection);
status_t enable(const sp<SensorEventConnection>& connection, int handle,
- nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags);
+ nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
+ const String16& opPackageName);
status_t disable(const sp<SensorEventConnection>& connection, int handle);
- status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns);
- status_t flushSensor(const sp<SensorEventConnection>& connection);
+ status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns,
+ const String16& opPackageName);
+ status_t flushSensor(const sp<SensorEventConnection>& connection,
+ const String16& opPackageName);
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
index 1025fa8..cfdf6a3 100644
--- a/services/sensorservice/tests/sensorservicetest.cpp
+++ b/services/sensorservice/tests/sensorservicetest.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <inttypes.h>
#include <android/sensor.h>
#include <gui/Sensor.h>
#include <gui/SensorManager.h>
@@ -25,7 +26,7 @@
static nsecs_t sStartTime = 0;
-int receiver(int fd, int events, void* data)
+int receiver(__unused int fd, __unused int events, void* data)
{
sp<SensorEventQueue> q((SensorEventQueue*)data);
ssize_t n;
@@ -44,7 +45,7 @@
oldTimeStamp = buffer[i].timestamp;
if (buffer[i].type == Sensor::TYPE_ACCELEROMETER) {
- printf("%lld\t%8f\t%8f\t%8f\t%f\n",
+ printf("%" PRId64 "\t%8f\t%8f\t%8f\t%f\n",
buffer[i].timestamp,
buffer[i].data[0], buffer[i].data[1], buffer[i].data[2],
1.0/t);
@@ -59,9 +60,9 @@
}
-int main(int argc, char** argv)
+int main()
{
- SensorManager& mgr(SensorManager::getInstance());
+ SensorManager mgr(String16("Sensor Service Test"));
Sensor const* const* list;
ssize_t count = mgr.getSensorList(&list);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index eade2e2..1eb2361 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -1,10 +1,10 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_SRC_FILES:= \
+LOCAL_SRC_FILES := \
Client.cpp \
DisplayDevice.cpp \
DispSync.cpp \
@@ -37,18 +37,18 @@
RenderEngine/GLES20RenderEngine.cpp
-LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
+LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
ifeq ($(TARGET_BOARD_PLATFORM),omap4)
- LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+ LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
endif
ifeq ($(TARGET_BOARD_PLATFORM),s5pc110)
- LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+ LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
endif
ifeq ($(TARGET_DISABLE_TRIPLE_BUFFERING),true)
- LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
+ LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
endif
ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
@@ -56,7 +56,7 @@
endif
ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
- LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
+ LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
endif
ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true)
@@ -93,20 +93,22 @@
LOCAL_CFLAGS += -std=c++11
LOCAL_SHARED_LIBRARIES := \
- libcutils \
- liblog \
- libdl \
- libhardware \
- libutils \
- libEGL \
- libGLESv1_CM \
- libGLESv2 \
- libbinder \
- libui \
- libgui \
- libpowermanager
+ libcutils \
+ liblog \
+ libdl \
+ libhardware \
+ libutils \
+ libEGL \
+ libGLESv1_CM \
+ libGLESv2 \
+ libbinder \
+ libui \
+ libgui \
+ libpowermanager
-LOCAL_MODULE:= libsurfaceflinger
+LOCAL_MODULE := libsurfaceflinger
+
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
include $(BUILD_SHARED_LIBRARY)
@@ -114,46 +116,56 @@
# build surfaceflinger's executable
include $(CLEAR_VARS)
-LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
-LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_CPPFLAGS:= -std=c++11
+LOCAL_CLANG := true
-LOCAL_SRC_FILES:= \
- main_surfaceflinger.cpp
+LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
+LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
+LOCAL_CPPFLAGS := -std=c++11
+
+LOCAL_SRC_FILES := \
+ main_surfaceflinger.cpp
LOCAL_SHARED_LIBRARIES := \
- libsurfaceflinger \
- libcutils \
- liblog \
- libbinder \
- libutils \
- libdl
+ libsurfaceflinger \
+ libcutils \
+ liblog \
+ libbinder \
+ libutils \
+ libdl
LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
-LOCAL_MODULE:= surfaceflinger
+LOCAL_MODULE := surfaceflinger
ifdef TARGET_32_BIT_SURFACEFLINGER
LOCAL_32_BIT_ONLY := true
endif
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+
include $(BUILD_EXECUTABLE)
###############################################################
# uses jni which may not be available in PDK
ifneq ($(wildcard libnativehelper/include),)
include $(CLEAR_VARS)
-LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_SRC_FILES:= \
+LOCAL_CLANG := true
+
+LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
+LOCAL_CPPFLAGS := -std=c++11
+
+LOCAL_SRC_FILES := \
DdmConnection.cpp
LOCAL_SHARED_LIBRARIES := \
- libcutils \
- liblog \
- libdl
+ libcutils \
+ liblog \
+ libdl
-LOCAL_MODULE:= libsurfaceflinger_ddmconnection
+LOCAL_MODULE := libsurfaceflinger_ddmconnection
+
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
include $(BUILD_SHARED_LIBRARY)
endif # libnativehelper
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index f7d32d0..49389e0 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -93,7 +93,7 @@
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
const int self_pid = getpid();
- if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
+ if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != AID_SYSTEM && uid != 0)) {
// we're called from a different process, do the real check
if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
{
diff --git a/services/surfaceflinger/DdmConnection.cpp b/services/surfaceflinger/DdmConnection.cpp
index 2477921..659c2c8 100644
--- a/services/surfaceflinger/DdmConnection.cpp
+++ b/services/surfaceflinger/DdmConnection.cpp
@@ -59,12 +59,14 @@
}
jint (*JNI_CreateJavaVM)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
- JNI_CreateJavaVM = (typeof JNI_CreateJavaVM)dlsym(libart_dso, "JNI_CreateJavaVM");
+ JNI_CreateJavaVM = reinterpret_cast<decltype(JNI_CreateJavaVM)>(
+ dlsym(libart_dso, "JNI_CreateJavaVM"));
ALOGE_IF(!JNI_CreateJavaVM, "DdmConnection: %s", dlerror());
jint (*registerNatives)(JNIEnv* env, jclass clazz);
- registerNatives = (typeof registerNatives)dlsym(libandroid_runtime_dso,
- "Java_com_android_internal_util_WithFramework_registerNatives");
+ registerNatives = reinterpret_cast<decltype(registerNatives)>(
+ dlsym(libandroid_runtime_dso,
+ "Java_com_android_internal_util_WithFramework_registerNatives"));
ALOGE_IF(!registerNatives, "DdmConnection: %s", dlerror());
if (!JNI_CreateJavaVM || !registerNatives) {
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 96efc34..67142b6 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -139,7 +139,7 @@
enum { MAX_RESYNC_SAMPLES = 32 };
enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
enum { NUM_PRESENT_SAMPLES = 8 };
- enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 12 };
+ enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
// mPeriod is the computed period of the modeled vsync events in
// nanoseconds.
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 564f974..13d44f3 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -44,6 +44,18 @@
using namespace android;
// ----------------------------------------------------------------------------
+#ifdef EGL_ANDROID_swap_rectangle
+static constexpr bool kEGLAndroidSwapRectangle = true;
+#else
+static constexpr bool kEGLAndroidSwapRectangle = false;
+#endif
+
+#if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
+// Dummy implementation in case it is missing.
+inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
+}
+#endif
+
/*
* Initialize the display to the specified values.
*
@@ -84,7 +96,6 @@
*/
EGLSurface surface;
- EGLint w, h;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
config = RenderEngine::chooseEglConfig(display, format);
@@ -188,19 +199,14 @@
{
mFlinger->getRenderEngine().checkErrors();
- EGLDisplay dpy = mDisplay;
- EGLSurface surface = mSurface;
-
-#ifdef EGL_ANDROID_swap_rectangle
- if (mFlags & SWAP_RECTANGLE) {
- const Region newDirty(dirty.intersect(bounds()));
- const Rect b(newDirty.getBounds());
- eglSetSwapRectangleANDROID(dpy, surface,
- b.left, b.top, b.width(), b.height());
+ if (kEGLAndroidSwapRectangle) {
+ if (mFlags & SWAP_RECTANGLE) {
+ const Region newDirty(dirty.intersect(bounds()));
+ const Rect b(newDirty.getBounds());
+ eglSetSwapRectangleANDROID(mDisplay, mSurface,
+ b.left, b.top, b.width(), b.height());
+ }
}
-#else
- (void) dirty; // Eliminate unused parameter warning
-#endif
mPageFlipCount++;
}
@@ -511,6 +517,6 @@
tr[0][2], tr[1][2], tr[2][2]);
String8 surfaceDump;
- mDisplaySurface->dump(surfaceDump);
+ mDisplaySurface->dumpAsString(surfaceDump);
result.append(surfaceDump);
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index e60c4fb..2f743c1 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -70,7 +70,7 @@
// frame's buffer.
virtual void onFrameCommitted() = 0;
- virtual void dump(String8& result) const = 0;
+ virtual void dumpAsString(String8& result) const = 0;
virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 22d3cec..6ef3295 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -29,8 +29,9 @@
#include <EGL/egl.h>
#include <hardware/hardware.h>
-#include <gui/Surface.h>
+#include <gui/BufferItem.h>
#include <gui/GraphicBufferAlloc.h>
+#include <gui/Surface.h>
#include <ui/GraphicBuffer.h>
#include "FramebufferSurface.h"
@@ -86,7 +87,7 @@
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
Mutex::Autolock lock(mMutex);
- BufferQueue::BufferItem item;
+ BufferItem item;
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
outBuffer = mCurrentBuffer;
@@ -160,23 +161,7 @@
return mHwc.fbCompositionComplete();
}
-// Since DisplaySurface and ConsumerBase both have a method with this
-// signature, results will vary based on the static pointer type the caller is
-// using:
-// void dump(FrameBufferSurface* fbs, String8& s) {
-// // calls FramebufferSurface::dump()
-// fbs->dump(s);
-//
-// // calls ConsumerBase::dump() since it is non-virtual
-// static_cast<ConsumerBase*>(fbs)->dump(s);
-//
-// // calls FramebufferSurface::dump() since it is virtual
-// static_cast<DisplaySurface*>(fbs)->dump(s);
-// }
-// To make sure that all of these end up doing the same thing, we just redirect
-// to ConsumerBase::dump() here. It will take the internal lock, and then call
-// virtual dumpLocked(), which is where the real work happens.
-void FramebufferSurface::dump(String8& result) const {
+void FramebufferSurface::dumpAsString(String8& result) const {
ConsumerBase::dump(result);
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 8605862..3d17840 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -44,10 +44,7 @@
virtual status_t compositionComplete();
virtual status_t advanceFrame();
virtual void onFrameCommitted();
-
- // Implementation of DisplaySurface::dump(). Note that ConsumerBase also
- // has a non-virtual dump() with the same signature.
- virtual void dump(String8& result) const;
+ virtual void dumpAsString(String8& result) const;
// Cannot resize a buffers in a FramebufferSurface. Only works with virtual
// displays.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index edfed49..2dad005 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -305,13 +305,16 @@
}
void HWComposer::hotplug(int disp, int connected) {
- if (disp == HWC_DISPLAY_PRIMARY || disp >= VIRTUAL_DISPLAY_ID_BASE) {
+ if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
disp, connected);
return;
}
queryDisplayProperties(disp);
- mEventHandler.onHotplugReceived(disp, bool(connected));
+ // Do not teardown or recreate the primary display
+ if (disp != HWC_DISPLAY_PRIMARY) {
+ mEventHandler.onHotplugReceived(disp, bool(connected));
+ }
}
static float getDefaultDensity(uint32_t width, uint32_t height) {
@@ -461,7 +464,7 @@
}
uint32_t HWComposer::getFormat(int disp) const {
- if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
+ if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
return HAL_PIXEL_FORMAT_RGBA_8888;
} else {
return mDisplayData[disp].format;
@@ -632,6 +635,7 @@
}
status_t HWComposer::prepare() {
+ Mutex::Autolock _l(mDisplayLock);
for (size_t i=0 ; i<mNumDisplays ; i++) {
DisplayData& disp(mDisplayData[i]);
if (disp.framebufferTarget) {
@@ -1020,6 +1024,21 @@
SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
}
+ virtual void setSurfaceDamage(const Region& reg) {
+ if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
+ return;
+ }
+ hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
+ // We encode default full-screen damage as INVALID_RECT upstream, but as
+ // 0 rects for HWComposer
+ if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
+ surfaceDamage.numRects = 0;
+ surfaceDamage.rects = NULL;
+ return;
+ }
+ SharedBuffer const* sb = reg.getSharedBuffer(&surfaceDamage.numRects);
+ surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
+ }
virtual void setSidebandStream(const sp<NativeHandle>& stream) {
ALOG_ASSERT(stream->handle() != NULL);
getLayer()->compositionType = HWC_SIDEBAND;
@@ -1050,6 +1069,18 @@
}
getLayer()->acquireFenceFd = -1;
+
+ if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
+ return;
+ }
+
+ hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
+ sb = SharedBuffer::bufferFromData(surfaceDamage.rects);
+ if (sb) {
+ sb->release();
+ surfaceDamage.numRects = 0;
+ surfaceDamage.rects = NULL;
+ }
}
};
@@ -1105,8 +1136,6 @@
case PIXEL_FORMAT_RGB_888: return String8("RGB_888");
case PIXEL_FORMAT_RGB_565: return String8("RGB_565");
case PIXEL_FORMAT_BGRA_8888: return String8("BGRA_8888");
- case PIXEL_FORMAT_sRGB_A_8888: return String8("sRGB_A_8888");
- case PIXEL_FORMAT_sRGB_X_8888: return String8("sRGB_x_8888");
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
return String8("ImplDef");
default:
@@ -1117,6 +1146,7 @@
}
void HWComposer::dump(String8& result) const {
+ Mutex::Autolock _l(mDisplayLock);
if (mHwc) {
result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a62ac5c..cc98b4c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -168,6 +168,7 @@
virtual void setFrame(const Rect& frame) = 0;
virtual void setCrop(const FloatRect& crop) = 0;
virtual void setVisibleRegionScreen(const Region& reg) = 0;
+ virtual void setSurfaceDamage(const Region& reg) = 0;
virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
@@ -353,6 +354,8 @@
// mLists[i>0] can be NULL. that display is to be ignored
struct hwc_display_contents_1* mLists[MAX_HWC_DISPLAYS];
DisplayData mDisplayData[MAX_HWC_DISPLAYS];
+ // protect mDisplayData from races between prepare and dump
+ mutable Mutex mDisplayLock;
size_t mNumDisplays;
cb_context* mCBContext;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c3d45ee..ba4c198 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -18,6 +18,8 @@
#include "VirtualDisplaySurface.h"
#include "HWComposer.h"
+#include <gui/BufferItem.h>
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -234,6 +236,7 @@
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
QueueBufferInput(
systemTime(), false /* isAutoTimestamp */,
+ HAL_DATASPACE_UNKNOWN,
Rect(mSinkBufferWidth, mSinkBufferHeight),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
true /* async*/,
@@ -254,7 +257,7 @@
resetPerFrameState();
}
-void VirtualDisplaySurface::dump(String8& /* result */) const {
+void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
}
void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
@@ -284,7 +287,7 @@
}
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
- uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) {
+ PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
// Don't let a slow consumer block us
bool async = (source == SOURCE_SINK);
@@ -329,7 +332,7 @@
}
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
if (mDisplayId < 0)
return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage);
@@ -364,7 +367,7 @@
usage |= GRALLOC_USAGE_HW_COMPOSER;
const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot];
if ((usage & ~buf->getUsage()) != 0 ||
- (format != 0 && format != (uint32_t)buf->getPixelFormat()) ||
+ (format != 0 && format != buf->getPixelFormat()) ||
(w != 0 && w != mSinkBufferWidth) ||
(h != 0 && h != mSinkBufferHeight)) {
VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
@@ -435,7 +438,7 @@
// Now acquire the buffer from the scratch pool -- should be the same
// slot and fence as we just queued.
Mutex::Autolock lock(mMutex);
- BufferQueue::BufferItem item;
+ BufferItem item;
result = acquireBufferLocked(&item, 0);
if (result != NO_ERROR)
return result;
@@ -453,12 +456,13 @@
// Extract the GLES release fence for HWC to acquire
int64_t timestamp;
bool isAutoTimestamp;
+ android_dataspace dataSpace;
Rect crop;
int scalingMode;
uint32_t transform;
bool async;
- input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode,
- &transform, &async, &mFbFence);
+ input.deflate(×tamp, &isAutoTimestamp, &dataSpace, &crop,
+ &scalingMode, &transform, &async, &mFbFence);
mFbProducerSlot = pslot;
mOutputFence = mFbFence;
@@ -517,11 +521,24 @@
}
void VirtualDisplaySurface::allocateBuffers(bool /* async */,
- uint32_t /* width */, uint32_t /* height */, uint32_t /* format */,
+ uint32_t /* width */, uint32_t /* height */, PixelFormat /* format */,
uint32_t /* usage */) {
// TODO: Should we actually allocate buffers for a virtual display?
}
+status_t VirtualDisplaySurface::allowAllocation(bool /* allow */) {
+ return INVALID_OPERATION;
+}
+
+status_t VirtualDisplaySurface::setGenerationNumber(uint32_t /* generation */) {
+ ALOGE("setGenerationNumber not supported on VirtualDisplaySurface");
+ return INVALID_OPERATION;
+}
+
+String8 VirtualDisplaySurface::getConsumerName() const {
+ return String8("VirtualDisplaySurface");
+}
+
void VirtualDisplaySurface::updateQueueBufferOutput(
const QueueBufferOutput& qbo) {
uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 363dce2..6298751 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -86,7 +86,7 @@
virtual status_t compositionComplete();
virtual status_t advanceFrame();
virtual void onFrameCommitted();
- virtual void dump(String8& result) const;
+ virtual void dumpAsString(String8& result) const;
virtual void resizeBuffers(const uint32_t w, const uint32_t h);
private:
@@ -100,7 +100,7 @@
virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
virtual status_t setBufferCount(int bufferCount);
virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
virtual status_t detachBuffer(int slot);
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);
@@ -114,13 +114,16 @@
virtual status_t disconnect(int api);
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
+ PixelFormat format, uint32_t usage);
+ virtual status_t allowAllocation(bool allow);
+ virtual status_t setGenerationNumber(uint32_t generationNumber);
+ virtual String8 getConsumerName() const override;
//
// Utility methods
//
static Source fbSourceForCompositionType(CompositionType type);
- status_t dequeueBuffer(Source source, uint32_t format, uint32_t usage,
+ status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage,
int* sslot, sp<Fence>* fence);
void updateQueueBufferOutput(const QueueBufferOutput& qbo);
void resetPerFrameState();
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 9b6360e..f760200 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -71,6 +71,11 @@
mVsyncHintSent = false;
}
+void EventThread::setPhaseOffset(nsecs_t phaseOffset) {
+ Mutex::Autolock _l(mLock);
+ mVSyncSource->setPhaseOffset(phaseOffset);
+}
+
void EventThread::sendVsyncHintOnLocked() {
struct itimerspec ts;
if(!mVsyncHintSent) {
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index d1c4fcd..9ba179a 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -51,6 +51,7 @@
virtual ~VSyncSource() {}
virtual void setVSyncEnabled(bool enable) = 0;
virtual void setCallback(const sp<Callback>& callback) = 0;
+ virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
};
class EventThread : public Thread, private VSyncSource::Callback {
@@ -99,6 +100,8 @@
void dump(String8& result) const;
void sendVsyncHintOff();
+ void setPhaseOffset(nsecs_t phaseOffset);
+
private:
virtual bool threadLoop();
virtual void onFirstRef();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5e3dfab..e2418cc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -64,7 +64,6 @@
mTextureName(-1U),
mPremultipliedAlpha(true),
mName("unnamed"),
- mDebug(false),
mFormat(PIXEL_FORMAT_NONE),
mTransactionFlags(0),
mQueuedFrames(0),
@@ -77,11 +76,15 @@
mFiltering(false),
mNeedsFiltering(false),
mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
- mSecure(false),
mProtectedByApp(false),
mHasSurface(false),
mClientRef(client),
- mPotentialCursor(false)
+ mPotentialCursor(false),
+ mQueueItemLock(),
+ mQueueItemCondition(),
+ mQueueItems(),
+ mLastFrameNumberReceived(0),
+ mUpdateTexImageFailed(false)
{
mCurrentCrop.makeInvalid();
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
@@ -92,6 +95,8 @@
layerFlags |= layer_state_t::eLayerHidden;
if (flags & ISurfaceComposerClient::eOpaque)
layerFlags |= layer_state_t::eLayerOpaque;
+ if (flags & ISurfaceComposerClient::eSecure)
+ layerFlags |= layer_state_t::eLayerSecure;
if (flags & ISurfaceComposerClient::eNonPremultiplied)
mPremultipliedAlpha = false;
@@ -164,20 +169,54 @@
// Add this buffer from our internal queue tracker
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
+
+ // Reset the frame number tracker when we receive the first buffer after
+ // a frame number reset
+ if (item.mFrameNumber == 1) {
+ mLastFrameNumberReceived = 0;
+ }
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+ ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
mQueueItems.push_back(item);
+ android_atomic_inc(&mQueuedFrames);
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
}
- android_atomic_inc(&mQueuedFrames);
mFlinger->signalLayerUpdate();
}
void Layer::onFrameReplaced(const BufferItem& item) {
Mutex::Autolock lock(mQueueItemLock);
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+ ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
if (mQueueItems.empty()) {
ALOGE("Can't replace a frame on an empty queue");
return;
}
mQueueItems.editItemAt(0) = item;
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
}
void Layer::onSidebandStreamChanged() {
@@ -218,7 +257,6 @@
mFormat = format;
mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
- mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
mCurrentOpacity = getOpacityForFormat(format);
@@ -513,6 +551,7 @@
const Transform& tr = hw->getTransform();
Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
layer.setVisibleRegionScreen(visible);
+ layer.setSurfaceDamage(surfaceDamageRegion);
if (mSidebandStream.get()) {
layer.setSidebandStream(mSidebandStream);
@@ -693,7 +732,6 @@
void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
const Region& /* clip */, bool useIdentityTransform) const {
- const uint32_t fbHeight = hw->getHeight();
const State& s(getDrawingState());
computeGeometry(hw, mMesh, useIdentityTransform);
@@ -766,7 +804,6 @@
switch (format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_sRGB_A_8888:
return false;
}
// in all other case, we have no blending (also for unknown formats)
@@ -814,6 +851,12 @@
return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
}
+bool Layer::isSecure() const
+{
+ const Layer::State& s(mDrawingState);
+ return (s.flags & layer_state_t::eLayerSecure);
+}
+
bool Layer::isProtected() const
{
const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
@@ -911,7 +954,7 @@
const bool resizePending = (c.requested.w != c.active.w) ||
(c.requested.h != c.active.h);
- if (resizePending) {
+ if (resizePending && mSidebandStream == NULL) {
// don't let Layer::doTransaction update the drawing state
// if we have a pending resize, unless we are in fixed-size mode.
// the drawing state will be updated only once we receive a buffer
@@ -920,6 +963,10 @@
// in particular, we want to make sure the clip (which is part
// of the geometry state) is latched together with the size but is
// latched immediately when no resizing is involved.
+ //
+ // If a sideband stream is attached, however, we want to skip this
+ // optimization so that transactions aren't missed when a buffer
+ // never arrives
flags |= eDontUpdateGeometryState;
}
@@ -1037,16 +1084,39 @@
return true;
}
+void Layer::useSurfaceDamage() {
+ if (mFlinger->mForceFullDamage) {
+ surfaceDamageRegion = Region::INVALID_REGION;
+ } else {
+ surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
+ }
+}
+
+void Layer::useEmptyDamage() {
+ surfaceDamageRegion.clear();
+}
+
// ----------------------------------------------------------------------------
// pageflip handling...
// ----------------------------------------------------------------------------
bool Layer::shouldPresentNow(const DispSync& dispSync) const {
Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return false;
+ }
+ auto timestamp = mQueueItems[0].mTimestamp;
nsecs_t expectedPresent =
mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
- return mQueueItems.empty() ?
- false : mQueueItems[0].mTimestamp < expectedPresent;
+
+ // Ignore timestamps more than a second in the future
+ bool isPlausible = timestamp < (expectedPresent + s2ns(1));
+ ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible "
+ "relative to expectedPresent %" PRId64, mName.string(), timestamp,
+ expectedPresent);
+
+ bool isDue = timestamp < expectedPresent;
+ return isDue || !isPlausible;
}
bool Layer::onPreComposition() {
@@ -1097,6 +1167,10 @@
if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
// mSidebandStreamChanged was true
mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
+ if (mSidebandStream != NULL) {
+ setTransactionFlags(eTransactionNeeded);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
+ }
recomputeVisibleRegions = true;
const State& s(getDrawingState());
@@ -1133,7 +1207,7 @@
}
virtual bool reject(const sp<GraphicBuffer>& buf,
- const IGraphicBufferConsumer::BufferItem& item) {
+ const BufferItem& item) {
if (buf == NULL) {
return false;
}
@@ -1229,21 +1303,62 @@
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0);
+ uint64_t maxFrameNumber = 0;
+ {
+ Mutex::Autolock lock(mQueueItemLock);
+ maxFrameNumber = mLastFrameNumberReceived;
+ }
+
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
- mFlinger->mPrimaryDispSync);
+ mFlinger->mPrimaryDispSync, maxFrameNumber);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
mFlinger->signalLayerUpdate();
return outDirtyRegion;
- }
-
- // Remove this buffer from our internal queue tracker
- { // Autolock scope
+ } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
+ // If the buffer has been rejected, remove it from the shadow queue
+ // and return early
Mutex::Autolock lock(mQueueItemLock);
mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ return outDirtyRegion;
+ } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
+ // This can occur if something goes wrong when trying to create the
+ // EGLImage for this buffer. If this happens, the buffer has already
+ // been released, so we need to clean up the queue and bug out
+ // early.
+ {
+ Mutex::Autolock lock(mQueueItemLock);
+ mQueueItems.clear();
+ android_atomic_and(0, &mQueuedFrames);
+ }
+
+ // Once we have hit this state, the shadow queue may no longer
+ // correctly reflect the incoming BufferQueue's contents, so even if
+ // updateTexImage starts working, the only safe course of action is
+ // to continue to ignore updates.
+ mUpdateTexImageFailed = true;
+
+ return outDirtyRegion;
}
+ { // Autolock scope
+ auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+ Mutex::Autolock lock(mQueueItemLock);
+
+ // Remove any stale buffers that have been dropped during
+ // updateTexImage
+ while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+ mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ }
+
+ mQueueItems.removeAt(0);
+ }
+
+
// Decrement the queued-frames count. Signal another event if we
// have more frames pending.
if (android_atomic_dec(&mQueuedFrames) > 1) {
@@ -1352,6 +1467,7 @@
s.activeTransparentRegion.dump(result, "transparentRegion");
visibleRegion.dump(result, "visibleRegion");
+ surfaceDamageRegion.dump(result, "surfaceDamageRegion");
sp<Client> client(mClientRef.promote());
result.appendFormat( " "
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1d4eee7..c1e5e9f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -76,6 +76,7 @@
Region visibleRegion;
Region coveredRegion;
Region visibleNonTransparentRegion;
+ Region surfaceDamageRegion;
// Layer serial number. This gives layers an explicit ordering, so we
// have a stable sort order when their layer stack and Z-order are
@@ -137,6 +138,12 @@
bool setCrop(const Rect& crop);
bool setLayerStack(uint32_t layerStack);
+ // If we have received a new buffer this frame, we will pass its surface
+ // damage down to hardware composer. Otherwise, we must send a region with
+ // one empty rect.
+ void useSurfaceDamage();
+ void useEmptyDamage();
+
uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags);
@@ -167,7 +174,7 @@
* isSecure - true if this surface is secure, that is if it prevents
* screenshots or VNC servers.
*/
- virtual bool isSecure() const { return mSecure; }
+ virtual bool isSecure() const;
/*
* isProtected - true if the layer may contain protected content in the
@@ -332,9 +339,9 @@
private:
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
- virtual void onFrameAvailable(const BufferItem& item);
- virtual void onFrameReplaced(const BufferItem& item);
- virtual void onSidebandStreamChanged();
+ virtual void onFrameAvailable(const BufferItem& item) override;
+ virtual void onFrameReplaced(const BufferItem& item) override;
+ virtual void onSidebandStreamChanged() override;
void commitTransaction();
@@ -364,7 +371,6 @@
uint32_t mTextureName; // from GLES
bool mPremultipliedAlpha;
String8 mName;
- mutable bool mDebug;
PixelFormat mFormat;
// these are protected by an external lock
@@ -396,7 +402,6 @@
mutable Texture mTexture;
// page-flip thread (currently main thread)
- bool mSecure; // no screenshots
bool mProtectedByApp; // application requires protected path to external sink
// protected by mLock
@@ -410,7 +415,10 @@
// Local copy of the queued contents of the incoming BufferQueue
mutable Mutex mQueueItemLock;
+ Condition mQueueItemCondition;
Vector<BufferItem> mQueueItems;
+ uint64_t mLastFrameNumberReceived;
+ bool mUpdateTexImageFailed; // This is only modified from the main thread
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 8739682..fb7af97 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -49,7 +49,7 @@
wp<IBinder> mProducer;
};
- mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder()));
+ mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(this)));
}
status_t MonitoredProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
@@ -61,7 +61,7 @@
}
status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
- bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+ bool async, uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
return mProducer->dequeueBuffer(slot, fence, async, w, h, format, usage);
}
@@ -106,12 +106,24 @@
}
void MonitoredProducer::allocateBuffers(bool async, uint32_t width,
- uint32_t height, uint32_t format, uint32_t usage) {
+ uint32_t height, PixelFormat format, uint32_t usage) {
mProducer->allocateBuffers(async, width, height, format, usage);
}
+status_t MonitoredProducer::allowAllocation(bool allow) {
+ return mProducer->allowAllocation(allow);
+}
+
+status_t MonitoredProducer::setGenerationNumber(uint32_t generationNumber) {
+ return mProducer->setGenerationNumber(generationNumber);
+}
+
+String8 MonitoredProducer::getConsumerName() const {
+ return mProducer->getConsumerName();
+}
+
IBinder* MonitoredProducer::onAsBinder() {
- return mProducer->asBinder().get();
+ return IInterface::asBinder(mProducer).get();
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index f6ccc51..da95766 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -37,7 +37,7 @@
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
virtual status_t setBufferCount(int bufferCount);
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
virtual status_t detachBuffer(int slot);
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);
@@ -52,7 +52,10 @@
virtual status_t disconnect(int api);
virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
+ PixelFormat format, uint32_t usage);
+ virtual status_t allowAllocation(bool allow);
+ virtual status_t setGenerationNumber(uint32_t generationNumber);
+ virtual String8 getConsumerName() const override;
virtual IBinder* onAsBinder();
private:
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 1adcd1f..0dab872 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -88,5 +88,9 @@
mColorMatrixEnabled = (mtx != identity);
}
+const mat4& Description::getColorMatrix() const {
+ return mColorMatrix;
+}
+
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 43b835f..8a3447c 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -66,6 +66,7 @@
void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void setProjectionMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
+ const mat4& getColorMatrix() const;
private:
bool mUniformsDirty;
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index c2768f3..1a9f59b 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -43,12 +43,6 @@
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);
- struct pack565 {
- inline uint16_t operator() (int r, int g, int b) const {
- return (r<<11)|(g<<5)|b;
- }
- } pack565;
-
const uint16_t protTexData[] = { 0 };
glGenTextures(1, &mProtectedTexName);
glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
@@ -268,14 +262,6 @@
}
}
-void GLES11RenderEngine::beginGroup(const mat4& /*colorTransform*/) {
- // doesn't do anything in GLES 1.1
-}
-
-void GLES11RenderEngine::endGroup() {
- // doesn't do anything in GLES 1.1
-}
-
void GLES11RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
}
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 87eb3e4..08de646 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -62,9 +62,6 @@
virtual void drawMesh(const Mesh& mesh);
- virtual void beginGroup(const mat4& colorTransform);
- virtual void endGroup();
-
virtual size_t getMaxTextureSize() const;
virtual size_t getMaxViewportDims() const;
};
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 8ebafbc..1fabaf5 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -48,12 +48,6 @@
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
- struct pack565 {
- inline uint16_t operator() (int r, int g, int b) const {
- return (r<<11)|(g<<5)|b;
- }
- } pack565;
-
const uint16_t protTexData[] = { 0 };
glGenTextures(1, &mProtectedTexName);
glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
@@ -175,6 +169,12 @@
mState.setTexture(texture);
}
+mat4 GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) {
+ mat4 oldTransform = mState.getColorMatrix();
+ mState.setColorMatrix(colorTransform);
+ return oldTransform;
+}
+
void GLES20RenderEngine::disableTexturing() {
mState.disableTexture();
}
@@ -243,78 +243,6 @@
}
}
-void GLES20RenderEngine::beginGroup(const mat4& colorTransform) {
-
- GLuint tname, name;
- // create the texture
- glGenTextures(1, &tname);
- glBindTexture(GL_TEXTURE_2D, tname);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mVpWidth, mVpHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
- // create a Framebuffer Object to render into
- glGenFramebuffers(1, &name);
- glBindFramebuffer(GL_FRAMEBUFFER, name);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
-
- Group group;
- group.texture = tname;
- group.fbo = name;
- group.width = mVpWidth;
- group.height = mVpHeight;
- group.colorTransform = colorTransform;
-
- mGroupStack.push(group);
-}
-
-void GLES20RenderEngine::endGroup() {
-
- const Group group(mGroupStack.top());
- mGroupStack.pop();
-
- // activate the previous render target
- GLuint fbo = 0;
- if (!mGroupStack.isEmpty()) {
- fbo = mGroupStack.top().fbo;
- }
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-
- // set our state
- Texture texture(Texture::TEXTURE_2D, group.texture);
- texture.setDimensions(group.width, group.height);
- glBindTexture(GL_TEXTURE_2D, group.texture);
-
- mState.setPlaneAlpha(1.0f);
- mState.setPremultipliedAlpha(true);
- mState.setOpaque(false);
- mState.setTexture(texture);
- mState.setColorMatrix(group.colorTransform);
- glDisable(GL_BLEND);
-
- Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
- Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
- Mesh::VertexArray<vec2> texCoord(mesh.getTexCoordArray<vec2>());
- position[0] = vec2(0, 0);
- position[1] = vec2(group.width, 0);
- position[2] = vec2(group.width, group.height);
- position[3] = vec2(0, group.height);
- texCoord[0] = vec2(0, 0);
- texCoord[1] = vec2(1, 0);
- texCoord[2] = vec2(1, 1);
- texCoord[3] = vec2(0, 1);
- drawMesh(mesh);
-
- // reset color matrix
- mState.setColorMatrix(mat4());
-
- // free our fbo and texture
- glDeleteFramebuffers(1, &group.fbo);
- glDeleteTextures(1, &group.texture);
-}
-
void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
}
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 3d6243e..819356a 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -72,14 +72,12 @@
virtual void setupLayerTexturing(const Texture& texture);
virtual void setupLayerBlackedOut();
virtual void setupFillWithColor(float r, float g, float b, float a);
+ virtual mat4 setupColorTransform(const mat4& colorTransform);
virtual void disableTexturing();
virtual void disableBlending();
virtual void drawMesh(const Mesh& mesh);
- virtual void beginGroup(const mat4& colorTransform);
- virtual void endGroup();
-
virtual size_t getMaxTextureSize() const;
virtual size_t getMaxViewportDims() const;
};
diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
index 3f50cb0..ffd9be2 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.cpp
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -16,14 +16,40 @@
#include "Mesh.h"
+#include <utils/Log.h>
+
namespace android {
Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize)
: mVertexCount(vertexCount), mVertexSize(vertexSize), mTexCoordsSize(texCoordSize),
mPrimitive(primitive)
{
- mVertices = new float[(vertexSize + texCoordSize) * vertexCount];
- mStride = mVertexSize + mTexCoordsSize;
+ if (vertexCount == 0) {
+ mVertices = new float[1];
+ mVertices[0] = 0.0f;
+ mStride = 0;
+ return;
+ }
+
+ size_t stride = vertexSize + texCoordSize;
+ size_t remainder = (stride * vertexCount) / vertexCount;
+ // Since all of the input parameters are unsigned, if stride is less than
+ // either vertexSize or texCoordSize, it must have overflowed. remainder
+ // will be equal to stride as long as stride * vertexCount doesn't overflow.
+ if ((stride < vertexSize) || (remainder != stride)) {
+ ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize,
+ texCoordSize);
+ mVertices = new float[1];
+ mVertices[0] = 0.0f;
+ mVertexCount = 0;
+ mVertexSize = 0;
+ mTexCoordsSize = 0;
+ mStride = 0;
+ return;
+ }
+
+ mVertices = new float[stride * vertexCount];
+ mStride = stride;
}
Mesh::~Mesh() {
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 0de5cca..ba11259 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -199,10 +199,8 @@
// un-premultiply if needed before linearization
fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
}
- fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));";
fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
- fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));";
if (!needs.isOpaque() && needs.isPremultiplied()) {
// and re-premultiply if needed after gamma correction
fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index a77e0e9..7cd42e4 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -283,7 +283,6 @@
static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
EGLint attribute, EGLint wanted, EGLConfig* outConfig) {
- EGLConfig config = NULL;
EGLint numConfigs = -1, n = 0;
eglGetConfigs(dpy, NULL, 0, &numConfigs);
EGLConfig* const configs = new EGLConfig[numConfigs];
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 8d7529c..31a961e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -99,18 +99,16 @@
virtual void setupLayerBlackedOut() = 0;
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
+ virtual mat4 setupColorTransform(const mat4& /* colorTransform */) {
+ return mat4();
+ }
+
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
// drawing
virtual void drawMesh(const Mesh& mesh) = 0;
- // grouping
- // creates a color-transform group, everything drawn in the group will be
- // transformed by the given color transform when endGroup() is called.
- virtual void beginGroup(const mat4& colorTransform) = 0;
- virtual void endGroup() = 0;
-
// queries
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 80d3cc2..9b9867d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -145,10 +145,15 @@
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
+ mForceFullDamage(false),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
- mHasColorMatrix(false)
+ mHasColorMatrix(false),
+ mHasPoweredOff(false),
+ mFrameBuckets(),
+ mTotalTime(0),
+ mLastSwapTime(0)
{
ALOGI("SurfaceFlinger is starting");
@@ -319,17 +324,20 @@
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
const char* label) :
mValue(0),
- mPhaseOffset(phaseOffset),
mTraceVsync(traceVsync),
mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
mVsyncEventLabel(String8::format("VSYNC-%s", label)),
- mDispSync(dispSync) {}
+ mDispSync(dispSync),
+ mCallbackMutex(),
+ mCallback(),
+ mVsyncMutex(),
+ mPhaseOffset(phaseOffset),
+ mEnabled(false) {}
virtual ~DispSyncSource() {}
virtual void setVSyncEnabled(bool enable) {
- // Do NOT lock the mutex here so as to avoid any mutex ordering issues
- // with locking it in the onDispSyncEvent callback.
+ Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mPhaseOffset,
static_cast<DispSync::Callback*>(this));
@@ -347,18 +355,54 @@
}
//ATRACE_INT(mVsyncOnLabel.string(), 0);
}
+ mEnabled = enable;
}
virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
- Mutex::Autolock lock(mMutex);
+ Mutex::Autolock lock(mCallbackMutex);
mCallback = callback;
}
+ virtual void setPhaseOffset(nsecs_t phaseOffset) {
+ Mutex::Autolock lock(mVsyncMutex);
+
+ // Normalize phaseOffset to [0, period)
+ auto period = mDispSync->getPeriod();
+ phaseOffset %= period;
+ if (phaseOffset < 0) {
+ // If we're here, then phaseOffset is in (-period, 0). After this
+ // operation, it will be in (0, period)
+ phaseOffset += period;
+ }
+ mPhaseOffset = phaseOffset;
+
+ // If we're not enabled, we don't need to mess with the listeners
+ if (!mEnabled) {
+ return;
+ }
+
+ // Remove the listener with the old offset
+ status_t err = mDispSync->removeEventListener(
+ static_cast<DispSync::Callback*>(this));
+ if (err != NO_ERROR) {
+ ALOGE("error unregistering vsync callback: %s (%d)",
+ strerror(-err), err);
+ }
+
+ // Add a listener with the new offset
+ err = mDispSync->addEventListener(mPhaseOffset,
+ static_cast<DispSync::Callback*>(this));
+ if (err != NO_ERROR) {
+ ALOGE("error registering vsync callback: %s (%d)",
+ strerror(-err), err);
+ }
+ }
+
private:
virtual void onDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
- Mutex::Autolock lock(mMutex);
+ Mutex::Autolock lock(mCallbackMutex);
callback = mCallback;
if (mTraceVsync) {
@@ -374,27 +418,39 @@
int mValue;
- const nsecs_t mPhaseOffset;
const bool mTraceVsync;
const String8 mVsyncOnLabel;
const String8 mVsyncEventLabel;
DispSync* mDispSync;
+
+ Mutex mCallbackMutex; // Protects the following
sp<VSyncSource::Callback> mCallback;
- Mutex mMutex;
+
+ Mutex mVsyncMutex; // Protects the following
+ nsecs_t mPhaseOffset;
+ bool mEnabled;
};
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
- status_t err;
Mutex::Autolock _l(mStateLock);
// initialize EGL for the default display
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
+ // start the EventThread
+ sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ vsyncPhaseOffsetNs, true, "app");
+ mEventThread = new EventThread(vsyncSrc);
+ sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ sfVsyncPhaseOffsetNs, true, "sf");
+ mSFEventThread = new EventThread(sfVsyncSrc);
+ mEventQueue.setEventThread(mSFEventThread);
+
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
mHwc = new HWComposer(this,
@@ -446,15 +502,6 @@
// (which may happens before we render something)
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
- // start the EventThread
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
- mEventQueue.setEventThread(mSFEventThread);
-
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -497,13 +544,13 @@
bool SurfaceFlinger::authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const {
Mutex::Autolock _l(mStateLock);
- sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder());
+ sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
- if (configs == NULL) {
+ if ((configs == NULL) || (display.get() == NULL)) {
return BAD_VALUE;
}
@@ -607,7 +654,7 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& display,
+status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */,
DisplayStatInfo* stats) {
if (stats == NULL) {
return BAD_VALUE;
@@ -621,7 +668,11 @@
}
int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
- return getDisplayDevice(display)->getActiveConfig();
+ sp<DisplayDevice> device(getDisplayDevice(display));
+ if (device != NULL) {
+ return device->getActiveConfig();
+ }
+ return BAD_VALUE;
}
void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) {
@@ -950,8 +1001,8 @@
}
}
+ const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
if (kIgnorePresentFences) {
- const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
@@ -970,6 +1021,26 @@
}
mAnimFrameTracker.advanceFrame();
}
+
+ if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
+ return;
+ }
+
+ nsecs_t currentTime = systemTime();
+ if (mHasPoweredOff) {
+ mHasPoweredOff = false;
+ } else {
+ nsecs_t period = mPrimaryDispSync.getPeriod();
+ nsecs_t elapsedTime = currentTime - mLastSwapTime;
+ size_t numPeriods = static_cast<size_t>(elapsedTime / period);
+ if (numPeriods < NUM_BUCKETS - 1) {
+ mFrameBuckets[numPeriods] += elapsedTime;
+ } else {
+ mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime;
+ }
+ mTotalTime += elapsedTime;
+ }
+ mLastSwapTime = currentTime;
}
void SurfaceFlinger::rebuildLayerStacks() {
@@ -1288,7 +1359,9 @@
// this display is in both lists. see if something changed.
const DisplayDeviceState& state(curr[j]);
const wp<IBinder>& display(curr.keyAt(j));
- if (state.surface->asBinder() != draw[i].surface->asBinder()) {
+ const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
+ const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
+ if (state_binder != draw_binder) {
// changing the surface is like destroying and
// recreating the DisplayDevice, so we just remove it
// from the drawing state, so that it get re-added
@@ -1720,12 +1793,17 @@
frameQueued = true;
if (layer->shouldPresentNow(mPrimaryDispSync)) {
layersWithQueuedFrames.push_back(layer.get());
+ } else {
+ layer->useEmptyDamage();
}
+ } else {
+ layer->useEmptyDamage();
}
}
for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
Layer* layer = layersWithQueuedFrames[i];
const Region dirty(layer->latchBuffer(visibleRegions));
+ layer->useSurfaceDamage();
const Layer::State& s(layer->getDrawingState());
invalidateLayerStack(s.layerStack, dirty);
}
@@ -1794,9 +1872,9 @@
if (mDaltonize) {
colorMatrix = colorMatrix * mDaltonizer();
}
- engine.beginGroup(colorMatrix);
+ mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
doComposeSurfaces(hw, dirtyRegion);
- engine.endGroup();
+ engine.setupColorTransform(oldMatrix);
}
// update the swap region and clear the dirty region
@@ -1940,18 +2018,25 @@
engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
}
-void SurfaceFlinger::addClientLayer(const sp<Client>& client,
+status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc)
{
+ // add this layer to the current state list
+ {
+ Mutex::Autolock _l(mStateLock);
+ if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) {
+ return NO_MEMORY;
+ }
+ mCurrentState.layersSortedByZ.add(lbc);
+ mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
+ }
+
// attach this layer to the client
client->attachLayer(handle, lbc);
- // add this layer to the current state list
- Mutex::Autolock _l(mStateLock);
- mCurrentState.layersSortedByZ.add(lbc);
- mGraphicBufferProducerList.add(gbc->asBinder());
+ return NO_ERROR;
}
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
@@ -2024,7 +2109,7 @@
// NOTE: it would be better to use RTTI as we could directly check
// that we have a Client*. however, RTTI is disabled in Android.
if (s.client != NULL) {
- sp<IBinder> binder = s.client->asBinder();
+ sp<IBinder> binder = IInterface::asBinder(s.client);
if (binder != NULL) {
String16 desc(binder->getInterfaceDescriptor());
if (desc == ISurfaceComposerClient::descriptor) {
@@ -2071,7 +2156,7 @@
if (disp.isValid()) {
const uint32_t what = s.what;
if (what & DisplayState::eSurfaceChanged) {
- if (disp.surface->asBinder() != s.surface->asBinder()) {
+ if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
disp.surface = s.surface;
flags |= eDisplayTransactionNeeded;
}
@@ -2150,9 +2235,7 @@
if (layer->setTransparentRegionHint(s.transparentRegion))
flags |= eTraversalNeeded;
}
- if ((what & layer_state_t::eVisibilityChanged) ||
- (what & layer_state_t::eOpacityChanged)) {
- // TODO: should we just use an eFlagsChanged for this?
+ if (what & layer_state_t::eFlagsChanged) {
if (layer->setFlags(s.flags, s.mask))
flags |= eTraversalNeeded;
}
@@ -2208,10 +2291,16 @@
break;
}
- if (result == NO_ERROR) {
- addClientLayer(client, *handle, *gbp, layer);
- setTransactionFlags(eTransactionNeeded);
+ if (result != NO_ERROR) {
+ return result;
}
+
+ result = addClientLayer(client, *handle, *gbp, layer);
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ setTransactionFlags(eTransactionNeeded);
return result;
}
@@ -2344,6 +2433,7 @@
}
mVisibleRegionsDirty = true;
+ mHasPoweredOff = true;
repaintEverything();
} else if (mode == HWC_POWER_MODE_OFF) {
if (type == DisplayDevice::DISPLAY_PRIMARY) {
@@ -2402,18 +2492,15 @@
result.appendFormat("Permission Denial: "
"can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
} else {
- // Try to get the main lock, but don't insist if we can't
+ // Try to get the main lock, but give up after one second
// (this would indicate SF is stuck, but we want to be able to
// print something in dumpsys).
- int retry = 3;
- while (mStateLock.tryLock()<0 && --retry>=0) {
- usleep(1000000);
- }
- const bool locked(retry >= 0);
+ status_t err = mStateLock.timedLock(s2ns(1));
+ bool locked = (err == NO_ERROR);
if (!locked) {
- result.append(
- "SurfaceFlinger appears to be unresponsive, "
- "dumping anyways (no locks held)\n");
+ result.appendFormat(
+ "SurfaceFlinger appears to be unresponsive (%s [%d]), "
+ "dumping anyways (no locks held)\n", strerror(-err), err);
}
bool dumpAll = true;
@@ -2447,6 +2534,13 @@
mPrimaryDispSync.dump(result);
dumpAll = false;
}
+
+ if ((index < numArgs) &&
+ (args[index] == String16("--static-screen"))) {
+ index++;
+ dumpStaticScreenStats(result);
+ dumpAll = false;
+ }
}
if (dumpAll) {
@@ -2550,6 +2644,23 @@
result.append(config);
}
+void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
+{
+ result.appendFormat("Static screen stats:\n");
+ for (size_t b = 0; b < NUM_BUCKETS - 1; ++b) {
+ float bucketTimeSec = mFrameBuckets[b] / 1e9;
+ float percent = 100.0f *
+ static_cast<float>(mFrameBuckets[b]) / mTotalTime;
+ result.appendFormat(" < %zd frames: %.3f s (%.1f%%)\n",
+ b + 1, bucketTimeSec, percent);
+ }
+ float bucketTimeSec = mFrameBuckets[NUM_BUCKETS - 1] / 1e9;
+ float percent = 100.0f *
+ static_cast<float>(mFrameBuckets[NUM_BUCKETS - 1]) / mTotalTime;
+ result.appendFormat(" %zd+ frames: %.3f s (%.1f%%)\n",
+ NUM_BUCKETS - 1, bucketTimeSec, percent);
+}
+
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
String8& result) const
{
@@ -2596,6 +2707,11 @@
mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
result.append("\n");
+ // Dump static screen stats
+ result.append("\n");
+ dumpStaticScreenStats(result);
+ result.append("\n");
+
/*
* Dump the visible layer list
*/
@@ -2743,7 +2859,7 @@
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) &&
+ if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
!PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
ALOGE("Permission Denial: "
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
@@ -2874,6 +2990,21 @@
mPrimaryDispSync.setRefreshSkipCount(n);
return NO_ERROR;
}
+ case 1017: {
+ n = data.readInt32();
+ mForceFullDamage = static_cast<bool>(n);
+ return NO_ERROR;
+ }
+ case 1018: { // Modify Choreographer's phase offset
+ n = data.readInt32();
+ mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+ return NO_ERROR;
+ }
+ case 1019: { // Modify SurfaceFlinger's phase offset
+ n = data.readInt32();
+ mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+ return NO_ERROR;
+ }
}
}
return err;
@@ -2962,7 +3093,7 @@
// Prevent reads below from happening before the read from Message
atomic_thread_fence(memory_order_acquire);
if (what == MSG_API_CALL) {
- result = impl->asBinder()->transact(code, data[0], reply);
+ result = IInterface::asBinder(impl)->transact(code, data[0], reply);
barrier.open();
} else if (what == MSG_EXIT) {
exitRequested = true;
@@ -3012,7 +3143,7 @@
// if we have secure windows on this display, never allow the screen capture
// unless the producer interface is local (i.e.: we can take a screenshot for
// ourselves).
- if (!producer->asBinder()->localBinder()) {
+ if (!IInterface::asBinder(producer)->localBinder()) {
Mutex::Autolock _l(mStateLock);
sp<const DisplayDevice> hw(getDisplayDevice(display));
if (hw->getSecureLayerVisible()) {
@@ -3076,7 +3207,7 @@
result = flinger->captureScreenImplLocked(hw, producer,
sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
useIdentityTransform, rotation);
- static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
+ static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
return true;
}
};
@@ -3118,9 +3249,10 @@
RenderEngine& engine(getRenderEngine());
// get screen geometry
- const uint32_t hw_w = hw->getWidth();
- const uint32_t hw_h = hw->getHeight();
- const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
+ const int32_t hw_w = hw->getWidth();
+ const int32_t hw_h = hw->getHeight();
+ const bool filtering = static_cast<int32_t>(reqWidth) != hw_w ||
+ static_cast<int32_t>(reqHeight) != hw_h;
// if a default or invalid sourceCrop is passed in, set reasonable values
if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
@@ -3133,13 +3265,13 @@
if (sourceCrop.left < 0) {
ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
}
- if (static_cast<uint32_t>(sourceCrop.right) > hw_w) {
+ if (sourceCrop.right > hw_w) {
ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
}
if (sourceCrop.top < 0) {
ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
}
- if (static_cast<uint32_t>(sourceCrop.bottom) > hw_h) {
+ if (sourceCrop.bottom > hw_h) {
ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
}
@@ -3186,8 +3318,12 @@
ATRACE_CALL();
// get screen geometry
- const uint32_t hw_w = hw->getWidth();
- const uint32_t hw_h = hw->getHeight();
+ uint32_t hw_w = hw->getWidth();
+ uint32_t hw_h = hw->getHeight();
+
+ if (rotation & Transform::ROT_90) {
+ std::swap(hw_w, hw_h);
+ }
if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
ALOGE("size mismatch (%d, %d) > (%d, %d)",
@@ -3203,8 +3339,8 @@
sp<Surface> sur = new Surface(producer, false);
ANativeWindow* window = sur.get();
- status_t result = NO_ERROR;
- if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) == NO_ERROR) {
+ status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ if (result == NO_ERROR) {
uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
@@ -3294,7 +3430,7 @@
result = BAD_VALUE;
}
// queueBuffer takes ownership of syncFd
- window->queueBuffer(window, buffer, syncFd);
+ result = window->queueBuffer(window, buffer, syncFd);
}
} else {
result = BAD_VALUE;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4deb815..3759a92 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -144,6 +144,8 @@
// every half hour.
enum { LOG_FRAME_STATS_PERIOD = 30*60*60 };
+ static const size_t MAX_LAYERS = 4096;
+
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -305,7 +307,7 @@
status_t removeLayer(const sp<Layer>& layer);
// add a layer to SurfaceFlinger
- void addClientLayer(const sp<Client>& client,
+ status_t addClientLayer(const sp<Client>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc);
@@ -416,6 +418,8 @@
void logFrameStats();
+ void dumpStaticScreenStats(String8& result) const;
+
/* ------------------------------------------------------------------------
* Attributes
*/
@@ -469,6 +473,7 @@
volatile nsecs_t mDebugInTransaction;
nsecs_t mLastTransactionTime;
bool mBootFinished;
+ bool mForceFullDamage;
// these are thread safe
mutable MessageQueue mEventQueue;
@@ -493,6 +498,13 @@
mat4 mColorMatrix;
bool mHasColorMatrix;
+
+ // Static screen stats
+ bool mHasPoweredOff;
+ static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
+ nsecs_t mFrameBuckets[NUM_BUCKETS];
+ nsecs_t mTotalTime;
+ nsecs_t mLastSwapTime;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 7de6ac4..ed1f31b 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -21,6 +21,8 @@
#include <private/gui/SyncFeatures.h>
+#include <gui/BufferItem.h>
+
#include <utils/Errors.h>
#include <utils/NativeHandle.h>
#include <utils/Trace.h>
@@ -30,7 +32,7 @@
// ---------------------------------------------------------------------------
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
- const DispSync& dispSync)
+ const DispSync& dispSync, uint64_t maxFrameNumber)
{
ATRACE_CALL();
ALOGV("updateTexImage");
@@ -47,12 +49,13 @@
return err;
}
- BufferQueue::BufferItem item;
+ BufferItem item;
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
- err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));
+ err = acquireBufferLocked(&item, computeExpectedPresent(dispSync),
+ maxFrameNumber);
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
err = NO_ERROR;
@@ -72,7 +75,7 @@
int buf = item.mBuf;
if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
- return NO_ERROR;
+ return BUFFER_REJECTED;
}
// Release the previous buffer.
@@ -101,11 +104,13 @@
return bindTextureImageLocked();
}
-status_t SurfaceFlingerConsumer::acquireBufferLocked(
- BufferQueue::BufferItem *item, nsecs_t presentWhen) {
- status_t result = GLConsumer::acquireBufferLocked(item, presentWhen);
+status_t SurfaceFlingerConsumer::acquireBufferLocked(BufferItem* item,
+ nsecs_t presentWhen, uint64_t maxFrameNumber) {
+ status_t result = GLConsumer::acquireBufferLocked(item, presentWhen,
+ maxFrameNumber);
if (result == NO_ERROR) {
mTransformToDisplayInverse = item->mTransformToDisplayInverse;
+ mSurfaceDamage = item->mSurfaceDamage;
}
return result;
}
@@ -114,6 +119,10 @@
return mTransformToDisplayInverse;
}
+const Region& SurfaceFlingerConsumer::getSurfaceDamage() const {
+ return mSurfaceDamage;
+}
+
sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
return mConsumer->getSidebandStream();
}
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 28f2f6a..779e5b7 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -28,6 +28,8 @@
*/
class SurfaceFlingerConsumer : public GLConsumer {
public:
+ static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
+
struct ContentsChangedListener: public FrameAvailableListener {
virtual void onSidebandStreamChanged() = 0;
};
@@ -35,31 +37,34 @@
SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
uint32_t tex)
: GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
- mTransformToDisplayInverse(false)
+ mTransformToDisplayInverse(false), mSurfaceDamage()
{}
class BufferRejecter {
friend class SurfaceFlingerConsumer;
virtual bool reject(const sp<GraphicBuffer>& buf,
- const IGraphicBufferConsumer::BufferItem& item) = 0;
+ const BufferItem& item) = 0;
protected:
virtual ~BufferRejecter() { }
};
- virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item, nsecs_t presentWhen);
+ virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) override;
// This version of updateTexImage() takes a functor that may be used to
// reject the newly acquired buffer. Unlike the GLConsumer version,
// this does not guarantee that the buffer has been bound to the GL
// texture.
- status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync);
+ status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
+ uint64_t maxFrameNumber = 0);
// See GLConsumer::bindTextureImageLocked().
status_t bindTextureImage();
// must be called from SF main thread
bool getTransformToDisplayInverse() const;
+ const Region& getSurfaceDamage() const;
// Sets the contents changed listener. This should be used instead of
// ConsumerBase::setFrameAvailableListener().
@@ -78,6 +83,9 @@
// it is displayed onto. This is applied after GLConsumer::mCurrentTransform.
// This must be set/read from SurfaceFlinger's main thread.
bool mTransformToDisplayInverse;
+
+ // The portion of this surface that has changed since the previous frame
+ Region mSurfaceDamage;
};
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 90e3f7d..a74bc4c 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#if defined(HAVE_PTHREADS)
#include <sys/resource.h>
-#endif
#include <cutils/sched_policy.h>
#include <binder/IServiceManager.h>
@@ -39,9 +37,8 @@
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
-#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
-#endif
+
set_sched_policy(0, SP_FOREGROUND);
// initialize before clients can connect
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index e210860..979062e 100644
--- a/services/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
@@ -1,6 +1,7 @@
# Build the unit tests,
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := SurfaceFlinger_test
@@ -15,16 +16,9 @@
libbinder \
libcutils \
libgui \
- libstlport \
libui \
libutils \
-LOCAL_C_INCLUDES := \
- bionic \
- bionic/libstdc++/include \
- external/gtest/include \
- external/stlport/stlport \
-
# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
# to integrate with auto-test framework.
include $(BUILD_NATIVE_TEST)
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 4d363c8..dcde512 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -16,6 +16,8 @@
#include <gtest/gtest.h>
+#include <android/native_window.h>
+
#include <binder/IMemory.h>
#include <gui/ISurfaceComposer.h>
@@ -53,21 +55,23 @@
class ScreenCapture : public RefBase {
public:
static void captureScreen(sp<ScreenCapture>* sc) {
- sp<IMemoryHeap> heap;
- uint32_t w=0, h=0;
- PixelFormat fmt=0;
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ IGraphicBufferProducer::QueueBufferOutput bufferOutput;
+ sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &heap, &w, &h, &fmt, 0, 0,
- 0, INT_MAX));
- ASSERT_TRUE(heap != NULL);
- ASSERT_EQ(PIXEL_FORMAT_RGBA_8888, fmt);
- *sc = new ScreenCapture(w, h, heap);
+ sp<IBinder> display(sf->getBuiltInDisplay(
+ ISurfaceComposer::eDisplayIdMain));
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 0, 0,
+ 0, INT_MAX, false));
+ *sc = new ScreenCapture(cpuConsumer);
}
void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
- const uint8_t* img = reinterpret_cast<const uint8_t*>(mHeap->base());
- const uint8_t* pixel = img + (4 * (y*mWidth + x));
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
+ const uint8_t* img = static_cast<const uint8_t*>(mBuf.data);
+ const uint8_t* pixel = img + (4 * (y * mBuf.stride + x));
if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
String8 err(String8::format("pixel @ (%3d, %3d): "
"expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
@@ -77,15 +81,17 @@
}
private:
- ScreenCapture(uint32_t w, uint32_t h, const sp<IMemoryHeap>& heap) :
- mWidth(w),
- mHeight(h),
- mHeap(heap)
- {}
+ ScreenCapture(const sp<CpuConsumer>& cc) :
+ mCC(cc) {
+ EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf));
+ }
- const uint32_t mWidth;
- const uint32_t mHeight;
- sp<IMemoryHeap> mHeap;
+ ~ScreenCapture() {
+ mCC->unlockBuffer(mBuf);
+ }
+
+ sp<CpuConsumer> mCC;
+ CpuConsumer::LockedBuffer mBuf;
};
class LayerUpdateTest : public ::testing::Test {
diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp
index b0d54c4..aa72c79 100644
--- a/services/surfaceflinger/tests/vsync/vsync.cpp
+++ b/services/surfaceflinger/tests/vsync/vsync.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <android/looper.h>
#include <gui/DisplayEventReceiver.h>
#include <utils/Looper.h>
diff --git a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
index 279b88b..b88b04a 100644
--- a/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
+++ b/services/surfaceflinger/tests/waitforvsync/waitforvsync.cpp
@@ -23,6 +23,7 @@
#include <errno.h>
#include <string.h>
#include <stdio.h>
+#include <unistd.h>
#ifndef FBIO_WAITFORVSYNC
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)