Rebind ContentCaptureService when the binderDied.
If the ContentCaptureService has package dependency with other package, if the package is updating, ContentCaptureService will also be killed. In the normal case, if the service will be reconnected but in this case the binding is cleared without any notification to the ContentCaptureManagerService. The bug is in the core platform infra. In the Content Capture code, we only see the binderDied. This change is a short term solution in S, we will rebind the service when the binderDied. To avoid crash loop, we only bind the service with limit rebind counts. Bug: 199609306 Test: manual. Add addPackageDependency to package and update the package. Make sure the state is not zombie. Change-Id: I09a4cf6281a5a259a9a759ca640d6f075726e562
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<ContentCaptureServerSession> 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:");
|
||||
|
||||
Reference in New Issue
Block a user