diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 0e9c2c4dd6599..dd1e4f46a5de8 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -19,6 +19,7 @@ package com.android.internal.os; import android.app.ActivityManager; import android.app.ActivityThread; import android.app.ApplicationErrorReport; +import android.app.IActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.type.DefaultMimeMapFactory; import android.os.Build; @@ -64,6 +65,8 @@ public class RuntimeInit { private static volatile boolean mCrashing = false; + private static volatile ApplicationWtfHandler sDefaultApplicationWtfHandler; + private static final native void nativeFinishInit(); private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup); @@ -438,10 +441,27 @@ public class RuntimeInit { */ public static void wtf(String tag, Throwable t, boolean system) { try { - if (ActivityManager.getService().handleApplicationWtf( - mApplicationObject, tag, system, - new ApplicationErrorReport.ParcelableCrashInfo(t), - Process.myPid())) { + boolean exit = false; + final IActivityManager am = ActivityManager.getService(); + if (am != null) { + exit = am.handleApplicationWtf( + mApplicationObject, tag, system, + new ApplicationErrorReport.ParcelableCrashInfo(t), + Process.myPid()); + } else { + // Unlikely but possible in early system boot + final ApplicationWtfHandler handler = sDefaultApplicationWtfHandler; + if (handler != null) { + exit = handler.handleApplicationWtf( + mApplicationObject, tag, system, + new ApplicationErrorReport.ParcelableCrashInfo(t), + Process.myPid()); + } else { + // Simply log the error + Slog.e(TAG, "Original WTF:", t); + } + } + if (exit) { // The Activity Manager has already written us off -- now exit. Process.killProcess(Process.myPid()); System.exit(10); @@ -456,6 +476,29 @@ public class RuntimeInit { } } + /** + * Set the default {@link ApplicationWtfHandler}, in case the ActivityManager is not ready yet. + */ + public static void setDefaultApplicationWtfHandler(final ApplicationWtfHandler handler) { + sDefaultApplicationWtfHandler = handler; + } + + /** + * The handler to deal with the serious application errors. + */ + public interface ApplicationWtfHandler { + /** + * @param app object of the crashing app, null for the system server + * @param tag reported by the caller + * @param system whether this wtf is coming from the system + * @param crashInfo describing the context of the error + * @param immediateCallerPid the caller Pid + * @return true if the process should exit immediately (WTF is fatal) + */ + boolean handleApplicationWtf(IBinder app, String tag, boolean system, + ApplicationErrorReport.ParcelableCrashInfo crashInfo, int immediateCallerPid); + } + /** * Set the object identifying this application/process, for reporting VM * errors. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 89aee78677c65..3fdf541566a55 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -397,6 +397,7 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -9990,6 +9991,30 @@ public class ActivityManagerService extends IActivityManager.Stub return r; } + /** + * Schedule to handle any pending system_server WTFs. + */ + public void schedulePendingSystemServerWtfs( + final LinkedList> list) { + mHandler.post(() -> handlePendingSystemServerWtfs(list)); + } + + /** + * Handle any pending system_server WTFs, add into the dropbox + */ + private void handlePendingSystemServerWtfs( + final LinkedList> list) { + ProcessRecord proc; + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(MY_PID); + } + for (Pair p = list.poll(); + p != null; p = list.poll()) { + addErrorToDropBox("wtf", proc, "system_server", null, null, null, p.first, null, null, + p.second); + } + } + /** * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit}) * @return the corresponding {@link ProcessRecord} object, or null if none could be found diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 8f2522a616731..cf6baf2c12d09 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -21,6 +21,8 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; import static android.os.IServiceManager.DUMP_FLAG_PROTO; +import static android.os.Process.SYSTEM_UID; +import static android.os.Process.myPid; import static android.view.Display.DEFAULT_DISPLAY; import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_TAG; @@ -29,6 +31,7 @@ import android.annotation.NonNull; import android.annotation.StringRes; import android.app.ActivityThread; import android.app.AppCompatCallbacks; +import android.app.ApplicationErrorReport; import android.app.INotificationManager; import android.app.SystemServiceRegistry; import android.app.usage.UsageStatsManagerInternal; @@ -53,6 +56,7 @@ import android.os.Debug; import android.os.Environment; import android.os.FactoryTest; import android.os.FileUtils; +import android.os.IBinder; import android.os.IIncidentManager; import android.os.Looper; import android.os.Message; @@ -67,16 +71,19 @@ import android.os.UserHandle; import android.os.storage.IStorageManager; import android.provider.DeviceConfig; import android.provider.Settings; +import android.server.ServerProtoEnums; import android.sysprop.VoldProperties; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.EventLog; +import android.util.Pair; import android.util.Slog; import android.view.contentcapture.ContentCaptureManager; import com.android.internal.R; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.BinderInternal; +import com.android.internal.os.RuntimeInit; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.EmergencyAffordanceManager; import com.android.internal.util.FrameworkStatsLog; @@ -179,6 +186,7 @@ import com.google.android.startop.iorap.IorapForwardingService; import java.io.File; import java.io.IOException; +import java.util.LinkedList; import java.util.Locale; import java.util.Timer; import java.util.concurrent.CountDownLatch; @@ -351,6 +359,11 @@ public final class SystemServer { private Future mZygotePreload; private Future mBlobStoreServiceStart; + /** + * The pending WTF to be logged into dropbox. + */ + private static LinkedList> sPendingWtfs; + /** * Start the sensor service. This is a blocking call and can take time. */ @@ -562,6 +575,9 @@ public final class SystemServer { t.traceEnd(); // InitBeforeStartServices } + // Setup the default WTF handler + RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf); + // Start services. try { t.traceBegin("StartServices"); @@ -2108,6 +2124,14 @@ public final class SystemServer { } t.traceEnd(); + // Emit any pending system_server WTFs + synchronized (SystemService.class) { + if (sPendingWtfs != null) { + mActivityManagerService.schedulePendingSystemServerWtfs(sPendingWtfs); + sPendingWtfs = null; + } + } + if (safeMode) { mActivityManagerService.showSafeModeOverlay(); } @@ -2497,4 +2521,29 @@ public final class SystemServer { context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted(); } + + /** + * Handle the serious errors during early system boot, used by {@link Log} via + * {@link com.android.internal.os.RuntimeInit}. + */ + private static boolean handleEarlySystemWtf(final IBinder app, final String tag, boolean system, + final ApplicationErrorReport.ParcelableCrashInfo crashInfo, int immediateCallerPid) { + final String processName = "system_server"; + final int myPid = myPid(); + + com.android.server.am.EventLogTags.writeAmWtf(UserHandle.getUserId(SYSTEM_UID), myPid, + processName, -1, tag, crashInfo.exceptionMessage); + + FrameworkStatsLog.write(FrameworkStatsLog.WTF_OCCURRED, SYSTEM_UID, tag, processName, + myPid, ServerProtoEnums.SYSTEM_SERVER); + + synchronized (SystemServer.class) { + if (sPendingWtfs == null) { + sPendingWtfs = new LinkedList<>(); + } + sPendingWtfs.add(new Pair<>(tag, crashInfo)); + } + return false; + } + }