Merge "ui: Fix Rect::reduce" into nyc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f302529..b52a829 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1273,7 +1273,6 @@
     /* close output if needed */
     if (is_redirecting) {
         fclose(stdout);
-        fclose(stderr);
     }
 
     /* rename or zip the (now complete) .tmp file to its final location */
@@ -1382,5 +1381,9 @@
     MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
     MYLOGI("done\n");
 
+    if (is_redirecting) {
+        fclose(stderr);
+    }
+
     return 0;
 }
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index f0ae325..884f250 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -501,7 +501,7 @@
     dirp = opendir(dir);
     if (dirp == NULL) {
         retval = -errno;
-        fprintf(stderr, "%s: %s\n", dir, strerror(errno));
+        MYLOGE("%s: %s\n", dir, strerror(errno));
         return retval;
     }
 
@@ -702,7 +702,7 @@
 
 void send_broadcast(const std::string& action, const std::vector<std::string>& args) {
     if (args.size() > 1000) {
-        fprintf(stderr, "send_broadcast: too many arguments (%d)\n", (int) args.size());
+        MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
         return;
     }
     const char *am_args[1024] = { SU_PATH, "shell", "/system/bin/am", "broadcast",
@@ -755,12 +755,12 @@
 void redirect_to_socket(FILE *redirect, const char *service) {
     int s = android_get_control_socket(service);
     if (s < 0) {
-        fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno));
+        MYLOGE("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));
+        MYLOGE("listen(control socket): %s\n", strerror(errno));
         exit(1);
     }
 
@@ -768,7 +768,7 @@
     socklen_t alen = sizeof(addr);
     int fd = accept(s, &addr, &alen);
     if (fd < 0) {
-        fprintf(stderr, "accept(control socket): %s\n", strerror(errno));
+        MYLOGE("accept(control socket): %s\n", strerror(errno));
         exit(1);
     }
 
@@ -810,7 +810,7 @@
     int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
     if (fd < 0) {
-        fprintf(stderr, "%s: %s\n", path, strerror(errno));
+        MYLOGE("%s: %s\n", path, strerror(errno));
         exit(1);
     }
 
@@ -842,7 +842,7 @@
     strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
     strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
     if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
-        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
+        MYLOGE("rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
         return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
     }
 
@@ -850,12 +850,12 @@
     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));
+        MYLOGE("%s: %s\n", traces_path, strerror(errno));
         return NULL;
     }
     int chmod_ret = fchmod(fd, 0666);
     if (chmod_ret < 0) {
-        fprintf(stderr, "fchmod on %s failed: %s\n", traces_path, strerror(errno));
+        MYLOGE("fchmod on %s failed: %s\n", traces_path, strerror(errno));
         close(fd);
         return NULL;
     }
