diff options
| -rw-r--r-- | core/java/android/app/ApplicationExitInfo.java | 3 | ||||
| -rw-r--r-- | core/java/com/android/internal/infra/AbstractRemoteService.java | 51 |
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; } |