Fixed issue 1709450: Requirements for CDMA Tone Generator

Added new tone types for CDMA IS-95 specific tones.
Automatic selection between IS-95, CEPT and JAPAN version base on operator
country code for call supervisory tones.
Also improved tone generator capabilities:
- Each tone segment can now generate its own set of frequencies
- A tone does not have to be a succession of alternating ON/OFF segments
- The sequence repetition does not have to start from first segment
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/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 8560593..d1789ad 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 {
@@ -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;
 }