summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ApplicationExitInfo.java3
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java51
2 files changed, 53 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..d5f7ba57a694 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,9 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
// Used just for debugging purposes (on dump)
private long mNextUnbind;
+ // Used just for debugging purposes (on dump)
+ 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 +135,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 +240,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 +251,33 @@ 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) {
+ return;
+ }
+ List<ApplicationExitInfo> list = plistSlice.getList();
+ if (list.isEmpty()) {
+ 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 +311,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 +547,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;
}