Merge "Clean up activities and displays when done" into klp-modular-dev
diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java
index a7d287b..461e8b8 100644
--- a/core/java/android/net/ProxyDataTracker.java
+++ b/core/java/android/net/ProxyDataTracker.java
@@ -16,13 +16,24 @@
 
 package android.net;
 
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -31,27 +42,70 @@
  * {@hide}
  */
 public class ProxyDataTracker extends BaseNetworkStateTracker {
-    private static final String NETWORK_TYPE = "PROXY";
     private static final String TAG = "ProxyDataTracker";
+    private static final String NETWORK_TYPE = "PROXY";
 
     // TODO: investigate how to get these DNS addresses from the system.
     private static final String DNS1 = "8.8.8.8";
     private static final String DNS2 = "8.8.4.4";
     private static final String REASON_ENABLED = "enabled";
+    private static final String REASON_DISABLED = "disabled";
+    private static final String REASON_PROXY_DOWN = "proxy_down";
 
+    private static final int MSG_TEAR_DOWN_REQUEST = 1;
+    private static final int MSG_SETUP_REQUEST = 2;
+
+    private static final String PERMISSION_PROXY_STATUS_SENDER =
+            "android.permission.ACCESS_NETWORK_CONDITIONS";
+    private static final String ACTION_PROXY_STATUS_CHANGE =
+            "com.android.net.PROXY_STATUS_CHANGE";
+    private static final String KEY_IS_PROXY_AVAILABLE = "is_proxy_available";
+    private static final String KEY_REPLY_TO_MESSENGER_BINDER = "reply_to_messenger_binder";
+    private static final String KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE =
+            "reply_to_messenger_binder_bundle";
+
+    private Handler mTarget;
+    private Messenger mProxyStatusService;
+    private AtomicBoolean mReconnectRequested = new AtomicBoolean(false);
+    private AtomicBoolean mIsProxyAvailable = new AtomicBoolean(false);
     private final AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
-    private final AtomicInteger mReconnectGeneration = new AtomicInteger(0);
+
+    private final BroadcastReceiver mProxyStatusServiceListener = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(ACTION_PROXY_STATUS_CHANGE)) {
+                mIsProxyAvailable.set(intent.getBooleanExtra(KEY_IS_PROXY_AVAILABLE, false));
+                if (mIsProxyAvailable.get()) {
+                    Bundle bundle = intent.getBundleExtra(KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE);
+                    if (bundle == null || bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER) == null) {
+                        Log.e(TAG, "no messenger binder in the intent to send future requests");
+                        mIsProxyAvailable.set(false);
+                        return;
+                    }
+                    mProxyStatusService =
+                            new Messenger(bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER));
+                    // If there is a pending reconnect request, do it now.
+                    if (mReconnectRequested.get()) {
+                        reconnect();
+                    }
+                } else {
+                    setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
+                            REASON_PROXY_DOWN, null);
+                }
+            } else {
+                Log.d(TAG, "Unrecognized broadcast intent");
+            }
+        }
+    };
 
     /**
      * Create a new ProxyDataTracker
      */
     public ProxyDataTracker() {
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, "");
-        // TODO: update available state according to proxy state.
-        mNetworkInfo.setIsAvailable(true);
         mLinkProperties = new LinkProperties();
         mLinkCapabilities = new LinkCapabilities();
-
+        mNetworkInfo.setIsAvailable(true);
         try {
           mLinkProperties.addDns(InetAddress.getByName(DNS1));
           mLinkProperties.addDns(InetAddress.getByName(DNS2));
@@ -64,11 +118,31 @@
         throw new CloneNotSupportedException();
     }
 
+    @Override
+    public void startMonitoring(Context context, Handler target) {
+        mContext = context;
+        mTarget = target;
+        mContext.registerReceiver(mProxyStatusServiceListener,
+                new IntentFilter(ACTION_PROXY_STATUS_CHANGE),
+                PERMISSION_PROXY_STATUS_SENDER,
+                null);
+    }
+
     /**
      * Disable connectivity to the network.
      */
     public boolean teardown() {
-        // TODO: tell relevant service to tear down proxy.
+        setTeardownRequested(true);
+        mReconnectRequested.set(false);
+        try {
+            if (mIsProxyAvailable.get() && mProxyStatusService != null) {
+                mProxyStatusService.send(Message.obtain(null, MSG_TEAR_DOWN_REQUEST));
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to connect to proxy status service", e);
+            return false;
+        }
+        setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_DISABLED, null);
         return true;
     }
 
