Merge "Remove a method" into jb-mr2-dev
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index f140282..518dd4b 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -50,7 +50,7 @@
 public class DhcpStateMachine extends StateMachine {
 
     private static final String TAG = "DhcpStateMachine";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
 
     /* A StateMachine that controls the DhcpStateMachine */
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 29b2a5c..627235f 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -632,6 +632,30 @@
                         GLUtils.getEGLErrorString(mEgl.eglGetError()));
             }
 
+            int attribs[] = {
+                EGL_WIDTH, 1,
+                EGL_HEIGHT, 1,
+                EGL_NONE
+            };
+            EGLSurface tmpSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
+            mEgl.eglMakeCurrent(mEglDisplay, tmpSurface, tmpSurface, mEglContext);
+
+            int[] maxSize = new int[1];
+            Rect frame = surfaceHolder.getSurfaceFrame();
+            glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0);
+
+            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            mEgl.eglDestroySurface(mEglDisplay, tmpSurface);
+
+            if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) {
+                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+                mEgl.eglTerminate(mEglDisplay);
+                Log.e(GL_LOG_TAG, "requested  texture size " +
+                    frame.width() + "x" + frame.height() + " exceeds the support maximum of " +
+                    maxSize[0] + "x" + maxSize[0]);
+                return false;
+            }
+
             mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
             if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
                 int error = mEgl.eglGetError();
@@ -649,20 +673,6 @@
                         GLUtils.getEGLErrorString(mEgl.eglGetError()));
             }
 
-            int[] maxSize = new int[1];
-            Rect frame = surfaceHolder.getSurfaceFrame();
-            glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0);
-            if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) {
-                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-                mEgl.eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-                mEgl.eglTerminate(mEglDisplay);
-                Log.e(GL_LOG_TAG, "requested  texture size " +
-                        frame.width() + "x" + frame.height() + " exceeds the support maximum of " +
-                        maxSize[0] + "x" + maxSize[0]);
-                return false;
-            }
-
             return true;
         }
         
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index fbdd333..dffb617 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -32,6 +32,7 @@
 import android.test.InstrumentationTestRunner;
 import android.util.Log;
 
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -48,16 +49,22 @@
 public class AppLaunch extends InstrumentationTestCase {
 
     private static final int JOIN_TIMEOUT = 10000;
-    private static final String TAG = "AppLaunch";
+    private static final String TAG = AppLaunch.class.getSimpleName();
     private static final String KEY_APPS = "apps";
+    private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
+    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle
+    private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
+    private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps
 
     private Map<String, Intent> mNameToIntent;
     private Map<String, String> mNameToProcess;
     private Map<String, String> mNameToResultKey;
-
+    private Map<String, Long> mNameToLaunchTime;
     private IActivityManager mAm;
+    private int mLaunchIterations = 10;
+    private Bundle mResult = new Bundle();
 
-    public void testMeasureStartUpTime() throws RemoteException {
+    public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException {
         InstrumentationTestRunner instrumentation =
                 (InstrumentationTestRunner)getInstrumentation();
         Bundle args = instrumentation.getArguments();
@@ -66,25 +73,59 @@
         createMappings();
         parseArgs(args);
 
-        Bundle results = new Bundle();
+        // do initial app launch, without force stopping
         for (String app : mNameToResultKey.keySet()) {
-            try {
-                startApp(app, results);
-                sleep(750);
-                closeApp(app);
-                sleep(2000);
-            } catch (NameNotFoundException e) {
-                Log.i(TAG, "Application " + app + " not found");
+            long launchTime = startApp(app, false);
+            if (launchTime <=0 ) {
+                mNameToLaunchTime.put(app, -1L);
+                // simply pass the app if launch isn't successful
+                // error should have already been logged by startApp
+                continue;
             }
-
+            sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
+            closeApp(app, false);
+            sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
         }
-        instrumentation.sendStatus(0, results);
+        // do the real app launch now
+        for (int i = 0; i < mLaunchIterations; i++) {
+            for (String app : mNameToResultKey.keySet()) {
+                long totalLaunchTime = mNameToLaunchTime.get(app);
+                long launchTime = 0;
+                if (totalLaunchTime < 0) {
+                    // skip if the app has previous failures
+                    continue;
+                }
+                launchTime = startApp(app, true);
+                if (launchTime <= 0) {
+                    // if it fails once, skip the rest of the launches
+                    mNameToLaunchTime.put(app, -1L);
+                    continue;
+                }
+                totalLaunchTime += launchTime;
+                mNameToLaunchTime.put(app, totalLaunchTime);
+                sleep(POST_LAUNCH_IDLE_TIMEOUT);
+                closeApp(app, true);
+                sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+            }
+        }
+        for (String app : mNameToResultKey.keySet()) {
+            long totalLaunchTime = mNameToLaunchTime.get(app);
+            if (totalLaunchTime != -1) {
+                mResult.putDouble(mNameToResultKey.get(app),
+                        ((double) totalLaunchTime) / mLaunchIterations);
+            }
+        }
+        instrumentation.sendStatus(0, mResult);
     }
 
     private void parseArgs(Bundle args) {
         mNameToResultKey = new LinkedHashMap<String, String>();
+        mNameToLaunchTime = new HashMap<String, Long>();
+        String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
+        if (launchIterations != null) {
+            mLaunchIterations = Integer.parseInt(launchIterations);
+        }
         String appList = args.getString(KEY_APPS);
-
         if (appList == null)
             return;
 
@@ -97,6 +138,7 @@
             }
 
             mNameToResultKey.put(parts[0], parts[1]);
+            mNameToLaunchTime.put(parts[0], 0L);
         }
     }
 
@@ -118,23 +160,26 @@
                         | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                 startIntent.setClassName(ri.activityInfo.packageName,
                         ri.activityInfo.name);
-                mNameToIntent.put(ri.loadLabel(pm).toString(), startIntent);
-                mNameToProcess.put(ri.loadLabel(pm).toString(),
-                        ri.activityInfo.processName);
+                String appName = ri.loadLabel(pm).toString();
+                if (appName != null) {
+                    mNameToIntent.put(appName, startIntent);
+                    mNameToProcess.put(appName, ri.activityInfo.processName);
+                }
             }
         }
     }
 
