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

Commit ee846feb authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Android (Google) Code Review
Browse files

Revert "Adding main thread binder tracing in development build."

Revert submission 23482347-launcher-binder-tracing

Reason for revert: Broken Build 10242119 on git_master on errorprone b/285434612

Reverted changes: /q/submissionid:23482347-launcher-binder-tracing

Change-Id: Id9726474265e839a59d6eb34822e7a86d40f0fc9
parent 3db98b11
Loading
Loading
Loading
Loading
+159 −0
Original line number Diff line number Diff line
/**
 * Copyright (C) 2019 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 com.android.launcher3.uioverrides;

import static android.os.IBinder.FLAG_ONEWAY;

import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.MainThread;

import java.util.HashSet;
import java.util.Locale;
import java.util.function.BiConsumer;
import java.util.function.Supplier;

/**
 * A binder proxy transaction listener for tracking non-whitelisted binder calls.
 */
public class DejankBinderTracker implements Binder.ProxyTransactListener {
    private static final String TAG = "DejankBinderTracker";

    private static final Object sLock = new Object();
    private static final HashSet<String> sWhitelistedFrameworkClasses = new HashSet<>();
    static {
        // Common IPCs that are ok to block the main thread.
        sWhitelistedFrameworkClasses.add("android.view.IWindowSession");
        sWhitelistedFrameworkClasses.add("android.os.IPowerManager");
    }
    private static boolean sTemporarilyIgnoreTracking = false;

    // Used by the client to limit binder tracking to specific regions
    private static boolean sTrackingAllowed = false;

    private BiConsumer<String, Integer> mUnexpectedTransactionCallback;
    private boolean mIsTracking = false;

    /**
     * Temporarily ignore blocking binder calls for the duration of this {@link Runnable}.
     */
    @MainThread
    public static void whitelistIpcs(Runnable runnable) {
        sTemporarilyIgnoreTracking = true;
        runnable.run();
        sTemporarilyIgnoreTracking = false;
    }

    /**
     * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}.
     */
    @MainThread
    public static <T> T whitelistIpcs(Supplier<T> supplier) {
        sTemporarilyIgnoreTracking = true;
        T value = supplier.get();
        sTemporarilyIgnoreTracking = false;
        return value;
    }

    /**
     * Enables binder tracking during a test.
     */
    @MainThread
    public static void allowBinderTrackingInTests() {
        sTrackingAllowed = true;
    }

    /**
     * Disables binder tracking during a test.
     */
    @MainThread
    public static void disallowBinderTrackingInTests() {
        sTrackingAllowed = false;
    }

    public DejankBinderTracker(BiConsumer<String, Integer> unexpectedTransactionCallback) {
        mUnexpectedTransactionCallback = unexpectedTransactionCallback;
    }

    @MainThread
    public void startTracking() {
        if (!Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
                && !Build.TYPE.toLowerCase(Locale.ROOT).equals("eng")) {
            Log.wtf(TAG, "Unexpected use of binder tracker in non-debug build", new Exception());
            return;
        }
        if (mIsTracking) {
            return;
        }
        mIsTracking = true;
        Binder.setProxyTransactListener(this);
    }

    @MainThread
    public void stopTracking() {
        if (!mIsTracking) {
            return;
        }
        mIsTracking = false;
        Binder.setProxyTransactListener(null);
    }

    // Override the hidden Binder#onTransactStarted method
    public synchronized Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
        if (!mIsTracking
                || !sTrackingAllowed
                || sTemporarilyIgnoreTracking
                || (flags & FLAG_ONEWAY) == FLAG_ONEWAY
                || !isMainThread()) {
            return null;
        }

        String descriptor;
        try {
            descriptor = binder.getInterfaceDescriptor();
            if (sWhitelistedFrameworkClasses.contains(descriptor)) {
                return null;
            }
        } catch (RemoteException e) {
            e.printStackTrace();
            descriptor = binder.getClass().getSimpleName();
        }