@@ -76,16 +150,24 @@
      * Re-enable proxy data connectivity after a {@link #teardown()}.
      */
     public boolean reconnect() {
-        if (!isAvailable()) {
-            Log.w(TAG, "Reconnect requested even though network is disabled. Bailing.");
+        mReconnectRequested.set(true);
+        setTeardownRequested(false);
+        if (!mIsProxyAvailable.get()) {
+            Log.w(TAG, "Reconnect requested even though proxy service is not up. Bailing.");
             return false;
         }
-        setTeardownRequested(false);
-        mReconnectGeneration.incrementAndGet();
-        // TODO: tell relevant service to setup proxy. Set state to connected only if setup
-        // succeeds.
-        setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null);
+        setDetailedState(NetworkInfo.DetailedState.CONNECTING, REASON_ENABLED, null);
 
+        try {
+            mProxyStatusService.send(Message.obtain(null, MSG_SETUP_REQUEST));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to connect to proxy status service", e);
+            setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_PROXY_DOWN, null);
+            return false;
+        }
+        // We'll assume proxy is set up successfully. If not, a status change broadcast will be
+        // received afterwards to indicate any failure.
+        setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null);
         return true;
     }
 
@@ -116,7 +198,7 @@
     private void setDetailedState(NetworkInfo.DetailedState state, String reason,
             String extraInfo) {
         mNetworkInfo.setDetailedState(state, reason, extraInfo);
-        Message msg = getTargetHandler().obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+        Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
         msg.sendToTarget();
     }
 }
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 1fe4b08..5b0a4b2 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -630,7 +630,7 @@
     if (producer == NULL)
         goto not_valid_surface;
 
-    window = new android::Surface(producer);
+    window = new android::Surface(producer, true);
 
     if (window == NULL)
         goto not_valid_surface;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 559b11b..96a920d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1077,8 +1077,16 @@
     <!-- Name of the wimax state tracker clas -->
     <string name="config_wimaxStateTrackerClassname" translatable="false"></string>
 
-    <!-- Is the dreams feature supported? -->
+    <!-- Specifies whether the dreams feature should be supported.
+         When true, the system will allow the user to configure dreams (screensavers)
+         to launch when a user activity timeout occurs or the system is told to nap.
+         When false, the dreams feature will be disabled (this does not affect dozing).
+
+         Consider setting this resource to false or disabling dreams by default when a
+         doze component is specified below since dreaming will supercede dozing and
+         will prevent the system from entering a low power state until the dream ends. -->
     <bool name="config_dreamsSupported">true</bool>
+
     <!-- If supported, are dreams enabled? (by default) -->
     <bool name="config_dreamsEnabledByDefault">true</bool>
     <!-- If supported and enabled, are dreams activated when docked? (by default) -->
diff --git a/docs/html/tools/help/avd-manager.jd b/docs/html/tools/help/avd-manager.jd
index ed90f43..20f6253 100644
--- a/docs/html/tools/help/avd-manager.jd
+++ b/docs/html/tools/help/avd-manager.jd
@@ -8,8 +8,11 @@
 
 <p>You can launch the AVD Manager in one of the following ways:</p>
 <ul>
-  <li>In Eclipse: select <strong>Window &gt; AVD Manager</strong>, or click
-  the AVD Manager icon in the Eclipse toolbar.</li>
+  <li>In Eclipse: select <strong>Window &gt; Android Virtual Device Manager</strong>, or click
+  the AVD Manager icon in the toolbar.</li>
+
+  <li>In Android Studio: select <strong>Tools &gt; Android &gt; AVD Manager</strong>, or click
+  the AVD Manager icon in the toolbar.</li>
 
   <li>In other IDEs: Navigate to your SDK's <code>tools/</code> directory and execute
   <code>android avd</code>.</li>
diff --git a/docs/html/tools/help/sdk-manager.jd b/docs/html/tools/help/sdk-manager.jd
index 276206f..57271bb 100644
--- a/docs/html/tools/help/sdk-manager.jd
+++ b/docs/html/tools/help/sdk-manager.jd
@@ -9,6 +9,8 @@
 <ul>
   <li>From Eclipse (with <a href="{@docRoot}tools/help/adt.html">ADT</a>),
   select <strong>Window</strong> &gt; <strong>Android SDK Manager</strong>.</li>
