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 #ifndef CPP_POWERPOLICY_CLIENT_INCLUDE_POWERPOLICYCLIENTBASE_H_
18 #define CPP_POWERPOLICY_CLIENT_INCLUDE_POWERPOLICYCLIENTBASE_H_
19 
20 #include <aidl/android/frameworks/automotive/powerpolicy/BnCarPowerPolicyChangeCallback.h>
21 #include <aidl/android/frameworks/automotive/powerpolicy/BnCarPowerPolicyServer.h>
22 #include <aidl/android/frameworks/automotive/powerpolicy/CarPowerPolicyFilter.h>
23 #include <android-base/result.h>
24 #include <android-base/thread_annotations.h>
25 
26 #include <condition_variable>  // NOLINT
27 #include <shared_mutex>
28 #include <thread>  // NOLINT(build/c++11)
29 #include <vector>
30 
31 namespace android {
32 namespace frameworks {
33 namespace automotive {
34 namespace powerpolicy {
35 
36 // Utility function to test if a PowerComponent list has the given component.
37 bool hasComponent(
38         const std::vector<::aidl::android::frameworks::automotive::powerpolicy::PowerComponent>&
39                 components,
40         ::aidl::android::frameworks::automotive::powerpolicy::PowerComponent component);
41 
42 /**
43  * PowerPolicyClientBase handles the connection to car power policy daemon and wraps
44  * ICarPowerPolicyChangeCallback in order to help HALs handle the policy change easier.
45  *
46  * In the inheriting class, the change notifiction can be handled as follows:
47  *   1. Implement getComponentsOfInterest() so that it returns the vector of components of interest.
48  *   2. Override ICarPowerPolicyChangeCallbackk::onPolicyChanged callback.
49  *   3. Check if the component of interest is in enabled or disabled components.
50  *   4. Handle each case.
51  *
52  * ScopedAStatus PowerPolicyClient::onPolicyChanged(const CarPowerPolicy& powerPolicy) {
53  *     if (hasComponent(powerPolicy.enabledComponents, PowerComponent::AUDIO)) {
54  *         // Do something when AUDIO is enabled.
55  *     } else if (hasComponent(powerPolicy.disabledComponents, PowerComponent::AUDIO)) {
56  *         // Do something when AUDIO is disabled.
57  *     }
58  *     return ScopedAStatus::ok();
59  * }
60  */
61 class PowerPolicyClientBase :
62       public ::aidl::android::frameworks::automotive::powerpolicy::BnCarPowerPolicyChangeCallback {
63 public:
64     static void onBinderDied(void* cookie);
65 
66     // When initialization fails, this callback is invoked from a (connection) thread other than the
67     // main thread.
onInitFailed()68     virtual void onInitFailed() {}
69 
70     // Implement this method to specify components of interest.
71     virtual std::vector<::aidl::android::frameworks::automotive::powerpolicy::PowerComponent>
72     getComponentsOfInterest() = 0;
73 
74     // Override this method to specify custom components of interest.
getCustomComponentsOfInterest()75     virtual std::vector<int> getCustomComponentsOfInterest() { return {}; }
76 
77     // init makes connection to power policy daemon and registers to policy change in the
78     // background. Call this method one time when you want to listen to power policy changes.
79     void init();
80     // release unregisters client callback from power policy daemon.
81     // Call this method one time when you do not want to listen to power policy changes.
82     // It blocks caller's thread by awaiting for connection thread join.
83     void release();
84 
85     void handleBinderDeath();
86 
87 protected:
88     PowerPolicyClientBase();
89     virtual ~PowerPolicyClientBase();
90 
91 private:
92     android::base::Result<void> connectToDaemon();
93 
94     std::mutex mLock;
95     std::thread mConnectionThread GUARDED_BY(mLock);
96     std::shared_ptr<::aidl::android::frameworks::automotive::powerpolicy::ICarPowerPolicyServer>
97             mPolicyServer;
98     std::shared_ptr<ICarPowerPolicyChangeCallback> mPolicyChangeCallback;
99     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
100     std::atomic<bool> mConnecting;
101     bool mDisconnecting GUARDED_BY(mLock);
102     std::condition_variable mDeathRecipientLinkedCv;
103     bool mDeathRecipientLinked GUARDED_BY(mLock) = false;
104 
105     static void onDeathRecipientUnlinked(void* cookie);
106 
107     void handleDeathRecipientUnlinked();
108 };
109 
110 }  // namespace powerpolicy
111 }  // namespace automotive
112 }  // namespace frameworks
113 }  // namespace android
114 
115 #endif  // CPP_POWERPOLICY_CLIENT_INCLUDE_POWERPOLICYCLIENTBASE_H_
116