Merge "batteryservice: Expose Charge Counters." into nyc-dev
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8556c23..374a5de 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -697,6 +697,21 @@
     return result;
 }
 
+void InputReader::toggleCapsLockState(int32_t deviceId) {
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
+        return;
+    }
+
+    InputDevice* device = mDevices.valueAt(deviceIndex);
+    if (device->isIgnored()) {
+        return;
+    }
+
+    device->updateMetaState(AKEYCODE_CAPS_LOCK);
+}
+
 bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
         size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
     AutoMutex _l(mLock);
@@ -1172,6 +1187,13 @@
     return result;
 }
 
+void InputDevice::updateMetaState(int32_t keyCode) {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        mMappers[i]->updateMetaState(keyCode);
+    }
+}
+
 void InputDevice::fadePointer() {
     size_t numMappers = mMappers.size();
     for (size_t i = 0; i < numMappers; i++) {
@@ -1880,6 +1902,9 @@
     return 0;
 }
 
+void InputMapper::updateMetaState(int32_t keyCode) {
+}
+
 void InputMapper::updateExternalStylusState(const StylusState& state) {
 
 }
@@ -2265,18 +2290,12 @@
         }
     }
 
-    int32_t oldMetaState = mMetaState;
-    int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
-    bool metaStateChanged = oldMetaState != newMetaState;
-    if (metaStateChanged) {
-        mMetaState = newMetaState;
-        updateLedState(false);
-
+    if (updateMetaStateIfNeeded(keyCode, down)) {
         // If global meta state changed send it along with the key.
         // If it has not changed then we'll use what keymap gave us,
         // since key replacement logic might temporarily reset a few
         // meta bits for given key.
-        keyMetaState = newMetaState;
+        keyMetaState = mMetaState;
     }
 
     nsecs_t downTime = mDownTime;
@@ -2294,10 +2313,6 @@
         policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
     }
 
-    if (metaStateChanged) {
-        getContext()->updateGlobalMetaState();
-    }
-
     if (down && !isMetaKey(keyCode)) {
         getContext()->fadePointer();
     }
@@ -2335,6 +2350,24 @@
     return mMetaState;
 }
 
+void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
+    updateMetaStateIfNeeded(keyCode, false);
+}
+
+bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
+    int32_t oldMetaState = mMetaState;
+    int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
+    bool metaStateChanged = oldMetaState != newMetaState;
+    if (metaStateChanged) {
+        mMetaState = newMetaState;
+        updateLedState(false);
+
+        getContext()->updateGlobalMetaState();
+    }
+
+    return metaStateChanged;
+}
+
 void KeyboardInputMapper::resetLedState() {
     initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
     initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index e554e57..076f3d6 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -359,6 +359,9 @@
     virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
             int32_t sw) = 0;
 
+    /* Toggle Caps Lock */
+    virtual void toggleCapsLockState(int32_t deviceId) = 0;
+
     /* Determine whether physical keys exist for the given framework-domain key codes. */
     virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
             size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
@@ -461,6 +464,8 @@
     virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
             int32_t sw);
 
+    virtual void toggleCapsLockState(int32_t deviceId);
+
     virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
             size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
 
@@ -616,6 +621,7 @@
     void cancelTouch(nsecs_t when);
 
     int32_t getMetaState();
+    void updateMetaState(int32_t keyCode);
 
     void fadePointer();
 
@@ -1031,6 +1037,7 @@
     virtual void cancelTouch(nsecs_t when);
 
     virtual int32_t getMetaState();
+    virtual void updateMetaState(int32_t keyCode);
 
     virtual void updateExternalStylusState(const StylusState& state);
 
@@ -1116,6 +1123,7 @@
             const int32_t* keyCodes, uint8_t* outFlags);
 
     virtual int32_t getMetaState();
+    virtual void updateMetaState(int32_t keyCode);
 
 private:
     struct KeyDown {
@@ -1156,6 +1164,8 @@
 
     void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
 
+    bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
+
     ssize_t findKeyDown(int32_t scanCode);
 
     void resetLedState();
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 89c4479..31ca0e3 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -826,10 +826,6 @@
     return sensor != NULL && sensor->getSensor().isWakeUpSensor();
 }
 
-SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
-     return mActiveSensors.valueFor(handle);
-}
-
 Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sensors", value, "0");
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 2c802fa..da97286 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -184,8 +184,6 @@
     bool isWakeUpSensorEvent(const sensors_event_t& event) const;
     bool isNewHandle(int handle);
 
-    SensorRecord * getSensorRecord(int handle);
-
     sp<Looper> getLooper() const;
 
     // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 44a3334..fb6307e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -12,6 +12,7 @@
     EventThread.cpp \
     FenceTracker.cpp \
     FrameTracker.cpp \
+    GpuService.cpp \
     Layer.cpp \
     LayerDim.cpp \
     MessageQueue.cpp \
@@ -37,6 +38,9 @@
     RenderEngine/GLES11RenderEngine.cpp \
     RenderEngine/GLES20RenderEngine.cpp
 
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include \
+	external/vulkan-validation-layers/libs/vkjson
 
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -106,6 +110,7 @@
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
 LOCAL_CFLAGS += -std=c++14
 
+LOCAL_STATIC_LIBRARIES := libvkjson
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     liblog \
@@ -118,7 +123,8 @@
     libbinder \
     libui \
     libgui \
-    libpowermanager
+    libpowermanager \
+    libvulkan
 
 LOCAL_MODULE := libsurfaceflinger
 
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp
new file mode 100644
index 0000000..0c29971
--- /dev/null
+++ b/services/surfaceflinger/GpuService.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 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 "GpuService.h"
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+#include <vkjson.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class BpGpuService : public BpInterface<IGpuService>
+{
+public:
+    BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
+};
+
+IMPLEMENT_META_INTERFACE(GpuService, "android.ui.IGpuService");
+
+status_t BnGpuService::onTransact(uint32_t code, const Parcel& data,
+        Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+    case SHELL_COMMAND_TRANSACTION: {
+        int in = data.readFileDescriptor();
+        int out = data.readFileDescriptor();
+        int err = data.readFileDescriptor();
+        int argc = data.readInt32();
+        Vector<String16> args;
+        for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+           args.add(data.readString16());
+        }
+        return shellCommand(in, out, err, args);
+    }
+
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+    status_t cmd_help(int out);
+    status_t cmd_vkjson(int out, int err);
+}
+
+const char* const GpuService::SERVICE_NAME = "gpu";
+
+GpuService::GpuService() {}
+
+status_t GpuService::shellCommand(int /*in*/, int out, int err,
+        Vector<String16>& args)
+{
+    ALOGV("GpuService::shellCommand");
+    for (size_t i = 0, n = args.size(); i < n; i++)
+        ALOGV("  arg[%zu]: '%s'", i, String8(args[i]).string());
+
+    if (args[0] == String16("vkjson"))
+        return cmd_vkjson(out, err);
+    else if (args[0] == String16("help"))
+        return cmd_help(out);
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+
+status_t cmd_help(int out) {
+    FILE* outs = fdopen(out, "w");
+    if (!outs) {
+        ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno),
+            errno);
+        return BAD_VALUE;
+    }
+    fprintf(outs,
+        "GPU Service commands:\n"
+        "  vkjson   dump Vulkan device capabilities as JSON\n");
+    fclose(outs);
+    return NO_ERROR;
+}
+
+VkResult vkjsonPrint(FILE* out, FILE* err) {
+    VkResult result;
+
+    const VkApplicationInfo app_info = {
+        VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr,
+        "vkjson", 1,    /* app name, version */
+        "", 0,          /* engine name, version */
+        VK_API_VERSION
+    };
+    const VkInstanceCreateInfo instance_info = {
+        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr,
+        0,              /* flags */
+        &app_info,
+        0, nullptr,     /* layers */
+        0, nullptr,     /* extensions */
+    };
+    VkInstance instance;
+    result = vkCreateInstance(&instance_info, nullptr, &instance);
+    if (result != VK_SUCCESS) {
+        fprintf(err, "vkCreateInstance failed: %d\n", result);
+        return result;
+    }
+
+    uint32_t ngpu = 0;
+    result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr);
+    if (result != VK_SUCCESS) {
+        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
+        return result;
+    }
+    std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE);
+    result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data());
+    if (result != VK_SUCCESS) {
+        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
+        return result;
+    }
+
+    for (size_t i = 0, n = gpus.size(); i < n; i++) {
+        auto props = VkJsonGetAllProperties(gpus[i]);
+        std::string json = VkJsonAllPropertiesToJson(props);
+        fwrite(json.data(), 1, json.size(), out);
+        if (i < n - 1)
+            fputc(',', out);
+        fputc('\n', out);
+    }
+
+    vkDestroyInstance(instance, nullptr);
+
+    return VK_SUCCESS;
+}
+
+status_t cmd_vkjson(int out, int err) {
+    int errnum;
+    FILE* outs = fdopen(out, "w");
+    if (!outs) {
+        errnum = errno;
+        ALOGE("vkjson: failed to create output stream: %s", strerror(errnum));
+        return -errnum;
+    }
+    FILE* errs = fdopen(err, "w");
+    if (!errs) {
+        errnum = errno;
+        ALOGE("vkjson: failed to create error stream: %s", strerror(errnum));
+        fclose(outs);
+        return -errnum;
+    }
+    fprintf(outs, "[\n");
+    VkResult result = vkjsonPrint(outs, errs);
+    fprintf(outs, "]\n");
+    fclose(errs);
+    fclose(outs);
+    return result >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+}
+
+} // anonymous namespace
+
+} // namespace android
diff --git a/services/surfaceflinger/GpuService.h b/services/surfaceflinger/GpuService.h
new file mode 100644
index 0000000..b8c28d2
--- /dev/null
+++ b/services/surfaceflinger/GpuService.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 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 ANDROID_GPUSERVICE_H
+#define ANDROID_GPUSERVICE_H
+
+#include <binder/IInterface.h>
+#include <cutils/compiler.h>
+
+namespace android {
+
+/*
+ * This class defines the Binder IPC interface for GPU-related queries and
+ * control.
+ */
+class IGpuService : public IInterface {
+public:
+    DECLARE_META_INTERFACE(GpuService);
+};
+
+class BnGpuService: public BnInterface<IGpuService> {
+protected:
+    virtual status_t shellCommand(int in, int out, int err,
+        Vector<String16>& args) = 0;
+
+    virtual status_t onTransact(uint32_t code, const Parcel& data,
+            Parcel* reply, uint32_t flags = 0) override;
+};
+
+class GpuService : public BnGpuService
+{
+public:
+    static const char* const SERVICE_NAME ANDROID_API;
+
+    GpuService() ANDROID_API;
+
+protected:
+    virtual status_t shellCommand(int in, int out, int err,
+        Vector<String16>& args) override;
+};
+
+} // namespace android
+
+#endif // ANDROID_GPUSERVICE_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ea9fe21..40e9ae7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1248,6 +1248,7 @@
         if (hwcId >= 0) {
             mHwc->commit(hwcId);
         }
+        displayDevice->onSwapBuffersCompleted();
         if (displayId == 0) {
             // Make the default display current because the VirtualDisplayDevice
             // code cannot deal with dequeueBuffer() being called outside of the
@@ -1255,7 +1256,6 @@
             // is allowed to (and does in some case) call dequeueBuffer().
             displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
         }
-        displayDevice->onSwapBuffersCompleted();
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             sp<Fence> releaseFence = Fence::NO_FENCE;
             if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 4cd7aeb..97a1e8b 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -21,6 +21,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include "GpuService.h"
 #include "SurfaceFlinger.h"
 
 using namespace android;
@@ -56,7 +57,11 @@
     sp<IServiceManager> sm(defaultServiceManager());
     sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
 
-    // run in this thread
+    // publish GpuService
+    sp<GpuService> gpuservice = new GpuService();
+    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
+
+    // run surface flinger in this thread
     flinger->run();
 
     return 0;