1 /*
2 * Copyright (C) 2021 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 "ResourceObserverNativeTest"
19
20 #include <aidl/android/media/BnResourceObserver.h>
21 #include <aidl/android/media/IResourceObserverService.h>
22 #include <android-base/logging.h>
23 #include <android/binder_ibinder.h>
24 #include <android/binder_manager.h>
25 #include <android/binder_process.h>
26 #include <gtest/gtest.h>
27
28 #include "media/NdkMediaCodec.h"
29
30 using namespace android;
31 using Status = ::ndk::ScopedAStatus;
32 using ::aidl::android::media::BnResourceObserver;
33 using ::aidl::android::media::IResourceObserverService;
34 using ::aidl::android::media::MediaObservableEvent;
35 using ::aidl::android::media::MediaObservableFilter;
36 using ::aidl::android::media::MediaObservableParcel;
37 using ::aidl::android::media::MediaObservableType;
38
39 static const char* MIMETYPE_AVC = "video/avc";
40
toString(const MediaObservableParcel & observable)41 static std::string toString(const MediaObservableParcel& observable) {
42 return "{" + ::aidl::android::media::toString(observable.type) + ", " +
43 std::to_string(observable.value) + "}";
44 }
45
46 class ResourceObserverNativeTest : public ::testing::Test {
47 public:
SetUp()48 void SetUp() override { ABinderProcess_startThreadPool(); }
TearDown()49 void TearDown() override {}
50
51 struct StatusChangeEvent {
52 MediaObservableEvent event;
53 int32_t uid;
54 int32_t pid;
55 std::vector<MediaObservableParcel> observables;
56 };
57 struct ResourceObserver : public BnResourceObserver {
ResourceObserverResourceObserverNativeTest::ResourceObserver58 explicit ResourceObserver() {}
59
60 // IResourceObserver
onStatusChangedResourceObserverNativeTest::ResourceObserver61 ::ndk::ScopedAStatus onStatusChanged(
62 MediaObservableEvent event, int32_t uid, int32_t pid,
63 const std::vector<MediaObservableParcel>& observables) override {
64 LOG(INFO) << ::aidl::android::media::toString(event) << ", uid: " << uid
65 << ", pid: " << pid << ", " << toString(observables[0]).c_str();
66
67 std::scoped_lock lock{mLock};
68 mLastEvent.event = event;
69 mLastEvent.uid = uid;
70 mLastEvent.pid = pid;
71 mLastEvent.observables = observables;
72 mStatusChangeCalled = true;
73 mCondition.notify_one();
74 return ::ndk::ScopedAStatus::ok();
75 }
76 // ~IResourceObserver
77
waitForEventResourceObserverNativeTest::ResourceObserver78 bool waitForEvent(StatusChangeEvent& event, int64_t timeoutUs = 0) {
79 std::unique_lock lock{mLock};
80 if (!mStatusChangeCalled && timeoutUs > 0) {
81 mCondition.wait_for(lock, std::chrono::microseconds(timeoutUs));
82 }
83 if (!mStatusChangeCalled) {
84 return false;
85 }
86 event = mLastEvent;
87 mStatusChangeCalled = false;
88 return true;
89 }
90 std::mutex mLock;
91 std::condition_variable mCondition;
92 bool mStatusChangeCalled = false;
93 StatusChangeEvent mLastEvent;
94 };
95
testResourceObserver(MediaObservableEvent eventType)96 void testResourceObserver(MediaObservableEvent eventType) {
97 ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_observer"));
98 std::shared_ptr<IResourceObserverService> service =
99 IResourceObserverService::fromBinder(binder);
100
101 EXPECT_NE(service, nullptr);
102
103 std::shared_ptr<ResourceObserver> observer = ::ndk::SharedRefBase::make<ResourceObserver>();
104 std::vector<MediaObservableFilter> filters = {{MediaObservableType::kVideoSecureCodec,
105 eventType},
106 {MediaObservableType::kVideoNonSecureCodec,
107 eventType}};
108
109 Status status = service->registerObserver(observer, filters);
110 EXPECT_TRUE(status.isOk());
111
112 AMediaCodec* dec = AMediaCodec_createDecoderByType(MIMETYPE_AVC);
113
114 // We only test this if the AVC non-secure decoder can be created.
115 if (dec != nullptr) {
116 StatusChangeEvent event;
117 if ((uint64_t)eventType & (uint64_t)MediaObservableEvent::kBusy) {
118 EXPECT_TRUE(observer->waitForEvent(event, 100000));
119 verifyEvent(event, MediaObservableEvent::kBusy,
120 MediaObservableType::kVideoNonSecureCodec);
121 } else {
122 // Should not receive any event, wait 1 second to confirm.
123 EXPECT_FALSE(observer->waitForEvent(event, 1000000));
124 }
125
126 AMediaCodec_delete(dec);
127
128 if ((uint64_t)eventType & (uint64_t)MediaObservableEvent::kIdle) {
129 EXPECT_TRUE(observer->waitForEvent(event, 100000));
130 verifyEvent(event, MediaObservableEvent::kIdle,
131 MediaObservableType::kVideoNonSecureCodec);
132 } else {
133 // Should not receive any event, wait 1 second to confirm.
134 EXPECT_FALSE(observer->waitForEvent(event, 1000000));
135 }
136 }
137
138 status = service->unregisterObserver(observer);
139 EXPECT_TRUE(status.isOk());
140 }
141
verifyEvent(const StatusChangeEvent & event,MediaObservableEvent expectedEventType,MediaObservableType expectedObservableType)142 void verifyEvent(const StatusChangeEvent& event, MediaObservableEvent expectedEventType,
143 MediaObservableType expectedObservableType) {
144 EXPECT_EQ(event.event, expectedEventType);
145 EXPECT_EQ(event.pid, getpid());
146 EXPECT_EQ(event.uid, getuid());
147 EXPECT_EQ(event.observables.size(), 1);
148 EXPECT_EQ(event.observables[0].type, expectedObservableType);
149 EXPECT_EQ(event.observables[0].value, 1);
150 }
151 };
152
153 //-------------------------------------------------------------------------------------------------
TEST_F(ResourceObserverNativeTest,testInvalidParameters)154 TEST_F(ResourceObserverNativeTest, testInvalidParameters) {
155 LOG(INFO) << "testInvalidParameters";
156
157 ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_observer"));
158 std::shared_ptr<IResourceObserverService> service =
159 IResourceObserverService::fromBinder(binder);
160
161 EXPECT_NE(service, nullptr);
162
163 std::shared_ptr<ResourceObserver> observer = ::ndk::SharedRefBase::make<ResourceObserver>();
164 std::vector<MediaObservableFilter> filters = {{MediaObservableType::kVideoSecureCodec,
165 MediaObservableEvent::kAll},
166 {MediaObservableType::kVideoNonSecureCodec,
167 MediaObservableEvent::kAll}};
168 std::vector<MediaObservableFilter> emptyFilters;
169
170 // Test register with null observer fails.
171 Status status = service->registerObserver(nullptr, filters);
172 EXPECT_FALSE(status.isOk());
173 EXPECT_EQ(status.getServiceSpecificError(), BAD_VALUE);
174
175 // Test register with empty filter list fails.
176 status = service->registerObserver(observer, emptyFilters);
177 EXPECT_FALSE(status.isOk());
178 EXPECT_EQ(status.getServiceSpecificError(), BAD_VALUE);
179
180 // Test register duplicate observer fails.
181 status = service->registerObserver(observer, filters);
182 EXPECT_TRUE(status.isOk());
183 status = service->registerObserver(observer, filters);
184 EXPECT_FALSE(status.isOk());
185 EXPECT_EQ(status.getServiceSpecificError(), ALREADY_EXISTS);
186
187 status = service->unregisterObserver(observer);
188 EXPECT_TRUE(status.isOk());
189 }
190
TEST_F(ResourceObserverNativeTest,testResourceObserverBusy)191 TEST_F(ResourceObserverNativeTest, testResourceObserverBusy) {
192 LOG(INFO) << "testResourceObserverBusy";
193
194 testResourceObserver(MediaObservableEvent::kBusy);
195 }
196
TEST_F(ResourceObserverNativeTest,testResourceObserverIdle)197 TEST_F(ResourceObserverNativeTest, testResourceObserverIdle) {
198 LOG(INFO) << "testResourceObserverIdle";
199
200 testResourceObserver(MediaObservableEvent::kIdle);
201 }
202
TEST_F(ResourceObserverNativeTest,testResourceObserverAll)203 TEST_F(ResourceObserverNativeTest, testResourceObserverAll) {
204 LOG(INFO) << "testResourceObserverAll";
205
206 testResourceObserver(MediaObservableEvent::kAll);
207 }
208