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 #include "CarPowerPolicyServer.h"
18
19 #include <aidl/android/frameworks/automotive/powerpolicy/BnCarPowerPolicyChangeCallback.h>
20 #include <aidl/android/frameworks/automotive/powerpolicy/CarPowerPolicy.h>
21 #include <aidl/android/frameworks/automotive/powerpolicy/CarPowerPolicyFilter.h>
22 #include <aidl/android/frameworks/automotive/powerpolicy/ICarPowerPolicyChangeCallback.h>
23 #include <aidl/android/frameworks/automotive/powerpolicy/ICarPowerPolicyServer.h>
24 #include <aidl/android/frameworks/automotive/powerpolicy/PowerComponent.h>
25 #include <android-base/thread_annotations.h>
26 #include <gmock/gmock.h>
27 #include <utils/Looper.h>
28 #include <utils/Mutex.h>
29 #include <utils/StrongPointer.h>
30
31 #include <unordered_set>
32
33 namespace android {
34 namespace frameworks {
35 namespace automotive {
36 namespace powerpolicy {
37
38 using android::IBinder;
39
40 using ::aidl::android::frameworks::automotive::powerpolicy::BnCarPowerPolicyChangeCallback;
41 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy;
42 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicyFilter;
43 using ::aidl::android::frameworks::automotive::powerpolicy::ICarPowerPolicyChangeCallback;
44 using ::aidl::android::frameworks::automotive::powerpolicy::ICarPowerPolicyServer;
45 using ::aidl::android::frameworks::automotive::powerpolicy::PowerComponent;
46
47 using ::ndk::ScopedAStatus;
48 using ::ndk::SpAIBinder;
49
50 using ::testing::_;
51 using ::testing::Invoke;
52 using ::testing::Return;
53
54 namespace {
55
56 class MockPowerPolicyChangeCallback : public BnCarPowerPolicyChangeCallback {
57 public:
onPolicyChanged(const CarPowerPolicy &)58 ScopedAStatus onPolicyChanged(const CarPowerPolicy& /*policy*/) override {
59 return ScopedAStatus::ok();
60 }
61 };
62
63 } // namespace
64
65 namespace internal {
66
67 class CarPowerPolicyServerPeer : public RefBase {
68 public:
CarPowerPolicyServerPeer()69 CarPowerPolicyServerPeer() {
70 std::unique_ptr<MockLinkUnlinkImpl> impl = std::make_unique<MockLinkUnlinkImpl>();
71 // We know this would be alive as long as server is alive.
72 mLinkUnlinkImpl = impl.get();
73 mServer = ::ndk::SharedRefBase::make<CarPowerPolicyServer>();
74 mServer->setLinkUnlinkImpl(std::move(impl));
75 mBinder = mServer->asBinder();
76 mServerProxy = ICarPowerPolicyServer::fromBinder(mBinder);
77 }
78
getCurrentPowerPolicy(CarPowerPolicy * aidlReturn)79 ScopedAStatus getCurrentPowerPolicy(CarPowerPolicy* aidlReturn) {
80 return mServerProxy->getCurrentPowerPolicy(aidlReturn);
81 }
82
registerPowerPolicyChangeCallback(const std::shared_ptr<ICarPowerPolicyChangeCallback> & callback,const CarPowerPolicyFilter & filter)83 ScopedAStatus registerPowerPolicyChangeCallback(
84 const std::shared_ptr<ICarPowerPolicyChangeCallback>& callback,
85 const CarPowerPolicyFilter& filter) {
86 return mServerProxy->registerPowerPolicyChangeCallback(callback, filter);
87 }
88
unregisterPowerPolicyChangeCallback(const std::shared_ptr<ICarPowerPolicyChangeCallback> & callback)89 ScopedAStatus unregisterPowerPolicyChangeCallback(
90 const std::shared_ptr<ICarPowerPolicyChangeCallback>& callback) {
91 return mServerProxy->unregisterPowerPolicyChangeCallback(callback);
92 }
93
onBinderDied(void * cookie)94 void onBinderDied(void* cookie) { mServer->onBinderDied(cookie); }
95
getPolicyChangeCallbacks()96 std::vector<CallbackInfo> getPolicyChangeCallbacks() {
97 return mServer->getPolicyChangeCallbacks();
98 }
99
countOnBinderDiedContexts()100 size_t countOnBinderDiedContexts() { return mServer->countOnBinderDiedContexts(); }
101
getCookies()102 std::unordered_set<void*> getCookies() { return mLinkUnlinkImpl->getCookies(); }
103
expectLinkToDeathStatus(AIBinder * binder,status_t linkToDeathResult)104 void expectLinkToDeathStatus(AIBinder* binder, status_t linkToDeathResult) {
105 mLinkUnlinkImpl->expectLinkToDeathStatus(binder, linkToDeathResult);
106 }
107
108 private:
109 class MockLinkUnlinkImpl : public CarPowerPolicyServer::LinkUnlinkImpl {
110 public:
111 MOCK_METHOD(binder_status_t, linkToDeath, (AIBinder*, AIBinder_DeathRecipient*, void*),
112 (override));
113 MOCK_METHOD(binder_status_t, unlinkToDeath, (AIBinder*, AIBinder_DeathRecipient*, void*),
114 (override));
115
expectLinkToDeathStatus(AIBinder * binder,binder_status_t linkToDeathResult)116 void expectLinkToDeathStatus(AIBinder* binder, binder_status_t linkToDeathResult) {
117 EXPECT_CALL(*this, linkToDeath(binder, _, _))
118 .WillRepeatedly(
119 Invoke([this, linkToDeathResult](AIBinder*, AIBinder_DeathRecipient*,
120 void* cookie) {
121 Mutex::Autolock lock(mMutex);
122 mCookies.insert(cookie);
123 return linkToDeathResult;
124 }));
125 EXPECT_CALL(*this, unlinkToDeath(binder, _, _))
126 .WillRepeatedly(
127 Invoke([this](AIBinder*, AIBinder_DeathRecipient*, void* cookie) {
128 Mutex::Autolock lock(mMutex);
129 mCookies.erase(cookie);
130 return STATUS_OK;
131 }));
132 }
133
getCookies()134 std::unordered_set<void*> getCookies() {
135 Mutex::Autolock lock(mMutex);
136 return mCookies;
137 }
138
139 private:
140 android::Mutex mMutex;
141 std::unordered_set<void*> mCookies GUARDED_BY(mMutex);
142 };
143
144 MockLinkUnlinkImpl* mLinkUnlinkImpl;
145 std::shared_ptr<CarPowerPolicyServer> mServer;
146 std::shared_ptr<ICarPowerPolicyServer> mServerProxy;
147 SpAIBinder mBinder;
148 };
149
150 } // namespace internal
151
152 class CarPowerPolicyServerTest : public ::testing::Test {
153 public:
getPowerPolicyChangeCallback()154 std::shared_ptr<ICarPowerPolicyChangeCallback> getPowerPolicyChangeCallback() {
155 std::shared_ptr<MockPowerPolicyChangeCallback> callback =
156 ndk::SharedRefBase::make<MockPowerPolicyChangeCallback>();
157 return ICarPowerPolicyChangeCallback::fromBinder(callback->asBinder());
158 }
159 };
160
TEST_F(CarPowerPolicyServerTest,TestRegisterCallback)161 TEST_F(CarPowerPolicyServerTest, TestRegisterCallback) {
162 sp<internal::CarPowerPolicyServerPeer> server = new internal::CarPowerPolicyServerPeer();
163 std::shared_ptr<ICarPowerPolicyChangeCallback> callbackOne = getPowerPolicyChangeCallback();
164 server->expectLinkToDeathStatus(callbackOne->asBinder().get(), STATUS_OK);
165
166 CarPowerPolicyFilter filter;
167 ScopedAStatus status = server->registerPowerPolicyChangeCallback(callbackOne, filter);
168 ASSERT_TRUE(status.isOk()) << status.getMessage();
169 status = server->registerPowerPolicyChangeCallback(callbackOne, filter);
170 ASSERT_FALSE(status.isOk()) << "Duplicated registration is not allowed";
171 filter.components = {PowerComponent::BLUETOOTH, PowerComponent::AUDIO};
172 status = server->registerPowerPolicyChangeCallback(callbackOne, filter);
173 ASSERT_FALSE(status.isOk()) << "Duplicated registration is not allowed";
174
175 std::shared_ptr<ICarPowerPolicyChangeCallback> callbackTwo = getPowerPolicyChangeCallback();
176 server->expectLinkToDeathStatus(callbackTwo->asBinder().get(), STATUS_OK);
177
178 status = server->registerPowerPolicyChangeCallback(callbackTwo, filter);
179 ASSERT_TRUE(status.isOk()) << status.getMessage();
180 }
181
TEST_F(CarPowerPolicyServerTest,TestRegisterCallback_BinderDied)182 TEST_F(CarPowerPolicyServerTest, TestRegisterCallback_BinderDied) {
183 sp<internal::CarPowerPolicyServerPeer> server = new internal::CarPowerPolicyServerPeer();
184 std::shared_ptr<ICarPowerPolicyChangeCallback> callback = getPowerPolicyChangeCallback();
185 server->expectLinkToDeathStatus(callback->asBinder().get(), STATUS_DEAD_OBJECT);
186 CarPowerPolicyFilter filter;
187
188 ASSERT_FALSE(server->registerPowerPolicyChangeCallback(callback, filter).isOk())
189 << "When linkToDeath fails, registerPowerPolicyChangeCallback should return an error";
190 }
191
TEST_F(CarPowerPolicyServerTest,TestOnBinderDied)192 TEST_F(CarPowerPolicyServerTest, TestOnBinderDied) {
193 sp<internal::CarPowerPolicyServerPeer> server = new internal::CarPowerPolicyServerPeer();
194 std::shared_ptr<ICarPowerPolicyChangeCallback> callbackOne = getPowerPolicyChangeCallback();
195 server->expectLinkToDeathStatus(callbackOne->asBinder().get(), STATUS_OK);
196
197 CarPowerPolicyFilter filter;
198 ScopedAStatus status = server->registerPowerPolicyChangeCallback(callbackOne, filter);
199 ASSERT_TRUE(status.isOk()) << status.getMessage();
200 ASSERT_EQ(server->getPolicyChangeCallbacks().size(), static_cast<size_t>(1));
201 ASSERT_EQ(server->countOnBinderDiedContexts(), static_cast<size_t>(1));
202 ASSERT_EQ(server->getCookies().size(), static_cast<size_t>(1));
203
204 void* cookie = *(server->getCookies().begin());
205 server->onBinderDied(cookie);
206
207 ASSERT_TRUE(server->getPolicyChangeCallbacks().empty());
208
209 ASSERT_EQ(server->countOnBinderDiedContexts(), static_cast<size_t>(0));
210 }
211
TEST_F(CarPowerPolicyServerTest,TestUnregisterCallback)212 TEST_F(CarPowerPolicyServerTest, TestUnregisterCallback) {
213 sp<internal::CarPowerPolicyServerPeer> server = new internal::CarPowerPolicyServerPeer();
214 std::shared_ptr<ICarPowerPolicyChangeCallback> callback = getPowerPolicyChangeCallback();
215 server->expectLinkToDeathStatus(callback->asBinder().get(), STATUS_OK);
216 CarPowerPolicyFilter filter;
217
218 server->registerPowerPolicyChangeCallback(callback, filter);
219 ScopedAStatus status = server->unregisterPowerPolicyChangeCallback(callback);
220 ASSERT_TRUE(status.isOk()) << status.getMessage();
221 ASSERT_FALSE(server->unregisterPowerPolicyChangeCallback(callback).isOk())
222 << "Unregistering an unregistered powerpolicy change callback should return an error";
223 }
224
TEST_F(CarPowerPolicyServerTest,TestGetCurrentPowerPolicy)225 TEST_F(CarPowerPolicyServerTest, TestGetCurrentPowerPolicy) {
226 sp<internal::CarPowerPolicyServerPeer> server = new internal::CarPowerPolicyServerPeer();
227 CarPowerPolicy currentPolicy;
228
229 ScopedAStatus status = server->getCurrentPowerPolicy(¤tPolicy);
230 ASSERT_FALSE(status.isOk()) << "The current policy at creation should be null";
231 // TODO(b/168545262): Add more test cases after VHAL integration is complete.
232 }
233
234 } // namespace powerpolicy
235 } // namespace automotive
236 } // namespace frameworks
237 } // namespace android
238