Merge "Do not use RefBase in EventHub"
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index c1d916c..bdf0f8e 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -17,15 +17,12 @@
 #include <binder/Binder.h>
 
 #include <atomic>
+#include <utils/misc.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
-#include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
 #include <binder/IShellCallback.h>
 #include <binder/Parcel.h>
-#include <cutils/android_filesystem_config.h>
-#include <cutils/compiler.h>
-#include <utils/misc.h>
 
 #include <stdio.h>
 
@@ -128,19 +125,6 @@
 {
     data.setDataPosition(0);
 
-    // Shell command transaction is conventionally implemented by
-    // overriding onTransact by copy/pasting the parceling code from
-    // this file. So, we must check permissions for it before we call
-    // onTransact. This check is here because shell APIs aren't
-    // guaranteed to be stable, and so they should only be used by
-    // developers.
-    if (CC_UNLIKELY(code == SHELL_COMMAND_TRANSACTION)) {
-        uid_t uid = IPCThreadState::self()->getCallingUid();
-        if (uid != AID_SHELL && uid != AID_ROOT) {
-            return PERMISSION_DENIED;
-        }
-    }
-
     status_t err = NO_ERROR;
     switch (code) {
         case PING_TRANSACTION:
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index 28cb138..9080ce1 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -19,7 +19,11 @@
     name: "libtimeinstate_test",
     srcs: ["testtimeinstate.cpp"],
     shared_libs: [
+        "libbase",
+        "libbpf",
+        "libbpf_android",
         "libtimeinstate",
+        "libnetdutils",
     ],
     cflags: [
         "-Werror",
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 41cbde1..0e68e62 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "libtimeinstate"
 
 #include "cputimeinstate.h"
+#include "timeinstate.h"
 
 #include <dirent.h>
 #include <errno.h>
@@ -38,23 +39,12 @@
 #include <libbpf.h>
 #include <log/log.h>
 
-#define BPF_FS_PATH "/sys/fs/bpf/"
-
 using android::base::StringPrintf;
 using android::base::unique_fd;
 
 namespace android {
 namespace bpf {
 
-struct time_key_t {
-    uint32_t uid;
-    uint32_t freq;
-};
-
-struct val_t {
-    uint64_t ar[100];
-};
-
 static std::mutex gInitializedMutex;
 static bool gInitialized = false;
 static uint32_t gNPolicies = 0;
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index d4b8738..6347de1 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -1,14 +1,24 @@
 
+#include "timeinstate.h"
+
+#include <sys/sysinfo.h>
+
 #include <unordered_map>
 #include <vector>
 
 #include <gtest/gtest.h>
 
+#include <android-base/unique_fd.h>
+#include <bpf/BpfMap.h>
 #include <cputimeinstate.h>
+#include <libbpf.h>
 
 namespace android {
 namespace bpf {
 
+static constexpr uint64_t NSEC_PER_SEC = 1000000000;
+static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365;
+
 using std::vector;
 
 TEST(TimeInStateTest, SingleUid) {
@@ -33,8 +43,95 @@
     }
 }
 
+TEST(TimeInStateTest, SingleAndAllUidConsistent) {
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
+    ASSERT_FALSE(map->empty());
+
+    for (const auto &kv : *map) {
+        uint32_t uid = kv.first;
+        auto times1 = kv.second;
+        auto times2 = getUidCpuFreqTimes(uid);
+        ASSERT_TRUE(times2.has_value());
+
+        ASSERT_EQ(times1.size(), times2->size());
+        for (uint32_t i = 0; i < times1.size(); ++i) {
+            ASSERT_EQ(times1[i].size(), (*times2)[i].size());
+            for (uint32_t j = 0; j < times1[i].size(); ++j) {
+                ASSERT_LE((*times2)[i][j] - times1[i][j], NSEC_PER_SEC);
+            }
+        }
+    }
+}
+
+void TestCheckDelta(uint64_t before, uint64_t after) {
+    // Times should never decrease
+    ASSERT_LE(before, after);
+    // UID can't have run for more than ~1s on each CPU
+    ASSERT_LE(after - before, NSEC_PER_SEC * 2 * get_nprocs_conf());
+}
+
+TEST(TimeInStateTest, AllUidMonotonic) {
+    auto map1 = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map1.has_value());
+    sleep(1);
+    auto map2 = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map2.has_value());
+
+    for (const auto &kv : *map1) {
+        uint32_t uid = kv.first;
+        auto times = kv.second;
+        ASSERT_NE(map2->find(uid), map2->end());
+        for (uint32_t policy = 0; policy < times.size(); ++policy) {
+            for (uint32_t freqIdx = 0; freqIdx < times[policy].size(); ++freqIdx) {
+                auto before = times[policy][freqIdx];
+                auto after = (*map2)[uid][policy][freqIdx];
+                ASSERT_NO_FATAL_FAILURE(TestCheckDelta(before, after));
+            }
+        }
+    }
+}
+
+TEST(TimeInStateTest, AllUidSanityCheck) {
+    auto map = getUidsCpuFreqTimes();
+    ASSERT_TRUE(map.has_value());
+
+    bool foundLargeValue = false;
+    for (const auto &kv : *map) {
+        for (const auto &timeVec : kv.second) {
+            for (const auto &time : timeVec) {
+                ASSERT_LE(time, NSEC_PER_YEAR);
+                if (time > UINT32_MAX) foundLargeValue = true;
+            }
+        }
+    }
+    // UINT32_MAX nanoseconds is less than 5 seconds, so if every part of our pipeline is using
+    // uint64_t as expected, we should have some times higher than that.
+    ASSERT_TRUE(foundLargeValue);
+}
+
 TEST(TimeInStateTest, RemoveUid) {
-    auto times = getUidCpuFreqTimes(0);
+    uint32_t uid = 0;
+    {
+        // Find an unused UID
+        auto times = getUidsCpuFreqTimes();
+        ASSERT_TRUE(times.has_value());
+        ASSERT_FALSE(times->empty());
+        for (const auto &kv : *times) uid = std::max(uid, kv.first);
+        ++uid;
+    }
+    {
+        // Add a map entry for our fake UID by copying a real map entry
+        android::base::unique_fd fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")};
+        ASSERT_GE(fd, 0);
+        time_key_t k;
+        ASSERT_FALSE(getFirstMapKey(fd, &k));
+        val_t val;
+        ASSERT_FALSE(findMapEntry(fd, &k, &val));
+        k.uid = uid;
+        ASSERT_FALSE(writeToMapEntry(fd, &k, &val, BPF_NOEXIST));
+    }
+    auto times = getUidCpuFreqTimes(uid);
     ASSERT_TRUE(times.has_value());
     ASSERT_FALSE(times->empty());
 
@@ -44,15 +141,12 @@
     }
     ASSERT_GT(sum, (uint64_t)0);
 
-    ASSERT_TRUE(clearUidCpuFreqTimes(0));
+    ASSERT_TRUE(clearUidCpuFreqTimes(uid));
 
-    auto times2 = getUidCpuFreqTimes(0);
-    ASSERT_TRUE(times2.has_value());
-    ASSERT_EQ(times2->size(), times->size());
-    for (size_t i = 0; i < times->size(); ++i) {
-        ASSERT_EQ((*times2)[i].size(), (*times)[i].size());
-        for (size_t j = 0; j < (*times)[i].size(); ++j) ASSERT_LE((*times2)[i][j], (*times)[i][j]);
-    }
+    auto allTimes = getUidsCpuFreqTimes();
+    ASSERT_TRUE(allTimes.has_value());
+    ASSERT_FALSE(allTimes->empty());
+    ASSERT_EQ(allTimes->find(uid), allTimes->end());
 }
 
 } // namespace bpf
diff --git a/libs/cputimeinstate/timeinstate.h b/libs/cputimeinstate/timeinstate.h
new file mode 100644
index 0000000..cf66ae7
--- /dev/null
+++ b/libs/cputimeinstate/timeinstate.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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 <inttypes.h>
+
+#define BPF_FS_PATH "/sys/fs/bpf/"
+
+struct time_key_t {
+    uint32_t uid;
+    uint32_t freq;
+};
+
+struct val_t {
+    uint64_t ar[100];
+};
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index be13707..3eebd34 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -253,9 +253,17 @@
     }
 }
 
