Merge "omx: add OMX_EventDataSpaceChanged" into nyc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f302529..458ed3e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -605,7 +605,6 @@
     run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
     run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
 
-    run_command("ROUTE", 10, "route", NULL);
     run_command("PRINTENV", 10, "printenv", NULL);
     run_command("NETSTAT", 10, "netstat", NULL);
     run_command("LSMOD", 10, "lsmod", NULL);
@@ -1273,7 +1272,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 +1380,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/installd/commands.cpp b/cmds/installd/commands.cpp
index ac2ee30..15c1036 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -1852,7 +1852,8 @@
     {
         struct stat s;
         if (stat(b_path.c_str(), &s) != 0) {
-            LOG(ERROR) << "Can't find A/B artifact at " << b_path;
+            // Silently ignore for now. The service calling this isn't smart enough to understand
+            // lack of artifacts at the moment.
             return -1;
         }
         if (!S_ISREG(s.st_mode)) {
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index 99cbedc..d8702e5 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -127,13 +127,13 @@
         if (!(mask & (mask - 1))) {
             // power-of-2, i.e.: just one bit is set
             if (mask & 1) {
-                result.right = exclude.left;
+                result.right = min(result.right, exclude.left);
             } else if (mask & 2) {
-                result.bottom = exclude.top;
+                result.bottom = min(result.bottom, exclude.top);
             } else if (mask & 4) {
-                result.left = exclude.right;
+                result.left = max(result.left, exclude.right);
             } else if (mask & 8) {
-                result.top = exclude.bottom;
+                result.top = max(result.top, exclude.bottom);
             }
         }
     }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index f91dac5..66ef4eb 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1278,6 +1278,9 @@
 }
 
 int SensorService::getNumEventsForSensorType(int sensor_event_type) {
+    if (sensor_event_type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
+        return 16;
+    }
     switch (sensor_event_type) {
         case SENSOR_TYPE_ROTATION_VECTOR:
         case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index e0d7339..5ba387d 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -322,7 +322,6 @@
     mNumResyncSamples = 0;
     mFirstResyncSample = 0;
     mNumResyncSamplesSincePresent = 0;
-    mNumPresentWithoutResyncSamples = 0;
     resetErrorLocked();
 }
 
@@ -347,15 +346,6 @@
 
     updateErrorLocked();
 
-    // This is a workaround for b/25845510.
-    // If we have no resync samples after many presents, something is wrong with
-    // HW vsync. Tell SF to disable HW vsync now and re-enable it next time.
-    if (mNumResyncSamples == 0 &&
-        mNumPresentWithoutResyncSamples++ > MAX_PRESENT_WITHOUT_RESYNC_SAMPLES) {
-        mNumPresentWithoutResyncSamples = 0;
-        return false;
-    }
-
     return !mModelUpdated || mError > kErrorThreshold;
 }
 
@@ -364,7 +354,6 @@
 
     mModelUpdated = false;
     mNumResyncSamples = 0;
-    mNumPresentWithoutResyncSamples = 0;
 }
 
 bool DispSync::addResyncSample(nsecs_t timestamp) {
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 1ee0865..a8524b9 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -140,7 +140,6 @@
     enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
     enum { NUM_PRESENT_SAMPLES = 8 };
     enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
-    enum { MAX_PRESENT_WITHOUT_RESYNC_SAMPLES = 8 };
 
     // mPeriod is the computed period of the modeled vsync events in
     // nanoseconds.
@@ -169,7 +168,6 @@
     size_t mFirstResyncSample;
     size_t mNumResyncSamples;
     int mNumResyncSamplesSincePresent;
-    int mNumPresentWithoutResyncSamples;
 
     // These member variables store information about the present fences used
     // to validate the currently computed model.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 99f0f0b..42d0810 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -780,7 +780,7 @@
     }
     // Subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, s.activeTransparentRegion);
-    Rect frame(s.transform.transform(bounds));
+    Rect frame(s.active.transform.transform(bounds));
     frame.intersect(displayDevice->getViewport(), &frame);
     auto& displayTransform(displayDevice->getTransform());
     auto position = displayTransform.transform(frame);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index db03c23..3a0e21f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3440,14 +3440,18 @@
                     } else {
                         ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
                         result = INVALID_OPERATION;
+                        window->cancelBuffer(window, buffer, syncFd);
+                        buffer = NULL;
                     }
                     // destroy our image
                     eglDestroyImageKHR(mEGLDisplay, image);
                 } else {
                     result = BAD_VALUE;
                 }