+  <li>From Android Studio, select <strong>Tools</strong> &gt; <strong>Android</strong>
+  &gt; <strong>SDK Manager</strong>.</li>
   <li>On Windows, double-click the <code>SDK Manager.exe</code> file at the root of the Android
 SDK directory.</li>
   <li>On Mac or Linux, open a terminal and navigate to the <code>tools/</code> directory in the
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 76f29cd..e38db58 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1672,7 +1672,8 @@
             return view.getParent() != null ? view : null;
         } catch (WindowManager.BadTokenException e) {
             // ignore
-            Log.w(TAG, appToken + " already running, starting window not displayed");
+            Log.w(TAG, appToken + " already running, starting window not displayed. " +
+                    e.getMessage());
         } catch (RuntimeException e) {
             // don't crash if something else bad happens, for example a
             // failure loading resources because we are loading from an app
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 16b09bc..9ffcc8c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1553,7 +1553,7 @@
             return false;
         }
         if (!isBeingKeptAwakeLocked()) {
-            if (!mIsPowered && !mDreamsEnabledByDefaultConfig) {
+            if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) {
                 return false;
             }
             if (!mIsPowered
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 036804c..09c4e20 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,11 +16,12 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowManagerService.TAG;
+
 import android.util.EventLog;
-import com.android.server.EventLogTags;
+import android.util.Slog;
 
 class Task {
-//    private final String TAG = "TaskGroup";
     TaskStack mStack;
     final AppTokenList mAppTokens = new AppTokenList();
     final int taskId;
@@ -39,17 +40,24 @@
     }
 
     void addAppToken(int addPos, AppWindowToken wtoken) {
+        final int lastPos = mAppTokens.size();
+        if (addPos > lastPos) {
+            // We lost an app token. Don't crash though.
+            Slog.e(TAG, "Task.addAppToken: Out of bounds attempt token=" + wtoken + " addPos="
+                    + addPos + " lastPos=" + lastPos);
+            addPos = lastPos;
+        }
         mAppTokens.add(addPos, wtoken);
+        mDeferRemoval = false;
     }
 
     boolean removeAppToken(AppWindowToken wtoken) {
-        mAppTokens.remove(wtoken);
+        boolean removed = mAppTokens.remove(wtoken);
         if (mAppTokens.size() == 0) {
             EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId,
                     "removeAppToken: last token");
-            return true;
         }
-        return false;
+        return removed;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9655de0..fb5d7a7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3487,7 +3487,7 @@
 
             Task task = mTaskIdToTask.get(taskId);
             if (task == null) {
-                task = createTask(taskId, stackId, userId, atoken);
+                createTask(taskId, stackId, userId, atoken);
             } else {
                 task.addAppToken(addPos, atoken);
             }
@@ -3840,27 +3840,23 @@
         }
 
         synchronized(mWindowMap) {
-            boolean changed = false;
+            final AppWindowToken newFocus;
             if (token == null) {
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
-                changed = mFocusedApp != null;
-                mFocusedApp = null;
-                if (changed) {
-                    mInputMonitor.setFocusedAppLw(null);
-                }
+                newFocus = null;
             } else {
-                AppWindowToken newFocus = findAppWindowToken(token);
+                newFocus = findAppWindowToken(token);
                 if (newFocus == null) {
                     Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
-                    return;
                 }
-                changed = mFocusedApp != newFocus;
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
+            }
+
+            final boolean changed = mFocusedApp != newFocus;
+            if (changed) {
                 mFocusedApp = newFocus;
-                if (changed) {
-                    mInputMonitor.setFocusedAppLw(newFocus);
-                }
+                mInputMonitor.setFocusedAppLw(null);
             }
 
             if (moveFocusNow && changed) {
@@ -4544,11 +4540,9 @@
     void removeAppFromTaskLocked(AppWindowToken wtoken) {
         final Task task = mTaskIdToTask.get(wtoken.groupId);
         if (task != null) {
-            task.removeAppToken(wtoken);
-            // Remove after bug resolved.
-            Slog.d(TAG, "removeAppFromTaskLocked: wtoken=" + wtoken
-                    + " numTokens left=" + task.mAppTokens.size()
-                    + " Callers=" + Debug.getCallers(5));
+            if (!task.removeAppToken(wtoken)) {
+                Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
+            }
         }
     }
 
@@ -4584,6 +4578,8 @@
                         TAG, "Removing app " + wtoken + " delayed=" + delayed
                         + " animation=" + wtoken.mAppAnimator.animation
                         + " animating=" + wtoken.mAppAnimator.animating);
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
+                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
                 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
@@ -4599,9 +4595,6 @@
                     wtoken.mAppAnimator.animating = false;
                     removeAppFromTaskLocked(wtoken);
                 }
-                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
-                        "removeAppToken: " + wtoken);
-
 
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0e056eb..db40cbe 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -857,9 +857,8 @@
                 }
             }
 
