am 4d8adefd: AI 149136: Restore RECORD_AUDIO permission check to MediaRecorder. When we moved the media recorder to the media server process, we lost the permission check that was done at the process boundary in the AudioRecord binder interface because the AudioRecord object is created in the same process. This change adds a permission check in the MediaRecorderClient:setAudioSource() method. BUG=1868334
Merge commit '4d8adefd35efdea849611b8b02d61f9517e47760' into donut
* commit '4d8adefd35efdea849611b8b02d61f9517e47760':
AI 149136: Restore RECORD_AUDIO permission check to MediaRecorder.
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 7164b78..6aa40d0 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -312,7 +312,6 @@
bool processAudioBuffer(const sp<ClientRecordThread>& thread);
- sp<IAudioFlinger> mAudioFlinger;
sp<IAudioRecord> mAudioRecord;
sp<IMemory> mCblkMemory;
sp<ClientRecordThread> mClientRecordThread;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 7645978..ba0467c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -383,7 +383,6 @@
bool processAudioBuffer(const sp<AudioTrackThread>& thread);
- sp<IAudioFlinger> mAudioFlinger;
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
sp<AudioTrackThread> mAudioTrackThread;
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index ec64e4d..6b0cc8a 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -18,7 +18,7 @@
#define ANDROID_TONEGENERATOR_H_
#include <utils/RefBase.h>
-#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
@@ -49,21 +49,30 @@
TONE_DTMF_C, // C key: 1633Hz, 852Hz
TONE_DTMF_D, // D key: 1633Hz, 941Hz
// Call supervisory tones: 3GPP TS 22.001 (CEPT)
- TONE_SUP_DIAL, // Dial tone: 425Hz, continuous
- TONE_SUP_BUSY, // Busy tone: 425Hz, 500ms ON, 500ms OFF...
- TONE_SUP_CONGESTION, // Congestion tone: 425Hz, 200ms ON, 200ms OFF...
- TONE_SUP_RADIO_ACK, // Radio path acknowlegment: 425Hz, 200ms ON
+ TONE_SUP_DIAL, // Dial tone: CEPT: 425Hz, continuous
+ FIRST_SUP_TONE = TONE_SUP_DIAL,
+ TONE_SUP_BUSY, // Busy tone, CEPT: 425Hz, 500ms ON, 500ms OFF...
+ TONE_SUP_CONGESTION, // Congestion tone CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF...
+ TONE_SUP_RADIO_ACK, // Radio path acknowlegment, CEPT, ANSI: 425Hz, 200ms ON
TONE_SUP_RADIO_NOTAVAIL, // Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts
TONE_SUP_ERROR, // Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF...
- TONE_SUP_CALL_WAITING, // Call Waiting: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
- TONE_SUP_RINGTONE, // Ring Tone: 425Hz, 1s ON, 4s OFF...
+ TONE_SUP_CALL_WAITING, // Call Waiting CEPT,JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+ TONE_SUP_RINGTONE, // Ring Tone CEPT, JAPAN: 425Hz, 1s ON, 4s OFF...
+ LAST_SUP_TONE = TONE_SUP_RINGTONE,
// Proprietary tones: 3GPP TS 31.111
TONE_PROP_BEEP, // General beep: 400Hz+1200Hz, 35ms ON
TONE_PROP_ACK, // Positive Acknowlgement: 1200Hz, 100ms ON, 100ms OFF 2 bursts
- TONE_PROP_NACK, // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON
+ TONE_PROP_NACK, // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON
TONE_PROP_PROMPT, // Prompt tone: 400Hz+1200Hz, 200ms ON
TONE_PROP_BEEP2, // General double beep: 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms on
- NUM_TONES
+ // Additional call supervisory tones: specified by IS-95 only
+ TONE_SUP_INTERCEPT, // Intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms.
+ TONE_SUP_INTERCEPT_ABBREV, // Abbreviated intercept: intercept tone limited to 4 seconds
+ TONE_SUP_CONGESTION_ABBREV, // Abbreviated congestion: congestion tone limited to 4 seconds
+ TONE_SUP_CONFIRM, // Confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle.
+ TONE_SUP_PIP, // Pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off).
+ NUM_TONES,
+ NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
};
ToneGenerator(int streamType, float volume);
@@ -85,13 +94,45 @@
TONE_RESTARTING //
};
- static const unsigned int TONEGEN_MAX_WAVES = 3;
- static const unsigned int TONEGEN_MAX_SEGMENTS = 4; // Maximun number of elenemts in
+
+ // Region specific tones.
+ // These supervisory tones are different depending on the region (USA/CANADA, JAPAN, rest of the world).
+ // When a tone in the range [FIRST_SUP_TONE, LAST_SUP_TONE] is requested, the region is determined
+ // from system property gsm.operator.iso-country and the proper tone descriptor is selected with the
+ // help of sToneMappingTable[]
+ enum regional_tone_type {
+ // ANSI supervisory tones
+ TONE_ANSI_DIAL = NUM_TONES, // Dial tone: a continuous 350 Hz + 440 Hz tone.
+ TONE_ANSI_BUSY, // Busy tone on: a 480 Hz + 620 Hz tone repeated in a 500 ms on, 500 ms off cycle.
+ TONE_ANSI_CONGESTION, // Network congestion (reorder) tone on: a 480 Hz + 620 Hz tone repeated in a 250 ms on, 250 ms off cycle.
+ TONE_ANSI_CALL_WAITING, // Call waiting tone on: 440 Hz, on for 300 ms, 9,7 s off followed by
+ // (440 Hz, on for 100 ms off for 100 ms, on for 100 ms, 9,7s off and repeated as necessary).
+ TONE_ANSI_RINGTONE, // Ring Tone: a 440 Hz + 480 Hz tone repeated in a 2 s on, 4 s off pattern.
+ // JAPAN Supervisory tones
+ TONE_JAPAN_DIAL, // Dial tone: 400Hz, continuous
+ TONE_JAPAN_BUSY, // Busy tone: 400Hz, 500ms ON, 500ms OFF...
+ TONE_JAPAN_RADIO_ACK, // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
+ NUM_ALTERNATE_TONES
+ };
+
+ enum region {
+ ANSI,
+ JAPAN,
+ CEPT,
+ NUM_REGIONS
+ };
+
+ static const unsigned char sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES];
+
+ static const unsigned int TONEGEN_MAX_WAVES = 3; // Maximun number of sine waves in a tone segment
+ static const unsigned int TONEGEN_MAX_SEGMENTS = 5; // Maximun number of segments in a tone descriptor
static const unsigned int TONEGEN_INF = 0xFFFFFFFF; // Represents infinite time duration
static const float TONEGEN_GAIN = 0.9; // Default gain passed to WaveGenerator().
// ToneDescriptor class contains all parameters needed to generate a tone:
- // - The array waveFreq[] contains the frequencies of all individual waves making the multi-tone.
+ // - The array waveFreq[]:
+ // 1 for static tone descriptors: contains the frequencies of all individual waves making the multi-tone.
+ // 2 for active tone descritors: contains the indexes of the WaveGenerator objects in mWaveGens
// The number of sine waves varies from 1 to TONEGEN_MAX_WAVES.
// The first null value indicates that no more waves are needed.
// - The array segments[] is used to generate the tone pulses. A segment is a period of time
@@ -100,17 +141,25 @@
// The data stored in segments[] is the duration of the corresponding period in ms.
// The first segment encountered with a 0 duration indicates that no more segment follows.
// - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated.
- // When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount.
- // If mCurCount > repeatCnt, the tone is stopped automatically.
+ // When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount.
+ // If mCurCount > repeatCnt, the tone is stopped automatically. Otherwise, tone sequence will be
+ // restarted from segment repeatSegment.
+ // - repeatSegment number of the first repeated segment when repeatCnt is not null
+
+ class ToneSegment {
+ public:
+ unsigned int duration;
+ unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
+ };
class ToneDescriptor {
public:
- unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
- unsigned long segments[TONEGEN_MAX_SEGMENTS+1];
+ ToneSegment segments[TONEGEN_MAX_SEGMENTS+1];
unsigned long repeatCnt;
+ unsigned long repeatSegment;
};
- static const ToneDescriptor toneDescriptors[NUM_TONES];
+ static const ToneDescriptor sToneDescriptors[];
unsigned int mTotalSmp; // Total number of audio samples played (gives current time)
unsigned int mNextSegSmp; // Position of next segment transition expressed in samples
@@ -121,6 +170,7 @@
unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[]
unsigned short mCurCount; // Current sequence repeat count
volatile unsigned short mState; // ToneGenerator state (tone_state)
+ unsigned short mRegion;
const ToneDescriptor *mpToneDesc; // pointer to active tone descriptor
const ToneDescriptor *mpNewToneDesc; // pointer to next active tone descriptor
@@ -136,8 +186,9 @@
bool initAudioTrack();
static void audioCallback(int event, void* user, void *info);
bool prepareWave();
- unsigned int numWaves();
+ unsigned int numWaves(unsigned int segmentIdx);
void clearWaveGens();
+ int getToneForRegion(int toneType);
// WaveGenerator generates a single sine wave
class WaveGenerator {
@@ -167,7 +218,7 @@
short mAmplitude_Q15; // Q15 amplitude
};
- Vector<WaveGenerator *> mWaveGens; // list of active wave generators.
+ KeyedVector<unsigned short, WaveGenerator *> mWaveGens; // list of active wave generators.
};
}
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 986f88e..1720af0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -73,7 +73,6 @@
// Otherwise the callback thread will never exit.
stop();
if (mClientRecordThread != 0) {
- mCblk->cv.signal();
mClientRecordThread->requestExitAndWait();
mClientRecordThread.clear();
}
@@ -96,7 +95,7 @@
{
LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
- if (mAudioFlinger != 0) {
+ if (mAudioRecord != 0) {
return INVALID_OPERATION;
}
@@ -181,7 +180,6 @@
mStatus = NO_ERROR;
- mAudioFlinger = audioFlinger;
mAudioRecord = record;
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
@@ -293,6 +291,7 @@
}
if (android_atomic_and(~1, &mActive) == 1) {
+ mCblk->cv.signal();
mAudioRecord->stop();
// the record head position will reset to 0, so if a marker is set, we need
// to activate it again
@@ -375,6 +374,7 @@
status_t result;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
+ uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
audioBuffer->frameCount = 0;
audioBuffer->size = 0;
@@ -391,9 +391,9 @@
if (UNLIKELY(!waitCount))
return WOULD_BLOCK;
timeout = 0;
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
if (__builtin_expect(result!=NO_ERROR, false)) {
- cblk->waitTimeMs += WAIT_PERIOD_MS;
+ cblk->waitTimeMs += waitTimeMs;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
LOGW( "obtainBuffer timed out (is the CPU pegged?) "
"user=%08x, server=%08x", cblk->user, cblk->server);
@@ -520,7 +520,7 @@
status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
- LOGE("Error obtaining an audio buffer, giving up.");
+ LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
return false;
}
break;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 24f7281..289bd75 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -92,7 +92,6 @@
// Otherwise the callback thread will never exit.
stop();
if (mAudioTrackThread != 0) {
- mCblk->cv.signal();
mAudioTrackThread->requestExitAndWait();
mAudioTrackThread.clear();
}
@@ -117,7 +116,7 @@
LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
- if (mAudioFlinger != 0) {
+ if (mAudioTrack != 0) {
LOGE("Track already in use");
return INVALID_OPERATION;
}
@@ -228,7 +227,6 @@
mStatus = NO_ERROR;
- mAudioFlinger = audioFlinger;
mAudioTrack = track;
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
@@ -357,6 +355,7 @@
}
if (android_atomic_and(~1, &mActive) == 1) {
+ mCblk->cv.signal();
mAudioTrack->stop();
// Cancel loops (If we are in the middle of a loop, playback
// would not stop until loopCount reaches 0).
@@ -596,6 +595,7 @@
status_t result;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
+ uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
audioBuffer->frameCount = 0;
audioBuffer->size = 0;
@@ -614,9 +614,9 @@
if (UNLIKELY(!waitCount))
return WOULD_BLOCK;
timeout = 0;
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
if (__builtin_expect(result!=NO_ERROR, false)) {
- cblk->waitTimeMs += WAIT_PERIOD_MS;
+ cblk->waitTimeMs += waitTimeMs;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
// timing out when a loop has been set and we have already written upto loop end
// is a normal condition: no need to wake AudioFlinger up.
@@ -798,7 +798,7 @@
status_t err = obtainBuffer(&audioBuffer, 1);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
- LOGE("Error obtaining an audio buffer, giving up.");
+ LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
return false;
}
break;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 5cbb25c..52bd7d4 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -336,7 +336,7 @@
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- remote()->transact(WAKE_UP, data, &reply);
+ remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
return;
}
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 5feb11f..9d00aef 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -43,7 +43,7 @@
Parcel data, reply;
data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
data.writeInt32((int)enabled);
- remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply);
+ remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 8560593..81ee92c 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -24,44 +24,235 @@
#include <sys/resource.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
+#include <cutils/properties.h>
#include "media/ToneGenerator.h"
+
namespace android {
+
// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
-const ToneGenerator::ToneDescriptor
- ToneGenerator::toneDescriptors[NUM_TONES] = {
- // waveFreq[] segments[] repeatCnt
- { { 1336, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_0
- { { 1209, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_1
- { { 1336, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_2
- { { 1477, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_3
- { { 1209, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_4
- { { 1336, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_5
- { { 1477, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_6
- { { 1209, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_7
- { { 1336, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_8
- { { 1477, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_9
- { { 1209, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_S
- { { 1477, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_P
- { { 1633, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_A
- { { 1633, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_B
- { { 1633, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_C
- { { 1633, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_D
- { { 425, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_DIAL
- { { 425, 0 }, { 500, 500, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_BUSY
- { { 425, 0 }, { 200, 200, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CONGESTION
- { { 425, 0 }, { 200, 0 }, 0 }, // TONE_SUP_RADIO_ACK
- { { 425, 0 }, { 200, 200, 0 }, 2 }, // TONE_SUP_RADIO_NOTAVAIL
- { { 950, 1400, 1800, 0 }, { 330, 1000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_ERROR
- { { 425, 0 }, { 200, 600, 200, 3000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CALL_WAITING
- { { 425, 0 }, { 1000, 4000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_RINGTONE
- { { 400, 1200, 0 }, { 40, 0 }, 0 }, // TONE_PROP_BEEP
- { { 1200, 0 }, { 100, 100, 0 }, 1 }, // TONE_PROP_ACK
- { { 300, 400, 500, 0 }, { 400, 0 }, 0 }, // TONE_PROP_NACK
- { { 400, 1200, 0 }, { 200, 0 }, 0 }, // TONE_PROP_PROMPT
- { { 400, 1200, 0 }, { 40, 200, 40, 0 }, 0 } // TONE_PROP_BEEP2
- };
+const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
+ { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }},
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_0
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_1
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_2
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_3
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_4
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_5
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_6
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_7
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_8
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_9
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_S
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_P
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_A
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_B
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_C
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_D
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_DIAL
+ { segments: { { duration: 500 , waveFreq: { 425, 0 }},
+ { duration: 500, waveFreq: { 0 }},
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_BUSY
+ { segments: { { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 200, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_CONGESTION
+ { segments: { { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_SUP_RADIO_ACK
+ { segments: { { duration: 200, waveFreq: { 425, 0 }},
+ { duration: 200, waveFreq: { 0 }},
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_SUP_RADIO_NOTAVAIL
+ { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }},
+ { duration: 1000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_ERROR
+ { segments: { { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 600, waveFreq: { 0 } },
+ { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 3000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_CALL_WAITING
+ { segments: { { duration: 1000, waveFreq: { 425, 0 } },
+ { duration: 4000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_RINGTONE
+ { segments: { { duration: 40, waveFreq: { 400, 1200, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_BEEP
+ { segments: { { duration: 100, waveFreq: { 1200, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 1,
+ repeatSegment: 0 }, // TONE_PROP_ACK
+ { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_NACK
+ { segments: { { duration: 200, waveFreq: { 400, 1200, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_PROMPT
+ { segments: { { duration: 40, waveFreq: { 400, 1200, 0 } },
+ { duration: 200, waveFreq: { 0 } },
+ { duration: 40, waveFreq: { 400, 1200, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_BEEP2
+ { segments: { { duration: 250, waveFreq: { 440, 0 } },
+ { duration: 250, waveFreq: { 620, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_INTERCEPT
+ { segments: { { duration: 250, waveFreq: { 440, 0 } },
+ { duration: 250, waveFreq: { 620, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_SUP_INTERCEPT_ABBREV
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 } },
+ { duration: 250, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_SUP_CONGESTION_ABBREV
+ { segments: { { duration: 100, waveFreq: { 350, 440, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_SUP_CONFIRM
+ { segments: { { duration: 100, waveFreq: { 480, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 3,
+ repeatSegment: 0 }, // TONE_SUP_PIP
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_DIAL
+ { segments: { { duration: 500, waveFreq: { 480, 620, 0 } },
+ { duration: 500, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_BUSY
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 } },
+ { duration: 250, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_CONGESTION
+ { segments: { { duration: 300, waveFreq: { 440, 0 } },
+ { duration: 9700, waveFreq: { 0 } },
+ { duration: 100, waveFreq: { 440, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 100, waveFreq: { 440, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 1 }, // TONE_ANSI_CALL_WAITING
+ { segments: { { duration: 2000, waveFreq: { 440, 480, 0 } },
+ { duration: 4000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_RINGTONE
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_DIAL
+ { segments: { { duration: 500, waveFreq: { 400, 0 } },
+ { duration: 500, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_BUSY
+ { segments: { { duration: 1000, waveFreq: { 400, 0 } },
+ { duration: 2000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_RADIO_ACK
+};
+
+// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
+// to actual tone for current region.
+const unsigned char ToneGenerator::sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES] = {
+ { // ANSI
+ TONE_ANSI_DIAL, // TONE_SUP_DIAL
+ TONE_ANSI_BUSY, // TONE_SUP_BUSY
+ TONE_ANSI_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_ANSI_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_ANSI_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // JAPAN
+ TONE_JAPAN_DIAL, // TONE_SUP_DIAL
+ TONE_JAPAN_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_JAPAN_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
// ToneGenerator class Implementation
@@ -105,6 +296,17 @@
// Generate tone by chunks of 20 ms to keep cadencing precision
mProcessSize = (mSamplingRate * 20) / 1000;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("gsm.operator.iso-country", value, "");
+ if (strcmp(value,"us") == 0 ||
+ strcmp(value,"ca") == 0) {
+ mRegion = ANSI;
+ } else if (strcmp(value,"jp") == 0) {
+ mRegion = JAPAN;
+ } else {
+ mRegion = CEPT;
+ }
+
if (initAudioTrack()) {
LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000));
} else {
@@ -155,7 +357,7 @@
bool ToneGenerator::startTone(int toneType) {
bool lResult = false;
- if (toneType >= NUM_TONES)
+ if ((toneType < 0) || (toneType >= NUM_TONES))
return lResult;
if (mState == TONE_IDLE) {
@@ -170,7 +372,8 @@
mLock.lock();
// Get descriptor for requested tone
- mpNewToneDesc = &toneDescriptors[toneType];
+ toneType = getToneForRegion(toneType);
+ mpNewToneDesc = &sToneDescriptors[toneType];
if (mState == TONE_INIT) {
if (prepareWave()) {
@@ -333,6 +536,7 @@
ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
short *lpOut = buffer->i16;
unsigned int lNumSmp = buffer->size/sizeof(short);
+ const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc;
if (buffer->size == 0) return;
@@ -377,7 +581,7 @@
// Exit if tone sequence is over
- if (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] == 0) {
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
if (lpToneGen->mState == TONE_PLAYING) {
lpToneGen->mState = TONE_STOPPING;
}
@@ -390,52 +594,64 @@
LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000));
lGenSmp = lReqSmp;
-
- if (lpToneGen->mCurSegment & 0x0001) {
- // If odd segment, OFF -> ON transition : reset wave generator
- lWaveCmd = WaveGenerator::WAVEGEN_START;
-
- LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
- } else {
- // If even segment, ON -> OFF transition : ramp volume down
+
+ // If segment, ON -> OFF transition : ramp volume down
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
lWaveCmd = WaveGenerator::WAVEGEN_STOP;
-
+ unsigned int lFreqIdx = 0;
+ unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
+
+ while (lFrequency != 0) {
+ WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
+ lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+ lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
+ }
LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
}
-
- // Pre increment segment index and handle loop if last segment reached
- if (lpToneGen->mpToneDesc->segments[++lpToneGen->mCurSegment] == 0) {
+
+ // Go to next segment
+ lpToneGen->mCurSegment++;
+
+ // Handle loop if last segment reached
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
LOGV("Last Seg: %d\n", lpToneGen->mCurSegment);
// Pre increment loop count and restart if total count not reached. Stop sequence otherwise
- if (++lpToneGen->mCurCount <= lpToneGen->mpToneDesc->repeatCnt) {
+ if (++lpToneGen->mCurCount <= lpToneDesc->repeatCnt) {
LOGV("Repeating Count: %d\n", lpToneGen->mCurCount);
- lpToneGen->mCurSegment = 0;
+ lpToneGen->mCurSegment = lpToneDesc->repeatSegment;
+ if (lpToneDesc->segments[lpToneDesc->repeatSegment].waveFreq[0] != 0) {
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+ }
LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
(lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
} else {
+ lGenSmp = 0;
LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000));
-
- // Cancel OFF->ON transition in case previous segment tone state was OFF
- if (!(lpToneGen->mCurSegment & 0x0001)) {
- lGenSmp = 0;
- }
}
} else {
LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
(lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
+ // If next segment is not silent, OFF -> ON transition : reset wave generator
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+
+ LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
+ } else {
+ lGenSmp = 0;
+ }
}
// Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more
lpToneGen->mNextSegSmp
- += (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] * lpToneGen->mSamplingRate) / 1000;
+ += (lpToneDesc->segments[lpToneGen->mCurSegment].duration * lpToneGen->mSamplingRate) / 1000;
} else {
// Inside a segment keep tone ON or OFF
- if (lpToneGen->mCurSegment & 0x0001) {
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] == 0) {
lGenSmp = 0; // If odd segment, tone is currently OFF
} else {
lGenSmp = lReqSmp; // If event segment, tone is currently ON
@@ -444,11 +660,13 @@
if (lGenSmp) {
// If samples must be generated, call all active wave generators and acumulate waves in lpOut
- unsigned int lWaveIdx;
+ unsigned int lFreqIdx = 0;
+ unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
- for (lWaveIdx = 0; lWaveIdx < (unsigned int)lpToneGen->mWaveGens.size(); lWaveIdx++) {
- WaveGenerator *lpWaveGen = lpToneGen->mWaveGens[lWaveIdx];
+ while (lFrequency != 0) {
+ WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+ lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
}
}
@@ -501,7 +719,7 @@
// Method: ToneGenerator::prepareWave()
//
// Description: Prepare wave generators and reset tone sequencer state machine.
-// mpNewToneDesc must have been initialized befoire calling this function.
+// mpNewToneDesc must have been initialized before calling this function.
// Input:
// none
//
@@ -510,40 +728,48 @@
//
////////////////////////////////////////////////////////////////////////////////
bool ToneGenerator::prepareWave() {
- unsigned int lCnt = 0;
- unsigned int lNumWaves;
+ unsigned int segmentIdx = 0;
if (!mpNewToneDesc) {
return false;
}
+
// Remove existing wave generators if any
clearWaveGens();
mpToneDesc = mpNewToneDesc;
- // Get total number of sine waves: needed to adapt sine wave gain.
- lNumWaves = numWaves();
-
- // Instantiate as many wave generators as listed in descriptor
- while (lCnt < lNumWaves) {
- ToneGenerator::WaveGenerator *lpWaveGen =
- new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
- mpToneDesc->waveFreq[lCnt],
- TONEGEN_GAIN/lNumWaves);
- if (lpWaveGen == 0) {
- goto prepareWave_exit;
+ while (mpToneDesc->segments[segmentIdx].duration) {
+ // Get total number of sine waves: needed to adapt sine wave gain.
+ unsigned int lNumWaves = numWaves(segmentIdx);
+ unsigned int freqIdx = 0;
+ unsigned int frequency = mpToneDesc->segments[segmentIdx].waveFreq[freqIdx];
+ while (frequency) {
+ // Instantiate a wave generator if ot already done for this frequency
+ if (mWaveGens.indexOfKey(frequency) == NAME_NOT_FOUND) {
+ ToneGenerator::WaveGenerator *lpWaveGen =
+ new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
+ frequency,
+ TONEGEN_GAIN/lNumWaves);
+ if (lpWaveGen == 0) {
+ goto prepareWave_exit;
+ }
+ mWaveGens.add(frequency, lpWaveGen);
+ }
+ frequency = mpNewToneDesc->segments[segmentIdx].waveFreq[++freqIdx];
}
-
- mWaveGens.push(lpWaveGen);
- LOGV("Create sine: %d\n", mpToneDesc->waveFreq[lCnt]);
- lCnt++;
+ segmentIdx++;
}
// Initialize tone sequencer
mTotalSmp = 0;
mCurSegment = 0;
mCurCount = 0;
- mNextSegSmp = (mpToneDesc->segments[0] * mSamplingRate) / 1000;
+ if (mpToneDesc->segments[0].duration == TONEGEN_INF) {
+ mNextSegSmp = TONEGEN_INF;
+ } else{
+ mNextSegSmp = (mpToneDesc->segments[0].duration * mSamplingRate) / 1000;
+ }
return true;
@@ -559,19 +785,22 @@
//
// Method: ToneGenerator::numWaves()
//
-// Description: Count number of sine waves needed to generate tone (e.g 2 for DTMF).
+// Description: Count number of sine waves needed to generate a tone segment (e.g 2 for DTMF).
//
// Input:
-// none
+// segmentIdx tone segment index
//
// Output:
// returned value: nummber of sine waves
//
////////////////////////////////////////////////////////////////////////////////
-unsigned int ToneGenerator::numWaves() {
+unsigned int ToneGenerator::numWaves(unsigned int segmentIdx) {
unsigned int lCnt = 0;
- while (mpToneDesc->waveFreq[lCnt]) {
+ if (mpToneDesc->segments[segmentIdx].duration) {
+ while (mpToneDesc->segments[segmentIdx].waveFreq[lCnt]) {
+ lCnt++;
+ }
lCnt++;
}
@@ -595,10 +824,38 @@
void ToneGenerator::clearWaveGens() {
LOGV("Clearing mWaveGens:");
- while (!mWaveGens.isEmpty()) {
- delete mWaveGens.top();
- mWaveGens.pop();
+ for (size_t lIdx = 0; lIdx < mWaveGens.size(); lIdx++) {
+ delete mWaveGens.valueAt(lIdx);
}
+ mWaveGens.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::getToneForRegion()
+//
+// Description: Get correct ringtone type according to current region.
+// The corrected ring tone type is the tone descriptor index in sToneDescriptors[].
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+int ToneGenerator::getToneForRegion(int toneType) {
+ int regionTone;
+
+ if (mRegion == CEPT || toneType < FIRST_SUP_TONE || toneType > LAST_SUP_TONE) {
+ regionTone = toneType;
+ } else {
+ regionTone = sToneMappingTable[mRegion][toneType - FIRST_SUP_TONE];
+ }
+
+ LOGV("getToneForRegion, tone %d, region %d, regionTone %d", toneType, mRegion, regionTone);
+
+ return regionTone;
}
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index f710921..f7f2490 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -7,28 +7,28 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- MediaRecorderClient.cpp \
- MediaPlayerService.cpp \
- MetadataRetrieverClient.cpp \
- VorbisPlayer.cpp \
- MidiFile.cpp
+ MediaRecorderClient.cpp \
+ MediaPlayerService.cpp \
+ MetadataRetrieverClient.cpp \
+ VorbisPlayer.cpp \
+ MidiFile.cpp
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -ldl -lpthread
endif
LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libvorbisidec \
- libsonivox \
- libopencoreplayer \
- libopencoreauthor \
- libmedia \
- libandroid_runtime
+ libcutils \
+ libutils \
+ libvorbisidec \
+ libsonivox \
+ libopencore_player \
+ libopencore_author \
+ libmedia \
+ libandroid_runtime
LOCAL_C_INCLUDES := external/tremor/Tremor \
- $(call include-path-for, graphics corecg)
+ $(call include-path-for, graphics corecg)
LOCAL_MODULE:= libmediaplayerservice
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index d03caa5..e9cbb97 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -89,7 +89,7 @@
// create playback thread
{
Mutex::Autolock l(mMutex);
- createThreadEtc(renderThread, this, "midithread");
+ createThreadEtc(renderThread, this, "midithread", ANDROID_PRIORITY_AUDIO);
mCondition.wait(mMutex);
LOGV("thread started");
}
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
index 0ad335f..14fd6ce 100644
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -67,7 +67,7 @@
LOGV("onFirstRef");
// create playback thread
Mutex::Autolock l(mMutex);
- createThreadEtc(renderThread, this, "vorbis decoder");
+ createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
mCondition.wait(mMutex);
if (mRenderTid > 0) {
LOGV("render thread(%d) started", mRenderTid);