• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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