diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index 8a42ddfdc19d1..71749e7871152 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 @@ public final class ContentCaptureManagerService extends @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 6bd1fa6c335dc..822a42bf50cf2 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.PackageManager.NameNotFoundException; 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.contentcapture.RemoteContentCaptureService.ContentCapt 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 @@ final class ContentCapturePerUserService 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 mSessions = new SparseArray<>(); @@ -121,11 +127,18 @@ final class ContentCapturePerUserService @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 @@ final class ContentCapturePerUserService 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 @@ final class ContentCapturePerUserService } void onPackageUpdatedLocked() { - updateRemoteServiceLocked(!isEnabledLocked()); - resurrectSessionsLocked(); + mRebindCount = 0; + updateRemoteServiceAndResurrectSessionsLocked(); } @GuardedBy("mLock") @@ -555,6 +602,8 @@ final class ContentCapturePerUserService 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:");