Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58e07cf5 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Write "wait" status to both logcat and stdout." into udc-dev

parents 94dfcbc2 3c5d178e
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.util;

import android.annotation.NonNull;

import java.io.IOException;
import java.io.Writer;
import java.util.Objects;

/**
 * Writer that offers to "tee" identical output to multiple underlying
 * {@link Writer} instances.
 *
 * @see https://man7.org/linux/man-pages/man1/tee.1.html
 * @hide
 */
public class TeeWriter extends Writer {
    private final @NonNull Writer[] mWriters;

    public TeeWriter(@NonNull Writer... writers) {
        for (Writer writer : writers) {
            Objects.requireNonNull(writer);
        }
        mWriters = writers;
    }

    @Override
    public void write(char[] cbuf, int off, int len) throws IOException {
        for (Writer writer : mWriters) {
            writer.write(cbuf, off, len);
        }
    }

    @Override
    public void flush() throws IOException {
        for (Writer writer : mWriters) {
            writer.flush();
        }
    }

    @Override
    public void close() throws IOException {
        for (Writer writer : mWriters) {
            writer.close();
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@

package com.android.server.am;

import android.util.Log;
import android.util.LogWriter;

import java.io.PrintWriter;

/**
 * Common class for the various debug {@link android.util.Log} output configuration in the activity
 * manager package.
@@ -38,6 +43,10 @@ class ActivityManagerDebugConfig {
    // Default log tag for the activity manager package.
    static final String TAG_AM = "ActivityManager";

    // Default writer that emits "info" log events for the activity manager package.
    static final PrintWriter LOG_WRITER_INFO = new PrintWriter(
            new LogWriter(Log.INFO, TAG_AM));

    // Enable all debug log categories.
    static final boolean DEBUG_ALL = false;

+11 −13
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.LOG_WRITER_INFO;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
@@ -18723,27 +18724,25 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public void waitForBroadcastIdle() {
        waitForBroadcastIdle(/* printWriter= */ null);
        waitForBroadcastIdle(LOG_WRITER_INFO);
    }
    public void waitForBroadcastIdle(@Nullable PrintWriter pw) {
    public void waitForBroadcastIdle(@NonNull PrintWriter pw) {
        enforceCallingPermission(permission.DUMP, "waitForBroadcastIdle()");
        BroadcastLoopers.waitForIdle(pw);
        for (BroadcastQueue queue : mBroadcastQueues) {
            queue.waitForIdle(pw);
        }
        if (pw != null) {
        pw.println("All broadcast queues are idle!");
        pw.flush();
    }
    }
    @Override
    public void waitForBroadcastBarrier() {
        waitForBroadcastBarrier(/* printWriter= */ null, false, false);
        waitForBroadcastBarrier(LOG_WRITER_INFO, false, false);
    }
    public void waitForBroadcastBarrier(@Nullable PrintWriter pw,
    public void waitForBroadcastBarrier(@NonNull PrintWriter pw,
            boolean flushBroadcastLoopers, boolean flushApplicationThreads) {
        enforceCallingPermission(permission.DUMP, "waitForBroadcastBarrier()");
        if (flushBroadcastLoopers) {
@@ -18761,11 +18760,7 @@ public class ActivityManagerService extends IActivityManager.Stub
     * Wait for all pending {@link IApplicationThread} events to be processed in
     * all currently running apps.
     */
    public void waitForApplicationBarrier(@Nullable PrintWriter pw) {
        if (pw == null) {
            pw = new PrintWriter(new LogWriter(Log.VERBOSE, TAG));
        }
    public void waitForApplicationBarrier(@NonNull PrintWriter pw) {
        final CountDownLatch finishedLatch = new CountDownLatch(1);
        final AtomicInteger pingCount = new AtomicInteger(0);
        final AtomicInteger pongCount = new AtomicInteger(0);
@@ -18815,15 +18810,18 @@ public class ActivityManagerService extends IActivityManager.Stub
            try {
                if (finishedLatch.await(1, TimeUnit.SECONDS)) {
                    pw.println("Finished application barriers!");
                    pw.flush();
                    return;
                } else {
                    pw.println("Waiting for application barriers, at " + pongCount.get() + " of "
                            + pingCount.get() + "...");
                    pw.flush();
                }
            } catch (InterruptedException ignored) {
            }
        }
        pw.println("Gave up waiting for application barriers!");
        pw.flush();
    }
    void setIgnoreDeliveryGroupPolicy(@NonNull String broadcastAction) {
+5 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRI
import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE;
import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL;
import static com.android.server.am.ActivityManagerDebugConfig.LOG_WRITER_INFO;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_COUNT;
@@ -112,6 +113,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.DisplayMetrics;
import android.util.TeeWriter;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.window.SplashScreen;
@@ -3364,11 +3366,13 @@ final class ActivityManagerShellCommand extends ShellCommand {
    }

    int runWaitForBroadcastIdle(PrintWriter pw) throws RemoteException {
        pw = new PrintWriter(new TeeWriter(LOG_WRITER_INFO, pw));
        mInternal.waitForBroadcastIdle(pw);
        return 0;
    }

    int runWaitForBroadcastBarrier(PrintWriter pw) throws RemoteException {
        pw = new PrintWriter(new TeeWriter(LOG_WRITER_INFO, pw));
        boolean flushBroadcastLoopers = false;
        boolean flushApplicationThreads = false;
        String opt;
@@ -3387,6 +3391,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
    }

    int runWaitForApplicationBarrier(PrintWriter pw) throws RemoteException {
        pw = new PrintWriter(new TeeWriter(LOG_WRITER_INFO, pw));
        mInternal.waitForApplicationBarrier(pw);
        return 0;
    }
+7 −14
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.server.am;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -74,7 +73,7 @@ public class BroadcastLoopers {
     * defined by {@link MessageQueue#isIdle()}. Note that {@link Message#when}
     * still in the future are ignored for the purposes of the idle test.
     */
    public static void waitForIdle(@Nullable PrintWriter pw) {
    public static void waitForIdle(@NonNull PrintWriter pw) {
        waitForCondition(pw, (looper, latch) -> {
            final MessageQueue queue = looper.getQueue();
            queue.addIdleHandler(() -> {
@@ -89,7 +88,7 @@ public class BroadcastLoopers {
     * Note that {@link Message#when} still in the future are ignored for the purposes
     * of the idle test.
     */
    public static void waitForBarrier(@Nullable PrintWriter pw) {
    public static void waitForBarrier(@NonNull PrintWriter pw) {
        waitForCondition(pw, (looper, latch) -> {
            (new Handler(looper)).post(() -> {
                latch.countDown();
@@ -100,7 +99,7 @@ public class BroadcastLoopers {
    /**
     * Wait for all registered {@link Looper} instances to meet a certain condition.
     */
    private static void waitForCondition(@Nullable PrintWriter pw,
    private static void waitForCondition(@NonNull PrintWriter pw,
            @NonNull BiConsumer<Looper, CountDownLatch> condition) {
        final CountDownLatch latch;
        synchronized (sLoopers) {
@@ -122,18 +121,12 @@ public class BroadcastLoopers {
            final long now = SystemClock.uptimeMillis();
            if (now >= lastPrint + 1000) {
                lastPrint = now;
                logv("Waiting for " + latch.getCount() + " loopers to drain...", pw);
                pw.println("Waiting for " + latch.getCount() + " loopers to drain...");
                pw.flush();
            }
            SystemClock.sleep(100);
        }
        logv("Loopers drained!", pw);
    }

    private static void logv(@NonNull String msg, @Nullable PrintWriter pw) {
        Slog.v(TAG, msg);
        if (pw != null) {
            pw.println(msg);
        pw.println("Loopers drained!");
        pw.flush();
    }
}
}
Loading