1 /*
2  * Copyright (C) 2017 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_TAG "audio_hw_primary"
18 
19 #include <cinttypes>
20 
21 #include <utils/Log.h>
22 #include <utils/Mutex.h>
23 
24 #include <android/hardware/power/1.2/IPower.h>
25 
26 #include "audio_perf.h"
27 
28 using android::hardware::power::V1_2::IPower;
29 using android::hardware::power::V1_2::PowerHint;
30 using android::hardware::power::V1_2::toString;
31 using android::hardware::Return;
32 using android::hardware::Void;
33 using android::hardware::hidl_death_recipient;
34 using android::hidl::base::V1_0::IBase;
35 
36 // Do not use gPowerHAL, use getPowerHal to retrieve a copy instead
37 static android::sp<IPower> gPowerHal_ = nullptr;
38 // Protect gPowerHal_
39 static std::mutex gPowerHalMutex;
40 
41 // PowerHalDeathRecipient to invalid the client when service dies
42 struct PowerHalDeathRecipient : virtual public hidl_death_recipient {
43     // hidl_death_recipient interface
serviceDiedPowerHalDeathRecipient44     virtual void serviceDied(uint64_t, const android::wp<IBase>&) override {
45         std::lock_guard<std::mutex> lock(gPowerHalMutex);
46         ALOGE("PowerHAL just died");
47         gPowerHal_ = nullptr;
48     }
49 };
50 
51 // Retrieve a copy of client
getPowerHal()52 static android::sp<IPower> getPowerHal() {
53     std::lock_guard<std::mutex> lock(gPowerHalMutex);
54     static android::sp<PowerHalDeathRecipient> gPowerHalDeathRecipient = nullptr;
55     static bool gPowerHalExists = true;
56 
57     if (gPowerHalExists && gPowerHal_ == nullptr) {
58         gPowerHal_ = IPower::getService();
59 
60         if (gPowerHal_ == nullptr) {
61             ALOGE("Unable to get Power service");
62             gPowerHalExists = false;
63         } else {
64             if (gPowerHalDeathRecipient == nullptr) {
65                 gPowerHalDeathRecipient = new PowerHalDeathRecipient();
66             }
67             Return<bool> linked = gPowerHal_->linkToDeath(
68                 gPowerHalDeathRecipient, 0 /* cookie */);
69             if (!linked.isOk()) {
70                 ALOGE("Transaction error in linking to PowerHAL death: %s",
71                       linked.description().c_str());
72                 gPowerHal_ = nullptr;
73             } else if (!linked) {
74                 ALOGW("Unable to link to PowerHal death notifications");
75                 gPowerHal_ = nullptr;
76             } else {
77                 ALOGD("Connect to PowerHAL and link to death "
78                       "notification successfully");
79             }
80         }
81     }
82     return gPowerHal_;
83 }
84 
powerHint(PowerHint hint,int32_t data)85 static bool powerHint(PowerHint hint, int32_t data) {
86     android::sp<IPower> powerHal = getPowerHal();
87     if (powerHal == nullptr) {
88         return false;
89     }
90 
91     auto ret = powerHal->powerHintAsync_1_2(hint, data);
92 
93     if (!ret.isOk()) {
94         ALOGE("powerHint failed, hint: %s, data: %" PRId32 ",  error: %s",
95               toString(hint).c_str(),
96               data,
97               ret.description().c_str());
98     }
99     return ret.isOk();
100 }
101 
audio_streaming_hint_start()102 int audio_streaming_hint_start() {
103     return powerHint(PowerHint::AUDIO_STREAMING, 1);
104 }
105 
audio_streaming_hint_end()106 int audio_streaming_hint_end() {
107     return powerHint(PowerHint::AUDIO_STREAMING, 0);
108 }
109 
audio_low_latency_hint_start()110 int audio_low_latency_hint_start() {
111     return powerHint(PowerHint::AUDIO_LOW_LATENCY, 1);
112 }
113 
audio_low_latency_hint_end()114 int audio_low_latency_hint_end() {
115     return powerHint(PowerHint::AUDIO_LOW_LATENCY, 0);
116 }
117