1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 #include <Log.h>
17 #include "audio/Buffer.h"
18 #include "audio/AudioLocal.h"
19 
prepare(AudioHardware::SamplingRate samplingRate,int gain,int)20 bool AudioLocal::prepare(AudioHardware::SamplingRate samplingRate,  int gain, int /*mode*/)
21 {
22     LOGV("prepare");
23     // gain control not necessary in MobilePre as there is no control.
24     // This means audio source itself should be adjusted to control volume
25     if (mState == EStNone) {
26         if (run("AudioLocal") != android::NO_ERROR) {
27             LOGE("AudioLocal cannot run");
28             // cannot run thread
29             return false;
30         }
31         mState = EStCreated;
32     } else if (mState == EStRunning) {
33         // wrong usage. first stop!
34         return false;
35     }
36     mClientCompletionWait.tryWait(); // this will reset semaphore to 0 if it is 1.
37     mSamplingRate = samplingRate;
38     return issueCommandAndWaitForCompletion(ECmInitialize);
39 }
40 
startPlaybackOrRecord(android::sp<Buffer> & buffer,int numberRepetition)41 bool AudioLocal::startPlaybackOrRecord(android::sp<Buffer>& buffer, int numberRepetition)
42 {
43     LOGV("startPlaybackOrRecord");
44     if (mState != EStInitialized) {
45         LOGE("startPlaybackOrRecord while not initialized");
46         // wrong state
47         return false;
48     }
49     mBuffer = buffer;
50     mNumberRepetition = numberRepetition;
51     mCurrentRepeat = 0;
52     return issueCommandAndWaitForCompletion(ECmRun);
53 }
54 
waitForCompletion()55 bool AudioLocal::waitForCompletion()
56 {
57     int waitTimeInMsec = mBuffer->getSamples() / (mSamplingRate/1000);
58     waitTimeInMsec += COMMAND_WAIT_TIME_MSEC;
59     LOGD("waitForCompletion will wait for %d", waitTimeInMsec);
60     if (!mClientCompletionWait.timedWait(waitTimeInMsec)) {
61         LOGE("waitForCompletion time-out");
62         return false;
63     }
64     return mCompletionResult;
65 }
66 
stopPlaybackOrRecord()67 void AudioLocal::stopPlaybackOrRecord()
68 {
69     LOGV("stopPlaybackOrRecord");
70     if (mState == EStRunning) {
71         issueCommandAndWaitForCompletion(ECmStop);
72     }
73 
74     if (mState != EStNone) { // thread alive
75         requestExit();
76         mCurrentCommand = ECmThreadStop;
77         mAudioThreadWait.post();
78         requestExitAndWait();
79         mState = EStNone;
80     }
81 }
82 
issueCommandAndWaitForCompletion(AudioCommand command)83 bool AudioLocal::issueCommandAndWaitForCompletion(AudioCommand command)
84 {
85     mCurrentCommand = command;
86     mAudioThreadWait.post();
87     if (!mClientCommandWait.timedWait(COMMAND_WAIT_TIME_MSEC)) {
88         LOGE("issueCommandAndWaitForCompletion timeout cmd %d", command);
89         return false;
90     }
91     return mCommandResult;
92 }
93 
~AudioLocal()94 AudioLocal::~AudioLocal()
95 {
96     LOGV("~AudioLocal");
97 }
98 
AudioLocal()99 AudioLocal::AudioLocal()
100     : mState(EStNone),
101       mCurrentCommand(ECmNone),
102       mClientCommandWait(0),
103       mClientCompletionWait(0),
104       mAudioThreadWait(0),
105       mCompletionResult(false)
106 {
107     LOGV("AudioLocal");
108 }
109 
110 
threadLoop()111 bool AudioLocal::threadLoop()
112 {
113     if (mCurrentCommand == ECmNone) {
114         if (mState == EStRunning) {
115             if (doPlaybackOrRecord(mBuffer)) {
116                 // check exit condition
117                 if (mBuffer->bufferHandled()) {
118                     mCurrentRepeat++;
119                     LOGV("repeat %d - %d", mCurrentRepeat, mNumberRepetition);
120                     if (mCurrentRepeat == mNumberRepetition) {
121                         LOGV("AudioLocal complete command");
122                         mState = EStInitialized;
123                         mCompletionResult = true;
124                         mClientCompletionWait.post();
125                     } else {
126                         mBuffer->restart();
127                     }
128                 }
129             } else {
130                 mState = EStInitialized;
131                 //notify error
132                 mCompletionResult = false;
133                 mClientCompletionWait.post();
134             }
135             return true;
136         }
137         //LOGV("audio thread waiting");
138         mAudioThreadWait.wait();
139         //LOGV("audio thread waken up");
140         if (mCurrentCommand == ECmNone) {
141             return true; // continue to check exit condition
142         }
143     }
144 
145     int pendingCommand = mCurrentCommand;
146     // now there is a command
147     switch (pendingCommand) {
148     case ECmInitialize:
149         mCommandResult = doPrepare(mSamplingRate, AudioHardware::SAMPLES_PER_ONE_GO);
150         if (mCommandResult) {
151             mState = EStInitialized;
152         }
153         break;
154     case ECmRun: {
155         mCommandResult = doPlaybackOrRecord(mBuffer);
156         if (mCommandResult) {
157             mState = EStRunning;
158         }
159     }
160         break;
161     case ECmStop:
162         doStop();
163         mState = EStCreated;
164         mCommandResult = true;
165         break;
166     case ECmThreadStop:
167         return false;
168         break;
169     default:
170         // this should not happen
171         ASSERT(false);
172         break;
173     }
174 
175     mCurrentCommand = ECmNone;
176     mClientCommandWait.post();
177 
178     return true;
179 }
180 
181 
182