1 /*
2 * Copyright 2019 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 "SuspendControlService.h"
18
19 #include "SystemSuspend.h"
20
21 #include <android-base/logging.h>
22
23 namespace android {
24 namespace system {
25 namespace suspend {
26 namespace V1_0 {
27
28 template <typename T>
retOk(const T & value,T * ret_val)29 binder::Status retOk(const T& value, T* ret_val) {
30 *ret_val = value;
31 return binder::Status::ok();
32 }
33
setSuspendService(const wp<SystemSuspend> & suspend)34 void SuspendControlService::setSuspendService(const wp<SystemSuspend>& suspend) {
35 mSuspend = suspend;
36 }
37
enableAutosuspend(bool * _aidl_return)38 binder::Status SuspendControlService::enableAutosuspend(bool* _aidl_return) {
39 const auto suspendService = mSuspend.promote();
40 return retOk(suspendService != nullptr && suspendService->enableAutosuspend(), _aidl_return);
41 }
42
registerCallback(const sp<ISuspendCallback> & callback,bool * _aidl_return)43 binder::Status SuspendControlService::registerCallback(const sp<ISuspendCallback>& callback,
44 bool* _aidl_return) {
45 if (!callback) {
46 return retOk(false, _aidl_return);
47 }
48
49 auto l = std::lock_guard(mCallbackLock);
50 sp<IBinder> cb = IInterface::asBinder(callback);
51 // Only remote binders can be linked to death
52 if (cb->remoteBinder() != nullptr) {
53 if (findCb(cb) == mCallbacks.end()) {
54 auto status = cb->linkToDeath(this);
55 if (status != NO_ERROR) {
56 LOG(ERROR) << __func__ << " Cannot link to death: " << status;
57 return retOk(false, _aidl_return);
58 }
59 }
60 }
61 mCallbacks.push_back(callback);
62 return retOk(true, _aidl_return);
63 }
64
forceSuspend(bool * _aidl_return)65 binder::Status SuspendControlService::forceSuspend(bool* _aidl_return) {
66 const auto suspendService = mSuspend.promote();
67 return retOk(suspendService != nullptr && suspendService->forceSuspend(), _aidl_return);
68 }
69
binderDied(const wp<IBinder> & who)70 void SuspendControlService::binderDied(const wp<IBinder>& who) {
71 auto l = std::lock_guard(mCallbackLock);
72 mCallbacks.erase(findCb(who));
73 }
74
notifyWakeup(bool success)75 void SuspendControlService::notifyWakeup(bool success) {
76 // A callback could potentially modify mCallbacks (e.g., via registerCallback). That must not
77 // result in a deadlock. To that end, we make a copy of mCallbacks and release mCallbackLock
78 // before calling the copied callbacks.
79 auto callbackLock = std::unique_lock(mCallbackLock);
80 auto callbacksCopy = mCallbacks;
81 callbackLock.unlock();
82
83 for (const auto& callback : callbacksCopy) {
84 callback->notifyWakeup(success).isOk(); // ignore errors
85 }
86 }
87
88 } // namespace V1_0
89 } // namespace suspend
90 } // namespace system
91 } // namespace android
92