Fix black wallpaper after repeated crashes

Adds logic to recover from a repeatedly crashing wallpaper. Before,
a wallpaper that crashed twice but not within 10s would not trigger
the recovery logic in WallpaperManagerService, but would also not be
restarted by ActivityManager (because two crashes will effectively
disable a service connection), thus resulting in a black wallpaper.

Change-Id: Ie4f7862dc07a89d13f5e2b56c825a3371ea21114
Fixes: 30250003
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 536e646..5f6800a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -89,6 +89,7 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
 import com.android.server.EventLogTags;
+import com.android.server.FgThread;
 import com.android.server.SystemService;
 
 import libcore.io.IoUtils;
@@ -589,6 +590,11 @@
 
     class WallpaperConnection extends IWallpaperConnection.Stub
             implements ServiceConnection {
+
+        /** Time in milliseconds until we expect the wallpaper to reconnect (unless we're in the
+         *  middle of an update). If exceeded, the wallpaper gets reset to the system default. */
+        private static final long WALLPAPER_RECONNECT_TIMEOUT_MS = 5000;
+
         final WallpaperInfo mInfo;
         final Binder mToken = new Binder();
         IWallpaperService mService;
@@ -599,6 +605,18 @@
         boolean mDimensionsChanged = false;
         boolean mPaddingChanged = false;
 
+        private Runnable mResetRunnable = () -> {
+            synchronized (mLock) {
+                if (!mWallpaper.wallpaperUpdating
+                        && mWallpaper.userId == mCurrentUserId) {
+                    Slog.w(TAG, "Wallpaper reconnect timed out, "
+                            + "reverting to built-in wallpaper!");
+                    clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
+                            null);
+                }
+            }
+        };
+
         public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
             mInfo = info;
             mWallpaper = wallpaper;
@@ -615,6 +633,7 @@
                     // locking there and anyway we always need to be able to
                     // recover if there is something wrong.
                     saveSettingsLocked(mWallpaper.userId);
+                    FgThread.getHandler().removeCallbacks(mResetRunnable);
                 }
             }
         }
@@ -641,6 +660,12 @@
                             clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
                         } else {
                             mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
+
+                            // If we didn't reset it right away, do so after we couldn't connect to
+                            // it for an extended amount of time to avoid having a black wallpaper.
+                            FgThread.getHandler().removeCallbacks(mResetRunnable);
+                            FgThread.getHandler().postDelayed(mResetRunnable,
+                                    WALLPAPER_RECONNECT_TIMEOUT_MS);
                         }
                         final String flattened = name.flattenToString();
                         EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
@@ -752,6 +777,10 @@
                     if (wallpaper.wallpaperComponent != null
                             && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
                         wallpaper.wallpaperUpdating = true;
+                        if (wallpaper.connection != null) {
+                            FgThread.getHandler().removeCallbacks(
+                                    wallpaper.connection.mResetRunnable);
+                        }
                     }
                 }
             }