Merge change 23218 into eclair

* changes:
  Fix property being cleared when DeviceFound signal is received.
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 77a126c..3a419b5 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -136,8 +136,17 @@
 
 AudioFlinger::~AudioFlinger()
 {
-    mRecordThreads.clear();
-    mPlaybackThreads.clear();
+    while (!mRecordThreads.isEmpty()) {
+        // closeInput() will remove first entry from mRecordThreads
+        closeInput(mRecordThreads.keyAt(0));
+    }
+    while (!mPlaybackThreads.isEmpty()) {
+        // closeOutput() will remove first entry from mPlaybackThreads
+        closeOutput(mPlaybackThreads.keyAt(0));
+    }
+    if (mAudioHardware) {
+        delete mAudioHardware;
+    }
 }
 
 
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
index ae17d76..5c3cc8e 100644
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -16,6 +16,13 @@
 
 #define LOG_TAG "AudioPolicyService"
 //#define LOG_NDEBUG 0
+
+#undef __STRICT_ANSI__
+#define __STDINT_LIMITS
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <sys/time.h>
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
 #include <cutils/properties.h>
@@ -54,7 +61,7 @@
     char value[PROPERTY_VALUE_MAX];
 
     // start tone playback thread
-    mTonePlaybacThread = new AudioCommandThread();
+    mTonePlaybackThread = new AudioCommandThread();
     // start audio commands thread
     mAudioCommandThread = new AudioCommandThread();
 
@@ -80,8 +87,8 @@
 
 AudioPolicyService::~AudioPolicyService()
 {
-    mTonePlaybacThread->exit();
-    mTonePlaybacThread.clear();
+    mTonePlaybackThread->exit();
+    mTonePlaybackThread.clear();
     mAudioCommandThread->exit();
     mAudioCommandThread.clear();
 
@@ -451,9 +458,9 @@
     return af->closeInput(input);
 }
 
-status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output)
+status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
 {
-    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output);
+    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
 }
 
 status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
@@ -465,9 +472,9 @@
 }
 
 
-void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
 {
-    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs);
+    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
 }
 
 String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
@@ -478,13 +485,13 @@
 
 status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
 {
-    mTonePlaybacThread->startToneCommand(tone, stream);
+    mTonePlaybackThread->startToneCommand(tone, stream);
     return NO_ERROR;
 }
 
 status_t AudioPolicyService::stopTone()
 {
-    mTonePlaybacThread->stopToneCommand();
+    mTonePlaybackThread->stopToneCommand();
     return NO_ERROR;
 }
 
