Merge "Dump App exit reason if the remote service died." into tm-qpr-dev am: 055796e826

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20392455

Change-Id: I83fa75898fcd5894e4dcc8d659e5035b4afce60d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Joanne Chung
2022-11-08 11:15:12 +00:00
committed by Automerger Merge Worker
2 changed files with 56 additions and 1 deletions

View File

@@ -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";

View File

@@ -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;
}