Merge changes I7389829a,I4f3f91e8 into nyc-dev
* changes:
vulkan: pass VK_LAYER_FUNCTION_DATA_CALLBACK to layers
vulkan: update vk_layer_interface.h
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 6892b57..917c813 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -28,6 +28,11 @@
// output. All of the dumpstate output is written to stdout, including
// any errors encountered while reading/writing the output.
int main() {
+
+ fprintf(stderr, "=============================================================================\n");
+ fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
+ fprintf(stderr, "=============================================================================\n\n\n");
+
// Start the dumpstate service.
property_set("ctl.start", "dumpstate");
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
new file mode 100644
index 0000000..14ba225
--- /dev/null
+++ b/cmds/bugreportz/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= bugreportz.cpp
+
+LOCAL_MODULE:= bugreportz
+
+LOCAL_CFLAGS := -Wall
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
new file mode 100644
index 0000000..b6856bb
--- /dev/null
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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>
+
+// TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
+// should be reused instead.
+int main() {
+
+ // Start the dumpstatez service.
+ property_set("ctl.start", "dumpstatez");
+
+ // 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 dumpstatez service: %s\n", strerror(errno));
+ return 1;
+ }
+
+ // Set a timeout so that if nothing is read in 10 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 = 10 * 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.cpp b/cmds/dumpstate/dumpstate.cpp
index f207bb5..ea14c66 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -63,6 +63,7 @@
void add_mountinfo();
static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
static bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
+static int control_socket_fd;
#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
@@ -929,15 +930,17 @@
static void usage() {
fprintf(stderr,
- "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
- "[-z]] [-s] [-q] [-B] [-P] [-R] [-V version]\n"
+ "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
+ "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+ " -h: display this help message\n"
" -b: play sound file instead of vibrate, at beginning of job\n"
" -e: play sound file instead of vibrate, at end of job\n"
" -o: write to file (instead of stdout)\n"
" -d: append date to filename (requires -o)\n"
" -p: capture screenshot to filename.png (requires -o)\n"
- " -z: generates zipped file (requires -o)\n"
+ " -z: generate zipped file (requires -o)\n"
" -s: write output to control socket (for init)\n"
+ " -S: write file location to control socket (for init; requires -o and -z)"
" -q: disable vibrate\n"
" -B: send broadcast when finished (requires -o)\n"
" -P: send broadcast when started and update system properties on "
@@ -1017,6 +1020,7 @@
int do_vibrate = 1;
char* use_outfile = 0;
int use_socket = 0;
+ int use_control_socket = 0;
int do_fb = 0;
int do_broadcast = 0;
int do_early_screenshot = 0;
@@ -1053,12 +1057,13 @@
format_args(argc, const_cast<const char **>(argv), &args);
MYLOGD("Dumpstate command line: %s\n", args.c_str());
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
switch (c) {
case 'd': do_add_date = 1; break;
case 'z': do_zip_file = 1; break;
case 'o': use_outfile = optarg; break;
case 's': use_socket = 1; break;
+ case 'S': use_control_socket = 1; break;
case 'v': break; // compatibility no-op
case 'q': do_vibrate = 0; break;
case 'p': do_fb = 1; break;
@@ -1078,6 +1083,11 @@
exit(1);
}
+ if (use_control_socket && !do_zip_file) {
+ usage();
+ exit(1);
+ }
+
if (do_update_progress && !do_broadcast) {
usage();
exit(1);
@@ -1103,6 +1113,11 @@
redirect_to_socket(stdout, "dumpstate");
}
+ if (use_control_socket) {
+ MYLOGD("Opening control socket\n");
+ control_socket_fd = open_socket("dumpstate");
+ }
+
/* full path of the directory where the bugreport files will be written */
std::string bugreport_dir;
@@ -1342,6 +1357,14 @@
path.clear();
}
}
+ if (use_control_socket) {
+ if (do_text_file) {
+ dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
+ "for more details\n", log_path.c_str());
+ } else {
+ dprintf(control_socket_fd, "OK:%s\n", path.c_str());
+ }
+ }
}
/* vibrate a few but shortly times to let user know it's finished */
@@ -1389,5 +1412,10 @@
fclose(stderr);
}
+ if (use_control_socket && control_socket_fd >= 0) {
+ MYLOGD("Closing control socket\n");
+ close(control_socket_fd);
+ }
+
return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index baba0f9..c51c79a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -130,6 +130,9 @@
/* prints all the system properties */
void print_properties();
+/** opens a socket and returns its file descriptor */
+int open_socket(const char *service);
+
/* redirect output to a service control socket */
void redirect_to_socket(FILE *redirect, const char *service);
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 96232c4..1f56d21 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -9,6 +9,15 @@
disabled
oneshot
+# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
+# it is finished.
+service dumpstatez /system/bin/dumpstate -S -d -z \
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+ socket dumpstate stream 0660 shell log
+ class main
+ disabled
+ oneshot
+
# bugreportplus is an enhanced version of bugreport that provides a better
# user interface (like displaying progress and allowing user to enter details).
# It's typically triggered by the power button or developer settings.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index d9738bb..da4b5ad 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -909,8 +909,7 @@
printf("\n");
}
-/* redirect output to a service control socket */
-void redirect_to_socket(FILE *redirect, const char *service) {
+int open_socket(const char *service) {
int s = android_get_control_socket(service);
if (s < 0) {
MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
@@ -930,11 +929,18 @@
exit(1);
}
+ return fd;
+}
+
+/* redirect output to a service control socket */
+void redirect_to_socket(FILE *redirect, const char *service) {
+ int fd = open_socket(service);
fflush(redirect);
dup2(fd, fileno(redirect));
close(fd);
}
+// TODO: should call is_valid_output_file and/or be merged into it.
void create_parent_dirs(const char *path) {
char *chp = const_cast<char *> (path);
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 878fb2d..5c2ad2d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -104,11 +104,16 @@
struct dirent* ent;
while ((ent = readdir(dir))) {
if (ent->d_ino == ce_data_inode) {
+ auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ if (resolved != fallback) {
+ LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
+ << " instead of " << fallback;
+ }
closedir(dir);
- return StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ return resolved;
}
}
- LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name;
+ LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
closedir(dir);
return fallback;
} else {
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 5d1d7bf..f76a9be 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -122,6 +122,13 @@
// See IGraphicBufferProducer::setDequeueTimeout
status_t setDequeueTimeout(nsecs_t timeout);
+ /*
+ * Wait for frame number to increase past lastFrame for at most
+ * timeoutNs. Useful for one thread to wait for another unknown
+ * thread to queue a buffer.
+ */
+ bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
+
protected:
virtual ~Surface();
@@ -348,6 +355,8 @@
// This is true if the shared buffer has already been queued/canceled. It's
// used to prevent a mismatch between the number of queue/dequeue calls.
bool mSharedBufferHasBeenQueued;
+
+ Condition mQueueBufferCondition;
};
namespace view {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 33fe26c..b221e51 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -40,12 +40,12 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/types.h>
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
#define DEFAULT_MAX_BINDER_THREADS 15
-
-// ---------------------------------------------------------------------------
+// -------------------------------------------------------------------------
namespace android {
@@ -278,8 +278,9 @@
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
+ pid_t pid = getpid();
String8 name;
- name.appendFormat("Binder_%X", s);
+ name.appendFormat("Binder:%d_%X", pid, s);
return name;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 76b62f1..5efc333 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -480,6 +480,8 @@
mSharedBufferHasBeenQueued = true;
}
+ mQueueBufferCondition.broadcast();
+
return err;
}
@@ -1259,6 +1261,15 @@
return err;
}
+bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
+ Mutex::Autolock lock(mMutex);
+ uint64_t currentFrame = mGraphicBufferProducer->getNextFrameNumber();
+ if (currentFrame > lastFrame) {
+ return true;
+ }
+ return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
+}
+
namespace view {
status_t Surface::writeToParcel(Parcel* parcel) const {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index f031296..418892a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -291,6 +291,9 @@
s->w = w;
s->h = h;
+ // Resizing a surface makes the transaction synchronous.
+ mForceSynchronous = true;
+
return NO_ERROR;
}
@@ -451,6 +454,7 @@
s.viewport = layerStackRect;
s.frame = displayRect;
s.what |= DisplayState::eDisplayProjectionChanged;
+ mForceSynchronous = true; // TODO: do we actually still need this?
}
void Composer::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 5d838e6..b1f51f7 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -602,8 +602,8 @@
#define EGL_ANDROID_create_native_client_buffer 1
#define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
-#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID 0x00000002
-#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID 0x00000004
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLClientBuffer eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
#else
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index e7703d8..b997574 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -603,6 +603,7 @@
EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
+ dp->removeSurface(surface);
}
return result;
}
@@ -1814,21 +1815,17 @@
case EGL_NATIVE_BUFFER_USAGE_ANDROID:
if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
usage |= GRALLOC_USAGE_PROTECTED;
- // If we are using QCOM then add in extra bits. This
- // should be removed before launch. These correspond to:
- // USAGE_PRIVATE_MM_HEAP | USAGE_PRIVATE_UNCACHED
- usage |= 0x82000000;
}
- if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) {
+ if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
usage |= GRALLOC_USAGE_HW_RENDER;
}
- if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID) {
+ if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
usage |= GRALLOC_USAGE_HW_TEXTURE;
}
// The buffer must be used for either a texture or a
// renderbuffer.
- if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) &&
- (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID)) {
+ if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
+ (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
}
break;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 6a9d7b6..d849693 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -89,6 +89,31 @@
return false;
}
+void egl_display_t::addContext(egl_context_t* context) {
+ Mutex::Autolock _l(lock);
+ contexts.add(context);
+}
+
+void egl_display_t::removeContext(egl_context_t* context) {
+ Mutex::Autolock _l(lock);
+ contexts.remove(context);
+}
+
+void egl_display_t::removeSurface(EGLSurface surface) const {
+ Mutex::Autolock _l(lock);
+ for (size_t i = 0; i < contexts.size(); i++) {
+ egl_context_t* context = contexts[i];
+ if (context->read == surface) {
+ SurfaceRef _r(get_surface(context->read));
+ _r.release();
+ }
+ if (context->draw == surface) {
+ SurfaceRef _d(get_surface(context->draw));
+ _d.release();
+ }
+ }
+}
+
EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
if (uintptr_t(disp) >= NUM_DISPLAYS)
return NULL;
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 2d86295..0ede705 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -68,6 +68,13 @@
// add reference to this object. returns true if this is a valid object.
bool getObject(egl_object_t* object) const;
+ // add context to this display's list
+ void addContext(egl_context_t* context);
+ // remove context from this display's list
+ void removeContext(egl_context_t* context);
+ // search for surface on all contexts and remove the references
+ void removeSurface(EGLSurface surface) const;
+
// These notifications allow the display to keep track of how many window
// surfaces exist, which it uses to decide whether to hibernate the
// underlying EGL implementation. They can be called by any thread without
@@ -135,6 +142,7 @@
mutable Mutex lock, refLock;
mutable Condition refCond;
SortedVector<egl_object_t*> objects;
+ SortedVector<egl_context_t*> contexts;
String8 mVendorString;
String8 mVersionString;
String8 mClientApiString;
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 918faa8..8859387 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -91,6 +91,12 @@
egl_connection_t const* cnx, int version) :
egl_object_t(get_display_nowake(dpy)), dpy(dpy), context(context),
config(config), read(0), draw(0), cnx(cnx), version(version) {
+ get_display_nowake(dpy)->addContext(this);
+}
+
+void egl_context_t::terminate() {
+ display->removeContext(this);
+ egl_object_t::terminate();
}
void egl_context_t::onLooseCurrent() {
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 17a8304..8268900 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -40,11 +40,12 @@
class egl_display_t;
class egl_object_t {
- egl_display_t *display;
mutable volatile int32_t count;
protected:
virtual ~egl_object_t();
+ virtual void terminate();
+ egl_display_t *display;
public:
egl_object_t(egl_display_t* display);
@@ -55,7 +56,6 @@
inline egl_display_t* getDisplay() const { return display; }
private:
- void terminate();
static bool get(egl_display_t const* display, egl_object_t* object);
public:
@@ -143,6 +143,7 @@
class egl_context_t: public egl_object_t {
protected:
~egl_context_t() {}
+ void terminate() override;
public:
typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;