@@ -516,58 +523,72 @@
 
 bool AudioPolicyService::AudioCommandThread::threadLoop()
 {
+    nsecs_t waitTime = INT64_MAX;
+
     mLock.lock();
     while (!exitPending())
     {
         while(!mAudioCommands.isEmpty()) {
-            AudioCommand *command = mAudioCommands[0];
-            mAudioCommands.removeAt(0);
-            switch (command->mCommand) {
-            case START_TONE: {
-                mLock.unlock();
-                ToneData *data = (ToneData *)command->mParam;
-                LOGV("AudioCommandThread() processing start tone %d on stream %d",
-                        data->mType, data->mStream);
-                if (mpToneGenerator != NULL)
-                    delete mpToneGenerator;
-                mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
-                mpToneGenerator->startTone(data->mType);
-                delete data;
-                mLock.lock();
-                }break;
-            case STOP_TONE: {
-                mLock.unlock();
-                LOGV("AudioCommandThread() processing stop tone");
-                if (mpToneGenerator != NULL) {
-                    mpToneGenerator->stopTone();
-                    delete mpToneGenerator;
-                    mpToneGenerator = NULL;
+            nsecs_t curTime = systemTime();
+            // commands are sorted by increasing time stamp: execute them from index 0 and up
+            if (mAudioCommands[0]->mTime <= curTime) {
+                AudioCommand *command = mAudioCommands[0];
+                mAudioCommands.removeAt(0);
+                switch (command->mCommand) {
+                case START_TONE: {
+                    mLock.unlock();
+                    ToneData *data = (ToneData *)command->mParam;
+                    LOGV("AudioCommandThread() processing start tone %d on stream %d",
+                            data->mType, data->mStream);
+                    if (mpToneGenerator != NULL)
+                        delete mpToneGenerator;
+                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
+                    mpToneGenerator->startTone(data->mType);
+                    delete data;
+                    mLock.lock();
+                    }break;
+                case STOP_TONE: {
+                    mLock.unlock();
+                    LOGV("AudioCommandThread() processing stop tone");
+                    if (mpToneGenerator != NULL) {
+                        mpToneGenerator->stopTone();
+                        delete mpToneGenerator;
+                        mpToneGenerator = NULL;
+                    }
+                    mLock.lock();
+                    }break;
+                case SET_VOLUME: {
+                    VolumeData *data = (VolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
+                    command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+                case SET_PARAMETERS: {
+                     ParametersData *data = (ParametersData *)command->mParam;
+                     LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
+                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
+                     if (command->mWaitStatus) {
+                         command->mCond.signal();
+                         mWaitWorkCV.wait(mLock);
+                     }
+                     delete data;
+                     }break;
+                default:
+                    LOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
-                mLock.lock();
-                }break;
-            case SET_VOLUME: {
-                VolumeData *data = (VolumeData *)command->mParam;
-                LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
-                mCommandStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
-                mCommandCond.signal();
-                mWaitWorkCV.wait(mLock);
-                delete data;
-                }break;
-            case SET_PARAMETERS: {
-                 ParametersData *data = (ParametersData *)command->mParam;
-                 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
-                 mCommandStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
-                 mCommandCond.signal();
-                 mWaitWorkCV.wait(mLock);
-                 delete data;
-                 }break;
-            default:
-                LOGW("AudioCommandThread() unknown command %d", command->mCommand);
+                delete command;
+                waitTime = INT64_MAX;
+            } else {
+                waitTime = mAudioCommands[0]->mTime - curTime;
+                break;
             }
-            delete command;
         }
         LOGV("AudioCommandThread() going to sleep");
-        mWaitWorkCV.wait(mLock);
+        mWaitWorkCV.waitRelative(mLock, waitTime);
         LOGV("AudioCommandThread() waking up");
     }
     mLock.unlock();
@@ -583,7 +604,8 @@
     data->mType = type;
     data->mStream = stream;
     command->mParam = (void *)data;
-    mAudioCommands.add(command);
+    command->mWaitStatus = false;
+    insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
     mWaitWorkCV.signal();
 }
@@ -594,13 +616,16 @@
     AudioCommand *command = new AudioCommand();
     command->mCommand = STOP_TONE;
     command->mParam = NULL;
-    mAudioCommands.add(command);
+    command->mWaitStatus = false;
+    insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone stop");
     mWaitWorkCV.signal();
 }
 
-status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output)
+status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
 {
+    status_t status = NO_ERROR;
+
     Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_VOLUME;
@@ -609,17 +634,26 @@
     data->mVolume = volume;
     data->mIO = output;
     command->mParam = data;
-    mAudioCommands.add(command);
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    insertCommand_l(command, delayMs);
     LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
     mWaitWorkCV.signal();
-    mCommandCond.wait(mLock);
-    status_t status =  mCommandStatus;
-    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
     return status;
 }
 
-status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs)
+status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
 {
+    status_t status = NO_ERROR;
+
     Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_PARAMETERS;
@@ -627,15 +661,102 @@
     data->mIO = ioHandle;
     data->mKeyValuePairs = keyValuePairs;
     command->mParam = data;
-    mAudioCommands.add(command);
-    LOGV("AudioCommandThread() adding set parameter string %s, io %d", keyValuePairs.string(), ioHandle);
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
     mWaitWorkCV.signal();
-    mCommandCond.wait(mLock);
-    status_t status =  mCommandStatus;
-    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
     return status;
 }
 
+// insertCommand_l() must be called with mLock held
+void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
+{
+    ssize_t i;
+    Vector <AudioCommand *> removedCommands;
+
+    command->mTime = systemTime() + milliseconds(delayMs);
+
+    // check same pending commands with later time stamps and eliminate them
+    for (i = mAudioCommands.size()-1; i >= 0; i--) {
+        AudioCommand *command2 = mAudioCommands[i];
+        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
+        if (command2->mTime <= command->mTime) break;
+        if (command2->mCommand != command->mCommand) continue;
+
+        switch (command->mCommand) {
+        case SET_PARAMETERS: {
+            ParametersData *data = (ParametersData *)command->mParam;
+            ParametersData *data2 = (ParametersData *)command2->mParam;
+            if (data->mIO != data2->mIO) break;
+            LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
+            AudioParameter param = AudioParameter(data->mKeyValuePairs);
+            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
+            for (size_t j = 0; j < param.size(); j++) {
+               String8 key;
+               String8 value;
+               param.getAt(j, key, value);
+               for (size_t k = 0; k < param2.size(); k++) {
+                  String8 key2;
+                  String8 value2;
+                  param2.getAt(k, key2, value2);
+                  if (key2 == key) {
+                      param2.remove(key2);
+                      LOGV("Filtering out parameter %s", key2.string());
+                      break;
+                  }
+               }
+            }
+            // if all keys have been filtered out, remove the command.
+            // otherwise, update the key value pairs
+            if (param2.size() == 0) {
+                removedCommands.add(command2);
+            } else {
+                data2->mKeyValuePairs = param2.toString();
+            }
+        } break;
+
+        case SET_VOLUME: {
+            VolumeData *data = (VolumeData *)command->mParam;
+            VolumeData *data2 = (VolumeData *)command2->mParam;
+            if (data->mIO != data2->mIO) break;
+            if (data->mStream != data2->mStream) break;
+            LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
+            removedCommands.add(command2);
+        } break;
+        case START_TONE:
+        case STOP_TONE:
+        default:
+            break;
+        }
+    }
+
+    // remove filtered commands
+    for (size_t j = 0; j < removedCommands.size(); j++) {
+        // removed commands always have time stamps greater than current command
+        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
+            if (mAudioCommands[k] == removedCommands[j]) {
+                LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+                mAudioCommands.removeAt(k);
+                break;
+            }
+        }
+    }
+    removedCommands.clear();
+
+    // insert command at the right place according to its time stamp
+    LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
+    mAudioCommands.insertAt(command, i + 1);
+}
+
 void AudioPolicyService::AudioCommandThread::exit()
 {
     LOGV("AudioCommandThread::exit");
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
index 3909fa4..56a85e1 100644
--- a/libs/audioflinger/AudioPolicyService.h
+++ b/libs/audioflinger/AudioPolicyService.h
@@ -20,6 +20,7 @@
 #include <media/IAudioPolicyService.h>
 #include <hardware_legacy/AudioPolicyInterface.h>
 #include <media/ToneGenerator.h>
+#include <utils/Vector.h>
 
 namespace android {
 
@@ -98,9 +99,9 @@
                                     uint32_t *pChannels,
                                     uint32_t acoustics);
     virtual status_t closeInput(audio_io_handle_t input);
-    virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output);
+    virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs = 0);
     virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
