• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
18 #define ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
19 
20 #include <utils/Condition.h>
21 #include <utils/Mutex.h>
22 #include <utils/Timers.h>
23 #include <utils/Log.h>
24 
25 #include <algorithm>
26 #include <utility>
27 #include <vector>
28 #include <set>
29 #include <map>
30 #include <memory>
31 #include <com_android_internal_camera_flags.h>
32 
33 namespace flags = com::android::internal::camera::flags;
34 
35 namespace android {
36 namespace resource_policy {
37 
38 // Values from frameworks/base/services/core/java/com/android/server/am/ProcessList.java
39 const int32_t INVALID_ADJ = -10000;
40 const int32_t UNKNOWN_ADJ = 1001;
41 const int32_t CACHED_APP_MAX_ADJ = 999;
42 const int32_t CACHED_APP_MIN_ADJ = 900;
43 const int32_t CACHED_APP_LMK_FIRST_ADJ = 950;
44 const int32_t CACHED_APP_IMPORTANCE_LEVELS = 5;
45 const int32_t SERVICE_B_ADJ = 800;
46 const int32_t PREVIOUS_APP_ADJ = 700;
47 const int32_t HOME_APP_ADJ = 600;
48 const int32_t SERVICE_ADJ = 500;
49 const int32_t HEAVY_WEIGHT_APP_ADJ = 400;
50 const int32_t BACKUP_APP_ADJ = 300;
51 const int32_t PERCEPTIBLE_LOW_APP_ADJ = 250;
52 const int32_t PERCEPTIBLE_MEDIUM_APP_ADJ = 225;
53 const int32_t PERCEPTIBLE_APP_ADJ = 200;
54 const int32_t VISIBLE_APP_ADJ = 100;
55 const int32_t VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
56 const int32_t PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
57 const int32_t FOREGROUND_APP_ADJ = 0;
58 const int32_t PERSISTENT_SERVICE_ADJ = -700;
59 const int32_t PERSISTENT_PROC_ADJ = -800;
60 const int32_t SYSTEM_ADJ = -900;
61 const int32_t NATIVE_ADJ = -1000;
62 
63 class ClientPriority {
64 public:
65     /**
66      * Choosing to set mIsVendorClient through a parameter instead of calling
67      * getCurrentServingCall() == BinderCallType::HWBINDER to protect against the
68      * case where the construction is offloaded to another thread which isn't a
69      * hwbinder thread.
70      */
71     ClientPriority(int32_t score, int32_t state, bool isVendorClient, int32_t scoreOffset = 0) :
mIsVendorClient(isVendorClient)72             mIsVendorClient(isVendorClient), mScoreOffset(scoreOffset) {
73         setScore(score);
74         setState(state);
75     }
76 
getScore()77     int32_t getScore() const { return mScore; }
getState()78     int32_t getState() const { return mState; }
isVendorClient()79     int32_t isVendorClient() const { return mIsVendorClient; }
80 
setScore(int32_t score)81     void setScore(int32_t score) {
82         // For vendor clients, the score is set once and for all during
83         // construction. Otherwise, it can get reset each time cameraserver
84         // queries ActivityManagerService for oom_adj scores / states .
85         // For clients where the score offset is set by the app, add it to the
86         // score provided by ActivityManagerService.
87         if (score == INVALID_ADJ) {
88             mScore = UNKNOWN_ADJ;
89         } else {
90             mScore = mScoreOffset + score;
91         }
92     }
93 
setState(int32_t state)94     void setState(int32_t state) {
95       // For vendor clients, the score is set once and for all during
96       // construction. Otherwise, it can get reset each time cameraserver
97       // queries ActivityManagerService for oom_adj scores / states
98       // (ActivityManagerService returns a vendor process' state as
99       // PROCESS_STATE_NONEXISTENT.
100       mState = state;
101     }
102 
103     bool operator==(const ClientPriority& rhs) const {
104         return (this->mScore == rhs.mScore) && (this->mState == rhs.mState);
105     }
106 
107     bool operator< (const ClientPriority& rhs)  const {
108         if (this->mScore == rhs.mScore) {
109             return this->mState < rhs.mState;
110         } else {
111             return this->mScore < rhs.mScore;
112         }
113     }
114 
115     bool operator> (const ClientPriority& rhs) const {
116         return rhs < *this;
117     }
118 
119     bool operator<=(const ClientPriority& rhs) const {
120         return !(*this > rhs);
121     }
122 
123     bool operator>=(const ClientPriority& rhs) const {
124         return !(*this < rhs);
125     }
126 
127 private:
128         int32_t mScore;
129         int32_t mState;
130         bool mIsVendorClient = false;
131         int32_t mScoreOffset = 0;
132 };
133 
134 // --------------------------------------------------------------------------------
135 
136 /**
137  * The ClientDescriptor class is a container for a given key/value pair identifying a shared
138  * resource, and the corresponding cost, priority, owner ID, and conflicting keys list used
139  * in determining eviction behavior.
140  *
141  * Aside from the priority, these values are immutable once the ClientDescriptor has been
142  * constructed.
143  */
144 template<class KEY, class VALUE>
145 class ClientDescriptor final {
146 public:
147     ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
148             const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
149             bool isVendorClient, int32_t oomScoreOffset, bool sharedMode = false);
150     ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
151             int32_t score, int32_t ownerId, int32_t state, bool isVendorClient,
152             int32_t oomScoreOffset, bool sharedMode = false);
153 
154     ~ClientDescriptor();
155 
156     /**
157      * Return the key for this descriptor.
158      */
159     const KEY& getKey() const;
160 
161     /**
162      * Return the value for this descriptor.
163      */
164     const VALUE& getValue() const;
165 
166     /**
167      * Return the cost for this descriptor.
168      */
169     int32_t getCost() const;
170 
171     /**
172      * Return the priority for this descriptor.
173      */
174     const ClientPriority &getPriority() const;
175 
176     /**
177      * Return the owner ID for this descriptor.
178      */
179     int32_t getOwnerId() const;
180 
181     /**
182      * Return true if the given key is in this descriptor's conflicting keys list.
183      */
184     bool isConflicting(const KEY& key) const;
185 
186     /**
187      * Return the set of all conflicting keys for this descriptor.
188      */
189     std::set<KEY> getConflicting() const;
190 
191     /**
192      * Set the proirity for this descriptor.
193      */
194     void setPriority(const ClientPriority& priority);
195 
196     /**
197      * Returns true when camera is opened in shared mode.
198      */
199     bool getSharedMode() const;
200 
201     // This class is ordered by key
202     template<class K, class V>
203     friend bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b);
204 
205 private:
206     KEY mKey;
207     VALUE mValue;
208     int32_t mCost;
209     std::set<KEY> mConflicting;
210     ClientPriority mPriority;
211     int32_t mOwnerId;
212     bool mSharedMode;
213 }; // class ClientDescriptor
214 
215 template<class K, class V>
216 bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b) {
217     return a.mKey < b.mKey;
218 }
219 
220 template<class KEY, class VALUE>
ClientDescriptor(const KEY & key,const VALUE & value,int32_t cost,const std::set<KEY> & conflictingKeys,int32_t score,int32_t ownerId,int32_t state,bool isVendorClient,int32_t scoreOffset,bool sharedMode)221 ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
222         const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
223         bool isVendorClient, int32_t scoreOffset, bool sharedMode) :
224         mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
225         mPriority(score, state, isVendorClient, scoreOffset),
226         mOwnerId{ownerId}, mSharedMode{sharedMode} {}
227 
228 template<class KEY, class VALUE>
ClientDescriptor(KEY && key,VALUE && value,int32_t cost,std::set<KEY> && conflictingKeys,int32_t score,int32_t ownerId,int32_t state,bool isVendorClient,int32_t scoreOffset,bool sharedMode)229 ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
230         std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
231         bool isVendorClient, int32_t scoreOffset, bool sharedMode) :
232         mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
233         mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
234         mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId},
235         mSharedMode{sharedMode} {}
236 
237 template<class KEY, class VALUE>
~ClientDescriptor()238 ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
239 
240 template<class KEY, class VALUE>
getKey()241 const KEY& ClientDescriptor<KEY, VALUE>::getKey() const {
242     return mKey;
243 }
244 
245 template<class KEY, class VALUE>
getValue()246 const VALUE& ClientDescriptor<KEY, VALUE>::getValue() const {
247     return mValue;
248 }
249 
250 template<class KEY, class VALUE>
getCost()251 int32_t ClientDescriptor<KEY, VALUE>::getCost() const {
252     return mCost;
253 }
254 
255 template<class KEY, class VALUE>
getPriority()256 const ClientPriority& ClientDescriptor<KEY, VALUE>::getPriority() const {
257     return mPriority;
258 }
259 
260 template<class KEY, class VALUE>
getOwnerId()261 int32_t ClientDescriptor<KEY, VALUE>::getOwnerId() const {
262     return mOwnerId;
263 }
264 
265 template<class KEY, class VALUE>
isConflicting(const KEY & key)266 bool ClientDescriptor<KEY, VALUE>::isConflicting(const KEY& key) const {
267     if (flags::camera_multi_client()) {
268         // In shared mode, there can be more than one client using the camera.
269         // Hence, having more than one client with the same key is not considered as
270         // conflicting.
271         if (!mSharedMode && key == mKey) return true;
272     } else {
273         if (key == mKey) return true;
274     }
275     for (const auto& x : mConflicting) {
276         if (key == x) return true;
277     }
278     return false;
279 }
280 
281 template<class KEY, class VALUE>
getConflicting()282 std::set<KEY> ClientDescriptor<KEY, VALUE>::getConflicting() const {
283     return mConflicting;
284 }
285 
286 template<class KEY, class VALUE>
getSharedMode()287 bool ClientDescriptor<KEY, VALUE>::getSharedMode() const {
288     return mSharedMode;
289 }
290 
291 template<class KEY, class VALUE>
setPriority(const ClientPriority & priority)292 void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
293     // We don't use the usual copy constructor here since we want to remember
294     // whether a client is a vendor client or not. This could have been wiped
295     // off in the incoming priority argument since an AIDL thread might have
296     // called getCurrentServingCall() == BinderCallType::HWBINDER after refreshing
297     // priorities for old clients through ProcessInfoService::getProcessStatesScoresFromPids().
298     if (mPriority.isVendorClient()) {
299         return;
300     }
301     mPriority.setScore(priority.getScore());
302     mPriority.setState(priority.getState());
303 }
304 
305 // --------------------------------------------------------------------------------
306 
307 /**
308  * A default class implementing the LISTENER interface used by ClientManager.
309  */
310 template<class KEY, class VALUE>
311 class DefaultEventListener {
312 public:
313     void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
314     void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
315 };
316 
317 template<class KEY, class VALUE>
onClientAdded(const ClientDescriptor<KEY,VALUE> &)318 void DefaultEventListener<KEY, VALUE>::onClientAdded(
319         const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}
320 
321 template<class KEY, class VALUE>
onClientRemoved(const ClientDescriptor<KEY,VALUE> &)322 void DefaultEventListener<KEY, VALUE>::onClientRemoved(
323         const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}
324 
325 // --------------------------------------------------------------------------------
326 
327 /**
328  * The ClientManager class wraps an LRU-ordered list of active clients and implements eviction
329  * behavior for handling shared resource access.
330  *
331  * When adding a new descriptor, eviction behavior is as follows:
332  *   - Keys are unique, adding a descriptor with the same key as an existing descriptor will
333  *     result in the lower-priority of the two being removed.  Priority ties result in the
334  *     LRU descriptor being evicted (this means the incoming descriptor be added in this case).
335  *   - Any descriptors with keys that are in the incoming descriptor's 'conflicting keys' list
336  *     will be removed if they have an equal or lower priority than the incoming descriptor;
337  *     if any have a higher priority, the incoming descriptor is removed instead.
338  *   - If the sum of all descriptors' costs, including the incoming descriptor's, is more than
339  *     the max cost allowed for this ClientManager, descriptors with non-zero cost, equal or lower
340  *     priority, and a different owner will be evicted in LRU order until either the cost is less
341  *     than the max cost, or all descriptors meeting this criteria have been evicted and the
342  *     incoming descriptor has the highest priority.  Otherwise, the incoming descriptor is
343  *     removed instead.
344  */
345 template<class KEY, class VALUE, class LISTENER=DefaultEventListener<KEY, VALUE>>
346 class ClientManager {
347 public:
348     // The default maximum "cost" allowed before evicting
349     static constexpr int32_t DEFAULT_MAX_COST = 100;
350 
351     ClientManager();
352     explicit ClientManager(int32_t totalCost);
353 
354     /**
355      * Add a given ClientDescriptor to the managed list.  ClientDescriptors for clients that
356      * are evicted by this action are returned in a vector.
357      *
358      * This may return the ClientDescriptor passed in if it would be evicted.
359      */
360     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> addAndEvict(
361             const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client);
362 
363     /**
364      * Given a map containing owner (pid) -> priority mappings, update the priority of each
365      * ClientDescriptor with an owner in this mapping.
366      */
367     void updatePriorities(const std::map<int32_t,ClientPriority>& ownerPriorityList);
368 
369     /**
370      * Remove all ClientDescriptors.
371      */
372     void removeAll();
373 
374     /**
375      * Remove all ClientDescriptors with a given key.
376      */
377     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> removeAll(const KEY& key);
378 
379     /**
380      * Remove and return the ClientDescriptors with a given key.
381      */
382     std::shared_ptr<ClientDescriptor<KEY, VALUE>> remove(const KEY& key);
383 
384     /**
385      * Remove the given ClientDescriptor.
386      */
387     virtual void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);
388 
389     /**
390      * Return a vector of the ClientDescriptors that would be evicted by adding the given
391      * ClientDescriptor.
392      *
393      * This may return the ClientDescriptor passed in if it would be evicted.
394      */
395     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvict(
396             const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const;
397 
398     /**
399      * Return a vector of active ClientDescriptors that prevent this client from being added.
400      */
401     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> getIncompatibleClients(
402             const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const;
403 
404     /**
405      * Return a vector containing all currently active ClientDescriptors.
406      */
407     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> getAll() const;
408 
409     /**
410      * Return a vector containing all keys of currently active ClientDescriptors.
411      */
412     std::vector<KEY> getAllKeys() const;
413 
414     /**
415      * Return a vector of the owner tags of all currently active ClientDescriptors (duplicates
416      * will be removed).
417      */
418     std::vector<int32_t> getAllOwners() const;
419 
420     /**
421      * Return the ClientDescriptor for a client which has opened the camera in
422      * shared mode corresponding to the given pid.
423      */
424     std::shared_ptr<ClientDescriptor<KEY, VALUE>> getSharedClient(int pid) const;
425 
426     /**
427      * Return the ClientDescriptor corresponding to the given key, or an empty shared pointer
428      * if none exists.
429      */
430     std::shared_ptr<ClientDescriptor<KEY, VALUE>> get(const KEY& key) const;
431 
432     std::shared_ptr<ClientDescriptor<KEY, VALUE>> getPrimaryClient(const KEY& key) const;
433 
434     /**
435      * Block until the given client is no longer in the active clients list, or the timeout
436      * occurred.
437      *
438      * Returns NO_ERROR if this succeeded, -ETIMEDOUT on a timeout, or a negative error code on
439      * failure.
440      */
441     status_t waitUntilRemoved(const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
442             nsecs_t timeout) const;
443 
444     /**
445      * Set the current listener for client add/remove events.
446      *
447      * The listener instance must inherit from the LISTENER class and implement the following
448      * methods:
449      *    void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
450      *    void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
451      *
452      * These callback methods will be called with the ClientManager's lock held, and should
453      * not call any further ClientManager methods.
454      *
455      * The onClientRemoved method will be called when the client has been removed or evicted
456      * from the ClientManager that this event listener has been added to. The onClientAdded
457      * method will be called when the client has been added to the ClientManager that this
458      * event listener has been added to.
459      */
460     void setListener(const std::shared_ptr<LISTENER>& listener);
461 
462 protected:
463     ~ClientManager();
464 
465 private:
466 
467     /**
468      * Return a vector of the ClientDescriptors that would be evicted by adding the given
469      * ClientDescriptor.  If returnIncompatibleClients is set to true, instead, return the
470      * vector of ClientDescriptors that are higher priority than the incoming client and
471      * either conflict with this client, or contribute to the resource cost if that would
472      * prevent the incoming client from being added.
473      *
474      * This may return the ClientDescriptor passed in.
475      */
476     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvictLocked(
477             const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
478             bool returnIncompatibleClients = false) const;
479 
480     int64_t getCurrentCostLocked() const;
481 
482     mutable Mutex mLock;
483     mutable Condition mRemovedCondition;
484     int32_t mMaxCost;
485     // LRU ordered, most recent at end
486     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> mClients;
487     std::shared_ptr<LISTENER> mListener;
488 }; // class ClientManager
489 
490 template<class KEY, class VALUE, class LISTENER>
ClientManager()491 ClientManager<KEY, VALUE, LISTENER>::ClientManager() :
492         ClientManager(DEFAULT_MAX_COST) {}
493 
494 template<class KEY, class VALUE, class LISTENER>
ClientManager(int32_t totalCost)495 ClientManager<KEY, VALUE, LISTENER>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}
496 
497 template<class KEY, class VALUE, class LISTENER>
~ClientManager()498 ClientManager<KEY, VALUE, LISTENER>::~ClientManager() {}
499 
500 template<class KEY, class VALUE, class LISTENER>
501 std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
wouldEvict(const std::shared_ptr<ClientDescriptor<KEY,VALUE>> & client)502 ClientManager<KEY, VALUE, LISTENER>::wouldEvict(
503         const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
504     Mutex::Autolock lock(mLock);
505     return wouldEvictLocked(client);
506 }
507 
508 template<class KEY, class VALUE, class LISTENER>
509 std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
getIncompatibleClients(const std::shared_ptr<ClientDescriptor<KEY,VALUE>> & client)510 ClientManager<KEY, VALUE, LISTENER>::getIncompatibleClients(
511         const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
512     Mutex::Autolock lock(mLock);
513     return wouldEvictLocked(client, /*returnIncompatibleClients*/true);
514 }
515 
516 template<class KEY, class VALUE, class LISTENER>
517 std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
wouldEvictLocked(const std::shared_ptr<ClientDescriptor<KEY,VALUE>> & client,bool returnIncompatibleClients)518 ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
519         const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
520         bool returnIncompatibleClients) const {
521 
522     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> evictList;
523 
524     // Disallow null clients, return input
525     if (client == nullptr) {
526         evictList.push_back(client);
527         return evictList;
528     }
529 
530     const KEY& key = client->getKey();
531     int32_t cost = client->getCost();
532     ClientPriority priority = client->getPriority();
533     int32_t owner = client->getOwnerId();
534     bool sharedMode = client->getSharedMode();
535 
536 
537     int64_t totalCost = getCurrentCostLocked() + cost;
538 
539     // Determine the MRU of the owners tied for having the highest priority
540     int32_t highestPriorityOwner = owner;
541     ClientPriority highestPriority = priority;
542     for (const auto& i : mClients) {
543         ClientPriority curPriority = i->getPriority();
544         if (curPriority <= highestPriority) {
545             highestPriority = curPriority;
546             highestPriorityOwner = i->getOwnerId();
547         }
548     }
549 
550     if (highestPriority == priority) {
551         // Switch back owner if the incoming client has the highest priority, as it is MRU
552         highestPriorityOwner = owner;
553     }
554 
555     // Build eviction list of clients to remove
556     for (const auto& i : mClients) {
557         const KEY& curKey = i->getKey();
558         int32_t curCost = i->getCost();
559         ClientPriority curPriority = i->getPriority();
560         int32_t curOwner = i->getOwnerId();
561         bool curSharedMode = i->getSharedMode();
562         bool conflicting;
563         if (flags::camera_multi_client()) {
564             conflicting = (((!sharedMode || !curSharedMode) && curKey == key)
565                     || i->isConflicting(key) || client->isConflicting(curKey));
566         } else {
567             conflicting = (curKey == key || i->isConflicting(key) ||
568                     client->isConflicting(curKey));
569         }
570 
571         if (!returnIncompatibleClients) {
572             // Find evicted clients
573 
574             if (conflicting && owner == curOwner) {
575                 // Pre-existing conflicting client with the same client owner exists
576                 // Open the same device twice -> most recent open wins
577                 // Otherwise let the existing client wins to avoid behaviors difference
578                 // due to how HAL advertising conflicting devices (which is hidden from
579                 // application)
580                 if (curKey == key) {
581                     evictList.push_back(i);
582                     totalCost -= curCost;
583                 } else {
584                     evictList.clear();
585                     evictList.push_back(client);
586                     return evictList;
587                 }
588             } else if (conflicting && curPriority < priority) {
589                 // Pre-existing conflicting client with higher priority exists
590                 evictList.clear();
591                 evictList.push_back(client);
592                 return evictList;
593             } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
594                     (curPriority >= priority) &&
595                     !(highestPriorityOwner == owner && owner == curOwner))) {
596                 // Add a pre-existing client to the eviction list if:
597                 // - We are adding a client with higher priority that conflicts with this one.
598                 // - The total cost including the incoming client's is more than the allowable
599                 //   maximum, and the client has a non-zero cost, lower priority, and a different
600                 //   owner than the incoming client when the incoming client has the
601                 //   highest priority.
602                 evictList.push_back(i);
603                 totalCost -= curCost;
604             }
605         } else {
606             // Find clients preventing the incoming client from being added
607 
608             if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
609                 // Pre-existing conflicting client with higher priority exists
610                 evictList.push_back(i);
611             }
612         }
613     }
614 
615     // Immediately return the incompatible clients if we are calculating these instead
616     if (returnIncompatibleClients) {
617         return evictList;
618     }
619 
620     // If the total cost is too high, return the input unless the input has the highest priority
621     if (totalCost > mMaxCost && highestPriorityOwner != owner) {
622         evictList.clear();
623         evictList.push_back(client);
624         return evictList;
625     }
626 
627     return evictList;
628 
629 }
630 
631 template<class KEY, class VALUE, class LISTENER>
632 std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
addAndEvict(const std::shared_ptr<ClientDescriptor<KEY,VALUE>> & client)633 ClientManager<KEY, VALUE, LISTENER>::addAndEvict(
634         const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) {
635     Mutex::Autolock lock(mLock);
636     auto evicted = wouldEvictLocked(client);
637     auto it = evicted.begin();
638     if (it != evicted.end() && *it == client) {
639         return evicted;
640     }
641 
642     auto iter = evicted.cbegin();
643 
644     if (iter != evicted.cend()) {
645 
646         if (mListener != nullptr) mListener->onClientRemoved(**iter);
647 
648         // Remove evicted clients from list
649         mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
650             [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
651                 if (curClientPtr->getKey() == (*iter)->getKey()) {
652                     iter++;
653                     return true;
654                 }
655                 return false;
656             }), mClients.end());
657     }
658 
659     if (mListener != nullptr) mListener->onClientAdded(*client);
660     mClients.push_back(client);
661     mRemovedCondition.broadcast();
662 
663     return evicted;
664 }
665 
666 template<class KEY, class VALUE, class LISTENER>
667 std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
getAll()668 ClientManager<KEY, VALUE, LISTENER>::getAll() const {
669     Mutex::Autolock lock(mLock);
670     return mClients;
671 }
672 
673 template<class KEY, class VALUE, class LISTENER>
getAllKeys()674 std::vector<KEY> ClientManager<KEY, VALUE, LISTENER>::getAllKeys() const {
675     Mutex::Autolock lock(mLock);
676     std::vector<KEY> keys(mClients.size());
677     for (const auto& i : mClients) {
678         keys.push_back(i->getKey());
679     }
680     return keys;
681 }
682 
683 template<class KEY, class VALUE, class LISTENER>
getAllOwners()684 std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {
685     Mutex::Autolock lock(mLock);
686     std::set<int32_t> owners;
687     for (const auto& i : mClients) {
688         owners.emplace(i->getOwnerId());
689     }
690     return std::vector<int32_t>(owners.begin(), owners.end());
691 }
692 
693 template<class KEY, class VALUE, class LISTENER>
getSharedClient(int pid)694 std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::getSharedClient(
695         int pid) const {
696     Mutex::Autolock lock(mLock);
697     if (flags::camera_multi_client()) {
698         for (const auto& i : mClients) {
699             if ((i->getOwnerId() == pid) && (i->getSharedMode())) {
700                 return i;
701             }
702         }
703     }
704     return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
705 }
706 
707 template<class KEY, class VALUE, class LISTENER>
updatePriorities(const std::map<int32_t,ClientPriority> & ownerPriorityList)708 void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
709         const std::map<int32_t,ClientPriority>& ownerPriorityList) {
710     Mutex::Autolock lock(mLock);
711     for (auto& i : mClients) {
712         auto j = ownerPriorityList.find(i->getOwnerId());
713         if (j != ownerPriorityList.end()) {
714             i->setPriority(j->second);
715         }
716     }
717 }
718 
719 template<class KEY, class VALUE, class LISTENER>
get(const KEY & key)720 std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::get(
721         const KEY& key) const {
722     Mutex::Autolock lock(mLock);
723     for (const auto& i : mClients) {
724         if (i->getKey() == key) return i;
725     }
726     return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
727 }
728 
729 template<class KEY, class VALUE, class LISTENER>
getPrimaryClient(const KEY & key)730 std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::getPrimaryClient(
731         const KEY& key) const {
732     Mutex::Autolock lock(mLock);
733     if (flags::camera_multi_client()) {
734         for (const auto& i : mClients) {
735             bool sharedMode =  i->getSharedMode();
736             bool primaryClient;
737             status_t ret = i->getValue()->isPrimaryClient(&primaryClient);
738             if (ret == OK) {
739                 if ((i->getKey() == key) && sharedMode && primaryClient) {
740                     return i;
741                 }
742             }
743         }
744     }
745     return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
746 }
747 
748 template<class KEY, class VALUE, class LISTENER>
removeAll()749 void ClientManager<KEY, VALUE, LISTENER>::removeAll() {
750     Mutex::Autolock lock(mLock);
751     if (mListener != nullptr) {
752         for (const auto& i : mClients) {
753             mListener->onClientRemoved(*i);
754         }
755     }
756     mClients.clear();
757     mRemovedCondition.broadcast();
758 }
759 
760 template<class KEY, class VALUE, class LISTENER>
761 std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
removeAll(const KEY & key)762         ClientManager<KEY, VALUE, LISTENER>::removeAll(const KEY& key) {
763     Mutex::Autolock lock(mLock);
764     std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> clients;
765     if (flags::camera_multi_client()) {
766         for (auto it = mClients.begin(); it != mClients.end();)
767         {
768             if ((*it)->getKey() == key) {
769                 if (mListener != nullptr) mListener->onClientRemoved(**it);
770                 clients.push_back(*it);
771                 it = mClients.erase(it);
772             } else {
773                 ++it;
774             }
775         }
776         mRemovedCondition.broadcast();
777     }
778     return clients;
779 }
780 
781 template<class KEY, class VALUE, class LISTENER>
remove(const KEY & key)782 std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::remove(
783     const KEY& key) {
784     Mutex::Autolock lock(mLock);
785 
786     std::shared_ptr<ClientDescriptor<KEY, VALUE>> ret;
787 
788     // Remove evicted clients from list
789     mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
790         [this, &key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
791             if (curClientPtr->getKey() == key) {
792                 if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
793                 ret = curClientPtr;
794                 return true;
795             }
796             return false;
797         }), mClients.end());
798 
799     mRemovedCondition.broadcast();
800     return ret;
801 }
802 
803 template<class KEY, class VALUE, class LISTENER>
waitUntilRemoved(const std::shared_ptr<ClientDescriptor<KEY,VALUE>> client,nsecs_t timeout)804 status_t ClientManager<KEY, VALUE, LISTENER>::waitUntilRemoved(
805         const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
806         nsecs_t timeout) const {
807     status_t ret = NO_ERROR;
808     Mutex::Autolock lock(mLock);
809 
810     bool isRemoved = false;
811 
812     // Figure out what time in the future we should hit the timeout
813     nsecs_t failTime = systemTime(SYSTEM_TIME_MONOTONIC) + timeout;
814 
815     while (!isRemoved) {
816         isRemoved = true;
817         for (const auto& i : mClients) {
818             if (i == client) {
819                 isRemoved = false;
820             }
821         }
822 
823         if (!isRemoved) {
824             ret = mRemovedCondition.waitRelative(mLock, timeout);
825             if (ret != NO_ERROR) {
826                 break;
827             }
828             timeout = failTime - systemTime(SYSTEM_TIME_MONOTONIC);
829         }
830     }
831 
832     return ret;
833 }
834 
835 template<class KEY, class VALUE, class LISTENER>
setListener(const std::shared_ptr<LISTENER> & listener)836 void ClientManager<KEY, VALUE, LISTENER>::setListener(const std::shared_ptr<LISTENER>& listener) {
837     Mutex::Autolock lock(mLock);
838     mListener = listener;
839 }
840 
841 template<class KEY, class VALUE, class LISTENER>
remove(const std::shared_ptr<ClientDescriptor<KEY,VALUE>> & value)842 void ClientManager<KEY, VALUE, LISTENER>::remove(
843         const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value) {
844     Mutex::Autolock lock(mLock);
845     // Remove evicted clients from list
846     mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
847         [this, &value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
848             if (curClientPtr == value) {
849                 if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
850                 return true;
851             }
852             return false;
853         }), mClients.end());
854     mRemovedCondition.broadcast();
855 }
856 
857 template<class KEY, class VALUE, class LISTENER>
getCurrentCostLocked()858 int64_t ClientManager<KEY, VALUE, LISTENER>::getCurrentCostLocked() const {
859     int64_t totalCost = 0;
860     for (const auto& x : mClients) {
861             totalCost += x->getCost();
862     }
863     return totalCost;
864 }
865 
866 // --------------------------------------------------------------------------------
867 
868 }; // namespace resource_policy
869 }; // namespace android
870 
871 #endif // ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
872