-            if (!disableNonCoreServices
-                    && context.getResources().getBoolean(R.bool.config_dreamsSupported)) {
-                // Dreams (interactive idle-time views, a/k/a screen savers)
+            if (!disableNonCoreServices) {
+                // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode)
                 mSystemServiceManager.startService(DreamManagerService.class);
             }
 
@@ -1000,138 +999,131 @@
         // where third party code can really run (but before it has actually
         // started launching the initial applications), for us to complete our
         // initialization.
-        final Handler handler = new Handler();
         mActivityManagerService.systemReady(new Runnable() {
             @Override
             public void run() {
-                // We initiate all boot phases on the SystemServer thread.
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        Slog.i(TAG, "Making services ready");
-                        mSystemServiceManager.startBootPhase(
-                                SystemService.PHASE_ACTIVITY_MANAGER_READY);
+                Slog.i(TAG, "Making services ready");
+                mSystemServiceManager.startBootPhase(
+                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
 
-                        try {
-                            mActivityManagerService.startObservingNativeCrashes();
-                        } catch (Throwable e) {
-                            reportWtf("observing native crashes", e);
-                        }
-                        try {
-                            startSystemUi(context);
-                        } catch (Throwable e) {
-                            reportWtf("starting System UI", e);
-                        }
-                        try {
-                            if (mountServiceF != null) mountServiceF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Mount Service ready", e);
-                        }
-                        try {
-                            if (batteryF != null) batteryF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Battery Service ready", e);
-                        }
-                        try {
-                            if (networkManagementF != null) networkManagementF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Network Managment Service ready", e);
-                        }
-                        try {
-                            if (networkStatsF != null) networkStatsF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Network Stats Service ready", e);
-                        }
-                        try {
-                            if (networkPolicyF != null) networkPolicyF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Network Policy Service ready", e);
-                        }
-                        try {
-                            if (connectivityF != null) connectivityF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Connectivity Service ready", e);
-                        }
-                        try {
-                            if (dockF != null) dockF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Dock Service ready", e);
-                        }
-                        try {
-                            if (recognitionF != null) recognitionF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Recognition Service ready", e);
-                        }
-                        Watchdog.getInstance().start();
+                try {
+                    mActivityManagerService.startObservingNativeCrashes();
+                } catch (Throwable e) {
+                    reportWtf("observing native crashes", e);
+                }
+                try {
+                    startSystemUi(context);
+                } catch (Throwable e) {
+                    reportWtf("starting System UI", e);
+                }
+                try {
+                    if (mountServiceF != null) mountServiceF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Mount Service ready", e);
+                }
+                try {
+                    if (batteryF != null) batteryF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Battery Service ready", e);
+                }
+                try {
+                    if (networkManagementF != null) networkManagementF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Managment Service ready", e);
+                }
+                try {
+                    if (networkStatsF != null) networkStatsF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Stats Service ready", e);
+                }
+                try {
+                    if (networkPolicyF != null) networkPolicyF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Policy Service ready", e);
+                }
+                try {
+                    if (connectivityF != null) connectivityF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Connectivity Service ready", e);
+                }
+                try {
+                    if (dockF != null) dockF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Dock Service ready", e);
+                }
+                try {
+                    if (recognitionF != null) recognitionF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Recognition Service ready", e);
+                }
+                Watchdog.getInstance().start();
 
-                        // It is now okay to let the various system services start their
-                        // third party code...
-                        mSystemServiceManager.startBootPhase(
-                                SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+                // It is now okay to let the various system services start their
+                // third party code...
+                mSystemServiceManager.startBootPhase(
+                        SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
 
-                        try {
-                            if (wallpaperF != null) wallpaperF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying WallpaperService running", e);
-                        }
-                        try {
-                            if (immF != null) immF.systemRunning(statusBarF);
-                        } catch (Throwable e) {
-                            reportWtf("Notifying InputMethodService running", e);
-                        }
-                        try {
-                            if (locationF != null) locationF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying Location Service running", e);
-                        }
-                        try {
-                            if (countryDetectorF != null) countryDetectorF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying CountryDetectorService running", e);
-                        }
-                        try {
-                            if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying NetworkTimeService running", e);
-                        }
-                        try {
-                            if (commonTimeMgmtServiceF != null) {
-                                commonTimeMgmtServiceF.systemRunning();
-                            }
-                        } catch (Throwable e) {
-                            reportWtf("Notifying CommonTimeManagementService running", e);
-                        }
-                        try {
-                            if (textServiceManagerServiceF != null)
-                                textServiceManagerServiceF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying TextServicesManagerService running", e);
-                        }
-                        try {
-                            if (atlasF != null) atlasF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying AssetAtlasService running", e);
-                        }
-                        try {
-                            // TODO(BT) Pass parameter to input manager
-                            if (inputManagerF != null) inputManagerF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying InputManagerService running", e);
-                        }
-                        try {
-                            if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying TelephonyRegistry running", e);
-                        }
-                        try {
-                            if (mediaRouterF != null) mediaRouterF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying MediaRouterService running", e);
-                        }
-
-                        mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
+                try {
+                    if (wallpaperF != null) wallpaperF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying WallpaperService running", e);
+                }
+                try {
+                    if (immF != null) immF.systemRunning(statusBarF);
+                } catch (Throwable e) {
+                    reportWtf("Notifying InputMethodService running", e);
+                }
+                try {
+                    if (locationF != null) locationF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying Location Service running", e);
+                }
+                try {
+                    if (countryDetectorF != null) countryDetectorF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying CountryDetectorService running", e);
+                }
+                try {
+                    if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying NetworkTimeService running", e);
+                }
+                try {
+                    if (commonTimeMgmtServiceF != null) {
+                        commonTimeMgmtServiceF.systemRunning();
                     }
-                });
+                } catch (Throwable e) {
+                    reportWtf("Notifying CommonTimeManagementService running", e);
+                }
+                try {
+                    if (textServiceManagerServiceF != null)
+                        textServiceManagerServiceF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying TextServicesManagerService running", e);
+                }
+                try {
+                    if (atlasF != null) atlasF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying AssetAtlasService running", e);
+                }
+                try {
+                    // TODO(BT) Pass parameter to input manager
+                    if (inputManagerF != null) inputManagerF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying InputManagerService running", e);
+                }
+                try {
+                    if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying TelephonyRegistry running", e);
+                }
+                try {
+                    if (mediaRouterF != null) mediaRouterF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying MediaRouterService running", e);
+                }
+
+                mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
             }
         });
     }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 9a4d8d8..bef33b9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -98,6 +98,13 @@
     // which need debouncing.
     private static final int UPDATE_DELAY = 1000;
 
+    // Time we received a request to enter USB accessory mode
+    private long mAccessoryModeRequestTime = 0;
+
+    // Timeout for entering USB request mode.
+    // Request is cancelled if host does not configure device within 10 seconds.
+    private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000;
+
     private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
 
     private UsbHandler mHandler;
@@ -205,6 +212,8 @@
     }
 
     private void startAccessoryMode() {
+        if (!mHasUsbAccessory) return;
+
         mAccessoryStrings = nativeGetAccessoryStrings();
         boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
         // don't start accessory mode if our mandatory strings have not been set
@@ -223,6 +232,7 @@
         }
 
         if (functions != null) {
+            mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
             setCurrentFunctions(functions, false);
         }
     }