-                // queueBuffer takes ownership of syncFd
-                result = window->queueBuffer(window, buffer, syncFd);
+                if (buffer) {
+                    // queueBuffer takes ownership of syncFd
+                    result = window->queueBuffer(window, buffer, syncFd);
+                }
             }
         } else {
             result = BAD_VALUE;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 16332f3..d864874 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -3478,14 +3478,18 @@
                     } else {
                         ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
                         result = INVALID_OPERATION;
+                        window->cancelBuffer(window, buffer, syncFd);
+                        buffer = NULL;
                     }
                     // destroy our image
                     eglDestroyImageKHR(mEGLDisplay, image);
                 } else {
                     result = BAD_VALUE;
                 }
-                // queueBuffer takes ownership of syncFd
-                result = window->queueBuffer(window, buffer, syncFd);
+                if (buffer) {
+                    // queueBuffer takes ownership of syncFd
+                    result = window->queueBuffer(window, buffer, syncFd);
+                }
             }
         } else {
             result = BAD_VALUE;
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index e77952a..aec0fd0 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -394,7 +394,7 @@
     }
 }
 
-const char* LayerRef::GetName() {
+const char* LayerRef::GetName() const {
     return layer_->properties.layerName;
 }
 
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index df088b3..d5cc280 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -450,6 +450,51 @@
     return VK_SUCCESS;
 }
 
