summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Joanne Chung <joannechung@google.com> 2022-11-08 10:41:39 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-11-08 10:41:39 +0000
commit055796e826d20f9764a9250db263d310d4635987 (patch)
tree9d8d5df86acb6160e3f205842095e70edfdd24fe
parent389d8389c54eae07fef556fe904a0b9249bac6e4 (diff)
parent908ee5ed9d3609cc0c18d15b1b48c325e32f0654 (diff)
Merge "Dump App exit reason if the remote service died." into tm-qpr-dev
-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;
}