@@ -867,20 +867,20 @@
     /* walk /proc and kill -QUIT all Dalvik processes */
     DIR *proc = opendir("/proc");
     if (proc == NULL) {
-        fprintf(stderr, "/proc: %s\n", strerror(errno));
+        MYLOGE("/proc: %s\n", strerror(errno));
         goto error_close_fd;
     }
 
     /* use inotify to find when processes are done dumping */
     ifd = inotify_init();
     if (ifd < 0) {
-        fprintf(stderr, "inotify_init: %s\n", strerror(errno));
+        MYLOGE("inotify_init: %s\n", strerror(errno));
         goto error_close_fd;
     }
 
     wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
     if (wfd < 0) {
-        fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
+        MYLOGE("inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
         goto error_close_ifd;
     }
 
@@ -915,7 +915,7 @@
             ++dalvik_found;
             uint64_t start = DurationReporter::nanotime();
             if (kill(pid, SIGQUIT)) {
-                fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
+                MYLOGE("kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
                 continue;
             }
 
@@ -923,16 +923,16 @@
             struct pollfd pfd = { ifd, POLLIN, 0 };
             int ret = poll(&pfd, 1, 5000);  /* 5 sec timeout */
             if (ret < 0) {
-                fprintf(stderr, "poll: %s\n", strerror(errno));
+                MYLOGE("poll: %s\n", strerror(errno));
             } else if (ret == 0) {
-                fprintf(stderr, "warning: timed out dumping pid %d\n", pid);
+                MYLOGE("warning: timed out dumping pid %d\n", pid);
             } else {
                 struct inotify_event ie;
                 read(ifd, &ie, sizeof(ie));
             }
 
             if (lseek(fd, 0, SEEK_END) < 0) {
-                fprintf(stderr, "lseek: %s\n", strerror(errno));
+                MYLOGE("lseek: %s\n", strerror(errno));
             } else {
                 dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n",
                         pid, (float)(DurationReporter::nanotime() - start) / NANOS_PER_SEC);
@@ -940,7 +940,7 @@
         } else if (should_dump_native_traces(data)) {
             /* dump native process if appropriate */
             if (lseek(fd, 0, SEEK_END) < 0) {
-                fprintf(stderr, "lseek: %s\n", strerror(errno));
+                MYLOGE("lseek: %s\n", strerror(errno));
             } else {
                 static uint16_t timeout_failures = 0;
                 uint64_t start = DurationReporter::nanotime();
@@ -961,14 +961,14 @@
     }
 
     if (dalvik_found == 0) {
-        fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n");
+        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
     }
 
     static char dump_traces_path[PATH_MAX];
     strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
     strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
     if (rename(traces_path, dump_traces_path)) {
-        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
+        MYLOGE("rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
         goto error_close_ifd;
     }
     result = dump_traces_path;
@@ -1021,7 +1021,7 @@
     // adjusts max on the fly
     if (progress > weight_total) {
         int new_total = weight_total * 1.2;
-        fprintf(stderr, "Adjusting total weight from %d to %d\n", weight_total, new_total);
+        MYLOGD("Adjusting total weight from %d to %d\n", weight_total, new_total);
         weight_total = new_total;
         sprintf(key, "dumpstate.%d.max", getpid());
         sprintf(value, "%d", weight_total);
@@ -1035,9 +1035,14 @@
     sprintf(key, "dumpstate.%d.progress", getpid());
     sprintf(value, "%d", progress);
 
-    // stderr is ignored on normal invocations, but useful when calling /system/bin/dumpstate
-    // directly for debuggging.
-    fprintf(stderr, "Setting progress (%s): %s/%d\n", key, value, weight_total);
+    if (progress % 100 == 0) {
+        // We don't want to spam logcat, so only log multiples of 100.
+        MYLOGD("Setting progress (%s): %s/%d\n", key, value, weight_total);
+    } else {
+        // stderr is ignored on normal invocations, but useful when calling /system/bin/dumpstate
+        // directly for debuggging.
+        fprintf(stderr, "Setting progress (%s): %s/%d\n", key, value, weight_total);
+    }
 
     int status = property_set(key, value);
     if (status) {
@@ -1195,5 +1200,5 @@
         args.append(argv[i]);
         args.append(" ");
     }
-    MYLOGI("%s: %s\n", message.c_str(), args.c_str());
+    MYLOGD("%s: %s\n", message.c_str(), args.c_str());
 }
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 46fb81a..003fcc3 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -141,9 +141,8 @@
         if (service != NULL) {
             int sfd[2];
 
-            // Use a socketpair instead of a pipe to avoid sending SIGPIPE to services that timeout.
-            if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) != 0) {
-                aerr << "Failed to create socketpair to dump service info for " << service_name
+            if (pipe(sfd) != 0) {
+                aerr << "Failed to create pipe to dump service info for " << service_name
                      << ": " << strerror(errno) << endl;
                 continue;
             }
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 44e2dd2..ac2ee30 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -161,17 +161,20 @@
     return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
 }
 
-static void unlink_reference_profile(const char* pkgname) {
+static bool unlink_reference_profile(const char* pkgname) {
     std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
     std::string reference_profile = create_primary_profile(reference_profile_dir);
     if (unlink(reference_profile.c_str()) != 0) {
         if (errno != ENOENT) {
             PLOG(WARNING) << "Could not unlink " << reference_profile;
+            return false;
         }
     }
+    return true;
 }
 
-static void unlink_current_profiles(const char* pkgname) {
+static bool unlink_current_profiles(const char* pkgname) {
+    bool success = true;
     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
     for (auto user : users) {
         std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
@@ -179,14 +182,18 @@
         if (unlink(profile.c_str()) != 0) {
             if (errno != ENOENT) {
                 PLOG(WARNING) << "Could not unlink " << profile;
+                success = false;
             }
         }
     }
+    return success;
 }
 
-static void unlink_all_profiles(const char* pkgname) {
-    unlink_reference_profile(pkgname);
-    unlink_current_profiles(pkgname);
+static bool unlink_all_profiles(const char* pkgname) {
+    bool success = true;
+    success &= unlink_reference_profile(pkgname);
+    success &= unlink_current_profiles(pkgname);
+    return success;
 }
 
 int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
@@ -1761,6 +1768,11 @@
     return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
 }
 
+int rm_profiles(const char* pkgname)
+{
+    return unlink_all_profiles(pkgname) ? 0 : -1;
+}
+
 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];
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 8507eff..b473e3e 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -56,6 +56,7 @@
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
 int create_oat_dir(const char* oat_dir, const char *instruction_set);
 int rm_package_dir(const char* apk_path);
+int rm_profiles(const char* pkgname);
 int link_file(const char *relative_path, const char *from_base, const char *to_base);
 
 // Move a B version over to the A location. Only works for oat_dir != nullptr.
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 54d3970..7ca7527 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -330,6 +330,12 @@
     return rm_package_dir(arg[0]);
 }
 
+static int do_rm_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+{
+    /* package_name */
+    return rm_profiles(arg[0]);
+}
+
 static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     /* relative_path, from_base, to_base */
@@ -368,6 +374,7 @@
     { "idmap",                3, do_idmap },
     { "createoatdir",         2, do_create_oat_dir },
     { "rmpackagedir",         1, do_rm_package_dir },
+    { "rmprofiles",           1, do_rm_profiles },
     { "linkfile",             3, do_link_file },
     { "move_ab",              3, do_move_ab },
 };
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index c373c28..77ce563 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -23,6 +23,8 @@
 #include <system/window.h>
 #include <utils/RefBase.h>
 
+#include "VideoAPI.h"
+
 #include <OMX_Component.h>
 
 namespace android {
@@ -225,79 +227,6 @@
     OMX_BOOL bEnable;
 };
 
-// Structure describing a media image (frame)
-// Currently only supporting YUV
-// @deprecated. Use MediaImage2 instead
-struct MediaImage {
-    enum Type {
-        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
-        MEDIA_IMAGE_TYPE_YUV,
-    };
-
-    enum PlaneIndex {
-        Y = 0,
-        U,
-        V,
-        MAX_NUM_PLANES
-    };
-
-    Type mType;
-    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 {
-        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];
-};
-
-struct MediaImage2 {
-    enum Type : uint32_t {
-        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
-        MEDIA_IMAGE_TYPE_YUV,
-        MEDIA_IMAGE_TYPE_YUVA,
-        MEDIA_IMAGE_TYPE_RGB,
-        MEDIA_IMAGE_TYPE_RGBA,
-        MEDIA_IMAGE_TYPE_Y,
-    };
-
-    enum PlaneIndex : uint32_t {
-        Y = 0,
-        U = 1,
-        V = 2,
-        R = 0,
-        G = 1,
-        B = 2,
-        A = 3,
-        MAX_NUM_PLANES = 4,
-    };
-
-    Type mType;
-    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 (always MSB)
-    uint32_t mBitDepthAllocated;      // bits per component (must be 8 or 16)
-
-    struct PlaneInfo {
-        uint32_t mOffset;             // offset of first pixel of the plane in bytes
-                                      // from buffer offset
-        int32_t mColInc;              // column increment in bytes
-        int32_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];
-
-    void initFromV1(const MediaImage&); // for internal use only
-};
-
 // A pointer to this struct is passed to OMX_GetParameter when the extension
 // index for the 'OMX.google.android.index.describeColorFormat'
 // extension is given.  This method can be called from any component state
@@ -428,84 +357,6 @@
 //   should be treated as defined by the relevant bitstream specifications/standards, or as
 //   Unspecified, if not defined.
 //
-// NOTE: this structure is expected to grow in the future if new color aspects are
-// added to codec bitstreams. OMX component should not require a specific nSize
-// though could verify that nSize is at least the size of the structure at the
-// time of implementation. All new fields will be added at the end of the structure
-// ensuring backward compatibility.
-
-struct ColorAspects {
-    // this is in sync with the range values in graphics.h
-    enum Range : uint32_t {
-        RangeUnspecified,
-        RangeFull,
-        RangeLimited,
-        RangeOther = 0xff,
-    };
-
-    enum Primaries : uint32_t {
-        PrimariesUnspecified,
-        PrimariesBT709_5,       // Rec.ITU-R BT.709-5 or equivalent
-        PrimariesBT470_6M,      // Rec.ITU-R BT.470-6 System M or equivalent
-        PrimariesBT601_6_625,   // Rec.ITU-R BT.601-6 625 or equivalent
-        PrimariesBT601_6_525,   // Rec.ITU-R BT.601-6 525 or equivalent
-        PrimariesGenericFilm,   // Generic Film
-        PrimariesBT2020,        // Rec.ITU-R BT.2020 or equivalent
-        PrimariesOther = 0xff,
-    };
-
-    // this partially in sync with the transfer values in graphics.h prior to the transfers
-    // unlikely to be required by Android section
-    enum Transfer : uint32_t {
-        TransferUnspecified,
-        TransferLinear,         // Linear transfer characteristics
-        TransferSRGB,           // sRGB or equivalent
-        TransferSMPTE170M,      // SMPTE 170M or equivalent (e.g. BT.601/709/2020)
-        TransferGamma22,        // Assumed display gamma 2.2
-        TransferGamma28,        // Assumed display gamma 2.8
-        TransferST2084,         // SMPTE ST 2084 for 10/12/14/16 bit systems
-        TransferHLG,            // ARIB STD-B67 hybrid-log-gamma
-
-        // transfers unlikely to be required by Android
-        TransferSMPTE240M = 0x40, // SMPTE 240M
-        TransferXvYCC,          // IEC 61966-2-4
-        TransferBT1361,         // Rec.ITU-R BT.1361 extended gamut
-        TransferST428,          // SMPTE ST 428-1
-        TransferOther = 0xff,
-    };
-
-    enum MatrixCoeffs : uint32_t {
-        MatrixUnspecified,
-        MatrixBT709_5,          // Rec.ITU-R BT.709-5 or equivalent
-        MatrixBT470_6M,         // KR=0.30, KB=0.11 or equivalent
-        MatrixBT601_6,          // Rec.ITU-R BT.601-6 625 or equivalent
-        MatrixSMPTE240M,        // SMPTE 240M or equivalent
-        MatrixBT2020,           // Rec.ITU-R BT.2020 non-constant luminance
-        MatrixBT2020Constant,   // Rec.ITU-R BT.2020 constant luminance
-        MatrixOther = 0xff,
-    };
-
-    // this is in sync with the standard values in graphics.h
-    enum Standard : uint32_t {
-        StandardUnspecified,
-        StandardBT709,                  // PrimariesBT709_5 and MatrixBT709_5
-        StandardBT601_625,              // PrimariesBT601_6_625 and MatrixBT601_6
-        StandardBT601_625_Unadjusted,   // PrimariesBT601_6_625 and KR=0.222, KB=0.071
-        StandardBT601_525,              // PrimariesBT601_6_525 and MatrixBT601_6
-        StandardBT601_525_Unadjusted,   // PrimariesBT601_6_525 and MatrixSMPTE240M
-        StandardBT2020,                 // PrimariesBT2020 and MatrixBT2020
-        StandardBT2020Constant,         // PrimariesBT2020 and MatrixBT2020Constant
-        StandardBT470M,                 // PrimariesBT470_6M and MatrixBT470_6M
-        StandardFilm,                   // PrimariesGenericFilm and KR=0.253, KB=0.068
-        StandardOther = 0xff,
-    };
-
-    Range mRange;                // IN/OUT
-    Primaries mPrimaries;        // IN/OUT
-    Transfer mTransfer;          // IN/OUT
-    MatrixCoeffs mMatrixCoeffs;  // IN/OUT
-};
-
 struct DescribeColorAspectsParams {
     OMX_U32 nSize;              // IN
     OMX_VERSIONTYPE nVersion;   // IN
diff --git a/include/media/hardware/VideoAPI.h b/include/media/hardware/VideoAPI.h
new file mode 100644
index 0000000..481cc67
--- /dev/null
+++ b/include/media/hardware/VideoAPI.h
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ */
+
+#ifndef VIDEO_API_H_
+
+#define VIDEO_API_H_
+
+namespace android {
+
+/**
+ * Structure describing a media image (frame)
+ * Currently only supporting YUV
+ * @deprecated. Use MediaImage2 instead
+ */
+struct MediaImage {
+    enum Type {
+        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
+        MEDIA_IMAGE_TYPE_YUV,
+    };
+
+    enum PlaneIndex {
+        Y = 0,
+        U,
+        V,
+        MAX_NUM_PLANES
+    };
+
+    Type mType;
+    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 {
+        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];
+};
+
+/**
+ * Structure describing a media image (frame)
+ */
+struct MediaImage2 {
+    enum Type : uint32_t {
+        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
+        MEDIA_IMAGE_TYPE_YUV,
+        MEDIA_IMAGE_TYPE_YUVA,
+        MEDIA_IMAGE_TYPE_RGB,
+        MEDIA_IMAGE_TYPE_RGBA,
+        MEDIA_IMAGE_TYPE_Y,
+    };
+
+    enum PlaneIndex : uint32_t {
+        Y = 0,
+        U = 1,
+        V = 2,
+        R = 0,
+        G = 1,
+        B = 2,
+        A = 3,
+        MAX_NUM_PLANES = 4,
+    };
+
+    Type mType;
+    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 (always MSB)
+    uint32_t mBitDepthAllocated;      // bits per component (must be 8 or 16)
+
+    struct PlaneInfo {
+        uint32_t mOffset;             // offset of first pixel of the plane in bytes
+                                      // from buffer offset
+        int32_t mColInc;              // column increment in bytes
+        int32_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];
+
+    void initFromV1(const MediaImage&); // for internal use only
+};
+
+/**
+ * Aspects of color.
+ */
+
+// NOTE: this structure is expected to grow in the future if new color aspects are
+// added to codec bitstreams. OMX component should not require a specific nSize
+// though could verify that nSize is at least the size of the structure at the
+// time of implementation. All new fields will be added at the end of the structure
+// ensuring backward compatibility.
+struct ColorAspects {
+    // this is in sync with the range values in graphics.h
+    enum Range : uint32_t {
+        RangeUnspecified,
+        RangeFull,
+        RangeLimited,
+        RangeOther = 0xff,
+    };
+
+    enum Primaries : uint32_t {
+        PrimariesUnspecified,
+        PrimariesBT709_5,       // Rec.ITU-R BT.709-5 or equivalent
+        PrimariesBT470_6M,      // Rec.ITU-R BT.470-6 System M or equivalent
+        PrimariesBT601_6_625,   // Rec.ITU-R BT.601-6 625 or equivalent
+        PrimariesBT601_6_525,   // Rec.ITU-R BT.601-6 525 or equivalent
+        PrimariesGenericFilm,   // Generic Film
+        PrimariesBT2020,        // Rec.ITU-R BT.2020 or equivalent
+        PrimariesOther = 0xff,
+    };
+
+    // this partially in sync with the transfer values in graphics.h prior to the transfers
+    // unlikely to be required by Android section
+    enum Transfer : uint32_t {
+        TransferUnspecified,
+        TransferLinear,         // Linear transfer characteristics
+        TransferSRGB,           // sRGB or equivalent
+        TransferSMPTE170M,      // SMPTE 170M or equivalent (e.g. BT.601/709/2020)
+        TransferGamma22,        // Assumed display gamma 2.2
+        TransferGamma28,        // Assumed display gamma 2.8
+        TransferST2084,         // SMPTE ST 2084 for 10/12/14/16 bit systems
+        TransferHLG,            // ARIB STD-B67 hybrid-log-gamma
+
+        // transfers unlikely to be required by Android
+        TransferSMPTE240M = 0x40, // SMPTE 240M
+        TransferXvYCC,          // IEC 61966-2-4
+        TransferBT1361,         // Rec.ITU-R BT.1361 extended gamut
+        TransferST428,          // SMPTE ST 428-1
+        TransferOther = 0xff,
+    };
+
+    enum MatrixCoeffs : uint32_t {
+        MatrixUnspecified,
+        MatrixBT709_5,          // Rec.ITU-R BT.709-5 or equivalent
+        MatrixBT470_6M,         // KR=0.30, KB=0.11 or equivalent
+        MatrixBT601_6,          // Rec.ITU-R BT.601-6 625 or equivalent
+        MatrixSMPTE240M,        // SMPTE 240M or equivalent
+        MatrixBT2020,           // Rec.ITU-R BT.2020 non-constant luminance
+        MatrixBT2020Constant,   // Rec.ITU-R BT.2020 constant luminance
+        MatrixOther = 0xff,
+    };
+
+    // this is in sync with the standard values in graphics.h
+    enum Standard : uint32_t {
+        StandardUnspecified,
+        StandardBT709,                  // PrimariesBT709_5 and MatrixBT709_5
+        StandardBT601_625,              // PrimariesBT601_6_625 and MatrixBT601_6
+        StandardBT601_625_Unadjusted,   // PrimariesBT601_6_625 and KR=0.222, KB=0.071
+        StandardBT601_525,              // PrimariesBT601_6_525 and MatrixBT601_6
+        StandardBT601_525_Unadjusted,   // PrimariesBT601_6_525 and MatrixSMPTE240M
+        StandardBT2020,                 // PrimariesBT2020 and MatrixBT2020
+        StandardBT2020Constant,         // PrimariesBT2020 and MatrixBT2020Constant
+        StandardBT470M,                 // PrimariesBT470_6M and MatrixBT470_6M
+        StandardFilm,                   // PrimariesGenericFilm and KR=0.253, KB=0.068
+        StandardOther = 0xff,
+    };
+
+    Range mRange;                // IN/OUT
+    Primaries mPrimaries;        // IN/OUT
+    Transfer mTransfer;          // IN/OUT
+    MatrixCoeffs mMatrixCoeffs;  // IN/OUT
+};
+
+#ifdef STRINGIFY_ENUMS
+
+inline static const char *asString(MediaImage::Type i, const char *def = "??") {
+    switch (i) {
+        case MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN: return "Unknown";
+        case MediaImage::MEDIA_IMAGE_TYPE_YUV:     return "YUV";
+        default:                                   return def;
+    }
+}
+
+inline static const char *asString(MediaImage::PlaneIndex i, const char *def = "??") {
+    switch (i) {
+        case MediaImage::Y: return "Y";
+        case MediaImage::U: return "U";
+        case MediaImage::V: return "V";
+        default:            return def;
+    }
+}
+
+inline static const char *asString(MediaImage2::Type i, const char *def = "??") {
+    switch (i) {
+        case MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN: return "Unknown";
+        case MediaImage2::MEDIA_IMAGE_TYPE_YUV:     return "YUV";
+        case MediaImage2::MEDIA_IMAGE_TYPE_YUVA:    return "YUVA";
+        case MediaImage2::MEDIA_IMAGE_TYPE_RGB:     return "RGB";
+        case MediaImage2::MEDIA_IMAGE_TYPE_RGBA:    return "RGBA";
+        case MediaImage2::MEDIA_IMAGE_TYPE_Y:       return "Y";
+        default:                                    return def;
+    }
+}
+
+inline static char asChar2(
+        MediaImage2::PlaneIndex i, MediaImage2::Type j, char def = '?') {
+    const char *planes = asString(j, NULL);
+    // handle unknown values
+    if (j == MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN || planes == NULL || i >= strlen(planes)) {
+        return def;
+    }
+    return planes[i];
+}
+
+inline static const char *asString(ColorAspects::Range i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::RangeUnspecified: return "Unspecified";
+        case ColorAspects::RangeFull:        return "Full";
+        case ColorAspects::RangeLimited:     return "Limited";
+        case ColorAspects::RangeOther:       return "Other";
+        default:                             return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::Primaries i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::PrimariesUnspecified: return "Unspecified";
+        case ColorAspects::PrimariesBT709_5:     return "BT709_5";
+        case ColorAspects::PrimariesBT470_6M:    return "BT470_6M";
+        case ColorAspects::PrimariesBT601_6_625: return "BT601_6_625";
+        case ColorAspects::PrimariesBT601_6_525: return "BT601_6_525";
+        case ColorAspects::PrimariesGenericFilm: return "GenericFilm";
+        case ColorAspects::PrimariesBT2020:      return "BT2020";
+        case ColorAspects::PrimariesOther:       return "Other";
+        default:                                 return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::Transfer i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::TransferUnspecified: return "Unspecified";
+        case ColorAspects::TransferLinear:      return "Linear";
+        case ColorAspects::TransferSRGB:        return "SRGB";
+        case ColorAspects::TransferSMPTE170M:   return "SMPTE170M";
+        case ColorAspects::TransferGamma22:     return "Gamma22";
+        case ColorAspects::TransferGamma28:     return "Gamma28";
+        case ColorAspects::TransferST2084:      return "ST2084";
+        case ColorAspects::TransferHLG:         return "HLG";
+        case ColorAspects::TransferSMPTE240M:   return "SMPTE240M";
+        case ColorAspects::TransferXvYCC:       return "XvYCC";
+        case ColorAspects::TransferBT1361:      return "BT1361";
+        case ColorAspects::TransferST428:       return "ST428";
+        case ColorAspects::TransferOther:       return "Other";
+        default:                                return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::MatrixCoeffs i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::MatrixUnspecified:    return "Unspecified";
+        case ColorAspects::MatrixBT709_5:        return "BT709_5";
+        case ColorAspects::MatrixBT470_6M:       return "BT470_6M";
+        case ColorAspects::MatrixBT601_6:        return "BT601_6";
+        case ColorAspects::MatrixSMPTE240M:      return "SMPTE240M";
+        case ColorAspects::MatrixBT2020:         return "BT2020";
+        case ColorAspects::MatrixBT2020Constant: return "BT2020Constant";
+        case ColorAspects::MatrixOther:          return "Other";
+        default:                                 return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::Standard i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::StandardUnspecified:          return "Unspecified";
+        case ColorAspects::StandardBT709:                return "BT709";
+        case ColorAspects::StandardBT601_625:            return "BT601_625";
+        case ColorAspects::StandardBT601_625_Unadjusted: return "BT601_625_Unadjusted";
+        case ColorAspects::StandardBT601_525:            return "BT601_525";
+        case ColorAspects::StandardBT601_525_Unadjusted: return "BT601_525_Unadjusted";
+        case ColorAspects::StandardBT2020:               return "BT2020";
+        case ColorAspects::StandardBT2020Constant:       return "BT2020Constant";
+        case ColorAspects::StandardBT470M:               return "BT470M";
+        case ColorAspects::StandardFilm:                 return "Film";
+        case ColorAspects::StandardOther:                return "Other";
+        default:                                         return def;
+    }
+}
+
+#endif
+
+}  // namespace android
+
+#endif  // VIDEO_API_H_
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index 0aa567d..aacffad 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -18,6 +18,10 @@
    Each section has its own include guard.  This file should be included AFTER
    the OMX include files. */
 
+#ifdef ANDROID
+namespace android {
+#endif
+
 #ifdef OMX_Audio_h
 /* asString definitions if media/openmax/OMX_Audio.h was included */
 
@@ -948,3 +952,7 @@
 #endif // AS_STRING_FOR_OMX_VIDEOEXT_H
 
 #endif // OMX_VideoExt_h
+
+#ifdef ANDROID
+} // namespace android
+#endif
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 818fac6..e9d0654 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1117,6 +1117,11 @@
 
         if (api == BufferQueueCore::CURRENTLY_CONNECTED_API) {
             api = mCore->mConnectedApi;
+            // If we're asked to disconnect the currently connected api but
+            // nobody is connected, it's not really an error.
+            if (api == BufferQueueCore::NO_CONNECTED_API) {
+                return NO_ERROR;
+            }
         }
 
         switch (api) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 267f8af..5d838e6 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -611,6 +611,12 @@
 #endif
 #endif
 
+#ifndef EGL_ANDROID_front_buffer_auto_refresh
+#define EGL_ANDROID_front_buffer_auto_refresh 1
+#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 05700f8..794a7e5 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -72,7 +72,7 @@
  * The rest (gExtensionString) depend on support in the EGL driver, and are
  * only available if the driver supports them. However, some of these must be
  * supported because they are used by the Android system itself; these are
- * listd as mandatory below and are required by the CDD. The system *assumes*
+ * listed as mandatory below and are required by the CDD. The system *assumes*
  * the mandatory extensions are present and may not function properly if some
  * are missing.
  *
@@ -83,6 +83,7 @@
         "EGL_ANDROID_presentation_time "
         "EGL_KHR_swap_buffers_with_damage "
         "EGL_ANDROID_create_native_client_buffer "
+        "EGL_ANDROID_front_buffer_auto_refresh "
         ;
 extern char const * const gExtensionString  =
         "EGL_KHR_image "                        // mandatory
@@ -1194,12 +1195,9 @@
 
     egl_surface_t const * const s = get_surface(surface);
 
-    //XXX: temporary hack for the EGL hook-up for single buffer mode
-    if (attribute == EGL_RENDER_BUFFER && (value == EGL_BACK_BUFFER ||
-            value == EGL_SINGLE_BUFFER)) {
-        native_window_set_auto_refresh(s->win.get(), true);
-        return (native_window_set_single_buffer_mode(s->win.get(),
-                value == EGL_SINGLE_BUFFER)) ? EGL_TRUE : EGL_FALSE;
+    if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
+        return (native_window_set_auto_refresh(s->win.get(),
+                value ? true : false)) ? EGL_TRUE : EGL_FALSE;
     }
 
     if (s->cnx->egl.eglSurfaceAttrib) {
diff --git a/opengl/specs/EGL_ANDROID_front_buffer_auto_refresh.txt b/opengl/specs/EGL_ANDROID_front_buffer_auto_refresh.txt
new file mode 100644
index 0000000..4c0e64c
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_front_buffer_auto_refresh.txt
@@ -0,0 +1,70 @@
+Name
+
+    ANDROID_front_buffer_auto_refresh
+
+Name Strings
+
+    EGL_ANDROID_front_buffer_auto_refresh
+
+Contributors
+
+    Pablo Ceballos
+
+Contact
+
+    Pablo Ceballos, Google Inc. (pceballos 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, February 3, 2016
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.2
+
+    This extension is written against the wording of the EGL 1.5 Specification
+
+Overview
+
+    This extension is intended for latency-sensitive applications that are doing
+    front-buffer rendering. It allows them to indicate to the Android compositor
+    that it should perform composition every time the display refreshes. This
+    removes the overhead of having to notify the compositor that the window
+    surface has been updated, but it comes at the cost of doing potentially
+    unneeded composition work if the window surface has not been updated.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+
+Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
+"Surface Attributes", page 43:
+
+    If attribute is EGL_ANDROID_front_buffer_auto_refresh, then value specifies
+    whether to enable or disable auto-refresh in the Android compositor when
+    doing front-buffer rendering.
+
+Issues
+
+    None
+
+Revision History
+
+#1 (Pablo Ceballos, February 3, 2016)
+    - Initial draft.
diff --git a/opengl/specs/README b/opengl/specs/README
index f4de1b3..8f1eaf3 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -6,10 +6,10 @@
 
      Value                       Extension
 ----------------     ----------------------------------
-0x3140               EGL_ANDROID_image_native_buffer
-0x3141               (unused)
+0x3140               EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
+0x3141               EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
 0x3142               EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
-0x3143               EGL_VERSION_HW_ANDROID (internal use)
+0x3143               EGL_NATIVE_BUFFER_USAGE_ANDROID (EGL_ANDROID_create_native_client_buffer)
 0x3144               EGL_SYNC_NATIVE_FENCE_ANDROID (EGL_ANDROID_native_fence_sync)
 0x3145               EGL_SYNC_NATIVE_FENCE_FD_ANDROID (EGL_ANDROID_native_fence_sync)
 0x3146               EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID (EGL_ANDROID_native_fence_sync)
@@ -18,4 +18,5 @@
 0x3149               EGL_IMAGE_CROP_TOP_ANDROID (EGL_ANDROID_image_crop)
 0x314A               EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
 0x314B               EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
-0x314C - 0x314F      (unused)
+0x314C               EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
+0x314D - 0x314F      (unused)
diff --git a/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp b/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp
index e701481..52295a1 100644
--- a/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp
@@ -2,7 +2,67 @@
 static jint
 android_glCreateShaderProgramv
   (JNIEnv *_env, jobject _this, jint type, jobjectArray strings) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLsizei _count;
+    const GLchar** _strings = NULL;
+    jstring* _jstrings = NULL;
+    GLuint _returnValue = 0;
 
-    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
-    return 0;
+    if (!strings) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "strings == null";
+        goto exit;
+    }
+
+    _count = _env->GetArrayLength(strings);
+
+    _strings = (const GLchar**) calloc(_count, sizeof(const GLchar*));
+    if (!_strings) {
+        _exception = 1;
+        _exceptionType = "java/lang/OutOfMemoryError";
+        _exceptionMessage = "out of memory";
+        goto exit;
+    }
+
+    _jstrings = (jstring*) calloc(_count, sizeof(jstring));
+    if (!_jstrings) {
+        _exception = 1;
+        _exceptionType = "java/lang/OutOfMemoryError";
+        _exceptionMessage = "out of memory";
+        goto exit;
+    }
+
+    for(int i = 0; i < _count; i++) {
+        _jstrings[i] = (jstring) _env->GetObjectArrayElement(strings, i);
+        if (!_jstrings[i]) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "strings == null";
+            goto exit;
+        }
+        _strings[i] = _env->GetStringUTFChars(_jstrings[i], 0);
+    }
+
+    _returnValue = glCreateShaderProgramv((GLenum)type, _count, _strings);
+exit:
+    if (_strings && _jstrings) {
+        for(int i = 0; i < _count; i++) {
+            if (_strings[i] && _jstrings[i]) {
+                _env->ReleaseStringUTFChars(_jstrings[i], _strings[i]);
+            }
+        }
+    }
+    if (_strings) {
+        free(_strings);
+    }
+    if (_jstrings) {
+        free(_jstrings);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return (jint)_returnValue;
 }
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index fc60f35..df088b3 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -528,17 +528,24 @@
     return create_info;
 }
 
