Merge "FIX BUG 5244136 - HOLO LIST SEPARATOR TEXT DOES NOT SHOUT"
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 496da41..ef6e131 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -191,6 +191,12 @@
     private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds
     private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours
 
+    /**
+     * The amount of time to wait after attempting a bind before canceling a sync and disabling
+     * the sync adapter
+     */
+    public static final long BIND_TIMEOUT_MS = 30 * 1000;
+
     public void onAccountsUpdated(Account[] accounts) {
         // remember if this was the first time this was called after an update
         final boolean justBootedUp = mAccounts == INITIAL_ACCOUNTS_ARRAY;
@@ -1068,6 +1074,9 @@
             pw.print(" - ");
             pw.print(activeSyncContext.mSyncOperation.dump(false));
             pw.println();
+            if (activeSyncContext.mSyncAdapter == null) {
+                pw.println("   **** Waiting for onServiceConnected ****");
+            }
         }
 
         synchronized (mSyncQueue) {
@@ -1424,6 +1433,7 @@
         public void handleMessage(Message msg) {
             long earliestFuturePollTime = Long.MAX_VALUE;
             long nextPendingSyncTime = Long.MAX_VALUE;
+            long nextBindTimeoutTime = Long.MAX_VALUE;
 
             // Setting the value here instead of a method because we want the dumpsys logs
             // to have the most recent value used.
@@ -1431,6 +1441,7 @@
                 waitUntilReadyToRun();
                 mDataConnectionIsConnected = readDataConnectionState();
                 mSyncManagerWakeLock.acquire();
+                nextBindTimeoutTime = auditRunningSyncsForStuckBindsLocked();
                 // Always do this first so that we be sure that any periodic syncs that
                 // are ready to run have been converted into pending syncs. This allows the
                 // logic that considers the next steps to take based on the set of pending syncs
@@ -1532,6 +1543,7 @@
                         break;
                 }
             } finally {
+                nextPendingSyncTime = Math.min(nextBindTimeoutTime, nextPendingSyncTime);
                 manageSyncNotificationLocked();
                 manageSyncAlarmLocked(earliestFuturePollTime, nextPendingSyncTime);
                 mSyncTimeTracker.update();
@@ -1540,6 +1552,36 @@
         }
 
         /**
+         * Looks to see if any of the active syncs have been waiting for a bind for too long,
+         * and if so the sync is canceled and the sync adapter is disabled for that account.
+         * @return the earliest time that an active sync can have waited too long to bind,
+         * relative to {@link android.os.SystemClock#elapsedRealtime()}.
+         */
+        private long auditRunningSyncsForStuckBindsLocked() {
+            final long now = SystemClock.elapsedRealtime();
+            long oldest = Long.MAX_VALUE;
+            for (ActiveSyncContext active : mActiveSyncContexts) {
+                if (active.mSyncAdapter == null) {
+                    final long timeoutTime = active.mStartTime + BIND_TIMEOUT_MS;
+                    if (timeoutTime < now) {
+                        Log.w(TAG, "canceling long-running bind and disabling sync for "
+                                + active.mSyncOperation.account + ", authority "
+                                + active.mSyncOperation.authority);
+                        runSyncFinishedOrCanceledLocked(null, active);
+                        ContentResolver.setIsSyncable(active.mSyncOperation.account,
+                                active.mSyncOperation.authority, 0);
+                    } else {
+                        if (oldest > timeoutTime) {
+                            oldest = timeoutTime;
+                        }
+                    }
+                }
+            }
+
+            return oldest;
+        }
+
+        /**
          * Turn any periodic sync operations that are ready to run into pending sync operations.
          * @return the desired start time of the earliest future  periodic sync operation,
          * in milliseconds since boot
@@ -1819,13 +1861,17 @@
                 synchronized (mSyncQueue){
                     mSyncQueue.remove(candidate);
                 }
-                dispatchSyncOperation(candidate);
+                ActiveSyncContext newSyncContext = dispatchSyncOperation(candidate);
+                if (newSyncContext != null) {
+                    nextReadyToRunTime = Math.min(nextReadyToRunTime,
+                            newSyncContext.mStartTime + BIND_TIMEOUT_MS);
+                }
             }
 
             return nextReadyToRunTime;
      }
 
-        private boolean dispatchSyncOperation(SyncOperation op) {
+        private ActiveSyncContext dispatchSyncOperation(SyncOperation op) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "dispatchSyncOperation: we are going to sync " + op);
                 Log.v(TAG, "num active syncs: " + mActiveSyncContexts.size());
@@ -1842,7 +1888,7 @@
                 Log.d(TAG, "can't find a sync adapter for " + syncAdapterType
                         + ", removing settings for it");
                 mSyncStorageEngine.removeAuthority(op.account, op.authority);
-                return false;
+                return null;
             }
 
             ActiveSyncContext activeSyncContext =
@@ -1855,10 +1901,10 @@
             if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo)) {
                 Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
                 closeActiveSyncContext(activeSyncContext);
-                return false;
+                return null;
             }
 
-            return true;
+            return activeSyncContext;
         }
 
         private void runBoundToSyncAdapter(final ActiveSyncContext activeSyncContext,
diff --git a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
index ff9be3c..9e77665 100644
--- a/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
+++ b/opengl/libs/GLES2_dbg/src/dbgcontext.cpp
@@ -88,7 +88,7 @@
     msg.set_arg1(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
     Send(msg, cmd);
 
-    *(DbgContext **)pthread_getspecific(dbgEGLThreadLocalStorageKey) = dbg;
+    pthread_setspecific(dbgEGLThreadLocalStorageKey, dbg);
     return dbg;
 }
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7779703..bad7e1f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -36,10 +36,10 @@
     <string name="status_bar_please_disturb_button">Show notifications</string>
 
     <!-- Title shown in recents popup for removing an application from the list -->
-    <string name="status_bar_recent_remove_item_title">Remove</string>
+    <string name="status_bar_recent_remove_item_title">Remove from list</string>
 
     <!-- Title shown in recents popup for inspecting an application's properties -->
-    <string name="status_bar_recent_inspect_item_title">Inspect</string>
+    <string name="status_bar_recent_inspect_item_title">App info</string>
 
     <!-- The label in the bar at the top of the status bar when there are no notifications
          showing.  [CHAR LIMIT=40]-->
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index d19b98a2..e59c109 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -243,6 +243,16 @@
         }
     }
 
+    public void hide(boolean animate) {
+        mShowing = false;
+        if (!animate) {
+            setVisibility(View.GONE);
+        }
+        if (mBar != null) {
+            mBar.animateCollapse();
+        }
+    }
+
     public void handleShowBackground(boolean show) {
         if (show) {
             mRecentsScrim.setBackgroundResource(R.drawable.status_bar_recents_background);
@@ -654,15 +664,6 @@
         mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
     }
 
-    public void hide(boolean animate) {
-        if (!animate) {
-            setVisibility(View.GONE);
-        }
-        if (mBar != null) {
-            mBar.animateCollapse();
-        }
-    }
-
     public void handleOnClick(View view) {
         ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
         final Context context = view.getContext();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 4ba514a..3d23abe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -404,7 +404,7 @@
         // Recents Panel
         boolean visible = false;
         if (mRecentsPanel != null) {
-            visible = mRecentsPanel.getVisibility() == View.VISIBLE;
+            visible = mRecentsPanel.isShowing();
             WindowManagerImpl.getDefault().removeView(mRecentsPanel);
         }
 
@@ -1125,20 +1125,22 @@
         Slog.i(TAG, "DISABLE_BACK: " + (disableBack ? "yes" : "no"));
         Slog.i(TAG, "DISABLE_NAVIGATION: " + (disableNavigation ? "yes" : "no"));
 
-        if (disableNavigation && disableBack) {
-            mNavigationBarView.setEnabled(false);
-        } else {
-            mNavigationBarView.getBackButton().setEnabled(!disableBack);
-            mNavigationBarView.getHomeButton().setEnabled(!disableNavigation);
-            mNavigationBarView.getRecentsButton().setEnabled(!disableNavigation);
+        if (mNavigationBarView != null) {
+            if (disableNavigation && disableBack) {
+                mNavigationBarView.setEnabled(false);
+            } else {
+                mNavigationBarView.getBackButton().setEnabled(!disableBack);
+                mNavigationBarView.getHomeButton().setEnabled(!disableNavigation);
+                mNavigationBarView.getRecentsButton().setEnabled(!disableNavigation);
 
-            if (disableNavigation) {
-                // close recents if it's visible
-                mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
-                mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
+                mNavigationBarView.setEnabled(true);
             }
+        }
 
-            mNavigationBarView.setEnabled(true);
+        if (disableNavigation) {
+            // close recents if it's visible
+            mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
+            mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
         }
     }