• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 #define LOG_NDEBUG 0
18 #define LOG_TAG "ClientManagerTest"
19 
20 #include <binder/ActivityManager.h>
21 
22 #include "../utils/ClientManager.h"
23 #include <gtest/gtest.h>
24 
25 using namespace android::resource_policy;
26 using namespace android;
27 
28 struct TestClient {
TestClientTestClient29     TestClient(int id, int32_t cost, const std::set<int>& conflictingKeys, int32_t ownerId,
30             int32_t score, int32_t state, bool isVendorClient) :
31             mId(id), mCost(cost), mConflictingKeys(conflictingKeys),
32             mOwnerId(ownerId), mScore(score), mState(state), mIsVendorClient(isVendorClient) {};
33     int mId;
34     int32_t mCost;    // Int 0..100
35     std::set<int> mConflictingKeys;
36     int32_t mOwnerId; // PID
37     int32_t mScore;   // Priority
38     int32_t mState;   // Foreground/background etc
39     bool mIsVendorClient;
40 };
41 
42 using TestClientDescriptor = ClientDescriptor<int, TestClient>;
43 using TestDescriptorPtr = std::shared_ptr<TestClientDescriptor>;
44 
makeDescFromTestClient(const TestClient & tc)45 TestDescriptorPtr makeDescFromTestClient(const TestClient& tc) {
46     return std::make_shared<TestClientDescriptor>(/*ID*/tc.mId, tc, tc.mCost, tc.mConflictingKeys,
47             tc.mScore, tc.mOwnerId, tc.mState, tc.mIsVendorClient, /*oomScoreOffset*/0);
48 }
49 
50 class TestClientManager : public ClientManager<int, TestClient> {
51 public:
TestClientManager()52     TestClientManager() {}
~TestClientManager()53     virtual ~TestClientManager() {}
54 };
55 
56 
57 // Test ClientMager behavior when there is only one single owner
58 // The expected behavior is that if one owner (application or vendor) is trying
59 // to open second camera, it may succeed or not, but the first opened camera
60 // should never be evicted.
TEST(ClientManagerTest,SingleOwnerMultipleCamera)61 TEST(ClientManagerTest, SingleOwnerMultipleCamera) {
62 
63     TestClientManager cm;
64     TestClient cam0Client(/*ID*/0, /*cost*/100, /*conflicts*/{1},
65             /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
66             ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
67     auto cam0Desc = makeDescFromTestClient(cam0Client);
68     auto evicted = cm.addAndEvict(cam0Desc);
69     ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
70 
71     TestClient cam1Client(/*ID*/1, /*cost*/100, /*conflicts*/{0},
72             /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
73             ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
74     auto cam1Desc = makeDescFromTestClient(cam1Client);
75 
76     // 1. Check with conflicting devices, new client would be evicted
77     auto wouldBeEvicted = cm.wouldEvict(cam1Desc);
78     ASSERT_EQ(wouldBeEvicted.size(), 1u) << "Evicted list length must be 1";
79     ASSERT_EQ(wouldBeEvicted[0]->getKey(), cam1Desc->getKey()) << "cam1 must be evicted";
80 
81     cm.removeAll();
82 
83     TestClient cam2Client(/*ID*/2, /*cost*/100, /*conflicts*/{},
84             /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
85             ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
86     auto cam2Desc = makeDescFromTestClient(cam2Client);
87     evicted = cm.addAndEvict(cam2Desc);
88     ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
89 
90     TestClient cam3Client(/*ID*/3, /*cost*/100, /*conflicts*/{},
91             /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
92             ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
93     auto cam3Desc = makeDescFromTestClient(cam3Client);
94 
95     // 2. Check without conflicting devices, the pre-existing client won't be evicted
96     // In this case, the new client would be granted, but could later be rejected by HAL due to
97     // resource cost.
98     wouldBeEvicted = cm.wouldEvict(cam3Desc);
99     ASSERT_EQ(wouldBeEvicted.size(), 0u) << "Evicted list must be empty";
100 
101     cm.removeAll();
102 
103     evicted = cm.addAndEvict(cam0Desc);
104     ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
105 
106     TestClient cam0ClientNew(/*ID*/0, /*cost*/100, /*conflicts*/{1},
107             /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
108             ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
109     auto cam0DescNew = makeDescFromTestClient(cam0ClientNew);
110     wouldBeEvicted = cm.wouldEvict(cam0DescNew);
111 
112     // 3. Check opening the same camera twice will evict the older client
113     ASSERT_EQ(wouldBeEvicted.size(), 1u) << "Evicted list length must be 1";
114     ASSERT_EQ(wouldBeEvicted[0], cam0Desc) << "cam0 (old) must be evicted";
115 
116     // 4. Check that an invalid client (dead process) will be evicted
117 
118     cm.removeAll();
119 
120     TestClient camDeadClient(/*ID*/ 0, /*cost*/100, /*conflicts*/{},
121             /*ownerId*/ 1000, INVALID_ADJ,
122             ActivityManager::PROCESS_STATE_NONEXISTENT, /*isVendorClient*/ false);
123     auto camDeadDesc = makeDescFromTestClient(camDeadClient);
124     evicted = cm.addAndEvict(camDeadDesc);
125     wouldBeEvicted = cm.wouldEvict(cam0Desc);
126 
127     ASSERT_EQ(evicted.size(), 0u) << "Evicted list must be empty";
128     ASSERT_EQ(wouldBeEvicted.size(), 1u) << "Evicted list length must be 1";
129     ASSERT_EQ(wouldBeEvicted[0], camDeadDesc) << "dead cam must be evicted";
130 
131     // 5. Check that a more important client will win
132 
133     TestClient cam0ForegroundClient(/*ID*/0, /*cost*/100, /*conflicts*/{1},
134             /*ownerId*/ 1000, FOREGROUND_APP_ADJ,
135             ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
136     auto cam0FgDesc = makeDescFromTestClient(cam0ForegroundClient);
137 
138     cm.removeAll();
139     evicted = cm.addAndEvict(cam0Desc);
140     wouldBeEvicted = cm.wouldEvict(cam0FgDesc);
141 
142     ASSERT_EQ(evicted.size(), 0u);
143     ASSERT_EQ(wouldBeEvicted.size(), 1u);
144     ASSERT_EQ(wouldBeEvicted[0],cam0Desc) << "less important cam0 must be evicted";
145 }
146