Adding binder tracking support in tests

- Whitelist specific binder calls when handling touch during swipe up
  gestures
- Only track binding for touch handling and certain launcher lifecycle
  changes for now

Bug: 140246642
Change-Id: I6ba30280dd17da358662870f8719ae851536ad8b
This commit is contained in:
Winson Chung
2019-09-06 12:04:27 -07:00
parent 2e71b8351c
commit a879f9c481
9 changed files with 252 additions and 13 deletions

View File

@@ -65,6 +65,10 @@ import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.Surface;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
@@ -75,6 +79,7 @@ import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
@@ -106,10 +111,6 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import androidx.annotation.BinderThread;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
/**
* Wrapper around a list for processing arguments.
*/
@@ -536,6 +537,7 @@ public class TouchInteractionService extends Service implements
}
private void onInputEvent(InputEvent ev) {
DejankBinderTracker.allowBinderTrackingInTests();
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onInputEvent " + ev);
}
@@ -571,6 +573,7 @@ public class TouchInteractionService extends Service implements
TOUCH_INTERACTION_LOG.addLog("onMotionEvent", event.getActionMasked());
mUncheckedConsumer.onMotionEvent(event);
DejankBinderTracker.disallowBinderTrackingInTests();
}
private boolean validSystemUiFlags() {
@@ -634,7 +637,8 @@ public class TouchInteractionService extends Service implements
}
private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
RunningTaskInfo runningTaskInfo = DejankBinderTracker.whitelistIpcs(
() -> mAM.getRunningTask(0));
if (!useSharedState) {
sSwipeSharedState.clearAllState(false /* finishAnimation */);
}
@@ -650,7 +654,8 @@ public class TouchInteractionService extends Service implements
if (isExcludedAssistant(runningTaskInfo)) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
runningTaskInfo = mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT);
runningTaskInfo = DejankBinderTracker.whitelistIpcs(
() -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
final ComponentName homeComponent =
mOverviewComponentObserver.getHomeIntent().getComponent();

View File

@@ -68,6 +68,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -423,9 +424,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private void initializeLauncherAnimationController() {
buildAnimationController();
if (LatencyTrackerCompat.isEnabled(mContext)) {
LatencyTrackerCompat.logToggleRecents((int) (mLauncherFrameDrawnTime - mTouchTimeMs));
}
DejankBinderTracker.whitelistIpcs(() -> {
// Only used in debug builds
if (LatencyTrackerCompat.isEnabled(mContext)) {
LatencyTrackerCompat.logToggleRecents(
(int) (mLauncherFrameDrawnTime - mTouchTimeMs));
}
});
// 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

View File

@@ -45,6 +45,7 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.appprediction.PredictionUiStateManager;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.views.ScrimView;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.ClipAnimationHelper;
@@ -172,7 +173,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
@Override
public boolean shouldUseMultiWindowTaskSizeStrategy() {
return mActivity.isInMultiWindowMode();
return DejankBinderTracker.whitelistIpcs(() -> mActivity.isInMultiWindowMode());
}
@Override

View File

@@ -0,0 +1,159 @@
/**
* 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();
}
}

View File

@@ -36,6 +36,7 @@ import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.uioverrides.DisplayRotationListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.util.PackageManagerHelper;
@@ -65,7 +66,8 @@ public abstract class BaseDraggingActivity extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIsSafeModeEnabled = getPackageManager().isSafeMode();
mIsSafeModeEnabled = DejankBinderTracker.whitelistIpcs(() ->
getPackageManager().isSafeMode());
mRotationListener = new DisplayRotationListener(this, this::onDeviceRotationChanged);
// Update theme

View File

@@ -116,6 +116,7 @@ import com.android.launcher3.qsb.QsbContainerView;
import com.android.launcher3.states.InternalStateHandler;
import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -309,6 +310,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
protected void onCreate(Bundle savedInstanceState) {
DejankBinderTracker.allowBinderTrackingInTests();
RaceConditionTracker.onEvent(ON_CREATE_EVT, ENTER);
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
@@ -430,6 +432,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
}
});
DejankBinderTracker.disallowBinderTrackingInTests();
}
protected LauncherOverlayManager getDefaultOverlay() {
@@ -941,6 +944,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
protected void onStart() {
DejankBinderTracker.allowBinderTrackingInTests();
RaceConditionTracker.onEvent(ON_START_EVT, ENTER);
super.onStart();
if (!mDeferOverlayCallbacks) {
@@ -949,6 +953,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
mAppWidgetHost.setListenIfResumed(true);
RaceConditionTracker.onEvent(ON_START_EVT, EXIT);
DejankBinderTracker.disallowBinderTrackingInTests();
}
private void handleDeferredResume() {
@@ -1043,6 +1048,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
protected void onResume() {
DejankBinderTracker.allowBinderTrackingInTests();
RaceConditionTracker.onEvent(ON_RESUME_EVT, ENTER);
TraceHelper.beginSection("ON_RESUME");
super.onResume();
@@ -1068,6 +1074,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
TraceHelper.endSection("ON_RESUME");
RaceConditionTracker.onEvent(ON_RESUME_EVT, EXIT);
DejankBinderTracker.disallowBinderTrackingInTests();
}
@Override

View File

@@ -22,6 +22,7 @@ import android.os.Looper;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.uioverrides.DejankBinderTracker;
import com.android.launcher3.util.ResourceBasedOverride.Overrides;
import java.util.concurrent.ExecutionException;
@@ -41,7 +42,8 @@ public class MainThreadInitializedObject<T> {
public T get(Context context) {
if (mValue == null) {
if (Looper.myLooper() == Looper.getMainLooper()) {
mValue = mProvider.get(context.getApplicationContext());
mValue = DejankBinderTracker.whitelistIpcs(() ->
mProvider.get(context.getApplicationContext()));
} else {
try {
return MAIN_EXECUTOR.submit(() -> get(context)).get();

View File

@@ -0,0 +1,57 @@
/**
* 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 android.os.IBinder;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
/**
* A binder proxy transaction listener for tracking non-whitelisted binder calls.
*/
public class DejankBinderTracker {
public static void whitelistIpcs(Runnable runnable) {}
public static <T> T whitelistIpcs(Supplier<T> supplier) {
return null;
}
public static void allowBinderTrackingInTests() {}
public static void disallowBinderTrackingInTests() {}
public DejankBinderTracker(BiConsumer<String, Integer> unexpectedTransactionCallback) { }
public void startTracking() {}
public void stopTracking() {}
public Object onTransactStarted(IBinder binder, int transactionCode, int flags) {
return null;
}
public Object onTransactStarted(IBinder binder, int transactionCode) {
return null;
}
public void onTransactEnded(Object session) {}
public static boolean isMainThread() {
return true;
}
}

View File

@@ -30,13 +30,14 @@ else
LOCAL_STATIC_JAVA_LIBRARIES += SystemUISharedLib
LOCAL_SRC_FILES := $(call all-java-files-under, tapl) \
../quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java \
../src/com/android/launcher3/ResourceUtils.java \
../src/com/android/launcher3/util/SecureSettingsObserver.java \
../src/com/android/launcher3/testing/TestProtocol.java
endif
LOCAL_MODULE := ub-launcher-aosp-tapl
LOCAL_SDK_VERSION := current
LOCAL_SDK_VERSION := system_current
include $(BUILD_STATIC_JAVA_LIBRARY)