-// Separate out cleaning up the layers and instance storage
-// to avoid code duplication in the many failure cases in
-// in CreateInstance_Top
-void TeardownInstance(
-    VkInstance vkinstance,
-    const VkAllocationCallbacks* /* allocator */) {
-    Instance& instance = GetDispatchParent(vkinstance);
-    instance.active_layers.clear();
-    const VkAllocationCallbacks* alloc = instance.alloc;
-    instance.~Instance();
-    alloc->pfnFree(alloc->pUserData, &instance);
+// Clean up and deallocate an Instance; called from both the failure paths in
+// CreateInstance_Top as well as from DestroyInstance_Top. This function does
+// not call down the dispatch chain; that should be done before calling this
+// function, iff the lower vkCreateInstance call has been made and returned
+// successfully.
+void DestroyInstance(Instance* instance,
+                     const VkAllocationCallbacks* allocator) {
+    if (instance->message) {
+        PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report_callback;
+        destroy_debug_report_callback =
+            reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+                GetInstanceProcAddr_Top(instance->handle,
+                                        "vkDestroyDebugReportCallbackEXT"));
+        destroy_debug_report_callback(instance->handle, instance->message,
+                                      allocator);
+    }
+    instance->~Instance();
+    allocator->pfnFree(allocator->pUserData, instance);
 }
 
 }  // anonymous namespace