-template<typename T, typename U>
-static T getValueByKey(std::unordered_map<U, T>& map, U key) {
-    typename std::unordered_map<U, T>::const_iterator it = map.find(key);
+/**
+ * Find the entry in std::unordered_map by key, and return it.
+ * If the entry is not found, return a default constructed entry.
+ *
+ * Useful when the entries are vectors, since an empty vector will be returned
+ * if the entry is not found.
+ * Also useful when the entries are sp<>. If an entry is not found, nullptr is returned.
+ */
+template <typename T, typename U>
+static T getValueByKey(const std::unordered_map<U, T>& map, U key) {
+    auto it = map.find(key);
     return it != map.end() ? it->second : T{};
 }
 
@@ -3144,14 +3152,7 @@
 
 std::vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(
         int32_t displayId) const {
-    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>::const_iterator it =
-            mWindowHandlesByDisplay.find(displayId);
-    if(it != mWindowHandlesByDisplay.end()) {
-        return it->second;
-    }
-
-    // Return an empty one if nothing found.
-    return std::vector<sp<InputWindowHandle>>();
+    return getValueByKey(mWindowHandlesByDisplay, displayId);
 }
 
 sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
@@ -3193,6 +3194,63 @@
     return mInputChannelsByToken.at(token);
 }
 
