Merge "Camera service: Update client eviction priorities"
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f429df8..579e87a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -651,22 +651,6 @@
     return String8(formattedTime);
 }
 
-int CameraService::getCameraPriorityFromProcState(int procState) {
-    // Find the priority for the camera usage based on the process state.  Higher priority clients
-    // win for evictions.
-    if (procState < 0) {
-        ALOGE("%s: Received invalid process state %d from ActivityManagerService!", __FUNCTION__,
-                procState);
-        return -1;
-    }
-    // Treat sleeping TOP processes the same as regular TOP processes, for
-    // access priority.  This is important for lock-screen camera launch scenarios
-    if (procState == PROCESS_STATE_TOP_SLEEPING) {
-        procState = PROCESS_STATE_TOP;
-    }
-    return INT_MAX - procState;
-}
-
 Status CameraService::getCameraVendorTagDescriptor(
         /*out*/
         hardware::camera2::params::VendorTagDescriptor* desc) {
@@ -1212,20 +1196,24 @@
         std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
         ownerPids.push_back(clientPid);
 
-        // Use the value +PROCESS_STATE_NONEXISTENT, to avoid taking
-        // address of PROCESS_STATE_NONEXISTENT as a reference argument
-        // for the vector constructor. PROCESS_STATE_NONEXISTENT does
-        // not have an out-of-class definition.
-        std::vector<int> priorities(ownerPids.size(), +PROCESS_STATE_NONEXISTENT);
+        std::vector<int> priorityScores(ownerPids.size());
+        std::vector<int> states(ownerPids.size());
 
-        // Get priorites of all active PIDs
-        ProcessInfoService::getProcessStatesFromPids(ownerPids.size(), &ownerPids[0],
-                /*out*/&priorities[0]);
+        // Get priority scores of all active PIDs
+        status_t err = ProcessInfoService::getProcessStatesScoresFromPids(
+                ownerPids.size(), &ownerPids[0], /*out*/&states[0],
+                /*out*/&priorityScores[0]);
+        if (err != OK) {
+            ALOGE("%s: Priority score query failed: %d",
+                  __FUNCTION__, err);
+            return err;
+        }
 
         // Update all active clients' priorities
-        std::map<int,int> pidToPriorityMap;
+        std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
         for (size_t i = 0; i < ownerPids.size() - 1; i++) {
-            pidToPriorityMap.emplace(ownerPids[i], getCameraPriorityFromProcState(priorities[i]));
+            pidToPriorityMap.emplace(ownerPids[i],
+                    resource_policy::ClientPriority(priorityScores[i], states[i]));
         }
         mActiveClientManager.updatePriorities(pidToPriorityMap);
 
@@ -1242,7 +1230,9 @@
         clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                 sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                 state->getConflicting(),
-                getCameraPriorityFromProcState(priorities[priorities.size() - 1]), clientPid);
+                priorityScores[priorityScores.size() - 1],
+                clientPid,
+                states[states.size() - 1]);
 
         // Find clients that would be evicted
         auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
@@ -1259,19 +1249,22 @@
                     mActiveClientManager.getIncompatibleClients(clientDescriptor);
 
             String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
-                    "(PID %d, priority %d) due to eviction policy", curTime.string(),
+                    "(PID %d, score %d state %d) due to eviction policy", curTime.string(),
                     cameraId.string(), packageName.string(), clientPid,