@@ -941,14 +948,7 @@
     if (instance.drv.instance != VK_NULL_HANDLE &&
         instance.drv.dispatch.DestroyInstance) {
         instance.drv.dispatch.DestroyInstance(instance.drv.instance, allocator);
-    }
-    if (instance.message) {
-        PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report_callback;
-        destroy_debug_report_callback =
-            reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
-                vkGetInstanceProcAddr(vkinstance,
-                                      "vkDestroyDebugReportCallbackEXT"));
-        destroy_debug_report_callback(vkinstance, instance.message, allocator);
+        instance.drv.instance = VK_NULL_HANDLE;
     }
 }
 
@@ -1093,8 +1093,7 @@
 
     result = ActivateAllLayers(create_info, instance, instance);
     if (result != VK_SUCCESS) {
-        DestroyInstance_Bottom(instance->handle, allocator);
-        TeardownInstance(instance->handle, allocator);
+        DestroyInstance(instance, allocator);
         return result;
     }
 
@@ -1115,8 +1114,7 @@
             sizeof(VkLayerInstanceLink) * instance->active_layers.size()));
         if (!layer_instance_link_info) {
             ALOGE("Failed to alloc Instance objects for layers");
-            DestroyInstance_Bottom(instance->handle, allocator);
-            TeardownInstance(instance->handle, allocator);
+            DestroyInstance(instance, allocator);
             return VK_ERROR_OUT_OF_HOST_MEMORY;
         }
 
