Merge "Rebind ContentCaptureService when the binderDied." into sc-v2-dev
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 8a42ddf..71749e7 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -223,7 +223,7 @@
     @Override // from AbstractMasterSystemService
     protected ContentCapturePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
             boolean disabled) {
-        return new ContentCapturePerUserService(this, mLock, disabled, resolvedUserId);
+        return new ContentCapturePerUserService(this, mLock, disabled, resolvedUserId, mHandler);
     }
 
     @Override // from SystemService
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 6bd1fa6..822a42b 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -46,6 +46,7 @@
 import android.content.pm.ServiceInfo;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -75,6 +76,7 @@
 import com.android.server.infra.AbstractPerUserSystemService;
 
 import java.io.PrintWriter;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -88,6 +90,10 @@
 
     private static final String TAG = ContentCapturePerUserService.class.getSimpleName();
 
+    private static final int MAX_REBIND_COUNTS = 5;
+    // 5 minutes
+    private static final long REBIND_DURATION_MS = 5 * 60 * 1_000;
+
     @GuardedBy("mLock")
     private final SparseArray<ContentCaptureServerSession> mSessions = new SparseArray<>();
 
@@ -121,11 +127,18 @@
     @GuardedBy("mLock")
     private ContentCaptureServiceInfo mInfo;
 
+    private Instant mLastRebindTime;
+    private int mRebindCount;
+    private final Handler mHandler;
+
+    private final Runnable mReBindServiceRunnable = new RebindServiceRunnable();
+
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
     ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
-            @NonNull Object lock, boolean disabled, @UserIdInt int userId) {
+            @NonNull Object lock, boolean disabled, @UserIdInt int userId, Handler handler) {
         super(master, lock, userId);
+        mHandler = handler;
         updateRemoteServiceLocked(disabled);
     }
 
@@ -190,9 +203,43 @@
         Slog.w(TAG, "remote service died: " + service);
         synchronized (mLock) {
             mZombie = true;
-            writeServiceEvent(
-                    FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_REMOTE_SERVICE_DIED,
-                    getServiceComponentName());
+            // Reset rebindCount if over 12 hours mLastRebindTime
+            if (mLastRebindTime != null && Instant.now().isAfter(
+                    mLastRebindTime.plusMillis(12 * 60 * 60 * 1000))) {
+                if (mMaster.debug) {
+                    Slog.i(TAG, "The current rebind count " + mRebindCount + " is reset.");
+                }
+                mRebindCount = 0;
+            }
+            if (mRebindCount >= MAX_REBIND_COUNTS) {
+                writeServiceEvent(
+                        FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_REMOTE_SERVICE_DIED,
+                        getServiceComponentName());
+            }
+            if (mRebindCount < MAX_REBIND_COUNTS) {
+                mHandler.removeCallbacks(mReBindServiceRunnable);
+                mHandler.postDelayed(mReBindServiceRunnable, REBIND_DURATION_MS);
+            }
+        }
+    }
+
+    private void updateRemoteServiceAndResurrectSessionsLocked() {
+        boolean disabled = !isEnabledLocked();
+        updateRemoteServiceLocked(disabled);
+        resurrectSessionsLocked();
+    }
+
+    private final class RebindServiceRunnable implements Runnable{
+
+        @Override
+        public void run() {
+            synchronized (mLock) {
+                if (mZombie) {
+                    mLastRebindTime = Instant.now();
+                    mRebindCount++;
+                    updateRemoteServiceAndResurrectSessionsLocked();
+                }
+            }
         }
     }
 
@@ -240,8 +287,8 @@
     }
 
     void onPackageUpdatedLocked() {
-        updateRemoteServiceLocked(!isEnabledLocked());
-        resurrectSessionsLocked();
+        mRebindCount = 0;
+        updateRemoteServiceAndResurrectSessionsLocked();
     }
 
     @GuardedBy("mLock")
@@ -555,6 +602,8 @@
             mInfo.dump(prefix2, pw);
         }
         pw.print(prefix); pw.print("Zombie: "); pw.println(mZombie);
+        pw.print(prefix); pw.print("Rebind count: "); pw.println(mRebindCount);
+        pw.print(prefix); pw.print("Last rebind: "); pw.println(mLastRebindTime);
 
         if (mRemoteService != null) {
             pw.print(prefix); pw.println("remote service:");