Merge "Put next task on top of stack if top is finishing." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index ab48c8d..fd4ddf3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12334,7 +12334,7 @@
     field public static final int EULER_Z = 2; // 0x2
   }
 
-  public abstract interface Image implements java.lang.AutoCloseable {
+  public abstract class Image implements java.lang.AutoCloseable {
     method public abstract void close();
     method public abstract int getFormat();
     method public abstract int getHeight();
@@ -12343,23 +12343,23 @@
     method public abstract int getWidth();
   }
 
-  public static abstract interface Image.Plane {
+  public static abstract class Image.Plane {
     method public abstract java.nio.ByteBuffer getBuffer();
     method public abstract int getPixelStride();
     method public abstract int getRowStride();
   }
 
-  public final class ImageReader implements java.lang.AutoCloseable {
-    ctor public ImageReader(int, int, int, int);
+  public class ImageReader implements java.lang.AutoCloseable {
+    method public android.media.Image acquireLatestImage();
+    method public android.media.Image acquireNextImage();
     method public void close();
     method public int getHeight();
     method public int getImageFormat();
     method public int getMaxImages();
-    method public android.media.Image getNextImage();
     method public android.view.Surface getSurface();
     method public int getWidth();
-    method public void releaseImage(android.media.Image);
-    method public void setImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
+    method public static android.media.ImageReader newInstance(int, int, int, int);
+    method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
   }
 
   public static abstract interface ImageReader.OnImageAvailableListener {
@@ -15211,9 +15211,9 @@
     field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
     field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
     field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
-    field public static final int FLAG_READER_KOVIO = 16; // 0x10
     field public static final int FLAG_READER_NFC_A = 1; // 0x1
     field public static final int FLAG_READER_NFC_B = 2; // 0x2
+    field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10
     field public static final int FLAG_READER_NFC_F = 4; // 0x4
     field public static final int FLAG_READER_NFC_V = 8; // 0x8
     field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index 2c05c58..d0b3ec4 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -19,6 +19,7 @@
 import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
 import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
 import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
+import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
 import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
 
 import android.os.DeadObjectException;
@@ -50,6 +51,7 @@
     public static final int EBUSY = -16;
     public static final int ENODEV = -19;
     public static final int EOPNOTSUPP = -95;
+    public static final int EDQUOT = -122;
 
     private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
 
@@ -83,6 +85,9 @@
                     case EBUSY:
                         UncheckedThrow.throwAnyException(new CameraRuntimeException(
                                 CAMERA_IN_USE));
+                    case EDQUOT:
+                        UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                                MAX_CAMERAS_IN_USE));
                     case ENODEV:
                         UncheckedThrow.throwAnyException(new CameraRuntimeException(
                                 CAMERA_DISCONNECTED));
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 2a18900..486e75a 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -227,9 +227,9 @@
     /**
      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
      * <p>
-     * Setting this flag enables polling for Kovio technology.
+     * Setting this flag enables polling for NfcBarcode technology.
      */
-    public static final int FLAG_READER_KOVIO = 0x10;
+    public static final int FLAG_READER_NFC_BARCODE = 0x10;
 
     /**
      * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 12e0d73..4cc2c42 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -91,6 +91,9 @@
             return null;
         }
         final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", startAlpha, endAlpha);
+        if (DBG) {
+            Log.d(LOG_TAG, "Created animator " + anim);
+        }
         if (listener != null) {
             anim.addListener(listener);
             anim.addPauseListener(listener);
@@ -146,12 +149,41 @@
         final View endView = endValues.view;
         if (DBG) {
             View startView = (startValues != null) ? startValues.view : null;
-            Log.d(LOG_TAG, "Fade.onDisappear: startView, startVis, endView, endVis = " +
+            Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " +
                     startView + ", " + startVisibility + ", " + endView + ", " + endVisibility);
         }
         // if alpha < 1, just fade it in from the current value
         if (endView.getAlpha() == 1.0f) {
             endView.setAlpha(0);
+            TransitionListener transitionListener = new TransitionListenerAdapter() {
+                boolean mCanceled = false;
+                float mPausedAlpha;
+
+                @Override
+                public void onTransitionCancel(Transition transition) {
+                    endView.setAlpha(1);
+                    mCanceled = true;
+                }
+
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    if (!mCanceled) {
+                        endView.setAlpha(1);
+                    }
+                }
+
+                @Override
+                public void onTransitionPause(Transition transition) {
+                    mPausedAlpha = endView.getAlpha();
+                    endView.setAlpha(1);
+                }
+
+                @Override
+                public void onTransitionResume(Transition transition) {
+                    endView.setAlpha(mPausedAlpha);
+                }
+            };
+            addListener(transitionListener);
         }
         return createAnimation(endView, endView.getAlpha(), 1, null);
     }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index c588c6b..60b4708 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1240,12 +1240,13 @@
                     View oldView = oldInfo.view;
                     TransitionValues newValues = mEndValues.viewValues != null ?
                             mEndValues.viewValues.get(oldView) : null;
+                    if (newValues == null) {
+                        newValues = mEndValues.idValues.get(oldView.getId());
+                    }
                     if (oldValues != null) {
                         // if oldValues null, then transition didn't care to stash values,
                         // and won't get canceled
-                        if (newValues == null) {
-                            cancel = true;
-                        } else {
+                        if (newValues != null) {
                             for (String key : oldValues.values.keySet()) {
                                 Object oldValue = oldValues.values.get(key);
                                 Object newValue = newValues.values.get(key);
@@ -1451,6 +1452,8 @@
         try {
             clone = (Transition) super.clone();
             clone.mAnimators = new ArrayList<Animator>();
+            clone.mStartValues = new TransitionValuesMaps();
+            clone.mEndValues = new TransitionValuesMaps();
         } catch (CloneNotSupportedException e) {}
 
         return clone;
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 54d801e..44ca4e5 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -22,6 +22,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 /**
@@ -68,8 +69,9 @@
     ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>();
     ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions =
             new ArrayMap<Scene, ArrayMap<Scene, Transition>>();
-    private static ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>> sRunningTransitions =
-            new ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>>();
+    private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>
+            sRunningTransitions =
+            new ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>();
     private static ArrayList<ViewGroup> sPendingTransitions = new ArrayList<ViewGroup>();
 
 
@@ -184,20 +186,24 @@
     }
 
     private static ArrayMap<ViewGroup, ArrayList<Transition>> getRunningTransitions() {
-        ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
+        WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>> runningTransitions =
                 sRunningTransitions.get();
-        if (runningTransitions == null) {
-            runningTransitions = new ArrayMap<ViewGroup, ArrayList<Transition>>();
+        if (runningTransitions == null || runningTransitions.get() == null) {
+            ArrayMap<ViewGroup, ArrayList<Transition>> transitions =
+                    new ArrayMap<ViewGroup, ArrayList<Transition>>();
+            runningTransitions = new WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>(
+                    transitions);
             sRunningTransitions.set(runningTransitions);
         }
-        return runningTransitions;
+        return runningTransitions.get();
     }
 
     private static void sceneChangeRunTransition(final ViewGroup sceneRoot,
             final Transition transition) {
         if (transition != null) {
             final ViewTreeObserver observer = sceneRoot.getViewTreeObserver();
-            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            final ViewTreeObserver.OnPreDrawListener listener =
+                    new ViewTreeObserver.OnPreDrawListener() {
                 public boolean onPreDraw() {
                     sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
                     sPendingTransitions.remove(sceneRoot);
@@ -236,7 +242,8 @@
                     // values set on them again and avoid artifacts.
                     return false;
                 }
-            });
+            };
+            observer.addOnPreDrawListener(listener);
         }
     }
 
@@ -342,23 +349,19 @@
      * value of null causes the TransitionManager to use the default transition.
      */
     public static void beginDelayedTransition(final ViewGroup sceneRoot, Transition transition) {
-
-        // TEMPORARY: disabling delayed transitions until a fix for the various ActionBar-
-        // triggered artifacts is found
-
-//        if (!sPendingTransitions.contains(sceneRoot) && sceneRoot.isLaidOut()) {
-//            if (Transition.DBG) {
-//                Log.d(LOG_TAG, "beginDelayedTransition: root, transition = " +
-//                        sceneRoot + ", " + transition);
-//            }
-//            sPendingTransitions.add(sceneRoot);
-//            if (transition == null) {
-//                transition = sDefaultTransition;
-//            }
-//            final Transition finalTransition = transition.clone();
-//            sceneChangeSetup(sceneRoot, transition);
-//            Scene.setCurrentScene(sceneRoot, null);
-//            sceneChangeRunTransition(sceneRoot, finalTransition);
-//        }
+        if (!sPendingTransitions.contains(sceneRoot) && sceneRoot.isLaidOut()) {
+            if (Transition.DBG) {
+                Log.d(LOG_TAG, "beginDelayedTransition: root, transition = " +
+                        sceneRoot + ", " + transition);
+            }
+            sPendingTransitions.add(sceneRoot);
+            if (transition == null) {
+                transition = sDefaultTransition;
+            }
+            final Transition transitionClone = transition.clone();
+            sceneChangeSetup(sceneRoot, transitionClone);
+            Scene.setCurrentScene(sceneRoot, null);
+            sceneChangeRunTransition(sceneRoot, transitionClone);
+        }
     }
 }
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 75d3e7c..f49821f 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -65,9 +65,6 @@
         ViewGroup endParent;
     }
 