@@ -1143,8 +1141,7 @@
         reinterpret_cast<PFN_vkCreateInstance>(
             next_gipa(VK_NULL_HANDLE, "vkCreateInstance"));
     if (!create_instance) {
-        DestroyInstance_Bottom(instance->handle, allocator);
-        TeardownInstance(instance->handle, allocator);
+        DestroyInstance(instance, allocator);
         return VK_ERROR_INITIALIZATION_FAILED;
     }
     VkLayerInstanceCreateInfo instance_create_info;
@@ -1170,14 +1167,10 @@
     }
 
     result = create_instance(&local_create_info, allocator, &local_instance);
-
-    if (enable_callback) {
+    if (enable_callback)
         FreeAllocatedCreateInfo(local_create_info, allocator);
-    }
-
     if (result != VK_SUCCESS) {
-        DestroyInstance_Bottom(instance->handle, allocator);
-        TeardownInstance(instance->handle, allocator);
+        DestroyInstance(instance, allocator);
         return result;
     }
 
@@ -1195,8 +1188,7 @@
             return VK_ERROR_INITIALIZATION_FAILED;
         }
         destroy_instance(local_instance, allocator);
-        DestroyInstance_Bottom(instance->handle, allocator);
-        TeardownInstance(instance->handle, allocator);
+        DestroyInstance(instance, allocator);
         return VK_ERROR_INITIALIZATION_FAILED;
     }
     *instance_out = local_instance;
@@ -1244,9 +1236,10 @@
                          const VkAllocationCallbacks* allocator) {
     if (!vkinstance)
         return;
+    if (!allocator)
+        allocator = &kDefaultAllocCallbacks;
     GetDispatchTable(vkinstance).DestroyInstance(vkinstance, allocator);
-
-    TeardownInstance(vkinstance, allocator);
+    DestroyInstance(&(GetDispatchParent(vkinstance)), allocator);
 }
 
 VKAPI_ATTR