blob: 037c5c2f5c17f2d289fbf9d00de7f6aec453c318 [file] [log] [blame]
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -07001/*
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
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -070020#include <binder/ActivityManager.h>
21
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -070022#include "../utils/ClientManager.h"
23#include <gtest/gtest.h>
24
25using namespace android::resource_policy;
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -070026using namespace android;
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -070027
28struct TestClient {
29 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
42using TestClientDescriptor = ClientDescriptor<int, TestClient>;
43using TestDescriptorPtr = std::shared_ptr<TestClientDescriptor>;
44
45TestDescriptorPtr 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);
48}
49
50class TestClientManager : public ClientManager<int, TestClient> {
51public:
52 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.
61TEST(ClientManagerTest, SingleOwnerMultipleCamera) {
62
63 TestClientManager cm;
64 TestClient cam0Client(/*ID*/0, /*cost*/100, /*conflicts*/{1},
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -070065 /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
66 ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -070067 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},
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -070072 /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
73 ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -070074 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*/{},
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -070084 /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
85 ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -070086 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*/{},
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -070091 /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
92 ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -070093 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},
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -0700107 /*ownerId*/ 1000, PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ,
108 ActivityManager::PROCESS_STATE_PERSISTENT_UI, /*isVendorClient*/ false);
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -0700109 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";
Yin-Chia Yeh8dfe4642020-06-01 11:57:45 -0700115
Eino-Ville Talvala7c602c32021-03-20 17:00:18 -0700116 // 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}