-    // Temporary structure, used in calculating state in setup() and play()
-    private VisibilityInfo mTmpVisibilityInfo = new VisibilityInfo();
-
     @Override
     public String[] getTransitionProperties() {
         return sTransitionProperties;
@@ -161,7 +158,7 @@
 
     private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
             TransitionValues endValues) {
-        final VisibilityInfo visInfo = mTmpVisibilityInfo;
+        final VisibilityInfo visInfo = new VisibilityInfo();
         visInfo.visibilityChange = false;
         visInfo.fadeIn = false;
         if (startValues != null) {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 730c4eb..ad8b51d 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -992,6 +992,8 @@
                 mData = mDataCopy;
             }
             mDataCopy = null;
+            mAccess.mData.clear();
+            mAccess.mSize = 0;
         }
 
         int size() {
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 91c47d1..76b8579 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -30,6 +30,8 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnticipateOvershootInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -41,6 +43,7 @@
     FrameLayout mContent;
     int mCount;
     final Handler mHandler = new Handler();
+    static final int BGCOLOR = 0xffed1d24;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -53,6 +56,7 @@
         Typeface light = Typeface.create("sans-serif-light", Typeface.NORMAL);
 
         mContent = new FrameLayout(this);
+        mContent.setBackgroundColor(0xC0000000);
         
         final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.WRAP_CONTENT,
@@ -64,13 +68,16 @@
         logo.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
         logo.setVisibility(View.INVISIBLE);
 
+        final View bg = new View(this);
+        bg.setBackgroundColor(BGCOLOR);
+        bg.setAlpha(0f);
+
         final TextView letter = new TextView(this);
 
         letter.setTypeface(bold);
         letter.setTextSize(300);
         letter.setTextColor(0xFFFFFFFF);
         letter.setGravity(Gravity.CENTER);
-        letter.setShadowLayer(12*metrics.density, 0, 0, 0xC085F985);
         letter.setText(String.valueOf(Build.VERSION.RELEASE).substring(0, 1));
 
         final int p = (int)(4 * metrics.density);
@@ -81,11 +88,11 @@
         tv.setPadding(p, p, p, p);
         tv.setTextColor(0xFFFFFFFF);
         tv.setGravity(Gravity.CENTER);
-        tv.setShadowLayer(4 * metrics.density, 0, 2 * metrics.density, 0x66000000);
         tv.setTransformationMethod(new AllCapsTransformationMethod(this));
         tv.setText("Android " + Build.VERSION.RELEASE);
         tv.setVisibility(View.INVISIBLE);
 
+        mContent.addView(bg);
         mContent.addView(letter, lp);
         mContent.addView(logo, lp);
 
@@ -96,24 +103,54 @@
         mContent.addView(tv, lp2);
 
         mContent.setOnClickListener(new View.OnClickListener() {
+            int clicks;
             @Override
             public void onClick(View v) {
-                if (logo.getVisibility() != View.VISIBLE) {
-                    letter.animate().alpha(0.25f).scaleY(0.75f).scaleX(0.75f).setDuration(2000)
-                            .start();
-                    logo.setAlpha(0f);
-                    logo.setVisibility(View.VISIBLE);
-                    logo.animate().alpha(1f).setDuration(1000).setStartDelay(500).start();
-                    tv.setAlpha(0f);
-                    tv.setVisibility(View.VISIBLE);
-                    tv.animate().alpha(1f).setDuration(1000).setStartDelay(1000).start();
+                clicks++;
+                if (clicks >= 6) {
+                    mContent.performLongClick();
+                    return;
                 }
+                letter.animate().cancel();
+                final float offset = (int)letter.getRotation() % 360;
+                letter.animate()
+                    .rotationBy((Math.random() > 0.5f ? 360 : -360) - offset)
+                    .setInterpolator(new DecelerateInterpolator())
+                    .setDuration(700).start();
             }
         });
 
         mContent.setOnLongClickListener(new View.OnLongClickListener() {
             @Override
             public boolean onLongClick(View v) {
+                if (logo.getVisibility() != View.VISIBLE) {
+                    bg.setScaleX(0.01f);
+                    bg.animate().alpha(1f).scaleX(1f).setStartDelay(500).start();
+                    letter.animate().alpha(0f).scaleY(0.5f).scaleX(0.5f)
+                            .rotationBy(360)
+                            .setInterpolator(new AccelerateInterpolator())
+                            .setDuration(1000)
+                            .start();
+                    logo.setAlpha(0f);
+                    logo.setVisibility(View.VISIBLE);
+                    logo.setScaleX(0.5f);
+                    logo.setScaleY(0.5f);
+                    logo.animate().alpha(1f).scaleX(1f).scaleY(1f)
+                        .setDuration(1000).setStartDelay(500)
+                        .setInterpolator(new AnticipateOvershootInterpolator())
+                        .start();
+                    tv.setAlpha(0f);
+                    tv.setVisibility(View.VISIBLE);
+                    tv.animate().alpha(1f).setDuration(1000).setStartDelay(1000).start();
+                    return true;
+                }
+                return false;
+            }
+        });
+
+        logo.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
                 try {
                     startActivity(new Intent(Intent.ACTION_MAIN)
                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index 2d06b68..f773f59 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -159,17 +159,26 @@
 }
 
 
-static SkMemoryStream* adaptor_to_mem_stream(SkStream* adaptor) {
-    SkASSERT(adaptor != NULL);
-    SkDynamicMemoryWStream wStream;
-    const int bufferSize = 256 * 1024; // 256 KB, same as ViewStateSerializer.
-    uint8_t buffer[bufferSize];
-    do {
-        size_t bytesRead = adaptor->read(buffer, bufferSize);
-        wStream.write(buffer, bytesRead);
-    } while (!adaptor->isAtEnd());
-    SkAutoTUnref<SkData> data(wStream.copyToData());
-    return new SkMemoryStream(data.get());
+static SkMemoryStream* adaptor_to_mem_stream(SkStream* stream) {
+    SkASSERT(stream != NULL);
+    size_t bufferSize = 4096;
+    size_t streamLen = 0;
+    size_t len;
+    char* data = (char*)sk_malloc_throw(bufferSize);
+
+    while ((len = stream->read(data + streamLen,
+                               bufferSize - streamLen)) != 0) {
+        streamLen += len;
+        if (streamLen == bufferSize) {
+            bufferSize *= 2;
+            data = (char*)sk_realloc_throw(data, bufferSize);
+        }
+    }
+    data = (char*)sk_realloc_throw(data, streamLen);
+
+    SkMemoryStream* streamMem = new SkMemoryStream();
+    streamMem->setMemoryOwned(data, streamLen);
+    return streamMem;
 }
 
 SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream,
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb_am.png b/core/res/res/drawable-hdpi/stat_sys_adb_am.png
index 0c13339..382557e 100644
--- a/core/res/res/drawable-hdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_adb_am.png b/core/res/res/drawable-mdpi/stat_sys_adb_am.png
index f0a5089..4380035 100644
--- a/core/res/res/drawable-mdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-mdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo.png b/core/res/res/drawable-nodpi/platlogo.png
index 4fd0e3c..6351c2d 100644
--- a/core/res/res/drawable-nodpi/platlogo.png
+++ b/core/res/res/drawable-nodpi/platlogo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_adb_am.png b/core/res/res/drawable-xhdpi/stat_sys_adb_am.png
index 789a3f5..3222a76 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png b/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png
index a36fa36..e01ad386 100644
--- a/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-xxhdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index b76c8be..1649268 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -23,13 +23,6 @@
          which is needed when building test cases. -->
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name="ConnectivityManagerTestActivity"
-          android:label="@string/app_name">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
     </application>
 
     <!--
@@ -87,4 +80,6 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
+    <uses-permission android:name="android.permission.DEVICE_POWER" />
+
 </manifest>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 0461c0b..b942eb6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -32,13 +32,11 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.RouteInfo;
-import android.util.Log;
 
 import java.io.InputStream;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
similarity index 88%
rename from core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
rename to core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index a0cb1bb..30eda75 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -16,7 +16,7 @@
 
 package com.android.connectivitymanagertest;
 
-import android.app.Activity;
+import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.BroadcastReceiver;
 import android.content.Intent;
@@ -26,21 +26,14 @@
 import android.net.NetworkInfo.State;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.os.Bundle;
 import android.os.Handler;
-import android.os.IPowerManager;
 import android.os.Message;
 import android.os.PowerManager;
-import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
+import android.test.InstrumentationTestCase;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.widget.LinearLayout;
 
 import com.android.internal.util.AsyncChannel;
 
@@ -52,13 +45,17 @@
 
 
 /**
- * An activity registered with connectivity manager broadcast
- * provides network connectivity information and
- * can be used to set device states: Cellular, Wifi, Airplane mode.
+ * Base InstrumentationTestCase for Connectivity Manager (CM) test suite
+ *
+ * It registers connectivity manager broadcast and WiFi broadcast to provide
+ * network connectivity information, also provides a set of utility functions
+ * to modify and verify connectivity states.
+ *
+ * A CM test case should extend this base class.
  */
-public class ConnectivityManagerTestActivity extends Activity {
+public class ConnectivityManagerTestBase extends InstrumentationTestCase {
 
-    public static final String LOG_TAG = "ConnectivityManagerTestActivity";
+    public static final String LOG_TAG = "ConnectivityManagerTestBase";
     public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
     public static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
     public static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
@@ -94,14 +91,9 @@
     private Context mContext;
     public boolean scanResultAvailable = false;
 
-    /*
-     * Control Wifi States
-     */
+    /* Control Wifi States */
     public WifiManager mWifiManager;
-
-    /*
-     * Verify connectivity state
-     */
+    /* Verify connectivity state */
     public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
     NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES];
 
@@ -208,26 +200,28 @@
         }
     }
 
-    public ConnectivityManagerTestActivity() {
+    @Override
+    public void setUp() throws Exception {
         mState = State.UNKNOWN;
         scanResultAvailable = false;
-    }
+        mContext = getInstrumentation().getContext();
 
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        log("onCreate, inst=" + Integer.toHexString(hashCode()));
+        // Get an instance of ConnectivityManager
+        mCM = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        // Get an instance of WifiManager
+        mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
 
-        // Create a simple layout
-        LinearLayout contentView = new LinearLayout(this);
-        contentView.setOrientation(LinearLayout.VERTICAL);
-        setContentView(contentView);
-        setTitle("ConnectivityManagerTestActivity");
+        if (mWifiManager.isWifiApEnabled()) {
+            // if soft AP is enabled, disable it
+            mWifiManager.setWifiApEnabled(null, false);
+            log("Disable soft ap");
+        }
 
+        initializeNetworkStates();
 
         // register a connectivity receiver for CONNECTIVITY_ACTION;
         mConnectivityReceiver = new ConnectivityReceiver();
-        registerReceiver(mConnectivityReceiver,
+        mContext.registerReceiver(mConnectivityReceiver,
                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
 
         mWifiReceiver = new WifiReceiver();
@@ -238,28 +232,15 @@
         mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
         mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
         mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
-        registerReceiver(mWifiReceiver, mIntentFilter);
+        mContext.registerReceiver(mWifiReceiver, mIntentFilter);
 
-        // Get an instance of ConnectivityManager
-        mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-        // Get an instance of WifiManager
-        mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
-        mContext = this;
-
-        if (mWifiManager.isWifiApEnabled()) {
-            // if soft AP is enabled, disable it
-            mWifiManager.setWifiApEnabled(null, false);
-            log("Disable soft ap");
-        }
-
-        initializeNetworkStates();
         log("Clear Wifi before we start the test.");
         removeConfiguredNetworksAndDisableWifi();
         mWifiRegexs = mCM.getTetherableWifiRegexs();
      }
 
     public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
-        InputStream in = getAssets().open(ACCESS_POINT_FILE);
+        InputStream in = mContext.getAssets().open(ACCESS_POINT_FILE);
         mParseHelper = new AccessPointParserHelper(in);
         return mParseHelper.getNetworkConfigurations();
     }
@@ -277,6 +258,12 @@
     public void recordNetworkState(int networkType, State networkState) {
         log("record network state for network " +  networkType +
                 ", state is " + networkState);
+        if (connectivityState == null) {
+             log("ConnectivityState is null");
+        }
+        if (connectivityState[networkType] == null) {
+             log("connectivityState[networkType] is null");
+        }
         connectivityState[networkType].recordState(networkState);
     }
 
@@ -503,7 +490,7 @@
     public void turnScreenOff() {
         log("Turn screen off");
         PowerManager pm =
-            (PowerManager) getSystemService(Context.POWER_SERVICE);
+            (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         pm.goToSleep(SystemClock.uptimeMillis());
     }
 
@@ -511,8 +498,13 @@
     public void turnScreenOn() {
         log("Turn screen on");
         PowerManager pm =
-                (PowerManager) getSystemService(Context.POWER_SERVICE);
+                (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         pm.wakeUp(SystemClock.uptimeMillis());
+        // disable lock screen
+        KeyguardManager km = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        if (km.inKeyguardRestrictedInputMode()) {
+            sendKeys(KeyEvent.KEYCODE_MENU);
+        }
     }
 
     /**
@@ -607,7 +599,12 @@
             mWifiManager.setWifiEnabled(true);
             sleep(SHORT_TIMEOUT);
         }
+
         List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
+        if (wifiConfigList == null) {
+            log("no configuration list is null");
+            return true;
+        }
         log("size of wifiConfigList: " + wifiConfigList.size());
         for (WifiConfiguration wifiConfig: wifiConfigList) {
             log("remove wifi configuration: " + wifiConfig.networkId);
@@ -656,57 +653,15 @@
     }
 
     @Override
-    protected void onDestroy() {
-        super.onDestroy();
-
+    public void tearDown() throws Exception{
         //Unregister receiver
         if (mConnectivityReceiver != null) {
-            unregisterReceiver(mConnectivityReceiver);
+          mContext.unregisterReceiver(mConnectivityReceiver);
         }
         if (mWifiReceiver != null) {
-            unregisterReceiver(mWifiReceiver);
+          mContext.unregisterReceiver(mWifiReceiver);
         }
-        log("onDestroy, inst=" + Integer.toHexString(hashCode()));
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        mContext = this;
-        Bundle bundle = this.getIntent().getExtras();
-        if (bundle != null){
-            mPowerSsid = bundle.getString("power_ssid");
-        }
-    }
-    //A thread to set the device into airplane mode then turn on wifi.
-    Thread setDeviceWifiAndAirplaneThread = new Thread(new Runnable() {
-        public void run() {
-            mCM.setAirplaneMode(true);
-            connectToWifi(mPowerSsid);
-        }
-    });
-
-    //A thread to set the device into wifi
-    Thread setDeviceInWifiOnlyThread = new Thread(new Runnable() {
-        public void run() {
-            connectToWifi(mPowerSsid);
-        }
-    });
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        switch (keyCode) {
-            //This is a tricky way for the scripted monkey to
-            //set the device in wifi and wifi in airplane mode.
-            case KeyEvent.KEYCODE_1:
-                setDeviceWifiAndAirplaneThread.start();
-                break;
-
-            case KeyEvent.KEYCODE_2:
-                setDeviceInWifiOnlyThread.start();
-                break;
-        }
-        return super.onKeyDown(keyCode, event);
+        super.tearDown();
     }
 
     private void log(String message) {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerUnitTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerUnitTestRunner.java
index 3a78f26..0e57a00 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerUnitTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerUnitTestRunner.java
@@ -16,10 +16,8 @@
 
 package com.android.connectivitymanagertest;
 
-import android.os.Bundle;
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
-import android.util.Log;
 import com.android.connectivitymanagertest.unit.WifiClientTest;
 import com.android.connectivitymanagertest.unit.WifiSoftAPTest;
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 729e1d2..05462b4 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -24,31 +24,24 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.provider.Settings;
-import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
-import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
 import com.android.connectivitymanagertest.NetworkState;
 
 public class ConnectivityManagerMobileTest extends
-        ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
-    private static final String LOG_TAG = "ConnectivityManagerMobileTest";
+        ConnectivityManagerTestBase {
+    private static final String TAG = "ConnectivityManagerMobileTest";
 
     private String mTestAccessPoint;
-    private ConnectivityManagerTestActivity cmActivity;
     private WakeLock wl;
     private boolean mWifiOnlyFlag;
 
-    public ConnectivityManagerMobileTest() {
-        super(ConnectivityManagerTestActivity.class);
-    }
-
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        cmActivity = getActivity();
         ConnectivityManagerTestRunner mRunner =
                 (ConnectivityManagerTestRunner)getInstrumentation();
         mTestAccessPoint = mRunner.mTestSsid;
@@ -62,12 +55,12 @@
         if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_ON) == 1) {
             log("airplane is not disabled, disable it.");
-            cmActivity.mCM.setAirplaneMode(false);
+            mCM.setAirplaneMode(false);
         }
 
         if (!mWifiOnlyFlag) {
-            if (!cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                    ConnectivityManagerTestActivity.LONG_TIMEOUT)) {
+            if (!waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.CONNECTED, LONG_TIMEOUT)) {
                 // Note: When the test fails in setUp(), tearDown is not called. In that case,
                 // the activity is destroyed which blocks the next test at "getActivity()".
                 // tearDown() is called here to avoid that situation.
@@ -79,29 +72,22 @@
 
     @Override
     public void tearDown() throws Exception {
-        cmActivity.finish();
-        log("tear down ConnectivityManagerTestActivity");
         wl.release();
-        cmActivity.removeConfiguredNetworksAndDisableWifi();
-        // if airplane mode is set, disable it.
-        if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
-                Settings.Global.AIRPLANE_MODE_ON) == 1) {
-            log("disable airplane mode if it is enabled");
-            cmActivity.mCM.setAirplaneMode(false);
-        }
+        removeConfiguredNetworksAndDisableWifi();
+        mCM.setAirplaneMode(false);
         super.tearDown();
     }
 
     // help function to verify 3G connection
     public void verifyCellularConnection() {
-        NetworkInfo extraNetInfo = cmActivity.mCM.getActiveNetworkInfo();
+        NetworkInfo extraNetInfo = mCM.getActiveNetworkInfo();
         assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
                 extraNetInfo.getType());
         assertTrue("not connected to cellular network", extraNetInfo.isConnected());
     }
 
     private void log(String message) {
-        Log.v(LOG_TAG, message);
+        Log.v(TAG, message);
     }
 
     private void sleep(long sleeptime) {
@@ -115,46 +101,46 @@
     @LargeTest
     public void test3GToWifiNotification() {
         if (mWifiOnlyFlag) {
-            Log.v(LOG_TAG, this.getName() + " is excluded for wifi-only test");
+            Log.v(TAG, this.getName() + " is excluded for wifi-only test");
             return;
         }
         // Enable Wi-Fi to avoid initial UNKNOWN state
-        cmActivity.enableWifi();
-        sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+        enableWifi();
+        sleep(2 * SHORT_TIMEOUT);
 
         // Wi-Fi is disabled
-        cmActivity.disableWifi();
+        disableWifi();
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.DISCONNECTED,  ConnectivityManagerTestActivity.LONG_TIMEOUT));
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.DISCONNECTED, LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                State.CONNECTED, LONG_TIMEOUT));
         // Wait for 10 seconds for broadcasts to be sent out
         sleep(10 * 1000);
 
         // As Wifi stays in DISCONNETED, Mobile statys in CONNECTED,
         // the connectivity manager will not broadcast any network connectivity event for Wifi
-        NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                 networkInfo.getState(), NetworkState.DO_NOTHING, State.CONNECTED);
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                 NetworkState.DO_NOTHING, State.DISCONNECTED);
         // Eanble Wifi without associating with any AP
-        cmActivity.enableWifi();
-        sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+        enableWifi();
+        sleep(2 * SHORT_TIMEOUT);
 
         // validate state and broadcast
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
             log("the state for WIFI is changed");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue("state validation fail", false);
         }
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
             log("the state for MOBILE is changed");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
             assertTrue("state validation fail", false);
         }
         // Verify that the device is still connected to MOBILE
@@ -168,40 +154,39 @@
         NetworkInfo networkInfo;
         if (!mWifiOnlyFlag) {
             //Prepare for connectivity verification
-            networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-            cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+            networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+            setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                     networkInfo.getState(), NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
         }
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                 NetworkState.TO_CONNECTION, State.CONNECTED);
 
         // Enable Wifi and connect to a test access point
         assertTrue("failed to connect to " + mTestAccessPoint,
-                cmActivity.connectToWifi(mTestAccessPoint));
+                connectToWifi(mTestAccessPoint));
 
-        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
         log("wifi state is enabled");
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
         if (!mWifiOnlyFlag) {
-            assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                    State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.DISCONNECTED, LONG_TIMEOUT));
         }
 
         // validate states
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
             log("Wifi state transition validation failed.");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
         if (!mWifiOnlyFlag) {
-            if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+            if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
                 log("Mobile state transition validation failed.");
                 log("reason: " +
-                        cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+                        getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
                 assertTrue(false);
             }
         }
@@ -213,61 +198,59 @@
         assertNotNull("SSID is null", mTestAccessPoint);
         // Connect to mTestAccessPoint
         assertTrue("failed to connect to " + mTestAccessPoint,
-                cmActivity.connectToWifi(mTestAccessPoint));
-        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+                connectToWifi(mTestAccessPoint));
+        assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
 
-        sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+        sleep(SHORT_TIMEOUT);
         // Disable Wifi
         log("Disable Wifi");
-        if (!cmActivity.disableWifi()) {
+        if (!disableWifi()) {
             log("disable Wifi failed");
             return;
         }
 
         // Wait for the Wifi state to be DISABLED
-        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForWifiState(WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.DISCONNECTED, LONG_TIMEOUT));
         if (!mWifiOnlyFlag) {
-            assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                    State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.CONNECTED, LONG_TIMEOUT));
         }
 
         NetworkInfo networkInfo;
         if (!mWifiOnlyFlag) {
             //Prepare for connectivity state verification
-            networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-            cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+            networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+            setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                                                   networkInfo.getState(), NetworkState.DO_NOTHING,
                                                   State.DISCONNECTED);
         }
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                 NetworkState.TO_CONNECTION, State.CONNECTED);
 
         // wait for 2 minutes before restart wifi
-        sleep(ConnectivityManagerTestActivity.WIFI_STOP_START_INTERVAL);
+        sleep(WIFI_STOP_START_INTERVAL);
         // Enable Wifi again
         log("Enable Wifi again");
-        cmActivity.enableWifi();
+        enableWifi();
 
         // Wait for Wifi to be connected and mobile to be disconnected
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
         if (!mWifiOnlyFlag) {
-            assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                    State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.DISCONNECTED, LONG_TIMEOUT));
         }
 
         // validate wifi states
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
             log("Wifi state transition validation failed.");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
     }
@@ -279,48 +262,48 @@
 
         // connect to Wifi
         assertTrue("failed to connect to " + mTestAccessPoint,
-                cmActivity.connectToWifi(mTestAccessPoint));
+                connectToWifi(mTestAccessPoint));
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
 
         // Wait for a few seconds to avoid the state that both Mobile and Wifi is connected
-        sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+        sleep(SHORT_TIMEOUT);
 
         NetworkInfo networkInfo;
         if (!mWifiOnlyFlag) {
-            networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-            cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+            networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+            setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                                                   networkInfo.getState(),
                                                   NetworkState.TO_CONNECTION,
                                                   State.CONNECTED);
         }
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                 NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
 
         // clear Wifi
-        cmActivity.removeConfiguredNetworksAndDisableWifi();
+        removeConfiguredNetworksAndDisableWifi();
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.DISCONNECTED, LONG_TIMEOUT));
         if (!mWifiOnlyFlag) {
-            assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                    State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.CONNECTED, LONG_TIMEOUT));
         }
 
         // validate states
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
             log("Wifi state transition validation failed.");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
         if (!mWifiOnlyFlag) {
-            if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+            if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
                 log("Mobile state transition validation failed.");
                 log("reason: " +
-                        cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+                        getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
                 assertTrue(false);
             }
         }
@@ -330,62 +313,62 @@
     @LargeTest
     public void testDataConnectionWith3GToAmTo3G() {
         if (mWifiOnlyFlag) {
-            Log.v(LOG_TAG, this.getName() + " is excluded for wifi-only test");
+            Log.v(TAG, this.getName() + " is excluded for wifi-only test");
             return;
         }
         //Prepare for state verification
-        NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                                               networkInfo.getState(),
                                               NetworkState.TO_DISCONNECTION,
                                               State.DISCONNECTED);
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
         assertEquals(State.DISCONNECTED, networkInfo.getState());
 
         // Enable airplane mode
         log("Enable airplane mode");
-        cmActivity.mCM.setAirplaneMode(true);
-        sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+        mCM.setAirplaneMode(true);
+        sleep(SHORT_TIMEOUT);
 
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
         assertEquals(State.DISCONNECTED, networkInfo.getState());
         // wait until mobile is turn off
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                State.DISCONNECTED, LONG_TIMEOUT));
+        if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
             log("Mobile state transition validation failed.");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
             assertTrue(false);
         }
 
         // reset state recorder
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                                               networkInfo.getState(),
                                               NetworkState.TO_CONNECTION,
                                               State.CONNECTED);
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                 NetworkState.DO_NOTHING, State.DISCONNECTED);
 
         // disable airplane mode
-        cmActivity.mCM.setAirplaneMode(false);
+        mCM.setAirplaneMode(false);
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                State.CONNECTED, LONG_TIMEOUT));
 
         // Validate the state transition
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
             log("Mobile state transition validation failed.");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
             assertTrue(false);
         }
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
           log("Wifi state transition validation failed.");
           log("reason: " +
-                  cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                  getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
           assertTrue(false);
         }
     }
@@ -394,107 +377,107 @@
     @LargeTest
     public void testDataConnectionOverAMWithWifi() {
         if (mWifiOnlyFlag) {
-            Log.v(LOG_TAG, this.getName() + " is excluded for wifi-only test");
+            Log.v(TAG, this.getName() + " is excluded for wifi-only test");
             return;
         }
         assertNotNull("SSID is null", mTestAccessPoint);
         // Eanble airplane mode
         log("Enable airplane mode");
-        cmActivity.mCM.setAirplaneMode(true);
+        mCM.setAirplaneMode(true);
 
         NetworkInfo networkInfo;
         if (!mWifiOnlyFlag) {
-            assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                    State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
-            networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-            cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
+            assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.DISCONNECTED, LONG_TIMEOUT));
+            networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+            setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
                                                   networkInfo.getState(),
                                                   NetworkState.DO_NOTHING,
                                                   State.DISCONNECTED);
         }
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
+        networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI, networkInfo.getState(),
                                               NetworkState.TO_CONNECTION, State.CONNECTED);
 
         // Connect to Wifi
         assertTrue("failed to connect to " + mTestAccessPoint,
-                cmActivity.connectToWifi(mTestAccessPoint));
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+                connectToWifi(mTestAccessPoint));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
 
         // validate state and broadcast
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
             log("state validate for Wifi failed");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue("State validation failed", false);
         }
         if (!mWifiOnlyFlag) {
-            if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
+            if (!validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
                 log("state validation for Mobile failed");
                 log("reason: " +
-                        cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
+                        getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
                 assertTrue("state validation failed", false);
             }
         }
-        cmActivity.mCM.setAirplaneMode(false);
+        mCM.setAirplaneMode(false);
     }
 
     // Test case 7: test connectivity while transit from Wifi->AM->Wifi
     @LargeTest
     public void testDataConnectionWithWifiToAMToWifi () {
         if (mWifiOnlyFlag) {
-            Log.v(LOG_TAG, this.getName() + " is excluded for wifi-only test");
+            Log.v(TAG, this.getName() + " is excluded for wifi-only test");
             return;
         }
         // Connect to mTestAccessPoint
         assertNotNull("SSID is null", mTestAccessPoint);
         // Connect to Wifi
         assertTrue("failed to connect to " + mTestAccessPoint,
-                cmActivity.connectToWifi(mTestAccessPoint));
+                connectToWifi(mTestAccessPoint));
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
 
         try {
-            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+            Thread.sleep(SHORT_TIMEOUT);
         } catch (Exception e) {
             log("exception: " + e.toString());
         }
 
         // Enable airplane mode without clearing Wifi
-        cmActivity.mCM.setAirplaneMode(true);
+        mCM.setAirplaneMode(true);
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.DISCONNECTED, LONG_TIMEOUT));
 
         try {
-            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+            Thread.sleep(SHORT_TIMEOUT);
         } catch (Exception e) {
             log("exception: " + e.toString());
         }
 
         // Prepare for state validation
-        NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
         assertEquals(State.DISCONNECTED, networkInfo.getState());
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI,
+        setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI,
                 networkInfo.getState(), NetworkState.TO_CONNECTION, State.CONNECTED);
 
         // Disable airplane mode
-        cmActivity.mCM.setAirplaneMode(false);
+        mCM.setAirplaneMode(false);
 
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
         if (!mWifiOnlyFlag) {
-            assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
-                    State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue(waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+                    State.DISCONNECTED, LONG_TIMEOUT));
         }
 
         // validate the state transition
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
+        if (!validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
             log("Wifi state transition validation failed.");
             log("reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
+                    getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
     }
@@ -505,35 +488,33 @@
         assertNotNull("SSID is null", mTestAccessPoint);
         //Connect to mTestAccessPoint
         assertTrue("failed to connect to " + mTestAccessPoint,
-                cmActivity.connectToWifi(mTestAccessPoint));
-        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+                connectToWifi(mTestAccessPoint));
+        assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
         assertNotNull("Not associated with any AP",
-                      cmActivity.mWifiManager.getConnectionInfo().getBSSID());
+                      mWifiManager.getConnectionInfo().getBSSID());
 
         try {
-            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+            Thread.sleep(SHORT_TIMEOUT);
         } catch (Exception e) {
             log("exception: " + e.toString());
         }
 
         // Disconnect from the current AP
         log("disconnect from the AP");
-        if (!cmActivity.disconnectAP()) {
+        if (!disconnectAP()) {
             log("failed to disconnect from " + mTestAccessPoint);
         }
 
         // Verify the connectivity state for Wifi is DISCONNECTED
-        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.DISCONNECTED, LONG_TIMEOUT));
 
-        if (!cmActivity.disableWifi()) {
+        if (!disableWifi()) {
             log("disable Wifi failed");
             return;
         }
-        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
-                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(waitForWifiState(WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
     }
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
index f12e62e..183f2a9 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
@@ -16,7 +16,7 @@
 
 package com.android.connectivitymanagertest.functional;
 
-import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 import com.android.connectivitymanagertest.WifiAssociationTestRunner;
 
 import android.content.Context;
@@ -32,7 +32,6 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo.State;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 
 /**
@@ -43,30 +42,22 @@
  * -w com.android.connectivitymanagertest/.WifiAssociationTestRunner"
  */
 public class WifiAssociationTest
-    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+        extends ConnectivityManagerTestBase {
     private static final String TAG = "WifiAssociationTest";
-    private ConnectivityManagerTestActivity mAct;
     private String mSsid = null;
     private String mPassword = null;
     private String mSecurityType = null;
     private String mFrequencyBand = null;
     private int mBand;
-    private WifiManager mWifiManager = null;
 
     enum SECURITY_TYPE {
         OPEN, WEP64, WEP128, WPA_TKIP, WPA2_AES
-    };
-
-    public WifiAssociationTest() {
-        super(ConnectivityManagerTestActivity.class);
     }
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
         WifiAssociationTestRunner mRunner = (WifiAssociationTestRunner)getInstrumentation();
-        mWifiManager = (WifiManager) mRunner.getContext().getSystemService(Context.WIFI_SERVICE);
-        mAct = getActivity();
         Bundle arguments = mRunner.getArguments();
         mSecurityType = arguments.getString("security-type");
         mSsid = arguments.getString("ssid");
@@ -77,17 +68,15 @@
         assertNotNull("Ssid is empty", mSsid);
         validateFrequencyBand();
         // enable Wifi and verify wpa_supplicant is started
-        assertTrue("enable Wifi failed", mAct.enableWifi());
-        sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT,
-                "interrupted while waiting for WPA_SUPPLICANT to start");
-        WifiInfo mConnection = mAct.mWifiManager.getConnectionInfo();
+        assertTrue("enable Wifi failed", enableWifi());
+        sleep(2 * SHORT_TIMEOUT, "interrupted while waiting for WPA_SUPPLICANT to start");
+        WifiInfo mConnection = mWifiManager.getConnectionInfo();
         assertNotNull(mConnection);
-        assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
+        assertTrue("wpa_supplicant is not started ", mWifiManager.pingSupplicant());
     }
 
     @Override
     public void tearDown() throws Exception {
-        log("tearDown()");
         super.tearDown();
     }
 
@@ -107,16 +96,16 @@
     private void connectToWifi(WifiConfiguration config) {
         // step 1: connect to the test access point
         assertTrue("failed to associate with " + config.SSID,
-                mAct.connectToWifiWithConfiguration(config));
+                connectToWifiWithConfiguration(config));
 
         // step 2: verify Wifi state and network state;
         assertTrue("failed to connect with " + config.SSID,
-                mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.CONNECTED, ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+                waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
 
         // step 3: verify the current connected network is the given SSID
-        assertNotNull("Wifi connection returns null", mAct.mWifiManager.getConnectionInfo());
-        assertTrue(config.SSID.contains(mAct.mWifiManager.getConnectionInfo().getSSID()));
+        assertNotNull("Wifi connection returns null", mWifiManager.getConnectionInfo());
+        assertTrue(config.SSID.contains(mWifiManager.getConnectionInfo().getSSID()));
     }
 
     private void sleep(long sometime, String errorMsg) {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index de0298e..ad73ee1 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -16,35 +16,19 @@
 
 package com.android.connectivitymanagertest.functional;
 
-import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
 
-import android.R;
-import android.app.Activity;
-import android.content.ContentResolver;
-import android.content.Intent;
 import android.content.Context;
-import android.content.res.Resources;
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.Status;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.ConnectivityManager;
-import android.net.DhcpInfo;
-import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Settings;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 
-import com.android.internal.util.AsyncChannel;
-
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -56,39 +40,25 @@
  *          -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
  */
 public class WifiConnectionTest
-    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+    extends ConnectivityManagerTestBase {
     private static final String TAG = "WifiConnectionTest";
     private static final boolean DEBUG = false;
     private List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
-    private ConnectivityManagerTestActivity mAct;
-    private ConnectivityManagerTestRunner mRunner;
-    private WifiManager mWifiManager = null;
-    private Set<WifiConfiguration> enabledNetworks = null;
-
-    public WifiConnectionTest() {
-        super(ConnectivityManagerTestActivity.class);
-    }
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mRunner = ((ConnectivityManagerTestRunner)getInstrumentation());
-        mWifiManager = (WifiManager) mRunner.getContext().getSystemService(Context.WIFI_SERVICE);
-
-        mAct = getActivity();
-
-        networks = mAct.loadNetworkConfigurations();
+        networks = loadNetworkConfigurations();
         if (DEBUG) {
             printNetworkConfigurations();
         }
 
         // enable Wifi and verify wpa_supplicant is started
-        assertTrue("enable Wifi failed", mAct.enableWifi());
-        sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT,
-                "interrupted while waiting for WPA_SUPPLICANT to start");
-        WifiInfo mConnection = mAct.mWifiManager.getConnectionInfo();
+        assertTrue("enable Wifi failed", enableWifi());
+        sleep(2 * SHORT_TIMEOUT, "interrupted while waiting for WPA_SUPPLICANT to start");
+        WifiInfo mConnection = mWifiManager.getConnectionInfo();
         assertNotNull(mConnection);
-        assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
+        assertTrue("wpa_supplicant is not started ", mWifiManager.pingSupplicant());
     }
 
     private void printNetworkConfigurations() {
@@ -101,8 +71,7 @@
 
     @Override
     public void tearDown() throws Exception {
-        log("tearDown()");
-        mAct.removeConfiguredNetworksAndDisableWifi();
+        removeConfiguredNetworksAndDisableWifi();
         super.tearDown();
     }
 
@@ -114,20 +83,20 @@
     private void connectToWifi(WifiConfiguration config) {
         // step 1: connect to the test access point
         assertTrue("failed to connect to " + config.SSID,
-                mAct.connectToWifiWithConfiguration(config));
+                connectToWifiWithConfiguration(config));
 
         // step 2: verify Wifi state and network state;
-        assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.CONNECTED, ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
 
         // step 3: verify the current connected network is the given SSID
-        assertNotNull("Wifi connection returns null", mAct.mWifiManager.getConnectionInfo());
+        assertNotNull("Wifi connection returns null", mWifiManager.getConnectionInfo());
         if (DEBUG) {
             log("config.SSID = " + config.SSID);
-            log("mAct.mWifiManager.getConnectionInfo.getSSID()" +
-                    mAct.mWifiManager.getConnectionInfo().getSSID());
+            log("mWifiManager.getConnectionInfo.getSSID()" +
+                    mWifiManager.getConnectionInfo().getSSID());
         }
-        assertTrue(config.SSID.contains(mAct.mWifiManager.getConnectionInfo().getSSID()));
+        assertTrue(config.SSID.contains(mWifiManager.getConnectionInfo().getSSID()));
     }
 
     private void sleep(long sometime, String errorMsg) {
@@ -149,8 +118,7 @@
             log("-- START Wi-Fi connection test to : " + ssid + " --");
             connectToWifi(networks.get(i));
             // wait for 2 minutes between wifi stop and start
-            sleep(ConnectivityManagerTestActivity.WIFI_STOP_START_INTERVAL,
-                  "interruped while connected to wifi");
+            sleep(WIFI_STOP_START_INTERVAL, "interruped while connected to wifi");
             log("-- END Wi-Fi connection test to " + ssid + " -- ");
         }
     }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index 60595fb..790ca38 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -18,19 +18,13 @@
 
 
 import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
-import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 
-import android.content.Context;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
 import android.net.wifi.WifiManager;
 import android.os.Environment;
-import android.os.IPowerManager;
-import android.os.PowerManager;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
@@ -42,30 +36,24 @@
  * Stress the wifi driver as access point.
  */
 public class WifiApStress
-    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+    extends ConnectivityManagerTestBase {
     private final static String TAG = "WifiApStress";
     private static String NETWORK_ID = "AndroidAPTest";
     private static String PASSWD = "androidwifi";
     private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
-    private ConnectivityManagerTestActivity mAct;
     private int iterations;
     private BufferedWriter mOutputWriter = null;
     private int mLastIteration = 0;
     private boolean mWifiOnlyFlag;
 
-    public WifiApStress() {
-        super(ConnectivityManagerTestActivity.class);
-    }
-
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mAct = getActivity();
         ConnectivityManagerStressTestRunner mRunner =
             (ConnectivityManagerStressTestRunner)getInstrumentation();
         iterations = mRunner.mSoftapIterations;
         mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
-        mAct.turnScreenOn();
+        turnScreenOn();
     }
 
     @Override
@@ -92,30 +80,28 @@
         config.preSharedKey = PASSWD;
 
         // If Wifi is enabled, disable it
-        if (mAct.mWifiManager.isWifiEnabled()) {
-            mAct.disableWifi();
+        if (mWifiManager.isWifiEnabled()) {
+            disableWifi();
         }
         int i;
         for (i = 0; i < iterations; i++) {
             Log.v(TAG, "iteration: " + i);
             mLastIteration = i;
             // enable Wifi tethering
-            assertTrue(mAct.mWifiManager.setWifiApEnabled(config, true));
+            assertTrue(mWifiManager.setWifiApEnabled(config, true));
             // Wait for wifi ap state to be ENABLED
-            assertTrue(mAct.waitForWifiAPState(WifiManager.WIFI_AP_STATE_ENABLED,
-                    2 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue(waitForWifiAPState(WifiManager.WIFI_AP_STATE_ENABLED, 2 * LONG_TIMEOUT));
             // Wait for wifi tethering result
-            assertEquals(ConnectivityManagerTestActivity.SUCCESS,
-                    mAct.waitForTetherStateChange(2*ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+            assertEquals(SUCCESS, waitForTetherStateChange(2 * SHORT_TIMEOUT));
             // Allow the wifi tethering to be enabled for 10 seconds
             try {
-                Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+                Thread.sleep(2 * SHORT_TIMEOUT);
             } catch (Exception e) {
                 fail("thread in sleep is interrupted");
             }
-            assertTrue("no uplink data connection after Wi-Fi tethering", mAct.pingTest(null));
+            assertTrue("no uplink data connection after Wi-Fi tethering", pingTest(null));
             // Disable soft AP
-            assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
+            assertTrue(mWifiManager.setWifiApEnabled(config, false));
             // Wait for 30 seconds until Wi-Fi tethering is stopped
             try {
                 Thread.sleep(30 * 1000);
@@ -123,7 +109,7 @@
             } catch (Exception e) {
                 fail("thread in sleep is interrupted");
             }
-            assertFalse("Wi-Fi AP disable failed", mAct.mWifiManager.isWifiApEnabled());
+            assertFalse("Wi-Fi AP disable failed", mWifiManager.isWifiApEnabled());
         }
         if (i == iterations) {
             mLastIteration = iterations;
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index e3c7cc4..04ce4b7 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -29,12 +29,11 @@
 import android.os.PowerManager;
 import android.provider.Settings;
 import android.view.KeyEvent;
-import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
 import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
-import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -50,7 +49,7 @@
  *                  -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
  */
 public class WifiStressTest
-    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+        extends ConnectivityManagerTestBase {
     private final static String TAG = "WifiStressTest";
 
     /**
@@ -67,7 +66,6 @@
     private final static long WIFI_SHUTDOWN_DELAY = 2 * 60 * 1000;
 
     private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
-    private ConnectivityManagerTestActivity mAct;
     private int mReconnectIterations;
     private int mWifiSleepTime;
     private int mScanIterations;
@@ -77,15 +75,10 @@
     private BufferedWriter mOutputWriter = null;
     private boolean mWifiOnlyFlag;
 
-    public WifiStressTest() {
-        super(ConnectivityManagerTestActivity.class);
-    }
-
     @Override
     public void setUp() throws Exception {
         super.setUp();
 
-        mAct = getActivity();
         mRunner = (ConnectivityManagerStressTestRunner) getInstrumentation();
         mReconnectIterations = mRunner.mReconnectIterations;
         mSsid = mRunner.mReconnectSsid;
@@ -98,15 +91,14 @@
             mPassword, mScanIterations, mWifiSleepTime));
         mOutputWriter = new BufferedWriter(new FileWriter(new File(
                 Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
-        mAct.turnScreenOn();
-        if (!mAct.mWifiManager.isWifiEnabled()) {
+        turnScreenOn();
+        if (!mWifiManager.isWifiEnabled()) {
             log("Enable wi-fi before stress tests.");
-            if (!mAct.enableWifi()) {
+            if (!enableWifi()) {
                 tearDown();
                 fail("enable wifi failed.");
             }
-            sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
-                    "Interruped while waiting for wifi on");
+            sleep(SHORT_TIMEOUT, "Interruped while waiting for wifi on");
         }
     }
 
@@ -166,33 +158,32 @@
             writeOutput(String.format("ssid appear %d out of %d scan iterations",
                     ssidAppearInScanResultsCount, i));
             long startTime = System.currentTimeMillis();
-            mAct.scanResultAvailable = false;
-            assertTrue("start scan failed", mAct.mWifiManager.startScan());
+            scanResultAvailable = false;
+            assertTrue("start scan failed", mWifiManager.startScan());
             while (true) {
                 if ((System.currentTimeMillis() - startTime) >
-                ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT) {
-                    fail("Wifi scanning takes more than " +
-                            ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT + " ms");
+                WIFI_SCAN_TIMEOUT) {
+                    fail("Wifi scanning takes more than " + WIFI_SCAN_TIMEOUT + " ms");
                 }
-                synchronized(mAct) {
+                synchronized(this) {
                     try {
-                        mAct.wait(ConnectivityManagerTestActivity.WAIT_FOR_SCAN_RESULT);
+                        wait(WAIT_FOR_SCAN_RESULT);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
-                    if (mAct.scanResultAvailable) {
+                    if (scanResultAvailable) {
                         long scanTime = (System.currentTimeMillis() - startTime);
                         scanTimeSum += scanTime;
                         break;
                     }
                 }
             }
-            if ((mAct.mWifiManager.getScanResults() == null) ||
-                    (mAct.mWifiManager.getScanResults().size() <= 0)) {
+            if ((mWifiManager.getScanResults() == null) ||
+                    (mWifiManager.getScanResults().size() <= 0)) {
                 fail("Scan results are empty ");
             }
 
-            List<ScanResult> netList = mAct.mWifiManager.getScanResults();
+            List<ScanResult> netList = mWifiManager.getScanResults();
             if (netList != null) {
                 log("size of scan result list: " + netList.size());
                 for (int s = 0; s < netList.size(); s++) {
@@ -244,13 +235,13 @@
         config.proxySettings = ProxySettings.NONE;
 
         assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
-                mAct.connectToWifiWithConfiguration(config));
-        assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
-                ConnectivityManagerTestActivity.SHORT_TIMEOUT));
-        assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+                connectToWifiWithConfiguration(config));
+        assertTrue(waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                SHORT_TIMEOUT));
+        assertTrue(waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                WIFI_CONNECTION_TIMEOUT));
         // Run ping test to verify the data connection
-        assertTrue("Wi-Fi is connected, but no data connection.", mAct.pingTest(null));
+        assertTrue("Wi-Fi is connected, but no data connection.", pingTest(null));
 
         int i;
         long sum = 0;
@@ -263,33 +254,33 @@
             writeOutput(String.format("iteration %d out of %d",
                     i, mReconnectIterations));
             log("iteration: " + i);
-            mAct.turnScreenOff();
+            turnScreenOff();
             PowerManager pm =
                 (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
             assertFalse(pm.isScreenOn());
             sleep(WIFI_IDLE_MS + WIFI_SHUTDOWN_DELAY, "Interruped while wait for wifi to be idle");
             assertTrue("Wait for Wi-Fi to idle timeout",
-                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                    6 * ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+                    waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                    6 * SHORT_TIMEOUT));
             if (!mWifiOnlyFlag) {
                 // use long timeout as the pppd startup may take several retries.
                 assertTrue("Wait for cellular connection timeout",
-                        mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                        2 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
+                        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                        2 * LONG_TIMEOUT));
             }
             sleep(mWifiSleepTime, "Interrupted while device is in sleep mode");
             // Verify the wi-fi is still off and data connection is on
             assertEquals("Wi-Fi is reconnected", State.DISCONNECTED,
-                    mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
+                    mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
 
             if (!mWifiOnlyFlag) {
                 assertEquals("Cellular connection is down", State.CONNECTED,
-                             mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
-                assertTrue("Mobile is connected, but no data connection.", mAct.pingTest(null));
+                             mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
+                assertTrue("Mobile is connected, but no data connection.", pingTest(null));
             }
 
             // Turn screen on again
-            mAct.turnScreenOn();
+            turnScreenOn();
             // Wait for 2 seconds for the lock screen
             sleep(2 * 1000, "wait 2 seconds for lock screen");
             // Disable lock screen by inject menu key event
@@ -298,16 +289,16 @@
             // Measure the time for Wi-Fi to get connected
             long startTime = System.currentTimeMillis();
             assertTrue("Wait for Wi-Fi enable timeout after wake up",
-                    mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
-                    ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+                    waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                    SHORT_TIMEOUT));
             assertTrue("Wait for Wi-Fi connection timeout after wake up",
-                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                    ConnectivityManagerTestActivity.WIFI_CONNECTION_TIMEOUT));
+                    waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                    WIFI_CONNECTION_TIMEOUT));
             long connectionTime = System.currentTimeMillis() - startTime;
             sum += connectionTime;
             log("average reconnection time is: " + sum/(i+1));
 
-            assertTrue("Reconnect to Wi-Fi network, but no data connection.", mAct.pingTest(null));
+            assertTrue("Reconnect to Wi-Fi network, but no data connection.", pingTest(null));
         }
         if (i == mReconnectIterations) {
             writeOutput(String.format("iteration %d out of %d",
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
index e44023b..7a9bc78 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
@@ -20,9 +20,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.Context;
-import android.app.Instrumentation;
-import android.os.Handler;
-import android.os.Message;
 import android.net.NetworkInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiConfiguration;
@@ -33,11 +30,8 @@
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.AndroidTestCase;
 
-import java.util.ArrayList;
 import java.util.List;
 
-import android.util.Log;
-
 /**
  * Test wifi client
  */
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiSoftAPTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiSoftAPTest.java
index 3f43e48..f202862 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiSoftAPTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiSoftAPTest.java
@@ -16,13 +16,7 @@
 
 package com.android.connectivitymanagertest.unit;
 
-import android.content.BroadcastReceiver;
-import android.content.Intent;
 import android.content.Context;
-import android.app.Instrumentation;
-import android.os.Handler;
-import android.os.Message;
-import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -30,8 +24,6 @@
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.AndroidTestCase;
 
-import java.util.ArrayList;
-
 import android.util.Log;
 
 /**
diff --git a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
index ebecf2e3..a2e9ae8 100644
--- a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
+++ b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
@@ -83,8 +83,8 @@
 
         mImageReaderLock.lock();
         try {
-            mImageReader = new ImageReader(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
-            mImageReader.setImageAvailableListener(mImageListener, mHandler);
+            mImageReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
+            mImageReader.setOnImageAvailableListener(mImageListener, mHandler);
             mSurface = mImageReader.getSurface();
         } finally {
             mImageReaderLock.unlock();
@@ -409,19 +409,11 @@
                 }
 
                 Log.d(TAG, "New image available from virtual display.");
-                Image image = reader.getNextImage();
+
+                // Get the latest buffer.
+                Image image = reader.acquireLatestImage();
                 if (image != null) {
                     try {
-                        // Get the latest buffer.
-                        for (;;) {
-                            Image nextImage = reader.getNextImage();
-                            if (nextImage == null) {
-                                break;
-                            }
-                            reader.releaseImage(image);
-                            image = nextImage;
-                        }
-
                         // Scan for colors.
                         int color = scanImage(image);
                         synchronized (this) {
@@ -431,7 +423,7 @@
                             }
                         }
                     } finally {
-                        reader.releaseImage(image);
+                        image.close();
                     }
                 }
             } finally {
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 607d16e..14a1682 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -10,6 +10,11 @@
 
     <ol>
       <li><a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a></li>
+      <li><a href="#access-rs-apis">Accessing RenderScript Java APIs</a>
+        <ol>
+          <li><a href="#ide-setup">Setting Up Your Development Environment</a></li>
+        </ol>
+      </li>
       <li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li>
     </ol>
 
@@ -144,9 +149,85 @@
 beneficial on some architectures due to additional optimizations only available with relaxed
 precision (such as SIMD CPU instructions).</p>
 
+
+<h2 id="access-rs-apis">Accessing RenderScript Java APIs</h2>
+
+<p>When developing an Android application that uses RenderScript, you can access its Java API in
+  one of two ways. The APIs are available in the {@link android.renderscript} package
+  on devices running Android 3.0 (API level 11) and higher. These are the original APIs for
+  RenderScript. The APIs are also available as a Support Library in the
+  {@link android.support.v8.renderscript} package, which allow you to use them on devices running
+  Android 2.2 (API level 8) and higher.</p>
+
+<p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
+  include the latest improvements to the RenderScript compute framework and provide a wider range
+  of device compatibility. Using the RenderScript APIs in the Support Library requires specific
+  setup procedures for your development environment, which is described in the next section.</p>
+
+
+<h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
+
+<p>In order to use the Support Library RenderScript APIs, you must configure your development
+  environment to be able to access them. The following Android SDK tools are required for using
+  these APIs:</p>
+
+<ul>
+  <li>Android SDK Tools revision 22.2 or higher</li>
+  <li>Android SDK Build-tools revision 18.1.0 or higher</li>
+</ul>
+
+<p>You can check and update the installed version of these tools in the
+  <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</p>
+
+<p class="note">
+  <strong>Note:</strong> Use of Support Library RenderScript APIs is not currently supported with
+  Android Studio or Gradle-based builds.
+</p>
+
+<p>To use the Support Library RenderScript APIs in Eclipse:</p>
+
+<ol>
+  <li>Make sure you have the required Android SDK version and Build Tools version installed.</li>
+  <li>Open the {@code project.properties} file in the root folder of your application project.</li>
+  <li>Add the following lines to the file:
+<pre>
+renderscript.target=18
+renderscript.support.mode=true
+sdk.buildtools=18.1.0
+</pre>
+  </li>
+  <li>In your application classes that use RenderScript, add an import for the Support Library
+    classes:
+<pre>
+import android.support.v8.renderscript.*;
+</pre>
+  </li>
+</ol>
+
+<p>The {@code project.properties} settings listed above control specific behavior in the Android
+  build process:</p>
+
+<ul>
+  <li>{@code renderscript.target} - Specifies the bytecode version to be generated. We
+    recommend you set this value the highest available API level and set {@code
+    renderscript.support.mode} to {@code true}. Valid values for this setting are any integer value
+    from 11 to the most recently released API level. If your minimum SDK version specified in your
+    application manifest is set to a higher value, this value is ignored and the target value is set
+    to the minimum SDK version.</li>
+  <li>{@code renderscript.support.mode} - Specifies that the generated bytecode should fall
+    back to a compatible version if the device it is running on does not support the target version.
+    </li>
+  <li>{@code sdk.buildtools} - The version of the Android SDK build tools to use. This value
+    should be set to 18.1.0 or higher. If this option is not specified, the highest installed build
+    tools version is used. You should always set this value to ensure the consistency of builds
+    across development machines with different configurations.</li>
+</ul>
+
+
 <h2 id="using-rs-from-java">Using RenderScript from Java Code</h2>
 
-<p>Using RenderScript from Java code relies on the {@link android.renderscript} APIs. Most
+<p>Using RenderScript from Java code relies on the API classes located in the
+{@link android.renderscript} or the {@link android.support.v8.renderscript} package. Most
 applications follow the same basic usage patterns:</p>
 
 <ol>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 4ea3752..0581435 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,43 +5,43 @@
 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 
 
-sdk.linux32_bundle_download=adt-bundle-linux-x86-20130729.zip
-sdk.linux32_bundle_bytes=457716139
-sdk.linux32_bundle_checksum=b3686d10dc1cbceba1074404d4386283
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20130911.zip
+sdk.linux32_bundle_bytes=474916528
+sdk.linux32_bundle_checksum=7eacc7124299ea99a8fa15c59123540f
 
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20130729.zip
-sdk.linux64_bundle_bytes=458006784
-sdk.linux64_bundle_checksum=1fabcc3f772ba8b2fc194d6e0449da17
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20130911.zip
+sdk.linux64_bundle_bytes=475207785
+sdk.linux64_bundle_checksum=daa5794a27be7c7fa708c3d28833b0d3
 
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20130729.zip
-sdk.mac64_bundle_bytes=428792424
-sdk.mac64_bundle_checksum=6c42b9966abcfa8a75c0ee83d0d95882
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20130911.zip
+sdk.mac64_bundle_bytes=448575446
+sdk.mac64_bundle_checksum=a1e0cbcc820ae734cfdf439c40811b4c
 
-sdk.win32_bundle_download=adt-bundle-windows-x86-20130729.zip
-sdk.win32_bundle_bytes=463931746
-sdk.win32_bundle_checksum=51faf4e5fdf9c5b4a176179a99ce3511
+sdk.win32_bundle_download=adt-bundle-windows-x86-20130911.zip
+sdk.win32_bundle_bytes=481794820
+sdk.win32_bundle_checksum=88a2f4f242aac44f4b1c53e6eccc8710
 
-sdk.win64_bundle_download=adt-bundle-windows-x86_64-20130729.zip
-sdk.win64_bundle_bytes=464064756
-sdk.win64_bundle_checksum=e8f05c1fddb8e609e880de23113c7426
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20130911.zip
+sdk.win64_bundle_bytes=481927327
+sdk.win64_bundle_checksum=e3fa9b7e38af9ed9ac0e99fce3c7026c
 
 
 
-sdk.linux_download=android-sdk_r22.0.5-linux.tgz
-sdk.linux_bytes=105641005
-sdk.linux_checksum=8201b10c21510f082c54f58a9bb082c8
+sdk.linux_download=android-sdk_r22.2-linux.tgz
+sdk.linux_bytes=100909403
+sdk.linux_checksum=2a3776839e823ba9acb7a87a3fe26e02
 
-sdk.mac_download=android-sdk_r22.0.5-macosx.zip
-sdk.mac_bytes=77225724
-sdk.mac_checksum=94f3cbe896c332b94ee0408ae610a4b8
+sdk.mac_download=android-sdk_r22.2-macosx.zip
+sdk.mac_bytes=74857114
+sdk.mac_checksum=9dfef6404e2f842c433073796aed8b7d
 
-sdk.win_download=android-sdk_r22.0.5-windows.zip
-sdk.win_bytes=113510621
-sdk.win_checksum=30695dffc41e0d7cf9ff948ab0c48920
+sdk.win_download=android-sdk_r22.2-windows.zip
+sdk.win_bytes=108790714
+sdk.win_checksum=1ac4c104378cd53049daa6c4458ec544
 
-sdk.win_installer=installer_r22.0.5-windows.exe
-sdk.win_installer_bytes=93505782
-sdk.win_installer_checksum=940849be19ac6151e3e35c8706c81d86
+sdk.win_installer=installer_r22.2-windows.exe
+sdk.win_installer_bytes=88788974
+sdk.win_installer_checksum=e5503fa059297d2b18475c086ac6e80c
 
 
 
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index bdc07d0..e038d20 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=22.0.5
-adt.zip.download=ADT-22.0.5.zip
-adt.zip.bytes=16839757
-adt.zip.checksum=1097fccf32063e3638a9d27aa0f295ca
+adt.zip.version=22.2.0
+adt.zip.download=ADT-22.2.0.zip
+adt.zip.bytes=14474195
+adt.zip.checksum=52892c9e3b1ad2d1e6edd50e48b2a127
 
 @jd:body
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index e9c514e..151707a 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -57,6 +57,44 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 22.2</a> <em>(September 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required.</li>
+      <li>Eclipse Helios (Version 3.6.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.2</a>.
+        If you haven't already installed SDK Tools r22.2 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Updated build tools to allow use of RenderScript on older versions of Android
+       using new features in the
+       <a href="{@docRoot}tools/support-library/features.html#v8">Support Library</a>.</li>
+      <li>Reverted signing changes that sometimes trigger a signing verification problem on older
+        platforms.</li>
+      <li>Fixed problem with gradle export function for the Windows platform.</li>
+    </ul>
+  </dd>
+
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 22.0.5</a> <em>(July 2013)</em>
   </p>
 
@@ -78,7 +116,7 @@
   <dt>General Notes:</dt>
   <dd>
     <ul>
-      <li>Fixed Renderscript compilation issue for Windows platforms.</li>
+      <li>Fixed RenderScript compilation issue for Windows platforms.</li>
       <li>Updated <a href="{@docRoot}tools/help/systrace.html">Systrace</a> report generation
         in the Monitor and DDMS perspectives.</li>
     </ul>
@@ -113,7 +151,7 @@
   <dt>General Notes:</dt>
   <dd>
     <ul>
-      <li>Fixed problem with compiling Renderscript code.</li>
+      <li>Fixed problem with compiling RenderScript code.</li>
       <li>Improved Gradle export with better workflow and error reporting.</li>
       <li>Improved Gradle multi-module export feature.</li>
       <li>Updated build logic to force exporting of the classpath containers unless you are using
@@ -1005,7 +1043,7 @@
 <dt>Bug fixes:</dt>
 <dd>
 <ul>
-  <li>Fixed build issue when using Renderscript in projects that target API levels 11-13
+  <li>Fixed build issue when using RenderScript in projects that target API levels 11-13
     (<a href="http://code.google.com/p/android/issues/detail?id=21006">Issue 21006</a>).</li>
   <li>Fixed issue when creating projects from existing source code.</li>
   <li>Fixed issues in the SDK Manager
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 4aef8a0..e8c4717 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -30,6 +30,54 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 22.2</a> <em>(September 2013)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 16 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+          designed for use with ADT 22.2 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.2.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Updated build tools to allow use of RenderScript on older versions of Android
+         using new features in the
+         <a href="{@docRoot}tools/support-library/features.html#v8">Support Library</a>.</li>
+        <li>Moved the Systrace tool to the {@code &gt;sdk&lt;/platform-tools/} directory. </li>
+        <li>Modified <a href="{@docRoot}tools/help/gltracer.html">Tracer for OpenGL ES</a> to
+          support OpenGL ES 3.0.</li>
+        <li>Lint
+          <ul>
+            <li>Fixed problem with lint not detecting custom namespaces.
+              (<a href="http://b.android.com/55673">Issue 55673</a>)</li>
+            <li>Fixed problem with the XML report including invalid characters.
+              (<a href="http://b.android.com/56205">Issue 56205</a>)</li>
+            <li>Fixed command-line execution of lint to work in headless mode to support execution
+              by build servers. (<a href="http://b.android.com/55820">Issue 55820</a>)</li>
+          </ul>
+        </li>
+        <li>Improved support for path names with spaces in the Windows command-line tools.</li>
+      </ul>
+    </dd>
+    </dl>
+  </div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 22.0.5</a> <em>(July 2013)</em>
   </p>
 
@@ -55,10 +103,10 @@
     <dt>General Notes:</dt>
     <dd>
       <ul>
-        <li>Fixed Renderscript compilation issue for Windows platforms with ant.</li>
+        <li>Fixed RenderScript compilation issue for Windows platforms with ant.</li>
         <li>Updated <a href="{@docRoot}tools/help/systrace.html">Systrace</a> to work with the
           Android 4.3 platform image.</li>
-        <li>Fixed packaging of Renderscript compiler.</li>
+        <li>Fixed packaging of RenderScript compiler.</li>
         <li>Build tools 18.0.0 is obsolete and 18.0.1 should be used instead.</li>
       </ul>
     </dd>
@@ -95,7 +143,7 @@
     <dt>General Notes:</dt>
     <dd>
       <ul>
-        <li>Fixed problem with compiling Renderscript code.</li>
+        <li>Fixed problem with compiling RenderScript code.</li>
       </ul>
     </dd>
     </dl>
@@ -274,17 +322,17 @@
           </ul>
         </li>
 
-        <li>Renderscript
+        <li>RenderScript
           <ul>
             <li>Added support for
               <a href="{@docRoot}guide/topics/renderscript/compute.html#filterscript">Filterscript</a>
               compilation.</li>
-            <li>Added new project setting to control the Renderscript compilation target separately
+            <li>Added new project setting to control the RenderScript compilation target separately
               from an Android project. Adding the following line to a {@code project.properties}
-              file causes Renderscript code to be compiled for Android API Level 17, while the
+              file causes RenderScript code to be compiled for Android API Level 17, while the
               containing application can target a different (lower) API level:
               <pre>renderscript.target = 17</pre>
-              Previously, the Renderscript compilation target was tied to the
+              Previously, the RenderScript compilation target was tied to the
               {@code android:minSdkVersion} setting in the manifest.
               (<a href="http://code.google.com/p/android/issues/detail?id=40487">Issue 40487</a>)
             </li>
@@ -483,7 +531,7 @@
         <li>Improved resize algorithm for better rendering on scaled emulator windows.</li>
         <li>Fixed a bug in the {@code lint} check for unprotected broadcast receivers to ignore
 unprotected receivers for default Android actions.</li>
-        <li>Fixed build issue for projects using Renderscript.</li>
+        <li>Fixed build issue for projects using RenderScript.</li>
         <li>Fixed memory leak in the emulator.</li>
       </ul>
     </dd>
@@ -823,7 +871,7 @@
     <li>Fixed emulator crash on Linux due to improper webcam detection
     (<a href="http://code.google.com/p/android/issues/detail?id=20952">Issue 20952</a>).</li>
     <li>Fixed emulator issue when using the <code>-wipe-data</code> argument.</li>
-    <li>Fixed build issue when using Renderscript in projects that target API levels 11-13
+    <li>Fixed build issue when using RenderScript in projects that target API levels 11-13
     (<a href="http://code.google.com/p/android/issues/detail?id=21006">Issue 21006</a>).</li>
     <li>Fixed issue when creating an AVD using the GoogleTV addon
     (<a href="http://code.google.com/p/android/issues/detail?id=20963">Issue 20963</a>).</li>
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index 8d25d96..65148bf 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -15,6 +15,7 @@
           <li><a href="#v7-mediarouter">v7 mediarouter library</a></li>
         </ol>
       </li>
+      <li><a href="#v8">v8 Support Library</a></li>
       <li><a href="#v13">v13 Support Library</a></li>
     </ol>
 
@@ -252,7 +253,7 @@
 where "18.0.0" is the minimum revision at which the library is available. For example:</p>
 
 <pre>
-com.android.support:support-v7-mediarouter:18.0.0
+com.android.support:mediarouter-v7:18.0.+
 </pre>
 
 <p class="caution">The v7 mediarouter library APIs introduced in Support Library
@@ -262,6 +263,24 @@
 developer preview</a>. </p>
 
 
+<h2 id="v8">v8 Support Library</h2>
+
+<p>This library is designed to be used with Android (API level 8) and higher. It adds support for
+  the <a href="{@docRoot}guide/topics/renderscript/compute.html">RenderScript</a> computation
+  framework. These APIs are included in the {@link android.support.v8.renderscript} package. You
+  should be aware that the steps for including these APIs in your application is <em>very
+  different</em> from other support library APIs. For more information about using these APIs
+  in your application, see the
+  <a href="{@docRoot}guide/topics/renderscript/compute.html#access-rs-apis">RenderScript</a>
+  developer guide.</p>
+
+<p class="note">
+  <strong>Note:</strong> Use of RenderScript with the support library is supported with the Android
+  Eclipse plugin and Ant build tools. It is <em>not currently</em> supported with Android Studio or
+  Gradle-based builds.
+</p>
+
+
 <h2 id="v13">v13 Support Library</h2>
 
 <p>This library is designed to be used for Android 3.2 (API level 13) and higher. It adds support
diff --git a/docs/html/tools/support-library/index.jd b/docs/html/tools/support-library/index.jd
index 06c7a3f..4ee8c12 100644
--- a/docs/html/tools/support-library/index.jd
+++ b/docs/html/tools/support-library/index.jd
@@ -58,6 +58,7 @@
 
 <p>This section provides details about the Support Library package releases.</p>
 
+
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt=""
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 9f442f5..a346e17 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -16,20 +16,19 @@
 
 package android.media;
 
-import android.graphics.ImageFormat;
 import java.nio.ByteBuffer;
 import java.lang.AutoCloseable;
 
 /**
  * <p>A single complete image buffer to use with a media source such as a
  * {@link MediaCodec} or a
- * {@link android.hardware.camera2.CameraDevice}.</p>
+ * {@link android.hardware.camera2.CameraDevice CameraDevice}.</p>
  *
  * <p>This class allows for efficient direct application access to the pixel
  * data of the Image through one or more
  * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a
  * {@link Plane} that describes the layout of the pixel data in that plane. Due
- * to this direct access, and unlike the {@link android.graphics.Bitmap} class,
+ * to this direct access, and unlike the {@link android.graphics.Bitmap Bitmap} class,
  * Images are not directly usable as as UI resources.</p>
  *
  * <p>Since Images are often directly produced or consumed by hardware
@@ -40,19 +39,28 @@
  * from various media sources, not closing old Image objects will prevent the
  * availability of new Images once
  * {@link ImageReader#getMaxImages the maximum outstanding image count} is
- * reached.</p>
+ * reached. When this happens, the function acquiring new Images will typically
+ * throw an {@link IllegalStateException}.</p>
  *
  * @see ImageReader
  */
-public interface Image extends AutoCloseable {
+public abstract class Image implements AutoCloseable {
+    /**
+     * @hide
+     */
+    protected Image() {
+    }
+
     /**
      * Get the format for this image. This format determines the number of
      * ByteBuffers needed to represent the image, and the general layout of the
      * pixel data in each in ByteBuffer.
      *
+     * <p>
      * The format is one of the values from
-     * {@link android.graphics.ImageFormat}. The mapping between the formats and
-     * the planes is as follows:
+     * {@link android.graphics.ImageFormat ImageFormat}. The mapping between the
+     * formats and the planes is as follows:
+     * </p>
      *
      * <table>
      * <tr>
@@ -61,13 +69,14 @@
      *   <th>Layout details</th>
      * </tr>
      * <tr>
-     *   <td>{@link android.graphics.ImageFormat#JPEG}</td>
+     *   <td>{@link android.graphics.ImageFormat#JPEG JPEG}</td>
      *   <td>1</td>
      *   <td>Compressed data, so row and pixel strides are 0. To uncompress, use
-     *      {@link android.graphics.BitmapFactory#decodeByteArray}.</td>
+     *      {@link android.graphics.BitmapFactory#decodeByteArray BitmapFactory#decodeByteArray}.
+     *   </td>
      * </tr>
      * <tr>
-     *   <td>{@link android.graphics.ImageFormat#YUV_420_888}</td>
+     *   <td>{@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}</td>
      *   <td>3</td>
      *   <td>A luminance plane followed by the Cb and Cr chroma planes.
      *     The chroma planes have half the width and height of the luminance
@@ -75,53 +84,60 @@
      *     Each plane has its own row stride and pixel stride.</td>
      * </tr>
      * <tr>
-     *   <td>{@link android.graphics.ImageFormat#RAW_SENSOR}</td>
+     *   <td>{@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}</td>
      *   <td>1</td>
      *   <td>A single plane of raw sensor image data, with 16 bits per color
      *     sample. The details of the layout need to be queried from the source of
      *     the raw sensor data, such as
-     *     {@link android.hardware.camera2.CameraDevice}.
+     *     {@link android.hardware.camera2.CameraDevice CameraDevice}.
      *   </td>
      * </tr>
      * </table>
      *
      * @see android.graphics.ImageFormat
      */
-    public int getFormat();
+    public abstract int getFormat();
 
     /**
      * The width of the image in pixels. For formats where some color channels
      * are subsampled, this is the width of the largest-resolution plane.
      */
-    public int getWidth();
+    public abstract int getWidth();
 
     /**
      * The height of the image in pixels. For formats where some color channels
      * are subsampled, this is the height of the largest-resolution plane.
      */
-    public int getHeight();
+    public abstract int getHeight();
 
     /**
-     * Get the timestamp associated with this frame. The timestamp is measured
-     * in nanoseconds, and is monotonically increasing. However, the zero point
-     * and whether the timestamp can be compared against other sources of time
-     * or images depend on the source of this image.
+     * Get the timestamp associated with this frame.
+     * <p>
+     * The timestamp is measured in nanoseconds, and is monotonically
+     * increasing. However, the zero point and whether the timestamp can be
+     * compared against other sources of time or images depend on the source of
+     * this image.
+     * </p>
      */
-    public long getTimestamp();
+    public abstract long getTimestamp();
 
     /**
      * Get the array of pixel planes for this Image. The number of planes is
      * determined by the format of the Image.
      */
-    public Plane[] getPlanes();
+    public abstract Plane[] getPlanes();
 
     /**
-     * Free up this frame for reuse. After calling this method, calling any
-     * methods on this Image will result in an IllegalStateException, and
-     * attempting to read from ByteBuffers returned by an earlier
-     * {@code Plane#getBuffer} call will have undefined behavior.
+     * Free up this frame for reuse.
+     * <p>
+     * After calling this method, calling any methods on this {@code Image} will
+     * result in an {@link IllegalStateException}, and attempting to read from
+     * {@link ByteBuffer ByteBuffers} returned by an earlier
+     * {@link Plane#getBuffer} call will have undefined behavior.
+     * </p>
      */
-    public void close();
+    @Override
+    public abstract void close();
 
     /**
      * <p>A single color plane of image data.</p>
@@ -134,29 +150,41 @@
      *
      * @see #getFormat
      */
-    public interface Plane {
+    public static abstract class Plane {
         /**
-         * <p>The row stride for this color plane, in bytes.
+         * @hide
+         */
+        protected Plane() {
+        }
+
+        /**
+         * <p>The row stride for this color plane, in bytes.</p>
          *
          * <p>This is the distance between the start of two consecutive rows of
-         * pixels in the image.</p>
+         * pixels in the image. The row stride is always greater than 0.</p>
          */
-        public int getRowStride();
+        public abstract int getRowStride();
         /**
          * <p>The distance between adjacent pixel samples, in bytes.</p>
          *
          * <p>This is the distance between two consecutive pixel values in a row
          * of pixels. It may be larger than the size of a single pixel to
-         * account for interleaved image data or padded formats.</p>
+         * account for interleaved image data or padded formats.
+         * The pixel stride is always greater than 0.</p>
          */
-        public int getPixelStride();
+        public abstract int getPixelStride();
         /**
-         * <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers}
+         * <p>Get a direct {@link java.nio.ByteBuffer ByteBuffer}
          * containing the frame data.</p>
          *
+         * <p>In particular, the buffer returned will always have
+         * {@link java.nio.ByteBuffer#isDirect isDirect} return {@code true}, so
+         * the underlying data could be mapped as a pointer in JNI without doing
+         * any copies with {@code GetDirectBufferAddress}.</p>
+         *
          * @return the byte buffer containing the image data for this plane.
          */
-        public ByteBuffer getBuffer();
+        public abstract ByteBuffer getBuffer();
     }
 
 }
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index b14a899..aee8362 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -40,41 +40,67 @@
  * <p>The image data is encapsulated in {@link Image} objects, and multiple such
  * objects can be accessed at the same time, up to the number specified by the
  * {@code maxImages} constructor parameter. New images sent to an ImageReader
- * through its Surface are queued until accessed through the
- * {@link #getNextImage} call. Due to memory limits, an image source will
+ * through its {@link Surface} are queued until accessed through the {@link #acquireLatestImage}
+ * or {@link #acquireNextImage} call. Due to memory limits, an image source will
  * eventually stall or drop Images in trying to render to the Surface if the
  * ImageReader does not obtain and release Images at a rate equal to the
  * production rate.</p>
  */
-public final class ImageReader implements AutoCloseable {
+public class ImageReader implements AutoCloseable {
+
+    /**
+     * Returned by nativeImageSetup when acquiring the image was successful.
+     */
+    private static final int ACQUIRE_SUCCESS = 0;
+    /**
+     * Returned by nativeImageSetup when we couldn't acquire the buffer,
+     * because there were no buffers available to acquire.
+     */
+    private static final int ACQUIRE_NO_BUFS = 1;
+    /**
+     * Returned by nativeImageSetup when we couldn't acquire the buffer
+     * because the consumer has already acquired {@maxImages} and cannot
+     * acquire more than that.
+     */
+    private static final int ACQUIRE_MAX_IMAGES = 2;
 
     /**
      * <p>Create a new reader for images of the desired size and format.</p>
      *
-     * <p>The maxImages parameter determines the maximum number of {@link Image}
-     * objects that can be be acquired from the ImageReader
+     * <p>The {@code maxImages} parameter determines the maximum number of {@link Image}
+     * objects that can be be acquired from the {@code ImageReader}
      * simultaneously. Requesting more buffers will use up more memory, so it is
      * important to use only the minimum number necessary for the use case.</p>
      *
      * <p>The valid sizes and formats depend on the source of the image
      * data.</p>
      *
-     * @param width the width in pixels of the Images that this reader will
-     * produce.
-     * @param height the height in pixels of the Images that this reader will
-     * produce.
-     * @param format the format of the Image that this reader will produce. This
-     * must be one of the {@link android.graphics.ImageFormat} or
-     * {@link android.graphics.PixelFormat} constants.
-     * @param maxImages the maximum number of images the user will want to
-     * access simultaneously. This should be as small as possible to limit
-     * memory use. Once maxImages Images are obtained by the user, one of them
-     * has to be released before a new Image will become available for access
-     * through getNextImage(). Must be greater than 0.
+     * @param width
+     *            The width in pixels of the Images that this reader will produce.
+     * @param height
+     *            The height in pixels of the Images that this reader will produce.
+     * @param format
+     *            The format of the Image that this reader will produce. This
+     *            must be one of the {@link android.graphics.ImageFormat} or
+     *            {@link android.graphics.PixelFormat} constants.
+     * @param maxImages
+     *            The maximum number of images the user will want to
+     *            access simultaneously. This should be as small as possible to limit
+     *            memory use. Once maxImages Images are obtained by the user, one of them
+     *            has to be released before a new Image will become available for access
+     *            through {@link #acquireLatestImage()} or {@link #acquireNextImage()}.
+     *            Must be greater than 0.
      *
      * @see Image
      */
-    public ImageReader(int width, int height, int format, int maxImages) {
+    public static ImageReader newInstance(int width, int height, int format, int maxImages) {
+        return new ImageReader(width, height, format, maxImages);
+    }
+
+    /**
+     * @hide
+     */
+    protected ImageReader(int width, int height, int format, int maxImages) {
         mWidth = width;
         mHeight = height;
         mFormat = format;
@@ -96,33 +122,79 @@
         mSurface = nativeGetSurface();
     }
 
+    /**
+     * The width of each {@link Image}, in pixels.
+     *
+     * <p>ImageReader guarantees that all Images acquired from ImageReader (for example, with
+     * {@link #acquireNextImage}) will have the same dimensions as specified in
+     * {@link #newInstance}.</p>
+     *
+     * @return the width of an Image
+     */
     public int getWidth() {
         return mWidth;
     }
 
+    /**
+     * The height of each {@link Image}, in pixels.
+     *
+     * <p>ImageReader guarantees that all Images acquired from ImageReader (for example, with
+     * {@link #acquireNextImage}) will have the same dimensions as specified in
+     * {@link #newInstance}.</p>
+     *
+     * @return the height of an Image
+     */
     public int getHeight() {
         return mHeight;
     }
 
+    /**
+     * The {@link ImageFormat image format} of each Image.
+     *
+     * <p>ImageReader guarantees that all {@link Image Images} acquired from ImageReader
+     *  (for example, with {@link #acquireNextImage}) will have the same format as specified in
+     * {@link #newInstance}.</p>
+     *
+     * @return the format of an Image
+     *
+     * @see ImageFormat
+     */
     public int getImageFormat() {
         return mFormat;
     }
 
+    /**
+     * Maximum number of images that can be acquired from the ImageReader by any time (for example,
+     * with {@link #acquireNextImage}).
+     *
+     * <p>An image is considered acquired after it's returned by a function from ImageReader, and
+     * until the Image is {@link Image#close closed} to release the image back to the ImageReader.
+     * </p>
+     *
+     * <p>Attempting to acquire more than {@code maxImages} concurrently will result in the
+     * acquire function throwing a {@link IllegalStateException}. Furthermore,
+     * while the max number of images have been acquired by the ImageReader user, the producer
+     * enqueueing additional images may stall until at least one image has been released. </p>
+     *
+     * @return Maximum number of images for this ImageReader.
+     *
+     * @see Image#close
+     */
     public int getMaxImages() {
         return mMaxImages;
     }
 
     /**
-     * <p>Get a Surface that can be used to produce Images for this
-     * ImageReader.</p>
+     * <p>Get a {@link Surface} that can be used to produce {@link Image Images} for this
+     * {@code ImageReader}.</p>
      *
-     * <p>Until valid image data is rendered into this Surface, the
-     * {@link #getNextImage} method will return {@code null}. Only one source
+     * <p>Until valid image data is rendered into this {@link Surface}, the
+     * {@link #acquireNextImage} method will return {@code null}. Only one source
      * can be producing data into this Surface at the same time, although the
-     * same Surface can be reused with a different API once the first source is
-     * disconnected from the Surface.</p>
+     * same {@link Surface} can be reused with a different API once the first source is
+     * disconnected from the {@link Surface}.</p>
      *
-     * @return A Surface to use for a drawing target for various APIs.
+     * @return A {@link Surface} to use for a drawing target for various APIs.
      */
     public Surface getSurface() {
         return mSurface;
@@ -130,41 +202,154 @@
 
     /**
      * <p>
-     * Get the next Image from the ImageReader's queue. Returns {@code null} if
-     * no new image is available.
+     * Acquire the latest {@link Image} from the ImageReader's queue, dropping older
+     * {@link Image images}. Returns {@code null} if no new image is available.
      * </p>
      * <p>
-     * This operation will fail by throwing an
-     * {@link Surface.OutOfResourcesException OutOfResourcesException} if too
-     * many images have been acquired with {@link #getNextImage}. In particular
-     * a sequence of {@link #getNextImage} calls greater than {@link #getMaxImages}
-     * without calling {@link Image#close} or {@link #releaseImage} in-between
-     * will exhaust the underlying queue. At such a time,
-     * {@link Surface.OutOfResourcesException OutOfResourcesException} will be
-     * thrown until more images are released with {@link Image#close} or
-     * {@link #releaseImage}.
+     * This operation will acquire all the images possible from the ImageReader,
+     * but {@link #close} all images that aren't the latest. This function is
+     * recommended to use over {@link #acquireNextImage} for most use-cases, as it's
+     * more suited for real-time processing.
+     * </p>
+     * <p>
+     * Note that {@link #getMaxImages maxImages} should be at least 2 for
+     * {@link #acquireLatestImage} to be any different than {@link #acquireNextImage} -
+     * discarding all-but-the-newest {@link Image} requires temporarily acquiring two
+     * {@link Image Images} at once. Or more generally, calling {@link #acquireLatestImage}
+     * with less than two images of margin, that is
+     * {@code (maxImages - currentAcquiredImages < 2)} will not discard as expected.
+     * </p>
+     * <p>
+     * This operation will fail by throwing an {@link IllegalStateException} if
+     * {@code maxImages} have been acquired with {@link #acquireLatestImage} or
+     * {@link #acquireNextImage}. In particular a sequence of {@link #acquireLatestImage}
+     * calls greater than {@link #getMaxImages} without calling {@link Image#close} in-between
+     * will exhaust the underlying queue. At such a time, {@link IllegalStateException}
+     * will be thrown until more images are
+     * released with {@link Image#close}.
      * </p>
      *
-     * @return a new frame of image data, or {@code null} if no image data is
-     *         available.
-     * @throws Surface.OutOfResourcesException if too many images are currently
-     *         acquired
+     * @return latest frame of image data, or {@code null} if no image data is available.
+     * @throws IllegalStateException if too many images are currently acquired
      */
-    public Image getNextImage() {
-        SurfaceImage si = new SurfaceImage();
-        if (nativeImageSetup(si)) {
-            // create SurfacePlane objects
-            si.createSurfacePlanes();
-            si.setImageValid(true);
-            return si;
+    public Image acquireLatestImage() {
+        Image image = acquireNextImage();
+        if (image == null) {
+            return null;
         }
-        return null;
+        try {
+            for (;;) {
+                Image next = acquireNextImageNoThrowISE();
+                if (next == null) {
+                    Image result = image;
+                    image = null;
+                    return result;
+                }
+                image.close();
+                image = next;
+            }
+        } finally {
+            if (image != null) {
+                image.close();
+            }
+        }
+    }
+
+    /**
+     * Don't throw IllegalStateException if there are too many images acquired.
+     *
+     * @return Image if acquiring succeeded, or null otherwise.
+     *
+     * @hide
+     */
+    public Image acquireNextImageNoThrowISE() {
+        SurfaceImage si = new SurfaceImage();
+        return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null;
+    }
+
+    /**
+     * Attempts to acquire the next image from the underlying native implementation.
+     *
+     * <p>
+     * Note that unexpected failures will throw at the JNI level.
+     * </p>
+     *
+     * @param si A blank SurfaceImage.
+     * @return One of the {@code ACQUIRE_*} codes that determine success or failure.
+     *
+     * @see #ACQUIRE_MAX_IMAGES
+     * @see #ACQUIRE_NO_BUFS
+     * @see #ACQUIRE_SUCCESS
+     */
+    private int acquireNextSurfaceImage(SurfaceImage si) {
+
+        int status = nativeImageSetup(si);
+
+        switch (status) {
+            case ACQUIRE_SUCCESS:
+                si.createSurfacePlanes();
+                si.setImageValid(true);
+            case ACQUIRE_NO_BUFS:
+            case ACQUIRE_MAX_IMAGES:
+                break;
+            default:
+                throw new AssertionError("Unknown nativeImageSetup return code " + status);
+        }
+
+        return status;
+    }
+
+    /**
+     * <p>
+     * Acquire the next Image from the ImageReader's queue. Returns {@code null} if
+     * no new image is available.
+     * </p>
+     *
+     * <p><i>Warning:</i> Consider using {@link #acquireLatestImage()} instead, as it will
+     * automatically release older images, and allow slower-running processing routines to catch
+     * up to the newest frame. Usage of {@link #acquireNextImage} is recommended for
+     * batch/background processing. Incorrectly using this function can cause images to appear
+     * with an ever-increasing delay, followed by a complete stall where no new images seem to
+     * appear.
+     * </p>
+     *
+     * <p>
+     * This operation will fail by throwing an {@link IllegalStateException} if
+     * {@code maxImages} have been acquired with {@link #acquireNextImage} or
+     * {@link #acquireLatestImage}. In particular a sequence of {@link #acquireNextImage} or
+     * {@link #acquireLatestImage} calls greater than {@link #getMaxImages maxImages} without
+     * calling {@link Image#close} in-between will exhaust the underlying queue. At such a time,
+     * {@link IllegalStateException} will be thrown until more images are released with
+     * {@link Image#close}.
+     * </p>
+     *
+     * @return a new frame of image data, or {@code null} if no image data is available.
+     * @throws IllegalStateException if {@code maxImages} images are currently acquired
+     * @see #acquireLatestImage
+     */
+    public Image acquireNextImage() {
+        SurfaceImage si = new SurfaceImage();
+        int status = acquireNextSurfaceImage(si);
+
+        switch (status) {
+            case ACQUIRE_SUCCESS:
+                return si;
+            case ACQUIRE_NO_BUFS:
+                return null;
+            case ACQUIRE_MAX_IMAGES:
+                throw new IllegalStateException(
+                        String.format(
+                                "maxImages (%d) has already been acquired, " +
+                                "call #close before acquiring more.", mMaxImages));
+            default:
+                throw new AssertionError("Unknown nativeImageSetup return code " + status);
+        }
     }
 
     /**
      * <p>Return the frame to the ImageReader for reuse.</p>
      */
-    public void releaseImage(Image i) {
+    private void releaseImage(Image i) {
         if (! (i instanceof SurfaceImage) ) {
             throw new IllegalArgumentException(
                 "This image was not produced by an ImageReader");
@@ -183,13 +368,16 @@
     /**
      * Register a listener to be invoked when a new image becomes available
      * from the ImageReader.
-     * @param listener the listener that will be run
-     * @param handler The handler on which the listener should be invoked, or null
-     * if the listener should be invoked on the calling thread's looper.
      *
-     * @throws IllegalArgumentException if no handler specified and the calling thread has no looper
+     * @param listener
+     *            The listener that will be run.
+     * @param handler
+     *            The handler on which the listener should be invoked, or null
+     *            if the listener should be invoked on the calling thread's looper.
+     * @throws IllegalArgumentException
+     *            If no handler specified and the calling thread has no looper.
      */
-   public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
+   public void setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
         mImageListener = listener;
 
         Looper looper;
@@ -206,12 +394,16 @@
 
     /**
      * Callback interface for being notified that a new image is available.
+     *
+     * <p>
      * The onImageAvailable is called per image basis, that is, callback fires for every new frame
      * available from ImageReader.
+     * </p>
      */
     public interface OnImageAvailableListener {
         /**
          * Callback that is called when a new image is available from ImageReader.
+         *
          * @param reader the ImageReader the callback is associated with.
          * @see ImageReader
          * @see Image
@@ -220,12 +412,17 @@
     }
 
     /**
-     * Free up all the resources associated with this ImageReader. After
-     * Calling this method, this ImageReader can not be used. calling
-     * any methods on this ImageReader and Images previously provided by {@link #getNextImage}
-     * will result in an IllegalStateException, and attempting to read from
-     * ByteBuffers returned by an earlier {@code Plane#getBuffer} call will
+     * Free up all the resources associated with this ImageReader.
+     *
+     * <p>
+     * After calling this method, this ImageReader can not be used. Calling
+     * any methods on this ImageReader and Images previously provided by
+     * {@link #acquireNextImage} or {@link #acquireLatestImage}
+     * will result in an {@link IllegalStateException}, and attempting to read from
+     * {@link ByteBuffer ByteBuffers} returned by an earlier
+     * {@link Image.Plane#getBuffer Plane#getBuffer} call will
      * have undefined behavior.
+     * </p>
      */
     @Override
     public void close() {
@@ -242,11 +439,14 @@
     }
 
     /**
-     * Only a subset of the formats defined in {@link android.graphics.ImageFormat} and
-     * {@link android.graphics.PixelFormat} are supported by ImageReader. When reading RGB
-     * data from a surface, the formats defined in {@link android.graphics.PixelFormat}
-     * can be used, when reading YUV, JPEG or raw sensor data ( for example, from camera
-     *  or video decoder), formats from {@link android.graphics.ImageFormat} are used.
+     * Only a subset of the formats defined in
+     * {@link android.graphics.ImageFormat ImageFormat} and
+     * {@link android.graphics.PixelFormat PixelFormat} are supported by
+     * ImageReader. When reading RGB data from a surface, the formats defined in
+     * {@link android.graphics.PixelFormat PixelFormat} can be used, when
+     * reading YUV, JPEG or raw sensor data (for example, from camera or video
+     * decoder), formats from {@link android.graphics.ImageFormat ImageFormat}
+     * are used.
      */
     private int getNumPlanesFromFormat() {
         switch (mFormat) {
@@ -308,7 +508,7 @@
      */
     private long mNativeContext;
 
-    private class SurfaceImage implements android.media.Image {
+    private class SurfaceImage extends android.media.Image {
         public SurfaceImage() {
             mIsImageValid = false;
         }
@@ -404,7 +604,7 @@
                 mPlanes[i] = nativeCreatePlane(i);
             }
         }
-        private class SurfacePlane implements android.media.Image.Plane {
+        private class SurfacePlane extends android.media.Image.Plane {
             // SurfacePlane instance is created by native code when a new SurfaceImage is created
             private SurfacePlane(int index, int rowStride, int pixelStride) {
                 mIndex = index;
@@ -479,9 +679,17 @@
     private synchronized native void nativeClose();
     private synchronized native void nativeReleaseImage(Image i);
     private synchronized native Surface nativeGetSurface();
-    private synchronized native boolean nativeImageSetup(Image i);
 
-    /*
+    /**
+     * @return A return code {@code ACQUIRE_*}
+     *
+     * @see #ACQUIRE_SUCCESS
+     * @see #ACQUIRE_NO_BUFS
+     * @see #ACQUIRE_MAX_IMAGES
+     */
+    private synchronized native int nativeImageSetup(Image i);
+
+    /**
      * We use a class initializer to allow the native code to cache some
      * field offsets.
      */
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 94f20bc..fb0f69b 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -43,13 +43,16 @@
 
 using namespace android;
 
-static const char* const OutOfResourcesException =
-    "android/view/Surface$OutOfResourcesException";
-
 enum {
     IMAGE_READER_MAX_NUM_PLANES = 3,
 };
 
+enum {
+    ACQUIRE_SUCCESS = 0,
+    ACQUIRE_NO_BUFFERS = 1,
+    ACQUIRE_MAX_IMAGES = 2,
+};
+
 static struct {
     jfieldID mNativeContext;
     jmethodID postEventFromNative;
@@ -685,14 +688,14 @@
     ctx->returnLockedBuffer(buffer);
 }
 
-static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
+static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz,
                                              jobject image)
 {
     ALOGV("%s:", __FUNCTION__);
     JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
     if (ctx == NULL) {
         jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
-        return false;
+        return -1;
     }
 
     CpuConsumer* consumer = ctx->getCpuConsumer();
@@ -700,27 +703,22 @@
     if (buffer == NULL) {
         ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
             " maxImages buffers");
-        jniThrowException(env, OutOfResourcesException,
-                  "Too many outstanding images, close existing images"
-                  " to be able to acquire more.");
-        return false;
+        return ACQUIRE_MAX_IMAGES;
     }
     status_t res = consumer->lockNextBuffer(buffer);
     if (res != NO_ERROR) {
         if (res != BAD_VALUE /*no buffers*/) {
             if (res == NOT_ENOUGH_DATA) {
-                jniThrowException(env, OutOfResourcesException,
-                          "Too many outstanding images, close existing images"
-                          " to be able to acquire more.");
+                return ACQUIRE_MAX_IMAGES;
             } else {
                 ALOGE("%s Fail to lockNextBuffer with error: %d ",
                       __FUNCTION__, res);
-                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                jniThrowExceptionFmt(env, "java/lang/AssertionError",
                           "Unknown error (%d) when we tried to lock buffer.",
                           res);
             }
         }
-        return false;
+        return ACQUIRE_NO_BUFFERS;
     }
 
     // Check if the left-top corner of the crop rect is origin, we currently assume this point is
@@ -730,7 +728,7 @@
         ALOGE("crop left: %d, top = %d", lt.x, lt.y);
         jniThrowException(env, "java/lang/UnsupportedOperationException",
                           "crop left top corner need to at origin");
-        return false;
+        return -1;
     }
 
     // Check if the producer buffer configurations match what ImageReader configured.
@@ -739,11 +737,9 @@
     int outputHeight = buffer->height;
 
     // Correct width/height when crop is set.
-    if (buffer->crop.getWidth() > 0) {
-        outputWidth = buffer->crop.getWidth() + 1;
-    }
-    if (buffer->crop.getHeight() > 0) {
-        outputHeight = buffer->crop.getHeight() + 1;
+    if (buffer->crop.isValid()) {
+        outputWidth = buffer->crop.getWidth();
+        outputHeight = buffer->crop.getHeight();
     }
 
     int imageReaderWidth = ctx->getBufferWidth();
@@ -761,6 +757,7 @@
         jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                 "Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
                 outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
+        return -1;
     }
 
     if (ctx->getBufferFormat() != buffer->format) {
@@ -777,14 +774,14 @@
                 buffer->format, ctx->getBufferFormat());
         jniThrowException(env, "java/lang/UnsupportedOperationException",
                 msg.string());
-        return false;
+        return -1;
     }
     // Set SurfaceImage instance member variables
     Image_setBuffer(env, image, buffer);
     env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
             static_cast<jlong>(buffer->timestamp));
 
-    return true;
+    return ACQUIRE_SUCCESS;
 }
 
 static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
@@ -855,7 +852,7 @@
     {"nativeInit",             "(Ljava/lang/Object;IIII)V",  (void*)ImageReader_init },
     {"nativeClose",            "()V",                        (void*)ImageReader_close },
     {"nativeReleaseImage",     "(Landroid/media/Image;)V",   (void*)ImageReader_imageRelease },
-    {"nativeImageSetup",       "(Landroid/media/Image;)Z",    (void*)ImageReader_imageSetup },
+    {"nativeImageSetup",       "(Landroid/media/Image;)I",    (void*)ImageReader_imageSetup },
     {"nativeGetSurface",       "()Landroid/view/Surface;",   (void*)ImageReader_getSurface },
 };
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
index ecdc287..64b12b7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -49,6 +49,7 @@
         addMediaPlayerStateUnitTests(suite);
         addMediaScannerUnitTests(suite);
         addCameraUnitTests(suite);
+        addImageReaderTests(suite);
         return suite;
     }
 
@@ -65,6 +66,10 @@
         suite.addTestSuite(CameraMetadataTest.class);
     }
 
+    private void addImageReaderTests(TestSuite suite) {
+        suite.addTestSuite(ImageReaderTest.class);
+    }
+
     // Running all unit tests checking the state machine may be time-consuming.
     private void addMediaMetadataRetrieverStateUnitTests(TestSuite suite) {
         suite.addTestSuite(MediaMetadataRetrieverTest.class);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 2d26ac7..7b2a20e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -61,6 +61,7 @@
     private SurfaceHolder mSurfaceHolder = null;
     private static final int NUM_STRESS_LOOP = 10;
     private static final int NUM_PLAYBACk_IN_EACH_LOOP = 20;
+    private static final int SHORT_WAIT = 2 * 1000; // 2 seconds
     private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds
     private static final String MEDIA_MEMORY_OUTPUT =
         "/sdcard/mediaMemOutput.txt";
@@ -99,16 +100,17 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        //Insert a 2 second before launching the test activity. This is
+        //the workaround for the race condition of requesting the updated surface.
+        Thread.sleep(SHORT_WAIT);
+        getActivity();
         //Check if the device support the camcorder
-        CamcorderProfile mCamcorderProfile = CamcorderProfile.get(CAMERA_ID);
+        mCamcorderProfile = CamcorderProfile.get(CAMERA_ID);
         if (mCamcorderProfile != null) {
             mVideoWidth = mCamcorderProfile.videoFrameWidth;
             mVideoHeight = mCamcorderProfile.videoFrameHeight;
+            Log.v(TAG, "height = " + mVideoHeight + " width= " + mVideoWidth);
         }
-        //Insert a 2 second before launching the test activity. This is
-        //the workaround for the race condition of requesting the updated surface.
-        Thread.sleep(2000);
-        getActivity();
         if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
             MediaTestUtil.getNativeHeapDump(this.getName() + "_before");
 
@@ -246,6 +248,8 @@
                 Thread.sleep(MEDIA_STRESS_WAIT_TIME);
                 mRecorder.stop();
                 mRecorder.release();
+                //Insert 2 seconds to make sure the camera released.
+                Thread.sleep(SHORT_WAIT);
             } catch (Exception e) {
                 Log.v("record video failed ", e.toString());
                 mRecorder.release();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java
new file mode 100644
index 0000000..f6cd990
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ImageReaderTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import static org.mockito.Mockito.*;
+
+import android.graphics.ImageFormat;
+import android.media.Image;
+import android.media.Image.Plane;
+import android.media.ImageReader;
+import android.media.ImageReader.OnImageAvailableListener;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class ImageReaderTest extends AndroidTestCase {
+
+    private static final String TAG = "ImageReaderTest-unit";
+
+    private static final int DEFAULT_WIDTH = 640;
+    private static final int DEFAULT_HEIGHT = 480;
+    private static final int DEFAULT_FORMAT = ImageFormat.YUV_420_888;
+    private static final int DEFAULT_MAX_IMAGES = 3;
+
+    private ImageReader mReader;
+    private Image mImage1;
+    private Image mImage2;
+    private Image mImage3;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        /**
+         * Workaround for mockito and JB-MR2 incompatibility
+         *
+         * Avoid java.lang.IllegalArgumentException: dexcache == null
+         * https://code.google.com/p/dexmaker/issues/detail?id=2
+         */
+        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+
+        // TODO: refactor above into one of the test runners
+
+        mReader = spy(ImageReader.newInstance(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                DEFAULT_MAX_IMAGES));
+        mImage1 = mock(Image.class);
+        mImage2 = mock(Image.class);
+        mImage3 = mock(Image.class);
+
+        /**
+         * Ensure rest of classes are mockable
+         */
+        {
+            mock(Plane.class);
+            mock(OnImageAvailableListener.class);
+        }
+
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mReader.close();
+
+        super.tearDown();
+    }
+
+    /**
+     * Return null when there is nothing in the image queue.
+     */
+    @SmallTest
+    public void testGetLatestImageEmpty() {
+        when(mReader.acquireNextImage()).thenReturn(null);
+        when(mReader.acquireNextImageNoThrowISE()).thenReturn(null);
+        assertEquals(null, mReader.acquireLatestImage());
+    }
+
+    /**
+     * Return the last image from the image queue, close up the rest.
+     */
+    @SmallTest
+    public void testGetLatestImage1() {
+        when(mReader.acquireNextImage()).thenReturn(mImage1);
+        when(mReader.acquireNextImageNoThrowISE()).thenReturn(null);
+        assertEquals(mImage1, mReader.acquireLatestImage());
+        verify(mImage1, never()).close();
+    }
+
+    /**
+     * Return the last image from the image queue, close up the rest.
+     */
+    @SmallTest
+    public void testGetLatestImage2() {
+        when(mReader.acquireNextImage()).thenReturn(mImage1);
+        when(mReader.acquireNextImageNoThrowISE()).thenReturn(mImage2).thenReturn(null);
+        assertEquals(mImage2, mReader.acquireLatestImage());
+        verify(mImage1, atLeastOnce()).close();
+        verify(mImage2, never()).close();
+    }
+
+    /**
+     * Return the last image from the image queue, close up the rest.
+     */
+    @SmallTest
+    public void testGetLatestImage3() {
+        when(mReader.acquireNextImage()).thenReturn(mImage1);
+        when(mReader.acquireNextImageNoThrowISE()).thenReturn(mImage2).
+                                                   thenReturn(mImage3).
+                                                   thenReturn(null);
+        assertEquals(mImage3, mReader.acquireLatestImage());
+        verify(mImage1, atLeastOnce()).close();
+        verify(mImage2, atLeastOnce()).close();
+        verify(mImage3, never()).close();
+    }
+
+    /**
+     * Return null if get a IllegalStateException with no images in the queue.
+     */
+    @SmallTest
+    public void testGetLatestImageTooManyBuffersAcquiredEmpty()  {
+        when(mReader.acquireNextImage()).thenThrow(new IllegalStateException());
+        try {
+            mReader.acquireLatestImage();
+            fail("Expected IllegalStateException to be thrown");
+        } catch(IllegalStateException e) {
+        }
+    }
+
+    /**
+     * All images are cleaned up when we get an unexpected Error.
+     */
+    @SmallTest
+    public void testGetLatestImageExceptionalError() {
+        when(mReader.acquireNextImage()).thenReturn(mImage1);
+        when(mReader.acquireNextImageNoThrowISE()).thenReturn(mImage2).
+                                                   thenReturn(mImage3).
+                                                   thenThrow(new OutOfMemoryError());
+        try {
+            mReader.acquireLatestImage();
+            fail("Impossible");
+        } catch(OutOfMemoryError e) {
+        }
+
+        verify(mImage1, atLeastOnce()).close();
+        verify(mImage2, atLeastOnce()).close();
+        verify(mImage3, atLeastOnce()).close();
+    }
+
+    /**
+     * All images are cleaned up when we get an unexpected RuntimeException.
+     */
+    @SmallTest
+    public void testGetLatestImageExceptionalRuntime() {
+
+        when(mReader.acquireNextImage()).thenReturn(mImage1);
+        when(mReader.acquireNextImageNoThrowISE()).thenReturn(mImage2).
+                                                   thenReturn(mImage3).
+                                                   thenThrow(new RuntimeException());
+        try {
+            mReader.acquireLatestImage();
+            fail("Impossible");
+        } catch(RuntimeException e) {
+        }
+
+        verify(mImage1, atLeastOnce()).close();
+        verify(mImage2, atLeastOnce()).close();
+        verify(mImage3, atLeastOnce()).close();
+    }
+}
diff --git a/media/tests/SoundPoolTest/AndroidManifest.xml b/media/tests/SoundPoolTest/AndroidManifest.xml
index 126276c..8a29052 100644
--- a/media/tests/SoundPoolTest/AndroidManifest.xml
+++ b/media/tests/SoundPoolTest/AndroidManifest.xml
@@ -8,4 +8,5 @@
             </intent-filter>
         </activity>
     </application>
+    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8"/>
 </manifest>
diff --git a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
index 33db2dd..cc3306c 100644
--- a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
+++ b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
@@ -143,7 +143,7 @@
                 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
                 sleep(50);
             }
-            if (DEBUG) Log.d(LOG_TAG, "End scale test");
+            if (DEBUG) Log.d(LOG_TAG, "End sounds test");
             return true;
         }
 
@@ -165,7 +165,7 @@
                 if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
                 sleep(50);
             }
-            if (DEBUG) Log.d(LOG_TAG, "End sounds test");
+            if (DEBUG) Log.d(LOG_TAG, "End scale test");
             return true;
         }
 
@@ -189,6 +189,7 @@
                 if (DEBUG) Log.d(LOG_TAG, "Change rate " + mScale[step]);
             }
             mSoundPool.stop(id);
+            if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
             if (DEBUG) Log.d(LOG_TAG, "End rate test");
             return true;
         }
@@ -205,34 +206,38 @@
                 Log.e(LOG_TAG, "Error occurred starting note");
                 return false;
             }
-            sleep(250);
+            sleep(1000);
 
             // play a low priority sound
-            int id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
+            int id = mSoundPool.play(mSounds[1], DEFAULT_VOLUME, DEFAULT_VOLUME,
                     LOW_PRIORITY, DEFAULT_LOOP, 1.0f);
-            if (id > 0) {
+            if (id != 0) {
                 Log.e(LOG_TAG, "Normal > Low priority test failed");
                 result = false;
                 mSoundPool.stop(id);
             } else {
-                Log.e(LOG_TAG, "Normal > Low priority test passed");
+                sleep(1000);
+                Log.i(LOG_TAG, "Normal > Low priority test passed");
             }
-            sleep(250);
 
             // play a high priority sound
-            id = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
+            id = mSoundPool.play(mSounds[2], DEFAULT_VOLUME, DEFAULT_VOLUME,
                     HIGH_PRIORITY, DEFAULT_LOOP, 1.0f);
             if (id == 0) {
                 Log.e(LOG_TAG, "High > Normal priority test failed");
                 result = false;
             } else {
-                Log.e(LOG_TAG, "High > Normal priority test passed");
+                sleep(1000);
+                Log.i(LOG_TAG, "Stopping high priority");
+                mSoundPool.stop(id);
+                sleep(1000);
+                Log.i(LOG_TAG, "High > Normal priority test passed");
             }
-            sleep(250);
-            mSoundPool.stop(id);
 
             // stop normal note
+            Log.i(LOG_TAG, "Stopping normal priority");
             mSoundPool.stop(normalId);
+            sleep(1000);
 
             if (DEBUG) Log.d(LOG_TAG, "End priority test");
             return result;
@@ -250,17 +255,21 @@
                 Log.e(LOG_TAG, "Error occurred starting note");
                 return false;
             }
-            sleep(250);
+            sleep(2500);
 
             // pause and resume sound a few times
             for (int count = 0; count < 5; count++) {
+                if (DEBUG) Log.d(LOG_TAG, "Pause note " + id);
                 mSoundPool.pause(id);
-                sleep(250);
+                sleep(1000);
+                if (DEBUG) Log.d(LOG_TAG, "Resume note " + id);
                 mSoundPool.resume(id);
-                sleep(250);
+                sleep(1000);
             }
 
+            if (DEBUG) Log.d(LOG_TAG, "Stop note " + id);
             mSoundPool.stop(id);
+            sleep(1000);
 
             // play 5 sounds, forces one to be stolen
             int ids[] = new int[5];
@@ -272,18 +281,21 @@
                     Log.e(LOG_TAG, "Error occurred starting note");
                     return false;
                 }
-                sleep(250);
+                sleep(1000);
             }
 
             // pause and resume sound a few times
             for (int count = 0; count < 5; count++) {
+                if (DEBUG) Log.d(LOG_TAG, "autoPause");
                 mSoundPool.autoPause();
-                sleep(250);
+                sleep(1000);
+                if (DEBUG) Log.d(LOG_TAG, "autoResume");
                 mSoundPool.autoResume();
-                sleep(250);
+                sleep(1000);
             }
 
             for (int i = 0; i < 5; i++) {
+                if (DEBUG) Log.d(LOG_TAG, "Stop note " + ids[i]);
                 mSoundPool.stop(ids[i]);
             }
 
@@ -302,9 +314,9 @@
                 return false;
             }
 
-            // pan from left to right
+            // pan from right to left
             for (int count = 0; count < 101; count++) {
-                sleep(20);
+                sleep(50);
                 double radians = PI_OVER_2 * count / 100.0;
                 float leftVolume = (float) Math.sin(radians);
                 float rightVolume = (float) Math.cos(radians);
diff --git a/media/tests/audiotests/Android.mk b/media/tests/audiotests/Android.mk
new file mode 100644
index 0000000..69f0bb5
--- /dev/null
+++ b/media/tests/audiotests/Android.mk
@@ -0,0 +1,21 @@
+ifeq ($(TARGET_ARCH),arm)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= shared_mem_test
+LOCAL_SRC_FILES := \
+		   shared_mem_test.cpp
+LOCAL_SHARED_LIBRARIES :=  \
+		libc \
+        libcutils \
+        libutils \
+        libbinder \
+        libhardware_legacy \
+		libmedia
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/media/tests/audiotests/shared_mem_test.cpp b/media/tests/audiotests/shared_mem_test.cpp
new file mode 100644
index 0000000..992c900
--- /dev/null
+++ b/media/tests/audiotests/shared_mem_test.cpp
@@ -0,0 +1,216 @@
+// Copyright 2008, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+#define LOG_NDEBUG 0
+#define LOG_TAG "shared_mem_test"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <cutils/properties.h>
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+#include <math.h>
+
+#include "shared_mem_test.h"
+#include <binder/MemoryDealer.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/ProcessState.h>
+
+
+#include <utils/Log.h>
+
+#include <fcntl.h>
+
+namespace android {
+
+/************************************************************
+*
+*    Constructor
+*
+************************************************************/
+AudioTrackTest::AudioTrackTest(void) {
+
+    InitSine();         // init sine table
+
+}
+
+
+/************************************************************
+*
+*
+************************************************************/
+void AudioTrackTest::Execute(void) {
+    if (Test01() == 0) {
+        ALOGD("01 passed\n");
+    } else {
+        ALOGD("01 failed\n");
+    }
+}
+
+/************************************************************
+*
+*    Shared memory test
+*
+************************************************************/
+#define BUF_SZ 44100
+
+int AudioTrackTest::Test01() {
+
+    sp<MemoryDealer> heap;
+    sp<IMemory> iMem;
+    uint8_t* p;
+
+    short smpBuf[BUF_SZ];
+    long rate = 44100;
+    unsigned long phi;
+    unsigned long dPhi;
+    long amplitude;
+    long freq = 1237;
+    float f0;
+
+    f0 = pow(2., 32.) * freq / (float)rate;
+    dPhi = (unsigned long)f0;
+    amplitude = 1000;
+    phi = 0;
+    Generate(smpBuf, BUF_SZ, amplitude, phi, dPhi);  // fill buffer
+
+    for (int i = 0; i < 1024; i++) {
+        heap = new MemoryDealer(1024*1024, "AudioTrack Heap Base");
+
+        iMem = heap->allocate(BUF_SZ*sizeof(short));
+
+        p = static_cast<uint8_t*>(iMem->pointer());
+        memcpy(p, smpBuf, BUF_SZ*sizeof(short));
+
+        sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_MUSIC,// stream type
+               rate,
+               AUDIO_FORMAT_PCM_16_BIT,// word length, PCM
+               AUDIO_CHANNEL_OUT_MONO,
+               iMem);
+
+        status_t status = track->initCheck();
+        if(status != NO_ERROR) {
+            track.clear();
+            ALOGD("Failed for initCheck()");
+            return -1;
+        }
+
+        // start play
+        ALOGD("start");
+        track->start();
+
+        usleep(20000);
+
+        ALOGD("stop");
+        track->stop();
+        iMem.clear();
+        heap.clear();
+        usleep(20000);
+    }
+
+    return 0;
+
+}
+
+/************************************************************
+*
+*    Generate a mono buffer
+*    Error is less than 3lsb
+*
+************************************************************/
+void AudioTrackTest::Generate(short *buffer, long bufferSz, long amplitude, unsigned long &phi, long dPhi)
+{
+    long pi13 = 25736;   // 2^13*pi
+    // fill buffer
+    for(int i0=0; i0<bufferSz; i0++) {
+        long sample;
+        long l0, l1;
+
+        buffer[i0] = ComputeSine( amplitude, phi);
+        phi += dPhi;
+    }
+}
+
+/************************************************************
+*
+*    Generate a sine
+*    Error is less than 3lsb
+*
+************************************************************/
+short AudioTrackTest::ComputeSine(long amplitude, long phi)
+{
+    long pi13 = 25736;   // 2^13*pi
+    long sample;
+    long l0, l1;
+
+    sample = (amplitude*sin1024[(phi>>22) & 0x3ff]) >> 15;
+    // correct with interpolation
+    l0 = (phi>>12) & 0x3ff;         // 2^20 * x / (2*pi)
+    l1 = (amplitude*sin1024[((phi>>22) + 256) & 0x3ff]) >> 15;    // 2^15*cosine
+    l0 = (l0 * l1) >> 10;
+    l0 = (l0 * pi13) >> 22;
+    sample = sample + l0;
+
+    return (short)sample;
+}
+
+
+/************************************************************
+*
+*    init sine table
+*
+************************************************************/
+void AudioTrackTest::InitSine(void) {
+    double phi = 0;
+    double dPhi = 2 * M_PI / SIN_SZ;
+    for(int i0 = 0; i0<SIN_SZ; i0++) {
+        long d0;
+
+        d0 = 32768. * sin(phi);
+        phi += dPhi;
+        if(d0 >= 32767) d0 = 32767;
+        if(d0 <= -32768) d0 = -32768;
+        sin1024[i0] = (short)d0;
+    }
+}
+
+/************************************************************
+*
+*    main in name space
+*
+************************************************************/
+int main() {
+    ProcessState::self()->startThreadPool();
+    AudioTrackTest *test;
+
+    test = new AudioTrackTest();
+    test->Execute();
+    delete test;
+
+    return 0;
+}
+
+}
+
+/************************************************************
+*
+*    global main
+*
+************************************************************/
+int main(int argc, char *argv[]) {
+
+    return android::main();
+}
diff --git a/media/tests/audiotests/shared_mem_test.h b/media/tests/audiotests/shared_mem_test.h
new file mode 100644
index 0000000..f495955
--- /dev/null
+++ b/media/tests/audiotests/shared_mem_test.h
@@ -0,0 +1,27 @@
+// Copyright 2008 The Android Open Source Project
+
+#ifndef AUDIOTRACKTEST_H_
+#define AUDIOTRACKTEST_H_
+
+namespace android {
+
+class AudioTrackTest{
+    public:
+        AudioTrackTest(void);
+        ~AudioTrackTest() {};
+
+        void Execute(void);
+        int Test01();
+
+        void Generate(short *buffer, long bufferSz, long amplitude, unsigned long &phi, long dPhi);
+        void InitSine();
+        short ComputeSine(long amplitude, long phi);
+
+        #define SIN_SZ    1024
+        short sin1024[SIN_SZ];           // sine table 2*pi = 1024
+};
+
+};
+
+
+#endif /*AUDIOTRACKTEST_H_*/
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5e198a2..fa5c769 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -189,6 +189,35 @@
             android:taskAffinity="com.android.systemui.net"
             android:excludeFromRecents="true" />
 
+        <!-- platform logo easter egg activity -->
+        <activity
+            android:name=".DessertCase"
+            android:exported="true"
+            android:label="@string/dessert_case"
+            android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+            android:hardwareAccelerated="true"
+            android:launchMode="singleInstance"
+            android:excludeFromRecents="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="com.android.internal.category.PLATLOGO" />
+            </intent-filter>
+        </activity>
+
+        <!-- a gallery of delicious treats -->
+        <service
+            android:name=".DessertCaseDream"
+            android:exported="true"
+            android:label="@string/dessert_case"
+            android:enabled="false"
+            >
+            <intent-filter>
+                <action android:name="android.service.dreams.DreamService" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </service>
+
         <activity android:name=".Somnambulator"
             android:label="@string/start_dreams"
             android:icon="@mipmap/ic_launcher_dreams"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bbfe383..7fdd308 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -431,8 +431,8 @@
     <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
     <string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string>
 
-    <!-- Name of the Jelly Bean platlogo screensaver -->
-    <string name="jelly_bean_dream_name">BeanFlinger</string>
+    <!-- Name of the K-release easter egg: a display case for all our tastiest desserts. [CHAR LIMIT=30] -->
+    <string name="dessert_case">Dessert Case</string>
 
     <!-- Name of the launcher shortcut icon that allows dreams to be started immediately [CHAR LIMIT=20] -->
     <string name="start_dreams">Daydream</string>
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCase.java b/packages/SystemUI/src/com/android/systemui/DessertCase.java
new file mode 100644
index 0000000..b6424af0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DessertCase.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.util.Slog;
+
+public class DessertCase extends Activity {
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        Slog.v("DessertCase", "ACHIEVEMENT UNLOCKED");
+        PackageManager pm = getPackageManager();
+        pm.setComponentEnabledSetting(new ComponentName(this, DessertCaseDream.class),
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+
+        finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseDream.java b/packages/SystemUI/src/com/android/systemui/DessertCaseDream.java
new file mode 100644
index 0000000..022e4d8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DessertCaseDream.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.service.dreams.DreamService;
+
+public class DessertCaseDream extends DreamService {
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        setInteractive(true);
+        setFullscreen(true);
+    }
+
+    @Override
+    public void onDreamingStarted() {
+        super.onDreamingStarted();
+    }
+
+    @Override
+    public void onDreamingStopped() {
+        super.onDreamingStopped();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index ada30ac..5ebd11e0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -23,6 +23,7 @@
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
 import android.app.TaskStackBuilder;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -698,6 +699,8 @@
                         new UserHandle(UserHandle.USER_CURRENT));
             } catch (SecurityException e) {
                 Log.e(TAG, "Recents does not have the permission to launch " + intent, e);
+            } catch (ActivityNotFoundException e) {
+                Log.e(TAG, "Error launching activity " + intent, e);
             }
         }
         if (usingDrawingCache) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 4683030..b56d7be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -424,7 +424,7 @@
                         mCurrentView.getWidth(), mCurrentView.getHeight(),
                         visibilityToString(mCurrentView.getVisibility())));
 
-        pw.println(String.format("      disabled=0x%08x vertical=%s hidden=%s low=%s menu=%s",
+        pw.println(String.format("      disabled=0x%08x vertical=%s menu=%s",
                         mDisabledFlags,
                         mVertical ? "true" : "false",
                         mShowMenu ? "true" : "false"));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index ceed30e..25ffbd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -671,7 +671,7 @@
         alarmTile.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                startSettingsActivity(AlarmClock.ACTION_SET_ALARM);
+                startSettingsActivity(AlarmClock.ACTION_SHOW_ALARMS);
             }
         });
         mModel.addAlarmTile(alarmTile, new QuickSettingsModel.RefreshCallback() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 8a285e3..ba8671a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2819,7 +2819,7 @@
 
                 // If the status bar is hidden, we don't want to cause
                 // windows behind it to scroll.
-                if (mStatusBar.isVisibleLw() && !statusBarTransient && !statusBarTransparent) {
+                if (mStatusBar.isVisibleLw() && !statusBarTransient) {
                     // Status bar may go away, so the screen area it occupies
                     // is available to apps but just covering them when the
                     // status bar is visible.
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 5a24ebb..bbcd01a 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -172,10 +172,16 @@
                 case WifiManager.CONNECT_NETWORK:
                 case WifiManager.SAVE_NETWORK: {
                     WifiConfiguration config = (WifiConfiguration) msg.obj;
-                    if (config.isValid()) {
+                    int networkId = msg.arg1;
+                    if (config != null && config.isValid()) {
+                        if (DBG) Slog.d(TAG, "Connect with config" + config);
+                        mWifiStateMachine.sendMessage(Message.obtain(msg));
+                    } else if (config == null
+                            && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
+                        if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
                         mWifiStateMachine.sendMessage(Message.obtain(msg));
                     } else {
-                        Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg);
+                        Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
                         if (msg.what == WifiManager.CONNECT_NETWORK) {
                             replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
                         } else {
@@ -582,7 +588,8 @@
      */
     public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         enforceChangePermission();
-        if (wifiConfig.isValid()) {
+        // null wifiConfig is a meaningful input for CMD_SET_AP
+        if (wifiConfig == null || wifiConfig.isValid()) {
             mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1 : 0, 0, wifiConfig).sendToTarget();
         } else {
             Slog.e(TAG, "Invalid WifiConfiguration");