@@ -456,6 +466,8 @@
         }
 
         private void setEnabledFunctions(String functions, boolean makeDefault) {
+            if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions
+                    + " makeDefault: " + makeDefault);
 
             // Do not update persystent.sys.usb.config if the device is booted up
             // with OEM specific mode.
@@ -517,9 +529,17 @@
         }
 
         private void updateCurrentAccessory() {
-            if (!mHasUsbAccessory) return;
+            // We are entering accessory mode if we have received a request from the host
+            // and the request has not timed out yet.
+            boolean enteringAccessoryMode =
+                    mAccessoryModeRequestTime > 0 &&
+                        SystemClock.elapsedRealtime() <
+                            mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
 
-            if (mConfigured) {
+            if (mConfigured && enteringAccessoryMode) {
+                // successfully entered accessory mode
+                mAccessoryModeRequestTime = 0;
+
                 if (mAccessoryStrings != null) {
                     mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
                     Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
@@ -530,7 +550,7 @@
                 } else {
                     Slog.e(TAG, "nativeGetAccessoryStrings failed");
                 }
-            } else if (!mConnected) {
+            } else if (!enteringAccessoryMode) {
                 // make sure accessory mode is off
                 // and restore default functions
                 Slog.d(TAG, "exited USB accessory mode");
@@ -560,6 +580,8 @@
                 }
             }
 
+            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " connected: " + mConnected
+                                    + " configured: " + mConfigured);
             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         }
 
@@ -599,9 +621,7 @@
                     if (containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
                         updateCurrentAccessory();
-                    }
-
-                    if (!mConnected) {
+                    } else if (!mConnected) {
                         // restore defaults when USB is disconnected
                         setEnabledFunctions(mDefaultFunctions, false);
                     }