+void InputDispatcher::updateWindowHandlesForDisplayLocked(
+        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
+    if (inputWindowHandles.empty()) {
+        // Remove all handles on a display if there are no windows left.
+        mWindowHandlesByDisplay.erase(displayId);
+        return;
+    }
+
+    // Since we compare the pointer of input window handles across window updates, we need
+    // to make sure the handle object for the same window stays unchanged across updates.
+    const std::vector<sp<InputWindowHandle>>& oldHandles = getWindowHandlesLocked(displayId);
+    std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
+    for (const sp<InputWindowHandle>& handle : oldHandles) {
+        oldHandlesByTokens[handle->getToken()] = handle;
+    }
+
+    std::vector<sp<InputWindowHandle>> newHandles;
+    for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
+        if (!handle->updateInfo()) {
+            // handle no longer valid
+            continue;
+        }
+
+        const InputWindowInfo* info = handle->getInfo();
+        if ((getInputChannelLocked(handle->getToken()) == nullptr &&
+             info->portalToDisplayId == ADISPLAY_ID_NONE)) {
+            const bool noInputChannel =
+                    info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
+            const bool canReceiveInput =
+                    !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
+                    !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
+            if (canReceiveInput && !noInputChannel) {
+                ALOGE("Window handle %s has no registered input channel",
+                      handle->getName().c_str());
+            }
+            continue;
+        }
+
+        if (info->displayId != displayId) {
+            ALOGE("Window %s updated by wrong display %d, should belong to display %d",
+                  handle->getName().c_str(), displayId, info->displayId);
+            continue;
+        }
+
+        if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
+            const sp<InputWindowHandle> oldHandle = oldHandlesByTokens.at(handle->getToken());
+            oldHandle->updateFrom(handle);
+            newHandles.push_back(oldHandle);
+        } else {
+            newHandles.push_back(handle);
+        }
+    }
+
+    // Insert or replace
+    mWindowHandlesByDisplay[displayId] = newHandles;
+}
+
 /**
  * Called from InputManagerService, update window handle list by displayId that can receive input.
  * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
@@ -3212,73 +3270,19 @@
         const std::vector<sp<InputWindowHandle>> oldWindowHandles =
                 getWindowHandlesLocked(displayId);
 
+        updateWindowHandlesForDisplayLocked(inputWindowHandles, displayId);
+
         sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
         bool foundHoveredWindow = false;
-
-        if (inputWindowHandles.empty()) {
-            // Remove all handles on a display if there are no windows left.
-            mWindowHandlesByDisplay.erase(displayId);
-        } else {
-            // Since we compare the pointer of input window handles across window updates, we need
-            // to make sure the handle object for the same window stays unchanged across updates.
-            const std::vector<sp<InputWindowHandle>>& oldHandles =
-                    mWindowHandlesByDisplay[displayId];
-            std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
-            for (const sp<InputWindowHandle>& handle : oldHandles) {
-                oldHandlesByTokens[handle->getToken()] = handle;
+        for (const sp<InputWindowHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
+            // Set newFocusedWindowHandle to the top most focused window instead of the last one
+            if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus &&
+                windowHandle->getInfo()->visible) {
+                newFocusedWindowHandle = windowHandle;
             }
-
-            std::vector<sp<InputWindowHandle>> newHandles;
-            for (const sp<InputWindowHandle>& handle : inputWindowHandles) {
-                if (!handle->updateInfo()) {
-                    // handle no longer valid
-                    continue;
-                }
-                const InputWindowInfo* info = handle->getInfo();
-
-                if ((getInputChannelLocked(handle->getToken()) == nullptr &&
-                     info->portalToDisplayId == ADISPLAY_ID_NONE)) {
-                    const bool noInputChannel =
-                            info->inputFeatures & InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL;
-                    const bool canReceiveInput =
-                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_TOUCHABLE) ||
-                            !(info->layoutParamsFlags & InputWindowInfo::FLAG_NOT_FOCUSABLE);
-                    if (canReceiveInput && !noInputChannel) {
-                        ALOGE("Window handle %s has no registered input channel",
-                              handle->getName().c_str());
-                    }
-                    continue;
-                }
-
-                if (info->displayId != displayId) {
-                    ALOGE("Window %s updated by wrong display %d, should belong to display %d",
-                          handle->getName().c_str(), displayId, info->displayId);
-                    continue;
-                }
-
-                if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
-                    const sp<InputWindowHandle> oldHandle =
-                            oldHandlesByTokens.at(handle->getToken());
-                    oldHandle->updateFrom(handle);
-                    newHandles.push_back(oldHandle);
-                } else {
-                    newHandles.push_back(handle);
-                }
+            if (windowHandle == mLastHoverWindowHandle) {
+                foundHoveredWindow = true;
             }
-
-            for (const sp<InputWindowHandle>& windowHandle : newHandles) {
-                // Set newFocusedWindowHandle to the top most focused window instead of the last one
-                if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus
-                        && windowHandle->getInfo()->visible) {
-                    newFocusedWindowHandle = windowHandle;
-                }
-                if (windowHandle == mLastHoverWindowHandle) {
-                    foundHoveredWindow = true;
-                }
-            }
-
-            // Insert or replace
-            mWindowHandlesByDisplay[displayId] = newHandles;
         }
 
         if (!foundHoveredWindow) {
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 46dd9bd..c30a8d6 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -1055,6 +1055,13 @@
     sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const REQUIRES(mLock);
     bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
 
+    /*
+     * Validate and update InputWindowHandles for a given display.
+     */
+    void updateWindowHandlesForDisplayLocked(
+            const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId)
+            REQUIRES(mLock);
+
     // Focus tracking for keys, trackball, etc.
     std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay
             GUARDED_BY(mLock);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ade4ab9..99440a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -358,6 +358,11 @@
     mPropagateBackpressure = !atoi(value);
     ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
 
