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