1 /*
2  * Copyright 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 #include <gtest/gtest.h>
18 #include <android/binder_process.h>
19 
20 #include "ResourceManagerService.h"
21 #include <aidl/android/media/BnResourceManagerClient.h>
22 #include <media/MediaResource.h>
23 #include <media/MediaResourcePolicy.h>
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <mediautils/ProcessInfoInterface.h>
26 
27 namespace android {
28 
29 using Status = ::ndk::ScopedAStatus;
30 using ::aidl::android::media::BnResourceManagerClient;
31 using ::aidl::android::media::IResourceManagerService;
32 using ::aidl::android::media::IResourceManagerClient;
33 using ::aidl::android::media::MediaResourceParcel;
34 
getId(const std::shared_ptr<IResourceManagerClient> & client)35 static int64_t getId(const std::shared_ptr<IResourceManagerClient>& client) {
36     return (int64_t) client.get();
37 }
38 
39 struct TestProcessInfo : public ProcessInfoInterface {
TestProcessInfoTestProcessInfo40     TestProcessInfo() {}
~TestProcessInfoTestProcessInfo41     virtual ~TestProcessInfo() {}
42 
getPriorityTestProcessInfo43     virtual bool getPriority(int pid, int *priority) {
44         // For testing, use pid as priority.
45         // Lower the value higher the priority.
46         *priority = pid;
47         return true;
48     }
49 
isPidTrustedTestProcessInfo50     virtual bool isPidTrusted(int /* pid */) {
51         return true;
52     }
53 
isPidUidTrustedTestProcessInfo54     virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
55         return true;
56     }
57 
overrideProcessInfoTestProcessInfo58     virtual bool overrideProcessInfo(
59             int /* pid */, int /* procState */, int /* oomScore */) {
60         return true;
61     }
62 
removeProcessInfoOverrideTestProcessInfo63     virtual void removeProcessInfoOverride(int /* pid */) {
64     }
65 
66 private:
67     DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
68 };
69 
70 struct TestSystemCallback :
71         public ResourceManagerService::SystemCallbackInterface {
TestSystemCallbackTestSystemCallback72     TestSystemCallback() :
73         mLastEvent({EventType::INVALID, 0}), mEventCount(0) {}
74 
75     enum EventType {
76         INVALID          = -1,
77         VIDEO_ON         = 0,
78         VIDEO_OFF        = 1,
79         VIDEO_RESET      = 2,
80         CPUSET_ENABLE    = 3,
81         CPUSET_DISABLE   = 4,
82     };
83 
84     struct EventEntry {
85         EventType type;
86         int arg;
87     };
88 
noteStartVideoTestSystemCallback89     virtual void noteStartVideo(int uid) override {
90         mLastEvent = {EventType::VIDEO_ON, uid};
91         mEventCount++;
92     }
93 
noteStopVideoTestSystemCallback94     virtual void noteStopVideo(int uid) override {
95         mLastEvent = {EventType::VIDEO_OFF, uid};
96         mEventCount++;
97     }
98 
noteResetVideoTestSystemCallback99     virtual void noteResetVideo() override {
100         mLastEvent = {EventType::VIDEO_RESET, 0};
101         mEventCount++;
102     }
103 
requestCpusetBoostTestSystemCallback104     virtual bool requestCpusetBoost(bool enable) override {
105         mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
106         mEventCount++;
107         return true;
108     }
109 
eventCountTestSystemCallback110     size_t eventCount() { return mEventCount; }
lastEventTypeTestSystemCallback111     EventType lastEventType() { return mLastEvent.type; }
lastEventTestSystemCallback112     EventEntry lastEvent() { return mLastEvent; }
113 
114 protected:
~TestSystemCallbackTestSystemCallback115     virtual ~TestSystemCallback() {}
116 
117 private:
118     EventEntry mLastEvent;
119     size_t mEventCount;
120 
121     DISALLOW_EVIL_CONSTRUCTORS(TestSystemCallback);
122 };
123 
124 
125 struct TestClient : public BnResourceManagerClient {
TestClientTestClient126     TestClient(int pid, int uid, int32_t clientImportance,
127                const std::shared_ptr<ResourceManagerService> &service)
128         : mPid(pid), mUid(uid), mClientImportance(clientImportance), mService(service) {}
129 
reclaimResourceTestClient130     Status reclaimResource(bool* _aidl_return) override {
131         ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
132                                     .uid = static_cast<int32_t>(mUid),
133                                     .id = getId(ref<TestClient>()),
134                                     .name = "none",
135                                     .importance = mClientImportance};
136         mService->removeClient(clientInfo);
137         mWasReclaimResourceCalled = true;
138         *_aidl_return = true;
139         return Status::ok();
140     }
141 
getNameTestClient142     Status getName(::std::string* _aidl_return) override {
143         *_aidl_return = "test_client";
144         return Status::ok();
145     }
146 
checkIfReclaimedAndResetTestClient147     bool checkIfReclaimedAndReset() {
148         bool wasReclaimResourceCalled = mWasReclaimResourceCalled;
149         mWasReclaimResourceCalled = false;
150         return wasReclaimResourceCalled;
151     }
152 
~TestClientTestClient153     virtual ~TestClient() {}
154 
pidTestClient155     inline int pid() const { return mPid; }
uidTestClient156     inline int uid() const { return mUid; }
clientImportanceTestClient157     inline int32_t clientImportance() const { return mClientImportance; }
158 
159 private:
160     bool mWasReclaimResourceCalled = false;
161     int mPid;
162     int mUid;
163     int32_t mClientImportance = 0;
164     std::shared_ptr<ResourceManagerService> mService;
165     DISALLOW_EVIL_CONSTRUCTORS(TestClient);
166 };
167 
168 // [pid, uid] used by the test.
169 static const int kTestPid1 = 30;
170 static const int kTestUid1 = 1010;
171 
172 static const int kTestPid2 = 20;
173 static const int kTestUid2 = 1011;
174 
175 static const int kLowPriorityPid = 40;
176 static const int kMidPriorityPid = 25;
177 static const int kHighPriorityPid = 10;
178 
179 // Client Ids used by the test.
180 static const int kLowPriorityClientId = 1111;
181 static const int kMidPriorityClientId = 2222;
182 static const int kHighPriorityClientId = 3333;
183 
184 // Client importance used by the test.
185 static const int32_t kHighestCodecImportance = 0;
186 static const int32_t kLowestCodecImportance = 100;
187 static const int32_t kMidCodecImportance = 50;
188 
189 using EventType = TestSystemCallback::EventType;
190 using EventEntry = TestSystemCallback::EventEntry;
191 bool operator== (const EventEntry& lhs, const EventEntry& rhs) {
192     return lhs.type == rhs.type && lhs.arg == rhs.arg;
193 }
194 
195 // The condition is expected to return a status but also update the local
196 // result variable.
197 #define CHECK_STATUS_TRUE(conditionThatUpdatesResult) \
198     do { \
199         bool result = false; \
200         EXPECT_TRUE((conditionThatUpdatesResult).isOk()); \
201         EXPECT_TRUE(result); \
202     } while(false)
203 
204 // The condition is expected to return a status but also update the local
205 // result variable.
206 #define CHECK_STATUS_FALSE(conditionThatUpdatesResult) \
207     do { \
208         bool result = true; \
209         EXPECT_TRUE((conditionThatUpdatesResult).isOk()); \
210         EXPECT_FALSE(result); \
211     } while(false)
212 
213 class ResourceManagerServiceTestBase : public ::testing::Test {
214 public:
toTestClient(std::shared_ptr<IResourceManagerClient> testClient)215     static TestClient* toTestClient(std::shared_ptr<IResourceManagerClient> testClient) {
216         return static_cast<TestClient*>(testClient.get());
217     }
218 
mNewRM(newRM)219     ResourceManagerServiceTestBase(bool newRM = false) : mNewRM(newRM) {
220         ALOGI("ResourceManagerServiceTestBase created with %s RM", newRM ? "new" : "old");
221     }
222 
SetUp()223     void SetUp() override {
224         // Need thread pool to receive callbacks, otherwise oneway callbacks are
225         // silently ignored.
226         ABinderProcess_startThreadPool();
227         mSystemCB = new TestSystemCallback();
228         if (mNewRM) {
229             mService = ResourceManagerService::CreateNew(new TestProcessInfo, mSystemCB);
230         } else {
231             mService = ResourceManagerService::Create(new TestProcessInfo, mSystemCB);
232         }
233         mTestClient1 = ::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, 0, mService);
234         mTestClient2 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
235         mTestClient3 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
236     }
237 
238     std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid,
239                                                              int32_t importance = 0) {
240         return ::ndk::SharedRefBase::make<TestClient>(pid, uid, importance, mService);
241     }
242 
243     sp<TestSystemCallback> mSystemCB;
244     std::shared_ptr<ResourceManagerService> mService;
245     std::shared_ptr<IResourceManagerClient> mTestClient1;
246     std::shared_ptr<IResourceManagerClient> mTestClient2;
247     std::shared_ptr<IResourceManagerClient> mTestClient3;
248 
249 protected:
isEqualResources(const std::vector<MediaResourceParcel> & resources1,const ResourceList & resources2)250     static bool isEqualResources(const std::vector<MediaResourceParcel> &resources1,
251             const ResourceList &resources2) {
252         // convert resource1 to ResourceList
253         ResourceList r1;
254         for (size_t i = 0; i < resources1.size(); ++i) {
255             r1.addOrUpdate(resources1[i]);
256         }
257         return r1 == resources2;
258     }
259 
expectEqResourceInfo(const ResourceInfo & info,int uid,std::shared_ptr<IResourceManagerClient> client,const std::vector<MediaResourceParcel> & resources)260     static void expectEqResourceInfo(const ResourceInfo &info,
261             int uid,
262             std::shared_ptr<IResourceManagerClient> client,
263             const std::vector<MediaResourceParcel> &resources) {
264         EXPECT_EQ(uid, info.uid);
265         EXPECT_EQ(client, info.client);
266         EXPECT_TRUE(isEqualResources(resources, info.resources));
267     }
268 
269     bool mNewRM = false;
270 };
271 
272 } // namespace android
273