-                    getCameraPriorityFromProcState(priorities[priorities.size() - 1]));
+                    priorityScores[priorityScores.size() - 1],
+                    states[states.size() - 1]);
 
             for (auto& i : incompatibleClients) {
                 msg.appendFormat("\n   - Blocked by existing device %s client for package %s"
-                        "(PID %" PRId32 ", priority %" PRId32 ")", i->getKey().string(),
-                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
-                        i->getPriority());
+                        "(PID %" PRId32 ", score %" PRId32 ", state %" PRId32 ")",
+                        i->getKey().string(),
+                        String8{i->getValue()->getPackageName()}.string(),
+                        i->getOwnerId(), i->getPriority().getScore(),
+                        i->getPriority().getState());
                 ALOGE("   Conflicts with: Device %s, client package %s (PID %"
-                        PRId32 ", priority %" PRId32 ")", i->getKey().string(),
+                        PRId32 ", score %" PRId32 ", state %" PRId32 ")", i->getKey().string(),
                         String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
-                        i->getPriority());
+                        i->getPriority().getScore(), i->getPriority().getState());
             }
 
             // Log the client's attempt
@@ -1299,12 +1292,14 @@
 
             // Log the clients evicted
             logEvent(String8::format("EVICT device %s client held by package %s (PID"
-                    " %" PRId32 ", priority %" PRId32 ")\n   - Evicted by device %s client for"
-                    " package %s (PID %d, priority %" PRId32 ")",
+                    " %" PRId32 ", score %" PRId32 ", state %" PRId32 ")\n - Evicted by device %s client for"
+                    " package %s (PID %d, score %" PRId32 ", state %" PRId32 ")",
                     i->getKey().string(), String8{clientSp->getPackageName()}.string(),
-                    i->getOwnerId(), i->getPriority(), cameraId.string(),
+                    i->getOwnerId(), i->getPriority().getScore(),
+                    i->getPriority().getState(), cameraId.string(),
                     packageName.string(), clientPid,
-                    getCameraPriorityFromProcState(priorities[priorities.size() - 1])));
+                    priorityScores[priorityScores.size() - 1],
+                    states[states.size() - 1]));
 
             // Notify the client of disconnection
             clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
@@ -2142,9 +2137,11 @@
 
         // Log the clients evicted
         logEvent(String8::format("EVICT device %s client held by package %s (PID %"
-                PRId32 ", priority %" PRId32 ")\n   - Evicted due to user switch.",
-                i->getKey().string(), String8{clientSp->getPackageName()}.string(),
-                i->getOwnerId(), i->getPriority()));
+                PRId32 ", score %" PRId32 ", state %" PRId32 ")\n   - Evicted due"
+                " to user switch.", i->getKey().string(),
+                String8{clientSp->getPackageName()}.string(),
+                i->getOwnerId(), i->getPriority().getScore(),
+                i->getPriority().getState()));
 
     }
 
@@ -2680,7 +2677,8 @@
         String8 key = i->getKey();
         int32_t cost = i->getCost();
         int32_t pid = i->getOwnerId();
-        int32_t priority = i->getPriority();
+        int32_t score = i->getPriority().getScore();
+        int32_t state = i->getPriority().getState();
         auto conflicting = i->getConflicting();
         auto clientSp = i->getValue();
         String8 packageName;
@@ -2690,8 +2688,8 @@
             uid_t clientUid = clientSp->getClientUid();
             clientUserId = multiuser_get_user_id(clientUid);
         }
-        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"
-                PRId32 ", ", key.string(), cost, pid, priority);
+        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Score: %"
+                PRId32 ", State: %" PRId32, key.string(), cost, pid, score, state);
 
         if (clientSp.get() != nullptr) {
             ret.appendFormat("User Id: %d, ", clientUserId);
@@ -2713,16 +2711,18 @@
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const String8& key, const sp<BasicClient>& value, int32_t cost,
-        const std::set<String8>& conflictingKeys, int32_t priority, int32_t ownerId) {
+        const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
+        int32_t state) {
 
     return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
-            key, value, cost, conflictingKeys, priority, ownerId);
+            key, value, cost, conflictingKeys, score, ownerId, state);
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
         const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial) {
     return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
-            partial->getConflicting(), partial->getPriority(), partial->getOwnerId());
+            partial->getConflicting(), partial->getPriority().getScore(),
+            partial->getOwnerId(), partial->getPriority().getState());
 }
 
 // ----------------------------------------------------------------------------