-    virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+    virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
     virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
     virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
     virtual status_t stopTone();
@@ -116,6 +117,7 @@
     // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
     // has permission to modify audio settings.
     class AudioCommandThread : public Thread {
+        class AudioCommand;
     public:
 
         // commands for tone AudioCommand
@@ -136,15 +138,20 @@
                     void        exit();
                     void        startToneCommand(int type = 0, int stream = 0);
                     void        stopToneCommand();
-                    status_t    volumeCommand(int stream, float volume, int output);
-                    status_t    parametersCommand(int ioHandle, const String8& keyValuePairs);
+                    status_t    volumeCommand(int stream, float volume, int output, int delayMs = 0);
+                    status_t    parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+                    void        insertCommand_l(AudioCommand *command, int delayMs = 0);
 
     private:
         // descriptor for requested tone playback event
         class AudioCommand {
         public:
             int mCommand;   // START_TONE, STOP_TONE ...
-            void *mParam;
+            nsecs_t mTime;  // time stamp
+            Condition mCond; // condition for status return
+            status_t mStatus; // command status
+            bool mWaitStatus; // true if caller is waiting for status
+            void *mParam;     // command parameter (ToneData, VolumeData, ParametersData)
         };
 
         class ToneData {
@@ -168,9 +175,7 @@
 
         Mutex   mLock;
         Condition mWaitWorkCV;
-        Vector<AudioCommand *> mAudioCommands;    // list of pending tone events
-        Condition              mCommandCond;
-        status_t               mCommandStatus;
+        Vector <AudioCommand *> mAudioCommands; // list of pending commands
         ToneGenerator *mpToneGenerator;     // the tone generator
     };
 
@@ -182,7 +187,7 @@
                         // connection stated our routing
     AudioPolicyInterface* mpPolicyManager;          // the platform specific policy manager
     sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
-    sp <AudioCommandThread> mTonePlaybacThread;     // tone playback thread
+    sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread
 };
 
 }; // namespace android
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index df713cb..60c177b 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -784,6 +784,7 @@
             int count = mFDCount - i - 1;
             int index = (device->id&ID_MASK);
             mDevicesById[index].device = NULL;
