summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Joanne <joannechung@google.com> 2022-10-03 22:05:29 +0800
committer Joanne Chung <joannechung@google.com> 2022-11-07 12:40:48 +0000
commit908ee5ed9d3609cc0c18d15b1b48c325e32f0654 (patch)
tree7128e7a54c207d3fb8684a6153c5db43cc22ca09
parent6cc66e4581998390ad63aee0fc566253a62fa0e7 (diff)
Dump App exit reason if the remote service died.
We received many bugs the ContentCaptureService entered zombie state but we don't know the reason why the process died. The issue timing didn't be captured in bugreport. Currently, the AbstractRemoteService will enter an odd state if the service cannot be reconnected. This state does not allow the requests be sent until the service be reconnected again on an unknown timing. In some cases, it is expected the service will not be reconnected. e.g. app stop from settings. We should fix the problem in the AbstractRemoteService but before doing this, we try to add debugging signal in bugreport to help us understand if the existing issues come from this odd state for reasonable reasons. The change was merged in master so skip automerge. The minor change here will have a seperate change in master. Bug: 248218072 Bug: 250859760 Test: disable app and dumpsys content_capture Change-Id: Ia33462006a3925754001562b0d80540b9b0bc45d Merged-in: Ia33462006a3925754001562b0d80540b9b0bc45d (cherry picked from commit d060ed56975495a8f6bff86f8b41f4d0a08457ea)
-rw-r--r--core/java/android/app/ApplicationExitInfo.java3
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java54
2 files changed, 56 insertions, 1 deletions
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index a8d8c75601aa..5517c57d1f1e 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -1196,7 +1196,8 @@ public final class ApplicationExitInfo implements Parcelable {
return sb.toString();
}
- private static String reasonCodeToString(@Reason int reason) {
+ /** @hide */
+ public static String reasonCodeToString(@Reason int reason) {
switch (reason) {
case REASON_EXIT_SELF:
return "EXIT_SELF";
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index f725b37acde7..0e1b7cb8090f 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -20,10 +20,14 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ApplicationExitInfo;
+import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ParceledListSlice;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
@@ -39,6 +43,7 @@ import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.List;
/**
* Base class representing a remote service.
@@ -66,6 +71,7 @@ import java.util.ArrayList;
@Deprecated
public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I>,
I extends IInterface> implements DeathRecipient {
+ private static final int SERVICE_NOT_EXIST = -1;
private static final int MSG_BIND = 1;
private static final int MSG_UNBIND = 2;
@@ -96,6 +102,8 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
// Used just for debugging purposes (on dump)
private long mNextUnbind;
+ private int mServiceExitReason;
+ private int mServiceExitSubReason;
/** Requests that have been scheduled, but that are not finished yet */
private final ArrayList<BasePendingRequest<S, I>> mUnfinishedRequests = new ArrayList<>();
@@ -126,6 +134,8 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
mUserId = userId;
mHandler = new Handler(handler.getLooper());
mBindingFlags = bindingFlags;
+ mServiceExitReason = SERVICE_NOT_EXIST;
+ mServiceExitSubReason = SERVICE_NOT_EXIST;
}
/**
@@ -229,6 +239,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
if (mService != null) {
mService.asBinder().unlinkToDeath(this, 0);
}
+ updateServicelicationExitInfo(mComponentName, mUserId);
mConnecting = true;
mService = null;
mServiceDied = true;
@@ -239,6 +250,37 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
handleBindFailure();
}
+ private void updateServicelicationExitInfo(ComponentName componentName, int userId) {
+ IActivityManager am = ActivityManager.getService();
+ String packageName = componentName.getPackageName();
+ ParceledListSlice<ApplicationExitInfo> plistSlice = null;
+ try {
+ plistSlice = am.getHistoricalProcessExitReasons(packageName, 0, 1, userId);
+ } catch (RemoteException e) {
+ // do nothing. The local binder so it can not throw it.
+ }
+ if (plistSlice == null) {
+ mServiceExitReason = ApplicationExitInfo.REASON_UNKNOWN;
+ mServiceExitSubReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
+ return;
+ }
+ List<ApplicationExitInfo> list = plistSlice.getList();
+ if (list.isEmpty()) {
+ mServiceExitReason = ApplicationExitInfo.REASON_UNKNOWN;
+ mServiceExitSubReason = ApplicationExitInfo.SUBREASON_UNKNOWN;
+ return;
+ }
+ ApplicationExitInfo info = list.get(0);
+ mServiceExitReason = info.getReason();
+ mServiceExitSubReason = info.getSubReason();
+ if (mVerbose) {
+ Slog.v(mTag, "updateServicelicationExitInfo: exitReason="
+ + ApplicationExitInfo.reasonCodeToString(mServiceExitReason)
+ + " exitSubReason= " + ApplicationExitInfo.subreasonToString(
+ mServiceExitSubReason));
+ }
+ }
+
// Note: we are dumping without a lock held so this is a bit racy but
// adding a lock to a class that offloads to a handler thread would
// mean adding a lock adding overhead to normal runtime operation.
@@ -272,6 +314,16 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
}
}
pw.println();
+ if (mServiceExitReason != SERVICE_NOT_EXIST) {
+ pw.append(prefix).append(tab).append("serviceExistReason=")
+ .append(ApplicationExitInfo.reasonCodeToString(mServiceExitReason));
+ pw.println();
+ }
+ if (mServiceExitSubReason != SERVICE_NOT_EXIST) {
+ pw.append(prefix).append(tab).append("serviceExistSubReason=")
+ .append(ApplicationExitInfo.subreasonToString(mServiceExitSubReason));
+ pw.println();
+ }
pw.append(prefix).append("mBindingFlags=").println(mBindingFlags);
pw.append(prefix).append("idleTimeout=")
.append(Long.toString(idleTimeout / 1000)).append("s\n");
@@ -498,6 +550,8 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
return;
}
mService = getServiceInterface(service);
+ mServiceExitReason = SERVICE_NOT_EXIST;
+ mServiceExitSubReason = SERVICE_NOT_EXIST;
handleOnConnectedStateChangedInternal(true);
mServiceDied = false;
}