@@ -2800,7 +2800,9 @@
         }
         dprintf(fd, "  Device %s is open. Client instance dump:\n",
                 cameraId.string());
-        dprintf(fd, "    Client priority level: %d\n", clientDescriptor->getPriority());
+        dprintf(fd, "    Client priority score: %d state: %d\n",
+                clientDescriptor->getPriority().getScore(),
+                clientDescriptor->getPriority().getState());
         dprintf(fd, "    Client PID: %d\n", clientDescriptor->getOwnerId());
 
         auto client = clientDescriptor->getValue();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d463b59..c7acdc9 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -75,11 +75,6 @@
         API_2 = 2
     };
 
-    // Process state (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
-    static const int PROCESS_STATE_NONEXISTENT = -1;
-    static const int PROCESS_STATE_TOP = 2;
-    static const int PROCESS_STATE_TOP_SLEEPING = 5;
-
     // 3 second busy timeout when other clients are connecting
     static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
 
@@ -402,8 +397,8 @@
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer.
          */
         static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
-                int32_t cost, const std::set<String8>& conflictingKeys, int32_t priority,
-                int32_t ownerId);
+                int32_t cost, const std::set<String8>& conflictingKeys, int32_t score,
+                int32_t ownerId, int32_t state);
 
         /**
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
@@ -775,11 +770,6 @@
      */
     static String8 getFormattedCurrentTime();
 
-    /**
-     * Get the camera eviction priority from the current process state given by ActivityManager.
-     */
-    static int getCameraPriorityFromProcState(int procState);
-
     static binder::Status makeClient(const sp<CameraService>& cameraService,
             const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
             int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 830c50b..d7135f1 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -31,6 +31,43 @@
 namespace android {
 namespace resource_policy {
 
+class ClientPriority {
+public:
+    ClientPriority(int32_t score, int32_t state) :
+        mScore(score), mState(state) {}
+
+    int32_t getScore() const { return mScore; }
+    int32_t getState() const { return mState; }
+
+    bool operator==(const ClientPriority& rhs) const {
+        return (this->mScore == rhs.mScore) && (this->mState == rhs.mState);
+    }
+
+    bool operator< (const ClientPriority& rhs)  const {
+        if (this->mScore == rhs.mScore) {
+            return this->mState < rhs.mState;
+        } else {
+            return this->mScore < rhs.mScore;
+        }
+    }
+
+    bool operator> (const ClientPriority& rhs) const {
+        return rhs < *this;
+    }
+
+    bool operator<=(const ClientPriority& rhs) const {
+        return !(*this > rhs);
+    }
+
+    bool operator>=(const ClientPriority& rhs) const {
+        return !(*this < rhs);
+    }
+
+private:
+        int32_t mScore;
+        int32_t mState;
+};
+
 // --------------------------------------------------------------------------------
 
 /**
@@ -45,9 +82,9 @@
 class ClientDescriptor final {
 public:
     ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
-            const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId);
+            const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state);
     ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
-            int32_t priority, int32_t ownerId);
+            int32_t score, int32_t ownerId, int32_t state);
 
     ~ClientDescriptor();
 
@@ -69,7 +106,7 @@
     /**
      * Return the priority for this descriptor.
      */
-    int32_t getPriority() const;
+    const ClientPriority &getPriority() const;
 
     /**
      * Return the owner ID for this descriptor.
@@ -89,7 +126,7 @@
     /**
      * Set the proirity for this descriptor.
      */
-    void setPriority(int32_t priority);
+    void setPriority(const ClientPriority& priority);
 
     // This class is ordered by key
     template<class K, class V>
@@ -100,7 +137,7 @@
     VALUE mValue;
     int32_t mCost;
     std::set<KEY> mConflicting;
-    int32_t mPriority;
+    ClientPriority mPriority;
     int32_t mOwnerId;
 }; // class ClientDescriptor
 
@@ -111,16 +148,17 @@
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
-        const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId) : mKey{key},
-        mValue{value}, mCost{cost}, mConflicting{conflictingKeys}, mPriority{priority},
+        const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
+        mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
+        mPriority(score, state),
         mOwnerId{ownerId} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
-        std::set<KEY>&& conflictingKeys, int32_t priority, int32_t ownerId) :
+        std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state) :
         mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
