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 ST_HAL_LPMA_HANDLER_H_ 18 #define ST_HAL_LPMA_HANDLER_H_ 19 20 #include <hardware_legacy/power.h> 21 #include <condition_variable> 22 #include <cstdio> 23 #include <functional> 24 #include <mutex> 25 #include <thread> 26 27 #include "chre_host/log.h" 28 29 #ifdef CHRE_ST_LPMA_HANDLER_AIDL 30 #include <aidl/android/hardware/soundtrigger3/ISoundTriggerHw.h> 31 #include <android/binder_manager.h> 32 #include <android/binder_process.h> 33 #else 34 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h> 35 #endif // CHRE_ST_LPMA_HANDLER_AIDL 36 37 #ifdef CHRE_ST_LPMA_HANDLER_AIDL 38 using aidl::android::hardware::soundtrigger3::ISoundTriggerHw; 39 #else 40 using android::hardware::hidl_death_recipient; 41 using android::hardware::Return; 42 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw; 43 using android::hardware::soundtrigger::V2_0::SoundModelHandle; 44 using android::hardware::soundtrigger::V2_0::SoundModelType; 45 using android::hidl::base::V1_0::IBase; 46 #endif // CHRE_ST_LPMA_HANDLER_AIDL 47 48 namespace android { 49 namespace chre { 50 51 /** 52 * Handles interactions with the SoundTrigger (ST) HAL, to issue configuration 53 * requests for the always-on audio hardware to enable Low Power Microphone 54 * Access (LPMA) in CHRE. Typically, this class is used when the CHRE audio 55 * implementation for a given system requires notifying the ST HAL when audio 56 * is requested/released within CHRE 57 */ 58 class StHalLpmaHandler { 59 public: 60 StHalLpmaHandler() = delete; 61 explicit StHalLpmaHandler(bool allowed); 62 63 ~StHalLpmaHandler(); 64 65 /** 66 * If LPMA is enabled, starts a worker thread to load/unload models. 67 */ 68 void init(); 69 70 /** 71 * Sets the target state for LPMA to be enabled. This triggers another thread 72 * to perform the async operation of enabling or disabling the LPMA use case. 73 * 74 * @param enabled Whether LPMA is to be enabled or disabled. 75 */ 76 void enable(bool enabled); 77 78 private: 79 const bool mIsLpmaAllowed; 80 bool mCurrentLpmaEnabled; 81 bool mTargetLpmaEnabled; 82 bool mCondVarPredicate; 83 bool mStThreadShouldExit = false; 84 85 int mRetryCount; 86 useconds_t mRetryDelay; 87 88 std::optional<std::thread> mThread; 89 std::mutex mMutex; 90 std::condition_variable mCondVar; 91 92 #ifdef CHRE_ST_LPMA_HANDLER_AIDL 93 int32_t mLpmaHandle = 0; 94 std::shared_ptr<ISoundTriggerHw> mStHalService; 95 #else 96 //! Class to handle when a connected ST HAL service dies 97 class StHalDeathRecipient : public hidl_death_recipient { 98 public: 99 StHalDeathRecipient() = delete; StHalDeathRecipient(std::function<void ()> cb)100 explicit StHalDeathRecipient(std::function<void()> cb) : mCallback(cb) {} 101 102 /** 103 * Callback that is called when a connected service dies. It mainly 104 * resets the LPMA Enabled flag, and unblocks the LPMA processing thread. 105 * It is to be used in conjunction with linkToDeath(), which we do 106 * in checkConnectionToStHalServiceLocked(). 107 */ serviceDied(uint64_t,const wp<IBase> &)108 void serviceDied(uint64_t /* cookie */, 109 const wp<IBase> & /* who */) override { 110 mCallback(); 111 } 112 113 private: 114 std::function<void()> mCallback; 115 }; 116 SoundModelHandle mLpmaHandle = 0; 117 sp<StHalDeathRecipient> mDeathRecipient; 118 sp<ISoundTriggerHw> mStHalService; 119 #endif // CHRE_ST_LPMA_HANDLER_AIDL 120 121 /** 122 * Loads the LPMA use case via the SoundTrigger HAL HIDL service. 123 * 124 * @return true if LPMA was enabled successfully, false otherwise. 125 */ 126 bool load(); 127 128 /** 129 * Unloads the LPMA use case via the SoundTrigger HAL HIDL service. This 130 * function does not indicate success/failure as it is expected that even in 131 * the event of a failure to unload, the use case will be unloaded. As long as 132 * the sound trigger HAL received the request we can be assured that the use 133 * case will be unloaded (even if it means reseting the codec or otherwise). 134 */ 135 void unload(); 136 137 /** 138 * If CHRE_LPMA_REQUEST_START_RECOGNITION is defined, calls startRecognition() 139 * on the currently loaded model. No-op otherwise. 140 * 141 * @return true on success 142 */ 143 bool start(); 144 145 //! Invokes stopRecognition() on the currently loaded model 146 /** 147 * If CHRE_LPMA_REQUEST_START_RECOGNITION is defined, calls stopRecognition() 148 * on the currently loaded model. No-op otherwise. 149 * 150 * @return true on success 151 */ 152 void stop(); 153 154 // Convenience methods 155 bool loadAndStart(); 156 void stopAndUnload(); 157 158 /** 159 * Entry point for the thread that loads/unloads sound models from the 160 * ST HAL 161 */ 162 void stHalLpmaHandlerThreadEntry(); 163 164 /** 165 * Checks for a valid connection to the ST HAL service, reconnects if not 166 * already connected. This method should only be invoked after acquiring the 167 * class mutex has been locked. 168 */ 169 void checkConnectionToStHalServiceLocked(); 170 171 /** 172 * Invoked by the HAL service death callback. see 173 * StHalDeathRecipient::ServiceDied() 174 */ 175 void onStHalServiceDeath(); 176 177 /** 178 * Invoke Hal to load or unload LPMA depending on the status of 179 * mTargetLpmaEnabled and mCurrentLpmaEnabled 180 * 181 * @param locked lock that holds the mutex that guards mTargetLpmaEnabled 182 */ 183 void stHalRequestAndProcessLocked(std::unique_lock<std::mutex> const &locked); 184 }; 185 } // namespace chre 186 } // namespace android 187 188 #endif // ST_HAL_LPMA_HANDLER_H_ 189