+            close(mFDs[i].fd);
             memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
             memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
 
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index f71bbea..6df612e 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -45,18 +45,25 @@
     /** Key to the error code of a connectivity broadcast event. */
     public static final String BROADCAST_ERROR_CODE = "err";
     /** Error code to indicate an error from authentication. */
-    public static final int VPN_ERROR_AUTH = 1;
+    public static final int VPN_ERROR_AUTH = 51;
     /** Error code to indicate the connection attempt failed. */
-    public static final int VPN_ERROR_CONNECTION_FAILED = 2;
+    public static final int VPN_ERROR_CONNECTION_FAILED = 101;
     /** Error code to indicate the server is not known. */
-    public static final int VPN_ERROR_UNKNOWN_SERVER = 3;
+    public static final int VPN_ERROR_UNKNOWN_SERVER = 102;
     /** Error code to indicate an error from challenge response. */
-    public static final int VPN_ERROR_CHALLENGE = 4;
+    public static final int VPN_ERROR_CHALLENGE = 5;
     /** Error code to indicate an error of remote server hanging up. */
-    public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
+    public static final int VPN_ERROR_REMOTE_HUNG_UP = 7;
+    /** Error code to indicate an error of remote PPP server hanging up. */
+    public static final int VPN_ERROR_REMOTE_PPP_HUNG_UP = 48;
+    /** Error code to indicate a PPP negotiation error. */
+    public static final int VPN_ERROR_PPP_NEGOTIATION_FAILED = 42;
     /** Error code to indicate an error of losing connectivity. */
-    public static final int VPN_ERROR_CONNECTION_LOST = 6;
-    private static final int VPN_ERROR_NO_ERROR = 0;
+    public static final int VPN_ERROR_CONNECTION_LOST = 103;
+    /** Largest error code used by VPN. */
+    public static final int VPN_ERROR_LARGEST = 200;
+    /** Error code to indicate a successful connection. */
+    public static final int VPN_ERROR_NO_ERROR = 0;
 
     public static final String PROFILES_PATH = "/data/misc/vpn/profiles";