-        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)}, mPriority{priority},
-        mOwnerId{ownerId} {}
+        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
+        mPriority(score, state), mOwnerId{ownerId} {}
 
 template<class KEY, class VALUE>
 ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -141,7 +179,7 @@
 }
 
 template<class KEY, class VALUE>
-int32_t ClientDescriptor<KEY, VALUE>::getPriority() const {
+const ClientPriority& ClientDescriptor<KEY, VALUE>::getPriority() const {
     return mPriority;
 }
 
@@ -165,7 +203,7 @@
 }
 
 template<class KEY, class VALUE>
-void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
+void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
     mPriority = priority;
 }
 
@@ -231,7 +269,7 @@
      * Given a map containing owner (pid) -> priority mappings, update the priority of each
      * ClientDescriptor with an owner in this mapping.
      */
-    void updatePriorities(const std::map<int32_t,int32_t>& ownerPriorityList);
+    void updatePriorities(const std::map<int32_t,ClientPriority>& ownerPriorityList);
 
     /**
      * Remove all ClientDescriptors.
@@ -383,17 +421,17 @@
 
     const KEY& key = client->getKey();
     int32_t cost = client->getCost();
-    int32_t priority = client->getPriority();
+    ClientPriority priority = client->getPriority();
     int32_t owner = client->getOwnerId();
 
     int64_t totalCost = getCurrentCostLocked() + cost;
 
     // Determine the MRU of the owners tied for having the highest priority
     int32_t highestPriorityOwner = owner;
-    int32_t highestPriority = priority;
+    ClientPriority highestPriority = priority;
     for (const auto& i : mClients) {
-        int32_t curPriority = i->getPriority();
-        if (curPriority >= highestPriority) {
+        ClientPriority curPriority = i->getPriority();
+        if (curPriority <= highestPriority) {
             highestPriority = curPriority;
             highestPriorityOwner = i->getOwnerId();
         }
@@ -408,7 +446,7 @@
     for (const auto& i : mClients) {
         const KEY& curKey = i->getKey();
         int32_t curCost = i->getCost();
-        int32_t curPriority = i->getPriority();
+        ClientPriority curPriority = i->getPriority();
         int32_t curOwner = i->getOwnerId();
 
         bool conflicting = (curKey == key || i->isConflicting(key) ||
@@ -417,13 +455,13 @@
         if (!returnIncompatibleClients) {
             // Find evicted clients
 
-            if (conflicting && curPriority > priority) {
+            if (conflicting && curPriority < priority) {
                 // Pre-existing conflicting client with higher priority exists
                 evictList.clear();
                 evictList.push_back(client);
                 return evictList;
             } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
-                    (curPriority <= priority) &&
+                    (curPriority >= priority) &&
                     !(highestPriorityOwner == owner && owner == curOwner))) {
                 // Add a pre-existing client to the eviction list if:
                 // - We are adding a client with higher priority that conflicts with this one.
@@ -437,7 +475,7 @@
         } else {
             // Find clients preventing the incoming client from being added
 
-            if (curPriority > priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
+            if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
                 // Pre-existing conflicting client with higher priority exists
                 evictList.push_back(i);
             }
@@ -524,7 +562,7 @@
 
 template<class KEY, class VALUE, class LISTENER>
 void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
-        const std::map<int32_t,int32_t>& ownerPriorityList) {
+        const std::map<int32_t,ClientPriority>& ownerPriorityList) {
     Mutex::Autolock lock(mLock);
     for (auto& i : mClients) {
         auto j = ownerPriorityList.find(i->getOwnerId());