-    private void startApp(String appName, Bundle results)
+    private long startApp(String appName, boolean forceStopBeforeLaunch)
             throws NameNotFoundException, RemoteException {
         Log.i(TAG, "Starting " + appName);
 
         Intent startIntent = mNameToIntent.get(appName);
         if (startIntent == null) {
             Log.w(TAG, "App does not exist: " + appName);
-            return;
+            mResult.putString(mNameToResultKey.get(appName), "App does not exist");
+            return -1;
         }
-        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch);
         Thread t = new Thread(runnable);
         t.start();
         try {
@@ -143,27 +188,38 @@
             // ignore
         }
         WaitResult result = runnable.getResult();
-        if(t.isAlive() || (result != null && result.result != ActivityManager.START_SUCCESS)) {
+        // report error if any of the following is true:
+        // * launch thread is alive
+        // * result is not null, but:
+        //   * result is not START_SUCESS
+        //   * or in case of no force stop, result is not TASK_TO_FRONT either
+        if (t.isAlive() || (result != null
+                && ((result.result != ActivityManager.START_SUCCESS)
+                        && (!forceStopBeforeLaunch
+                                && result.result != ActivityManager.START_TASK_TO_FRONT)))) {
             Log.w(TAG, "Assuming app " + appName + " crashed.");
-            reportError(appName, mNameToProcess.get(appName), results);
-            return;
+            reportError(appName, mNameToProcess.get(appName));
+            return -1;
         }
-        results.putString(mNameToResultKey.get(appName), String.valueOf(result.thisTime));
+        return result.thisTime;
     }
 
-    private void closeApp(String appName) {
+    private void closeApp(String appName, boolean forceStopApp) {
         Intent homeIntent = new Intent(Intent.ACTION_MAIN);
         homeIntent.addCategory(Intent.CATEGORY_HOME);
         homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         getInstrumentation().getContext().startActivity(homeIntent);
-        Intent startIntent = mNameToIntent.get(appName);
-        if (startIntent != null) {
-            String packageName = startIntent.getComponent().getPackageName();
-            try {
-                mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Error closing app", e);
+        sleep(POST_LAUNCH_IDLE_TIMEOUT);
+        if (forceStopApp) {
+            Intent startIntent = mNameToIntent.get(appName);
+            if (startIntent != null) {
+                String packageName = startIntent.getComponent().getPackageName();
+                try {
+                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error closing app", e);
+                }
             }
         }
     }
@@ -176,7 +232,7 @@
         }
     }
 
-    private void reportError(String appName, String processName, Bundle results) {
+    private void reportError(String appName, String processName) {
         ActivityManager am = (ActivityManager) getInstrumentation()
                 .getContext().getSystemService(Context.ACTIVITY_SERVICE);
         List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
@@ -186,12 +242,12 @@
                     continue;
 
                 Log.w(TAG, appName + " crashed: " + crash.shortMsg);
-                results.putString(mNameToResultKey.get(appName), crash.shortMsg);
+                mResult.putString(mNameToResultKey.get(appName), crash.shortMsg);
                 return;
             }
         }
 
-        results.putString(mNameToResultKey.get(appName),
+        mResult.putString(mNameToResultKey.get(appName),
                 "Crashed for unknown reason");
         Log.w(TAG, appName
                 + " not found in process list, most likely it is crashed");
@@ -200,8 +256,11 @@
     private class AppLaunchRunnable implements Runnable {
         private Intent mLaunchIntent;
         private IActivityManager.WaitResult mResult;
-        public AppLaunchRunnable(Intent intent) {
+        private boolean mForceStopBeforeLaunch;
+
+        public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) {
             mLaunchIntent = intent;
+            mForceStopBeforeLaunch = forceStopBeforeLaunch;
         }
 
         public IActivityManager.WaitResult getResult() {
@@ -211,7 +270,9 @@
         public void run() {
             try {
                 String packageName = mLaunchIntent.getComponent().getPackageName();
-                mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+                if (mForceStopBeforeLaunch) {
+                    mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
+                }
                 String mimeType = mLaunchIntent.getType();
                 if (mimeType == null && mLaunchIntent.getData() != null
                         && "content".equals(mLaunchIntent.getData().getScheme())) {