Automated import from //branches/master/...@140567,140567
diff --git a/api/current.xml b/api/current.xml
index 65ffa82..9c7018a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -64504,6 +64504,23 @@
  visibility="public"
 >
 </method>
+<method name="getMinBufferSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sampleRateInHz" type="int">
+</parameter>
+<parameter name="channelConfig" type="int">
+</parameter>
+<parameter name="audioFormat" type="int">
+</parameter>
+</method>
 <method name="getNotificationMarkerPosition"
  return="int"
  abstract="false"
@@ -64619,19 +64636,6 @@
  visibility="public"
 >
 </method>
-<method name="setMarkerReachedListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.AudioRecord.OnMarkerReachedListener">
-</parameter>
-</method>
 <method name="setNotificationMarkerPosition"
  return="int"
  abstract="false"
@@ -64645,19 +64649,6 @@
 <parameter name="markerInFrames" type="int">
 </parameter>
 </method>
-<method name="setPeriodicNotificationListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.AudioRecord.OnPeriodicNotificationListener">
-</parameter>
-</method>
 <method name="setPositionNotificationPeriod"
  return="int"
  abstract="false"
@@ -64671,6 +64662,34 @@
 <parameter name="periodInFrames" type="int">
 </parameter>
 </method>
+<method name="setRecordPositionUpdateListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.AudioRecord.OnRecordPositionUpdateListener">
+</parameter>
+</method>
+<method name="setRecordPositionUpdateListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.AudioRecord.OnRecordPositionUpdateListener">
+</parameter>
+<parameter name="handler" type="android.os.Handler">
+</parameter>
+</method>
 <method name="startRecording"
  return="void"
  abstract="false"
@@ -64786,7 +64805,7 @@
 >
 </field>
 </class>
-<interface name="AudioRecord.OnMarkerReachedListener"
+<interface name="AudioRecord.OnRecordPositionUpdateListener"
  abstract="true"
  static="true"
  final="false"
@@ -64806,14 +64825,6 @@
 <parameter name="recorder" type="android.media.AudioRecord">
 </parameter>
 </method>
-</interface>
-<interface name="AudioRecord.OnPeriodicNotificationListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
 <method name="onPeriodicNotification"
  return="void"
  abstract="true"
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 0ef7760..a49bd67 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -165,27 +165,24 @@
      */
     private Object mRecordingStateLock = new Object();
     /**
-     * The listener the AudioRecord notifies when a previously set marker is reached.
-     *  @see #setMarkerReachedListener(OnMarkerReachedListener)
+     * The listener the AudioRecord notifies when the record position reaches a marker
+     * or for periodic updates during the progression of the record head.
+     *  @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)
+     *  @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)
      */
-    private OnMarkerReachedListener mMarkerListener = null;
+    private OnRecordPositionUpdateListener mPositionListener = null;
     /**
-     * Lock to protect marker listener updates against event notifications
+     * Lock to protect position listener updates against event notifications
      */
-    private final Object mMarkerListenerLock = new Object();
+    private final Object mPositionListenerLock = new Object();
     /**
-     * The listener the AudioRecord notifies periodically during recording.
-     *  @see #setPeriodicNotificationListener(OnPeriodicNotificationListener)
+     * Handler for marker events coming from the native code
      */
-    private OnPeriodicNotificationListener mPeriodicListener = null;
+    private NativeEventHandler mEventHandler = null;
     /**
-     * Lock to protect periodic listener updates against event notifications
+     * Looper associated with the thread that creates the AudioRecord instance
      */
-    private final Object mPeriodicListenerLock = new Object();
-    /**
-     * Handler for events coming from the native code
-     */
-    private NativeEventHandler mNativeEventHandler = null;
+    private Looper mInitializationLooper = null;
     /**
      * Size of the native audio buffer.
      */
@@ -217,6 +214,11 @@
     throws IllegalArgumentException {   
         mState = STATE_UNINITIALIZED;
         mRecordingState = RECORDSTATE_STOPPED;
+        
+        // remember which looper is associated with the AudioRecord instanciation
+        if ((mInitializationLooper = Looper.myLooper()) == null) {
+            mInitializationLooper = Looper.getMainLooper();
+        }
 
         audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat);
 
@@ -319,21 +321,6 @@
     }    
     
     
-    // Convenience method for the creation of the native event handler
-    // It is called only when a non-null event listener is set.
-    // precondition:
-    //    mNativeEventHandler is null
-    private void createNativeEventHandler() {
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mNativeEventHandler = new NativeEventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mNativeEventHandler = new NativeEventHandler(this, looper);
-        } else {
-            mNativeEventHandler = null;
-        }
-    }
-    
 
     /**
      * Releases the native AudioRecord resources.
@@ -433,7 +420,6 @@
     }
     
     /**
-     * {@hide}
      * Returns the minimum buffer size required for the successful creation of an AudioRecord
      * object.
      * @param sampleRateInHz the sample rate expressed in Hertz.
@@ -602,36 +588,40 @@
     // Initialization / configuration
     //--------------------  
     /**
-     * Sets the listener the AudioRecord notifies when a previously set marker is reached.
+     * Sets the listener the AudioRecord notifies when a previously set marker is reached or
+     * for each periodic record head position update.
      * @param listener
      */
