• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <condition_variable>
21 #include <cstdio>
22 #include <functional>
23 #include <mutex>
24 #include <thread>
25 
26 #include "chre_host/log.h"
27 
28 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
29 #include <hardware_legacy/power.h>
30 
31 using android::hardware::hidl_death_recipient;
32 using android::hardware::Return;
33 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
34 using android::hardware::soundtrigger::V2_0::SoundModelHandle;
35 using android::hardware::soundtrigger::V2_0::SoundModelType;
36 using android::hidl::base::V1_0::IBase;
37 
38 namespace android {
39 namespace chre {
40 
41 /**
42  * Handles interactions with the SoundTrigger (ST) HAL, to issue configuration
43  * requests for the always-on audio hardware to enable Low Power Microphone
44  * Access (LPMA) in CHRE. Typically, this class is used when the CHRE audio
45  * implementation for a given system requires notifying the ST HAL when audio
46  * is requested/released within CHRE
47  */
48 class StHalLpmaHandler {
49  public:
50   //! Class to handle when a connected ST HAL service dies
51   class StHalDeathRecipient : public hidl_death_recipient {
52    public:
53     StHalDeathRecipient() = delete;
StHalDeathRecipient(std::function<void ()> cb)54     explicit StHalDeathRecipient(std::function<void()> cb) : mCallback(cb) {}
55 
56     /**
57      * Callback that is called when a connected service dies. It mainly
58      * resets the LPMA Enabled flag, and unblocks the LPMA processing thread.
59      * It is to be used in conjunction with linkToDeath(), which we do
60      * in checkConnectionToStHalServiceLocked().
61      */
serviceDied(uint64_t,const wp<IBase> &)62     virtual void serviceDied(uint64_t /* cookie */,
63                              const wp<IBase> & /* who */) override {
64       mCallback();
65     }
66 
67    private:
68     std::function<void()> mCallback;
69   };
70 
71   StHalLpmaHandler() = delete;
72 
73   explicit StHalLpmaHandler(bool allowed);
74 
~StHalLpmaHandler()75   ~StHalLpmaHandler() {
76     if (mThread.has_value()) {
77       // TODO: Change this to join after adding proper handler
78       mThread->detach();
79     }
80   }
81 
82   /**
83    * If LPMA is enabled, starts a worker thread to load/unload models.
84    */
85   void init();
86 
87   /**
88    * Sets the target state for LPMA to be enabled. This triggers another thread
89    * to perform the async operation of enabling or disabling the LPMA use case.
90    *
91    * @param enabled Whether LPMA is to be enabled or disabled.
92    */
93   void enable(bool enabled);
94 
95   /**
96    * Loads the LPMA use case via the SoundTrigger HAL HIDL service.
97    *
98    * @return true if LPMA was enabled successfully, false otherwise.
99    */
100   bool load();
101 
102   /**
103    * Unloads the LPMA use case via the SoundTrigger HAL HIDL service. This
104    * function does not indicate success/failure as it is expected that even in
105    * the event of a failure to unload, the use case will be unloaded. As long as
106    * the sound trigger HAL received the request we can be assured that the use
107    * case will be unloaded (even if it means reseting the codec or otherwise).
108    */
109   void unload();
110 
111   /**
112    * Entry point for the thread that loads/unloads sound models from the
113    * ST HAL
114    */
115   void StHalLpmaHandlerThreadEntry();
116 
117  private:
118   const bool mIsLpmaAllowed;
119   bool mCurrentLpmaEnabled;
120   bool mTargetLpmaEnabled;
121   bool mCondVarPredicate;
122   SoundModelHandle mLpmaHandle = 0;
123 
124   int mRetryCount;
125   useconds_t mRetryDelay;
126 
127   std::optional<std::thread> mThread;
128   std::mutex mMutex;
129   std::condition_variable mCondVar;
130 
131   sp<StHalDeathRecipient> mDeathRecipient;
132   sp<ISoundTriggerHw> mStHalService;
133 
134   /**
135    * Checks for a valid connection to the ST HAL service, reconnects if not
136    * already connected. This method should only be invoked after acquiring the
137    * class mutex has been locked.
138    */
139   void checkConnectionToStHalServiceLocked();
140 
141   /**
142    * Invoked by the HAL service death callback. see
143    * StHalDeathRecipient::ServiceDied()
144    */
145   void onStHalServiceDeath();
146 
147   /**
148    * This function blocks on a condition variable and when notified, based
149    * on its current state and as notified by enable(), performs a load or
150    * unload. The function also resets the delay and retry counts if the current
151    * and next states match
152    *
153    * @return true if the state update succeeded, and we don't need to retry with
154    * a delay
155    */
156   bool waitOnStHalRequestAndProcess();
157 
158   /**
159    * Delay retrying a load if a state update failed
160    */
161   void delay();
162 };
163 
164 }  // namespace chre
165 }  // namespace android
166 
167 #endif  // ST_HAL_LPMA_HANDLER_H_
168