Fix issue 4604090: notification sound interrupted.
The problem is that the audio HAL fails to acquire the wake lock when playing the notification. This is because of a change that removed the mediaserver process form the system group for honeycomb. The fix consists in requesting the wake lock from PowerManagerService when AudioFlinger mixer wakes up. A consequence of this change is that audio HALs or pcm drivers do not have to hold wake locks anymore as in the past. Change-Id: I4fb3cc84816c9c408ab7fec75886baf801e1ecb5
This commit is contained in:
@@ -20,12 +20,15 @@ package android.os;
|
|||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
|
|
||||||
interface IPowerManager
|
interface IPowerManager
|
||||||
{
|
{
|
||||||
|
// WARNING: changes in acquireWakeLock() signature must be reflected in IPowerManager.cpp/h
|
||||||
void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
|
void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
|
||||||
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
|
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
|
||||||
void goToSleep(long time);
|
void goToSleep(long time);
|
||||||
void goToSleepWithReason(long time, int reason);
|
void goToSleepWithReason(long time, int reason);
|
||||||
|
// WARNING: changes in releaseWakeLock() signature must be reflected in IPowerManager.cpp/h
|
||||||
void releaseWakeLock(IBinder lock, int flags);
|
void releaseWakeLock(IBinder lock, int flags);
|
||||||
void userActivity(long when, boolean noChangeLights);
|
void userActivity(long when, boolean noChangeLights);
|
||||||
void userActivityWithForce(long when, boolean noChangeLights, boolean force);
|
void userActivityWithForce(long when, boolean noChangeLights, boolean force);
|
||||||
|
|||||||
@@ -159,6 +159,7 @@
|
|||||||
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
|
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
|
||||||
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
|
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
|
||||||
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
|
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
|
||||||
|
<assign-permission name="android.permission.WAKE_LOCK" uid="media" />
|
||||||
|
|
||||||
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
|
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
|
||||||
|
|
||||||
|
|||||||
41
include/powermanager/IPowerManager.h
Normal file
41
include/powermanager/IPowerManager.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANDROID_IPOWERMANAGER_H
|
||||||
|
#define ANDROID_IPOWERMANAGER_H
|
||||||
|
|
||||||
|
#include <utils/Errors.h>
|
||||||
|
#include <binder/IInterface.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// must be kept in sync with interface defined in IPowerManager.aidl
|
||||||
|
class IPowerManager : public IInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_META_INTERFACE(PowerManager);
|
||||||
|
|
||||||
|
virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag) = 0;
|
||||||
|
virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
}; // namespace android
|
||||||
|
|
||||||
|
#endif // ANDROID_IPOWERMANAGER_H
|
||||||
29
include/powermanager/PowerManager.h
Normal file
29
include/powermanager/PowerManager.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANDROID_POWERMANAGER_H
|
||||||
|
#define ANDROID_POWERMANAGER_H
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
// must be kept in sync with definitions in PowerManager.java
|
||||||
|
enum {
|
||||||
|
POWERMANAGER_PARTIAL_WAKE_LOCK = 1, // equals PowerManager.PARTIAL_WAKE_LOCK constant
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace android
|
||||||
|
|
||||||
|
#endif // ANDROID_POWERMANAGER_H
|
||||||
@@ -21,7 +21,8 @@ LOCAL_SHARED_LIBRARIES := \
|
|||||||
libhardware \
|
libhardware \
|
||||||
libhardware_legacy \
|
libhardware_legacy \
|
||||||
libeffects \
|
libeffects \
|
||||||
libdl
|
libdl \
|
||||||
|
libpowermanager
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := \
|
LOCAL_STATIC_LIBRARIES := \
|
||||||
libcpustats \
|
libcpustats \
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
#include <audio_effects/effect_visualizer.h>
|
#include <audio_effects/effect_visualizer.h>
|
||||||
|
|
||||||
#include <cpustats/ThreadCpuUsage.h>
|
#include <cpustats/ThreadCpuUsage.h>
|
||||||
|
#include <powermanager/PowerManager.h>
|
||||||
// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
|
// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -887,14 +888,18 @@ void AudioFlinger::removeClient_l(pid_t pid)
|
|||||||
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
|
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
|
||||||
: Thread(false),
|
: Thread(false),
|
||||||
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
|
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
|
||||||
mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device)
|
mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
|
||||||
|
mDevice(device)
|
||||||
{
|
{
|
||||||
|
mDeathRecipient = new PMDeathRecipient(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioFlinger::ThreadBase::~ThreadBase()
|
AudioFlinger::ThreadBase::~ThreadBase()
|
||||||
{
|
{
|
||||||
mParamCond.broadcast();
|
mParamCond.broadcast();
|
||||||
mNewParameters.clear();
|
mNewParameters.clear();
|
||||||
|
// do not lock the mutex in destructor
|
||||||
|
releaseWakeLock_l();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioFlinger::ThreadBase::exit()
|
void AudioFlinger::ThreadBase::exit()
|
||||||
@@ -1061,6 +1066,69 @@ status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String1
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioFlinger::ThreadBase::acquireWakeLock()
|
||||||
|
{
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
acquireWakeLock_l();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioFlinger::ThreadBase::acquireWakeLock_l()
|
||||||
|
{
|
||||||
|
if (mPowerManager == 0) {
|
||||||
|
// use checkService() to avoid blocking if power service is not up yet
|
||||||
|
sp<IBinder> binder =
|
||||||
|
defaultServiceManager()->checkService(String16("power"));
|
||||||
|
if (binder == 0) {
|
||||||
|
LOGW("Thread %s cannot connect to the power manager service", mName);
|
||||||
|
} else {
|
||||||
|
mPowerManager = interface_cast<IPowerManager>(binder);
|
||||||
|
binder->linkToDeath(mDeathRecipient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mPowerManager != 0) {
|
||||||
|
sp<IBinder> binder = new BBinder();
|
||||||
|
status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
|
||||||
|
binder,
|
||||||
|
String16(mName));
|
||||||
|
if (status == NO_ERROR) {
|
||||||
|
mWakeLockToken = binder;
|
||||||
|
}
|
||||||
|
LOGV("acquireWakeLock_l() %s status %d", mName, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioFlinger::ThreadBase::releaseWakeLock()
|
||||||
|
{
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
releaseWakeLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioFlinger::ThreadBase::releaseWakeLock_l()
|
||||||
|
{
|
||||||
|
if (mWakeLockToken != 0) {
|
||||||
|
LOGV("releaseWakeLock_l() %s", mName);
|
||||||
|
if (mPowerManager != 0) {
|
||||||
|
mPowerManager->releaseWakeLock(mWakeLockToken, 0);
|
||||||
|
}
|
||||||
|
mWakeLockToken.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioFlinger::ThreadBase::clearPowerManager()
|
||||||
|
{
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
releaseWakeLock_l();
|
||||||
|
mPowerManager.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
|
||||||
|
{
|
||||||
|
sp<ThreadBase> thread = mThread.promote();
|
||||||
|
if (thread != 0) {
|
||||||
|
thread->clearPowerManager();
|
||||||
|
}
|
||||||
|
LOGW("power manager service died !!!");
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -1072,6 +1140,8 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge
|
|||||||
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
|
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
|
||||||
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
|
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
|
||||||
{
|
{
|
||||||
|
snprintf(mName, kNameLength, "AudioOut_%d", id);
|
||||||
|
|
||||||
readOutputParameters();
|
readOutputParameters();
|
||||||
|
|
||||||
mMasterVolume = mAudioFlinger->masterVolume();
|
mMasterVolume = mAudioFlinger->masterVolume();
|
||||||
@@ -1170,12 +1240,7 @@ status_t AudioFlinger::PlaybackThread::readyToRun()
|
|||||||
|
|
||||||
void AudioFlinger::PlaybackThread::onFirstRef()
|
void AudioFlinger::PlaybackThread::onFirstRef()
|
||||||
{
|
{
|
||||||
const size_t SIZE = 256;
|
run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
|
||||||
char buffer[SIZE];
|
|
||||||
|
|
||||||
snprintf(buffer, SIZE, "Playback Thread %p", this);
|
|
||||||
|
|
||||||
run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
|
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
|
||||||
@@ -1522,6 +1587,8 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
const CentralTendencyStatistics& stats = cpu.statistics();
|
const CentralTendencyStatistics& stats = cpu.statistics();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
acquireWakeLock();
|
||||||
|
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_CPU_USAGE
|
#ifdef DEBUG_CPU_USAGE
|
||||||
@@ -1585,10 +1652,12 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
|
|
||||||
if (exitPending()) break;
|
if (exitPending()) break;
|
||||||
|
|
||||||
|
releaseWakeLock_l();
|
||||||
// wait until we have something to do...
|
// wait until we have something to do...
|
||||||
LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
|
LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
|
||||||
mWaitWorkCV.wait(mLock);
|
mWaitWorkCV.wait(mLock);
|
||||||
LOGV("MixerThread %p TID %d waking up\n", this, gettid());
|
LOGV("MixerThread %p TID %d waking up\n", this, gettid());
|
||||||
|
acquireWakeLock_l();
|
||||||
|
|
||||||
if (mMasterMute == false) {
|
if (mMasterMute == false) {
|
||||||
char value[PROPERTY_VALUE_MAX];
|
char value[PROPERTY_VALUE_MAX];
|
||||||
@@ -1689,6 +1758,8 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
mOutput->stream->common.standby(&mOutput->stream->common);
|
mOutput->stream->common.standby(&mOutput->stream->common);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
releaseWakeLock();
|
||||||
|
|
||||||
LOGV("MixerThread %p exiting", this);
|
LOGV("MixerThread %p exiting", this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2176,6 +2247,8 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
// hardware resources as soon as possible
|
// hardware resources as soon as possible
|
||||||
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
|
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
|
||||||
|
|
||||||
|
acquireWakeLock();
|
||||||
|
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
bool rampVolume;
|
bool rampVolume;
|
||||||
@@ -2215,9 +2288,11 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
|
|
||||||
if (exitPending()) break;
|
if (exitPending()) break;
|
||||||
|
|
||||||
|
releaseWakeLock_l();
|
||||||
LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
|
LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
|
||||||
mWaitWorkCV.wait(mLock);
|
mWaitWorkCV.wait(mLock);
|
||||||
LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
|
LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
|
||||||
|
acquireWakeLock_l();
|
||||||
|
|
||||||
if (mMasterMute == false) {
|
if (mMasterMute == false) {
|
||||||
char value[PROPERTY_VALUE_MAX];
|
char value[PROPERTY_VALUE_MAX];
|
||||||
@@ -2436,6 +2511,8 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
mOutput->stream->common.standby(&mOutput->stream->common);
|
mOutput->stream->common.standby(&mOutput->stream->common);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
releaseWakeLock();
|
||||||
|
|
||||||
LOGV("DirectOutputThread %p exiting", this);
|
LOGV("DirectOutputThread %p exiting", this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2561,6 +2638,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
|
|||||||
uint32_t sleepTime = idleSleepTime;
|
uint32_t sleepTime = idleSleepTime;
|
||||||
Vector< sp<EffectChain> > effectChains;
|
Vector< sp<EffectChain> > effectChains;
|
||||||
|
|
||||||
|
acquireWakeLock();
|
||||||
|
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
processConfigEvents();
|
processConfigEvents();
|
||||||
@@ -2601,9 +2680,12 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
|
|||||||
|
|
||||||
if (exitPending()) break;
|
if (exitPending()) break;
|
||||||
|
|
||||||
|
releaseWakeLock_l();
|
||||||
LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
|
LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
|
||||||
mWaitWorkCV.wait(mLock);
|
mWaitWorkCV.wait(mLock);
|
||||||
LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
|
LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
|
||||||
|
acquireWakeLock_l();
|
||||||
|
|
||||||
if (mMasterMute == false) {
|
if (mMasterMute == false) {
|
||||||
char value[PROPERTY_VALUE_MAX];
|
char value[PROPERTY_VALUE_MAX];
|
||||||
property_get("ro.audio.silent", value, "0");
|
property_get("ro.audio.silent", value, "0");
|
||||||
@@ -2690,6 +2772,8 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
|
|||||||
effectChains.clear();
|
effectChains.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
releaseWakeLock();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3814,6 +3898,9 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
|
|||||||
mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
|
mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
|
||||||
{
|
{
|
||||||
mType = ThreadBase::RECORD;
|
mType = ThreadBase::RECORD;
|
||||||
|
|
||||||
|
snprintf(mName, kNameLength, "AudioIn_%d", id);
|
||||||
|
|
||||||
mReqChannelCount = popcount(channels);
|
mReqChannelCount = popcount(channels);
|
||||||
mReqSampleRate = sampleRate;
|
mReqSampleRate = sampleRate;
|
||||||
readInputParameters();
|
readInputParameters();
|
||||||
@@ -3831,12 +3918,7 @@ AudioFlinger::RecordThread::~RecordThread()
|
|||||||
|
|
||||||
void AudioFlinger::RecordThread::onFirstRef()
|
void AudioFlinger::RecordThread::onFirstRef()
|
||||||
{
|
{
|
||||||
const size_t SIZE = 256;
|
run(mName, PRIORITY_URGENT_AUDIO);
|
||||||
char buffer[SIZE];
|
|
||||||
|
|
||||||
snprintf(buffer, SIZE, "Record Thread %p", this);
|
|
||||||
|
|
||||||
run(buffer, PRIORITY_URGENT_AUDIO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioFlinger::RecordThread::threadLoop()
|
bool AudioFlinger::RecordThread::threadLoop()
|
||||||
@@ -3847,6 +3929,8 @@ bool AudioFlinger::RecordThread::threadLoop()
|
|||||||
|
|
||||||
nsecs_t lastWarning = 0;
|
nsecs_t lastWarning = 0;
|
||||||
|
|
||||||
|
acquireWakeLock();
|
||||||
|
|
||||||
// start recording
|
// start recording
|
||||||
while (!exitPending()) {
|
while (!exitPending()) {
|
||||||
|
|
||||||
@@ -3863,10 +3947,12 @@ bool AudioFlinger::RecordThread::threadLoop()
|
|||||||
|
|
||||||
if (exitPending()) break;
|
if (exitPending()) break;
|
||||||
|
|
||||||
|
releaseWakeLock_l();
|
||||||
LOGV("RecordThread: loop stopping");
|
LOGV("RecordThread: loop stopping");
|
||||||
// go to sleep
|
// go to sleep
|
||||||
mWaitWorkCV.wait(mLock);
|
mWaitWorkCV.wait(mLock);
|
||||||
LOGV("RecordThread: loop starting");
|
LOGV("RecordThread: loop starting");
|
||||||
|
acquireWakeLock_l();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mActiveTrack != 0) {
|
if (mActiveTrack != 0) {
|
||||||
@@ -4021,6 +4107,8 @@ bool AudioFlinger::RecordThread::threadLoop()
|
|||||||
|
|
||||||
mStartStopCond.broadcast();
|
mStartStopCond.broadcast();
|
||||||
|
|
||||||
|
releaseWakeLock();
|
||||||
|
|
||||||
LOGV("RecordThread %p exiting", this);
|
LOGV("RecordThread %p exiting", this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
|
|
||||||
#include "AudioBufferProvider.h"
|
#include "AudioBufferProvider.h"
|
||||||
|
|
||||||
|
#include <powermanager/IPowerManager.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
class audio_track_cblk_t;
|
class audio_track_cblk_t;
|
||||||
@@ -287,6 +289,8 @@ private:
|
|||||||
status_t dumpBase(int fd, const Vector<String16>& args);
|
status_t dumpBase(int fd, const Vector<String16>& args);
|
||||||
status_t dumpEffectChains(int fd, const Vector<String16>& args);
|
status_t dumpEffectChains(int fd, const Vector<String16>& args);
|
||||||
|
|
||||||
|
void clearPowerManager();
|
||||||
|
|
||||||
// base for record and playback
|
// base for record and playback
|
||||||
class TrackBase : public AudioBufferProvider, public RefBase {
|
class TrackBase : public AudioBufferProvider, public RefBase {
|
||||||
|
|
||||||
@@ -386,6 +390,21 @@ private:
|
|||||||
int mParam;
|
int mParam;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PMDeathRecipient : public IBinder::DeathRecipient {
|
||||||
|
public:
|
||||||
|
PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
|
||||||
|
virtual ~PMDeathRecipient() {}
|
||||||
|
|
||||||
|
// IBinder::DeathRecipient
|
||||||
|
virtual void binderDied(const wp<IBinder>& who);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PMDeathRecipient(const PMDeathRecipient&);
|
||||||
|
PMDeathRecipient& operator = (const PMDeathRecipient&);
|
||||||
|
|
||||||
|
wp<ThreadBase> mThread;
|
||||||
|
};
|
||||||
|
|
||||||
virtual status_t initCheck() const = 0;
|
virtual status_t initCheck() const = 0;
|
||||||
int type() const { return mType; }
|
int type() const { return mType; }
|
||||||
uint32_t sampleRate() const;
|
uint32_t sampleRate() const;
|
||||||
@@ -462,6 +481,11 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void acquireWakeLock();
|
||||||
|
void acquireWakeLock_l();
|
||||||
|
void releaseWakeLock();
|
||||||
|
void releaseWakeLock_l();
|
||||||
|
|
||||||
friend class Track;
|
friend class Track;
|
||||||
friend class TrackBase;
|
friend class TrackBase;
|
||||||
friend class PlaybackThread;
|
friend class PlaybackThread;
|
||||||
@@ -490,6 +514,11 @@ private:
|
|||||||
Vector< sp<EffectChain> > mEffectChains;
|
Vector< sp<EffectChain> > mEffectChains;
|
||||||
uint32_t mDevice; // output device for PlaybackThread
|
uint32_t mDevice; // output device for PlaybackThread
|
||||||
// input + output devices for RecordThread
|
// input + output devices for RecordThread
|
||||||
|
static const int kNameLength = 32;
|
||||||
|
char mName[kNameLength];
|
||||||
|
sp<IPowerManager> mPowerManager;
|
||||||
|
sp<IBinder> mWakeLockToken;
|
||||||
|
sp<PMDeathRecipient> mDeathRecipient;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- PlaybackThread ---
|
// --- PlaybackThread ---
|
||||||
|
|||||||
15
services/powermanager/Android.mk
Normal file
15
services/powermanager/Android.mk
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES:= \
|
||||||
|
IPowerManager.cpp
|
||||||
|
|
||||||
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
|
libutils \
|
||||||
|
libbinder
|
||||||
|
|
||||||
|
LOCAL_MODULE:= libpowermanager
|
||||||
|
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
71
services/powermanager/IPowerManager.cpp
Normal file
71
services/powermanager/IPowerManager.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "IPowerManager"
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <binder/Parcel.h>
|
||||||
|
|
||||||
|
#include <powermanager/IPowerManager.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
// must be kept in sync with IPowerManager.aidl
|
||||||
|
enum {
|
||||||
|
ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
|
||||||
|
RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
class BpPowerManager : public BpInterface<IPowerManager>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BpPowerManager(const sp<IBinder>& impl)
|
||||||
|
: BpInterface<IPowerManager>(impl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag)
|
||||||
|
{
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
|
||||||
|
|
||||||
|
data.writeInt32(flags);
|
||||||
|
data.writeStrongBinder(lock);
|
||||||
|
data.writeString16(tag);
|
||||||
|
// no WorkSource passed
|
||||||
|
data.writeInt32(0);
|
||||||
|
return remote()->transact(ACQUIRE_WAKE_LOCK, data, &reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags)
|
||||||
|
{
|
||||||
|
Parcel data, reply;
|
||||||
|
data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
|
||||||
|
data.writeStrongBinder(lock);
|
||||||
|
data.writeInt32(flags);
|
||||||
|
return remote()->transact(RELEASE_WAKE_LOCK, data, &reply);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
}; // namespace android
|
||||||
Reference in New Issue
Block a user