+template <class TCreateInfo, class TObject>
+bool AddLayersToCreateInfo(TCreateInfo& local_create_info,
+                           const TObject& object,
+                           const VkAllocationCallbacks* alloc,
+                           bool& allocatedMemory) {
+    // This should never happen and means there is a likely a bug in layer
+    // tracking
+    if (object->active_layers.size() < local_create_info.enabledLayerCount) {
+        ALOGE("Total number of layers is less than those enabled by the app!");
+        return false;
+    }
+    // Check if the total number of layers enabled is greater than those
+    // enabled by the application. If it is then we have system enabled
+    // layers which need to be added to the list of layers passed in through
+    // create.
+    if (object->active_layers.size() > local_create_info.enabledLayerCount) {
+        void* mem = alloc->pfnAllocation(
+            alloc->pUserData, object->active_layers.size() * sizeof(char*),
+            alignof(char*), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+        if (mem) {
+            local_create_info.enabledLayerCount = 0;
+            const char** names = static_cast<const char**>(mem);
+            for (const auto& layer : object->active_layers) {
+                const char* name = layer.GetName();
+                names[local_create_info.enabledLayerCount++] = name;
+            }
+            local_create_info.ppEnabledLayerNames = names;
+        } else {
+            ALOGE("System layers cannot be enabled: memory allocation failed");
+            return false;
+        }
+        allocatedMemory = true;
+    } else {
+        allocatedMemory = false;
+    }
+    return true;
+}
+
+template <class T>
+void FreeAllocatedLayerCreateInfo(T& local_create_info,
+                                  const VkAllocationCallbacks* alloc) {
+    alloc->pfnFree(alloc->pUserData,
+                   const_cast<char**>(local_create_info.ppEnabledLayerNames));
+}
+
 template <class TCreateInfo>
 bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
                               const char* extension_name,
@@ -459,7 +504,7 @@
     void* mem = alloc->pfnAllocation(
         alloc->pUserData,
         local_create_info.enabledExtensionCount * sizeof(char*), alignof(char*),
-        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+        VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
     if (mem) {
         const char** enabled_extensions = static_cast<const char**>(mem);
         for (uint32_t i = 0; i < extension_count; ++i) {
@@ -469,17 +514,16 @@
         enabled_extensions[extension_count] = extension_name;
         local_create_info.ppEnabledExtensionNames = enabled_extensions;
     } else {
-        ALOGW("%s extension cannot be enabled: memory allocation failed",
+        ALOGE("%s extension cannot be enabled: memory allocation failed",
               extension_name);
-        local_create_info.enabledExtensionCount--;
         return false;
     }
     return true;
 }
 
 template <class T>
-void FreeAllocatedCreateInfo(T& local_create_info,
-                             const VkAllocationCallbacks* alloc) {
+void FreeAllocatedExtensionCreateInfo(T& local_create_info,
+                                      const VkAllocationCallbacks* alloc) {
     alloc->pfnFree(
         alloc->pUserData,
         const_cast<char**>(local_create_info.ppEnabledExtensionNames));
@@ -1161,14 +1205,32 @@
         enable_callback =
             property_get_bool("debug.vulkan.enable_callback", false);
         if (enable_callback) {
-            enable_callback = AddExtensionToCreateInfo(
-                local_create_info, "VK_EXT_debug_report", instance->alloc);
+            if (!AddExtensionToCreateInfo(local_create_info,
+                                          "VK_EXT_debug_report", allocator)) {
+                DestroyInstance(instance, allocator);
+                return VK_ERROR_INITIALIZATION_FAILED;
+            }
         }
     }
+    bool allocatedLayerMem;
+    if (!AddLayersToCreateInfo(local_create_info, instance, allocator,
+                               allocatedLayerMem)) {
+        if (enable_callback) {
+            FreeAllocatedExtensionCreateInfo(local_create_info, allocator);
+        }
+        DestroyInstance(instance, allocator);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
 
     result = create_instance(&local_create_info, allocator, &local_instance);
-    if (enable_callback)
-        FreeAllocatedCreateInfo(local_create_info, allocator);
+
+    if (allocatedLayerMem) {
+        FreeAllocatedLayerCreateInfo(local_create_info, allocator);
+    }
+    if (enable_callback) {
+        FreeAllocatedExtensionCreateInfo(local_create_info, allocator);
+    }
+
     if (result != VK_SUCCESS) {
         DestroyInstance(instance, allocator);
         return result;
@@ -1182,7 +1244,7 @@
         ALOGV("Failed to initialize instance dispatch table");
         PFN_vkDestroyInstance destroy_instance =
             reinterpret_cast<PFN_vkDestroyInstance>(
-                next_gipa(VK_NULL_HANDLE, "vkDestroyInstance"));
+                next_gipa(local_instance, "vkDestroyInstance"));
         if (!destroy_instance) {
             ALOGD("Loader unable to find DestroyInstance");
             return VK_ERROR_INITIALIZATION_FAILED;
@@ -1330,7 +1392,7 @@
     }
 
     PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
-        next_gipa(VK_NULL_HANDLE, "vkCreateDevice"));
+        next_gipa(instance.handle, "vkCreateDevice"));
     if (!create_device) {
         ALOGE("Unable to find vkCreateDevice for driver");
         DestroyDevice(device);
@@ -1348,8 +1410,19 @@
     device_create_info.pNext = local_create_info.pNext;
     local_create_info.pNext = &device_create_info;
 
+    bool allocatedLayerMem;
+    if (!AddLayersToCreateInfo(local_create_info, device, allocator,
+                               allocatedLayerMem)) {
+        DestroyDevice(device);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
     result = create_device(gpu, &local_create_info, allocator, &local_device);
 
+    if (allocatedLayerMem) {
+        FreeAllocatedLayerCreateInfo(local_create_info, allocator);
+    }
+
     if (result != VK_SUCCESS) {
         DestroyDevice(device);
         return result;
@@ -1367,7 +1440,7 @@
         ALOGV("Failed to initialize device dispatch table");
         PFN_vkDestroyDevice destroy_device =
             reinterpret_cast<PFN_vkDestroyDevice>(
-                next_gipa(VK_NULL_HANDLE, "vkDestroyDevice"));
+                next_gipa(instance.handle, "vkDestroyDevice"));
         ALOG_ASSERT(destroy_device != nullptr,
                     "Loader unable to find DestroyDevice");
         destroy_device(local_device, allocator);
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index 77c8ebe..cec0ff6 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -153,7 +153,7 @@
     LayerRef(const LayerRef&) = delete;
     LayerRef& operator=(const LayerRef&) = delete;
 
-    const char* GetName();
+    const char* GetName() const;
     uint32_t GetSpecVersion();
 
     // provides bool-like behavior