-    public void setMarkerReachedListener(OnMarkerReachedListener listener) {
-        synchronized (mMarkerListenerLock) {
-            mMarkerListener = listener;
+    public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener) {
+        setRecordPositionUpdateListener(listener, null);
+    }
+    
+
+    public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener, 
+                                                    Handler handler) {
+        synchronized (mPositionListenerLock) {
+            
+            mPositionListener = listener;
+            
+            if (listener != null) {
+                if (handler != null) {
+                    mEventHandler = new NativeEventHandler(this, handler.getLooper());
+                } else {
+                    // no given handler, use the looper the AudioRecord was created in
+                    mEventHandler = new NativeEventHandler(this, mInitializationLooper);
+                }
+            } else {
+                mEventHandler = null;
+            }
         }
-        if ((listener != null) && (mNativeEventHandler == null)) {
-            createNativeEventHandler();
-        }
+        
     }
     
     
     /**
-     * Sets the listener the AudioRecord notifies periodically during recording.
-     * @param listener
-     */
-    public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) {
-        synchronized (mPeriodicListenerLock) {
-            mPeriodicListener = listener;
-        }
-        if ((listener != null) && (mNativeEventHandler == null)) {
-            createNativeEventHandler();
-        }
-    }
-    
-    
-    /**
-     * Sets the marker position at which the listener, if set with 
-     * {@link #setMarkerReachedListener(OnMarkerReachedListener)}, is called.
+     * Sets the marker position at which the listener is called, if set with 
+     * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or 
+     * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}.
      * @param markerInFrames marker position expressed in frames
      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
      *  {@link #ERROR_INVALID_OPERATION} 
@@ -642,8 +632,9 @@
     
     
     /**
-     * Sets the period at which the listener, if set with
-     * {@link #setPositionNotificationPeriod(int)}, is called.
+     * Sets the period at which the listener is called, if set with
+     * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or 
+     * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}.
      * @param periodInFrames update period expressed in frames
      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}
      */
@@ -659,70 +650,65 @@
      * Interface definition for a callback to be invoked when an AudioRecord has
      * reached a notification marker set by setNotificationMarkerPosition().
      */
-    public interface OnMarkerReachedListener  {
+    public interface OnRecordPositionUpdateListener  {
         /**
          * Called on the listener to notify it that the previously set marker has been reached
          * by the recording head.
          */
         void onMarkerReached(AudioRecord recorder);
-    }
-
-
-    /**
-     * Interface definition for a callback to be invoked for each periodic AudioRecord 
-     * update during recording. The update interval is set by setPositionNotificationPeriod().
-     */
-    public interface OnPeriodicNotificationListener  {
+        
         /**
-         * Called on the listener to periodically notify it that the recording head has reached
+         * Called on the listener to periodically notify it that the record head has reached
          * a multiple of the notification period.
          */
         void onPeriodicNotification(AudioRecord recorder);
     }
+    
+    
 
     
     //---------------------------------------------------------
     // Inner classes
     //--------------------
+      
     /**
-     * Helper class to handle the forwarding of native events to the appropriate listeners
-     */
-    private class NativeEventHandler extends Handler
-    {
-        private AudioRecord mAudioRecord;
-
-        public NativeEventHandler(AudioRecord ar, Looper looper) {
+     * Helper class to handle the forwarding of native events to the appropriate listener
+     * (potentially) handled in a different thread
+     */  
+    private class NativeEventHandler extends Handler {
+        
+        private final AudioRecord mAudioRecord;
+        
+        NativeEventHandler(AudioRecord recorder, Looper looper) {
             super(looper);
-            mAudioRecord = ar;
+            mAudioRecord = recorder;
         }
-
+        
         @Override
         public void handleMessage(Message msg) {
-            if (mAudioRecord == null) {
-                return;
+            OnRecordPositionUpdateListener listener = null;
+            synchronized (mPositionListenerLock) {
+                listener = mAudioRecord.mPositionListener;
             }
+            
             switch(msg.what) {
             case NATIVE_EVENT_MARKER:
-                synchronized (mMarkerListenerLock) {
-                    if (mAudioRecord.mMarkerListener != null) {
-                        mAudioRecord.mMarkerListener.onMarkerReached(mAudioRecord);
-                    }
+                if (listener != null) {
+                    listener.onMarkerReached(mAudioRecord);
                 }
                 break;
             case NATIVE_EVENT_NEW_POS:
-                synchronized (mPeriodicListenerLock) {
-                    if (mAudioRecord.mPeriodicListener != null) {
-                        mAudioRecord.mPeriodicListener.onPeriodicNotification(mAudioRecord);
-                    }
+                if (listener != null) {
+                    listener.onPeriodicNotification(mAudioRecord);
                 }
                 break;
             default:
                 Log.e(TAG, "[ android.media.AudioRecord.NativeEventHandler ] " +
                         "Unknown event type: " + msg.what);
-                break;
+            break;
             }
         }
-    }
+    };
     
     
     //---------------------------------------------------------
@@ -737,9 +723,10 @@
             return;
         }
         
-        if (recorder.mNativeEventHandler != null) {
-            Message m = recorder.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
-            recorder.mNativeEventHandler.sendMessage(m);
+        if (recorder.mEventHandler != null) {
+            Message m = 
+                recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+            recorder.mEventHandler.sendMessage(m);
         }
 
     }