        mUnexpectedTransactionCallback.accept(descriptor, transactionCode);
        return null;
    }

    @Override
    public Object onTransactStarted(IBinder binder, int transactionCode) {
        // Do nothing
        return null;
    }

    @Override
    public void onTransactEnded(Object session) {
        // Do nothing
    }

    public static boolean isMainThread() {
        return Thread.currentThread() == Looper.getMainLooper().getThread();
    }
}
+10 −9
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ import com.android.launcher3.tracing.SwipeHandlerProto;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.WindowBounds;
@@ -588,7 +587,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
        if (mWasLauncherAlreadyVisible) {
            mStateCallback.setState(STATE_LAUNCHER_DRAWN);
        } else {
            SafeCloseable traceToken = TraceHelper.INSTANCE.beginAsyncSection("WTS-init");
            Object traceToken = TraceHelper.INSTANCE.beginSection("WTS-init");
            View dragLayer = activity.getDragLayer();
            dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
                boolean mHandled = false;
@@ -600,7 +599,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
                    }
                    mHandled = true;

                    traceToken.close();
                    TraceHelper.INSTANCE.endSection(traceToken);
                    dragLayer.post(() ->
                            dragLayer.getViewTreeObserver().removeOnDrawListener(this));
                    if (activity != mActivity) {
@@ -682,10 +681,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
    private void initializeLauncherAnimationController() {
        buildAnimationController();

        try (SafeCloseable c = TraceHelper.INSTANCE.allowIpcs("logToggleRecents")) {
        Object traceToken = TraceHelper.INSTANCE.beginSection("logToggleRecents",
                TraceHelper.FLAG_IGNORE_BINDERS);
        LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
                (int) (mLauncherFrameDrawnTime - mTouchTimeMs));
        }
        TraceHelper.INSTANCE.endSection(traceToken);

        // This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
        // high-res thumbnail loader here once we are sure that we will end up in an overview state
@@ -2039,9 +2039,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,

    private void setScreenshotCapturedState() {
        // If we haven't posted a draw callback, set the state immediately.
        TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT);
        Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT,
                TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS);
        mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
        TraceHelper.INSTANCE.endSection();
        TraceHelper.INSTANCE.endSection(traceToken);
    }

    private void finishCurrentTransitionToRecents() {
+0 −187
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 com.android.quickstep;

import static android.os.IBinder.FLAG_ONEWAY;

import android.os.Binder;
import android.os.Binder.ProxyTransactListener;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Log;

import androidx.annotation.Nullable;

import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.TraceHelper;

import java.util.LinkedList;
import java.util.Set;
import java.util.function.Consumer;

import kotlin.random.Random;

/**
 * A binder proxy transaction listener for tracking binder calls on main thread.
 */
public class BinderTracker {

    private static final String TAG = "BinderTracker";

    // Common IPCs that are ok to block the main thread.
    private static final Set<String> sAllowedFrameworkClasses = Set.of(
            "android.view.IWindowSession",
            "android.os.IPowerManager",
            "android.os.IServiceManager");

    /**
     * Starts tracking binder class and returns a {@link SafeCloseable} to end tracking
     */
    public static SafeCloseable startTracking(Consumer<BinderCallSite> callback) {
        TraceHelper current = TraceHelper.INSTANCE;

        TraceHelperExtension helper = new TraceHelperExtension(callback);
        TraceHelper.INSTANCE = helper;
        Binder.setProxyTransactListener(helper);

        return () -> {
            Binder.setProxyTransactListener(null);
            TraceHelper.INSTANCE = current;
        };
    }

    private static final LinkedList<String> mMainThreadTraceStack = new LinkedList<>();
    private static final LinkedList<String> mMainThreadIgnoreIpcStack = new LinkedList<>();

    private static class TraceHelperExtension extends TraceHelper implements ProxyTransactListener {

        private final Consumer<BinderCallSite> mUnexpectedTransactionCallback;

        TraceHelperExtension(Consumer<BinderCallSite> unexpectedTransactionCallback) {
            mUnexpectedTransactionCallback = unexpectedTransactionCallback;
        }

        @Override
        public void beginSection(String sectionName) {
            if (isMainThread()) {
                mMainThreadTraceStack.add(sectionName);
            }
            super.beginSection(sectionName);
        }

        @Override
        public SafeCloseable beginAsyncSection(String sectionName) {
            if (!isMainThread()) {
                return super.beginAsyncSection(sectionName);
            }

            mMainThreadTraceStack.add(sectionName);
            int cookie = Random.Default.nextInt();
            Trace.beginAsyncSection(sectionName, cookie);
            return () -> {
                Trace.endAsyncSection(sectionName, cookie);
                mMainThreadTraceStack.remove(sectionName);
            };
        }

        @Override
        public void endSection() {
            super.endSection();
            if (isMainThread()) {
                mMainThreadTraceStack.pollLast();
            }
        }

        @Override
        public SafeCloseable allowIpcs(String rpcName) {
            if (!isMainThread()) {
                return super.allowIpcs(rpcName);
            }

            mMainThreadTraceStack.add(rpcName);
            mMainThreadIgnoreIpcStack.add(rpcName);
            int cookie = Random.Default.nextInt();
            Trace.beginAsyncSection(rpcName, cookie);
            return () -> {
                Trace.endAsyncSection(rpcName, cookie);
                mMainThreadTraceStack.remove(rpcName);
                mMainThreadIgnoreIpcStack.remove(rpcName);
            };
        }

        @Override
        public Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
            if (!isMainThread() || (flags & FLAG_ONEWAY) == FLAG_ONEWAY) {
                return null;
            }

            String ipcBypass = mMainThreadIgnoreIpcStack.peekLast();
            String descriptor;
            try {
                descriptor = binder.getInterfaceDescriptor();
                if (sAllowedFrameworkClasses.contains(descriptor)) {
                    return null;
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Error getting IPC descriptor", e);
                descriptor = binder.getClass().getSimpleName();
            }

            if (ipcBypass == null) {
                mUnexpectedTransactionCallback.accept(new BinderCallSite(
                        mMainThreadTraceStack.peekLast(), descriptor, transactionCode));
            } else {
                Log.d(TAG, "MainThread-IPC " + descriptor + " ignored due to " + ipcBypass);
            }
            return null;
        }

        @Override
        public Object onTransactStarted(IBinder binder, int transactionCode) {
            // Do nothing
            return null;
        }

        @Override
        public void onTransactEnded(Object session) {
            // Do nothing
        }
    }

    private static boolean isMainThread() {
        return Thread.currentThread() == Looper.getMainLooper().getThread();
    }

    /**
     * Information about a binder call
     */
    public static class BinderCallSite {

        @Nullable
        public final String activeTrace;
        public final String descriptor;
        public final int transactionCode;

        BinderCallSite(String activeTrace, String descriptor, int transactionCode) {
            this.activeTrace = activeTrace;
            this.descriptor = descriptor;
            this.transactionCode = transactionCode;
        }
    }
}
+0 −13
Original line number Diff line number Diff line
@@ -16,13 +16,10 @@

package com.android.quickstep;

import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.util.Log;

import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.InstantAppResolver;
@@ -52,14 +49,4 @@ public class InstantAppResolverImpl extends InstantAppResolver {
        ComponentName cn = info.getTargetComponent();
        return cn != null && cn.getClassName().equals(COMPONENT_CLASS_MARKER);
    }

    @Override
    public boolean isInstantApp(String packageName, int userId) {
        try {
            return ActivityThread.getPackageManager().isInstantApp(packageName, userId);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to determine whether package is instant app " + packageName, e);
            return false;
        }
    }
}
+0 −5
Original line number Diff line number Diff line
@@ -60,10 +60,5 @@ public class QuickstepProcessInitializer extends MainProcessInitializer {
        // Elevate GPU priority for Quickstep and Remote animations.
        ThreadedRenderer.setContextPriority(
                ThreadedRenderer.EGL_CONTEXT_PRIORITY_HIGH_IMG);

        if (BuildConfig.IS_STUDIO_BUILD) {
            BinderTracker.startTracking(call ->  Log.e("BinderCall",
                    call.descriptor + " called on mainthread under " + call.activeTrace));
        }
    }
}
Loading