+    property_get("debug.sf.enable_gl_backpressure", value, "0");
+    mPropagateBackpressureClientComposition = atoi(value);
+    ALOGI_IF(mPropagateBackpressureClientComposition,
+             "Enabling backpressure propagation for Client Composition");
+
     property_get("debug.sf.enable_hwc_vds", value, "0");
     mUseHwcVirtualDisplays = atoi(value);
     ALOGI_IF(mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
@@ -1737,9 +1742,9 @@
                 break;
             }
 
-            // For now, only propagate backpressure when missing a hwc frame.
-            if (hwcFrameMissed && !gpuFrameMissed) {
-                if (mPropagateBackpressure) {
+            if (frameMissed && mPropagateBackpressure) {
+                if ((hwcFrameMissed && !gpuFrameMissed) ||
+                    mPropagateBackpressureClientComposition) {
                     signalLayerUpdate();
                     break;
                 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 294bd8d..0e6eacf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1016,6 +1016,7 @@
     volatile nsecs_t mDebugInTransaction = 0;
     bool mForceFullDamage = false;
     bool mPropagateBackpressure = true;
+    bool mPropagateBackpressureClientComposition = false;
     std::unique_ptr<SurfaceInterceptor> mInterceptor;
     SurfaceTracing mTracing{*this};
     bool mTracingEnabled = false;