Loading quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +1 −1 Original line number Diff line number Diff line Loading @@ -164,7 +164,7 @@ public abstract class RecentsUiFactory { } } if (FeatureFlags.PULL_DOWN_STATUS_BAR && Utilities.IS_DEBUG_DEVICE if (FeatureFlags.PULL_DOWN_STATUS_BAR && !launcher.getDeviceProfile().isMultiWindowMode && !launcher.getDeviceProfile().isVerticalBarLayout()) { list.add(new StatusBarTouchController(launcher)); Loading quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +57 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.RectF; import android.graphics.Region; Loading Loading @@ -74,6 +76,8 @@ import com.android.launcher3.Utilities; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.logging.EventLogArray; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.UiThreadHelper; import com.android.quickstep.SysUINavigationMode.Mode; Loading @@ -91,6 +95,7 @@ import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.BackgroundExecutor; import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputMonitorCompat; Loading Loading @@ -152,6 +157,7 @@ public class TouchInteractionService extends Service implements .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY)); MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor); MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet); MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */)); } @Override Loading Loading @@ -502,6 +508,9 @@ public class TouchInteractionService extends Service implements } private void onInputEvent(InputEvent ev) { if (TestProtocol.sDebugTracing) { Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onInputEvent " + ev); } if (!(ev instanceof MotionEvent)) { Log.e(TAG, "Unknown event " + ev); return; Loading Loading @@ -684,6 +693,54 @@ public class TouchInteractionService extends Service implements } } private void preloadOverview(boolean fromInit) { if (!mIsUserUnlocked) { return; } final ActivityControlHelper<BaseDraggingActivity> activityControl = mOverviewComponentObserver.getActivityControlHelper(); if (activityControl.getCreatedActivity() == null) { // Make sure that UI states will be initialized. activityControl.createActivityInitListener((activity, wasVisible) -> { AppLaunchTracker.INSTANCE.get(activity); return false; }).register(); } else if (fromInit) { // The activity has been created before the initialization of overview service. It is // usually happens when booting or launcher is the top activity, so we should already // have the latest state. return; } // Pass null animation handler to indicate this start is preload. BackgroundExecutor.get().submit( () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null /* assistDataReceiver */, null /* animationHandler */, null /* resultCallback */, null /* resultCallbackHandler */)); } @Override public void onConfigurationChanged(Configuration newConfig) { if (!mIsUserUnlocked) { return; } final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); final BaseDraggingActivity activity = activityControl.getCreatedActivity(); if (activity == null || activity.isStarted()) { // We only care about the existing background activity. return; } if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(), activity.getResources().getConfiguration().diff(newConfig))) { return; } preloadOverview(false /* fromInit */); } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) { if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) { Loading quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; Loading @@ -26,6 +27,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.OverviewCallbacks; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading Loading @@ -80,6 +82,9 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity> @Override public void onMotionEvent(MotionEvent ev) { if (TestProtocol.sDebugTracing) { Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onMotionEvent " + ev); } if (!mProxyTouch) { return; } Loading quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java +51 −17 Original line number Diff line number Diff line Loading @@ -17,17 +17,22 @@ package com.android.launcher3.uioverrides.touchcontrollers; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_CANCEL; import android.graphics.PointF; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.Window; import android.view.WindowManager; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.touch.TouchEventTranslator; import com.android.launcher3.util.TouchController; import com.android.quickstep.RecentsModel; import com.android.systemui.shared.recents.ISystemUiProxy; Loading @@ -36,18 +41,29 @@ import java.io.PrintWriter; /** * TouchController for handling touch events that get sent to the StatusBar. Once the * Once the event delta y passes the touch slop, the events start getting forwarded. * Once the event delta mDownY passes the touch slop, the events start getting forwarded. * All events are offset by initial Y value of the pointer. */ public class StatusBarTouchController implements TouchController { private static final String TAG = "StatusBarController"; /** * Window flag: Enable touches to slide out of a window into neighboring * windows in mid-gesture instead of being captured for the duration of * the gesture. * * This flag changes the behavior of touch focus for this window only. * Touches can slide out of the window but they cannot necessarily slide * back in (unless the other window with touch focus permits it). */ private static final int FLAG_SLIPPERY = 0x20000000; protected final Launcher mLauncher; protected final TouchEventTranslator mTranslator; private final float mTouchSlop; private ISystemUiProxy mSysUiProxy; private int mLastAction; private final SparseArray<PointF> mDownEvents; /* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/ private boolean mCanIntercept; Loading @@ -56,7 +72,7 @@ public class StatusBarTouchController implements TouchController { mLauncher = l; // Guard against TAPs by increasing the touch slop. mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop(); mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev)); mDownEvents = new SparseArray<>(); } @Override Loading @@ -64,7 +80,6 @@ public class StatusBarTouchController implements TouchController { writer.println(prefix + "mCanIntercept:" + mCanIntercept); writer.println(prefix + "mLastAction:" + MotionEvent.actionToString(mLastAction)); writer.println(prefix + "mSysUiProxy available:" + (mSysUiProxy != null)); } private void dispatchTouchEvent(MotionEvent ev) { Loading @@ -81,26 +96,31 @@ public class StatusBarTouchController implements TouchController { @Override public final boolean onControllerInterceptTouchEvent(MotionEvent ev) { int action = ev.getActionMasked(); int idx = ev.getActionIndex(); int pid = ev.getPointerId(idx); if (action == ACTION_DOWN) { mCanIntercept = canInterceptTouch(ev); if (!mCanIntercept) { return false; } mTranslator.reset(); mTranslator.setDownParameters(0, ev); mDownEvents.put(pid, new PointF(ev.getX(), ev.getY())); } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { // Check!! should only set it only when threshold is not entered. mTranslator.setDownParameters(ev.getActionIndex(), ev); mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx))); } if (!mCanIntercept) { return false; } if (action == ACTION_MOVE) { float dy = ev.getY() - mTranslator.getDownY(); float dx = ev.getX() - mTranslator.getDownX(); if (dy > mTouchSlop && dy > Math.abs(dx)) { mTranslator.dispatchDownEvents(ev); mTranslator.processMotionEvent(ev); float dy = ev.getY(idx) - mDownEvents.get(pid).y; float dx = ev.getX(idx) - mDownEvents.get(pid).x; // Currently input dispatcher will not do touch transfer if there are more than // one touch pointer. Hence, even if slope passed, only set the slippery flag // when there is single touch event. (context: InputDispatcher.cpp line 1445) if (dy > mTouchSlop && dy > Math.abs(dx) && ev.getPointerCount() == 1) { ev.setAction(ACTION_DOWN); dispatchTouchEvent(ev); setWindowSlippery(true); return true; } if (Math.abs(dx) > mTouchSlop) { Loading @@ -110,12 +130,26 @@ public class StatusBarTouchController implements TouchController { return false; } @Override public final boolean onControllerTouchEvent(MotionEvent ev) { mTranslator.processMotionEvent(ev); if (ev.getAction() == ACTION_UP || ev.getAction() == ACTION_CANCEL) { dispatchTouchEvent(ev); setWindowSlippery(false); return true; } return true; } private void setWindowSlippery(boolean enable) { Window w = mLauncher.getWindow(); WindowManager.LayoutParams wlp = w.getAttributes(); if (enable) { wlp.flags |= FLAG_SLIPPERY; } else { wlp.flags &= ~FLAG_SLIPPERY; } w.setAttributes(wlp); } private boolean canInterceptTouch(MotionEvent ev) { if (!mLauncher.isInState(LauncherState.NORMAL) || Loading quickstep/src/com/android/quickstep/OverviewComponentObserver.java +63 −28 Original line number Diff line number Diff line Loading @@ -29,11 +29,15 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.util.SparseIntArray; import com.android.systemui.shared.system.PackageManagerWrapper; import java.util.ArrayList; import java.util.Objects; /** * Class to keep track of the current overview component based off user preferences and app updates Loading @@ -53,22 +57,41 @@ public final class OverviewComponentObserver { } }; private final Context mContext; private final ComponentName mMyHomeComponent; private final Intent mCurrentHomeIntent; private final Intent mMyHomeIntent; private final Intent mFallbackIntent; private final SparseIntArray mConfigChangesMap = new SparseIntArray(); private String mUpdateRegisteredPackage; private ActivityControlHelper mActivityControlHelper; private Intent mOverviewIntent; private Intent mHomeIntent; private int mSystemUiStateFlags; private boolean mIsHomeAndOverviewSame; private boolean mIsDefaultHome; public OverviewComponentObserver(Context context) { mContext = context; Intent myHomeIntent = new Intent(Intent.ACTION_MAIN) mCurrentHomeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) .setPackage(mContext.getPackageName()); ResolveInfo info = context.getPackageManager().resolveActivity(myHomeIntent, 0); mMyHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name); .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName()); ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0); ComponentName myHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name); mMyHomeIntent.setComponent(myHomeComponent); mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges); ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class); mFallbackIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_DEFAULT) .setComponent(fallbackComponent) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { ActivityInfo fallbackInfo = context.getPackageManager().getActivityInfo( mFallbackIntent.getComponent(), 0 /* flags */); mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges); } catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ } mContext.registerReceiver(mUserPreferenceChangeReceiver, new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED)); Loading @@ -92,17 +115,14 @@ public final class OverviewComponentObserver { ComponentName defaultHome = PackageManagerWrapper.getInstance() .getHomeActivities(new ArrayList<>()); final String overviewIntentCategory; ComponentName overviewComponent; mHomeIntent = null; if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 && (defaultHome == null || mMyHomeComponent.equals(defaultHome))) { mIsDefaultHome = Objects.equals(mMyHomeIntent.getComponent(), defaultHome); if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 && (defaultHome == null || mIsDefaultHome)) { // User default home is same as out home app. Use Overview integrated in Launcher. overviewComponent = mMyHomeComponent; mActivityControlHelper = new LauncherActivityControllerHelper(); mIsHomeAndOverviewSame = true; overviewIntentCategory = Intent.CATEGORY_HOME; mOverviewIntent = mMyHomeIntent; mCurrentHomeIntent.setComponent(mMyHomeIntent.getComponent()); if (mUpdateRegisteredPackage != null) { // Remove any update listener as we don't care about other packages. Loading @@ -111,14 +131,11 @@ public final class OverviewComponentObserver { } } else { // The default home app is a different launcher. Use the fallback Overview instead. overviewComponent = new ComponentName(mContext, RecentsActivity.class); mActivityControlHelper = new FallbackActivityControllerHelper(); mIsHomeAndOverviewSame = false; overviewIntentCategory = Intent.CATEGORY_DEFAULT; mOverviewIntent = mFallbackIntent; mCurrentHomeIntent.setComponent(defaultHome); mHomeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) .setComponent(defaultHome); // User's default home app can change as a result of package updates of this app (such // as uninstalling the app or removing the "Launcher" feature in an update). // Listen for package updates of this app (and remove any previously attached Loading @@ -138,14 +155,6 @@ public final class OverviewComponentObserver { ACTION_PACKAGE_REMOVED)); } } mOverviewIntent = new Intent(Intent.ACTION_MAIN) .addCategory(overviewIntentCategory) .setComponent(overviewComponent) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (mHomeIntent == null) { mHomeIntent = mOverviewIntent; } } /** Loading @@ -160,6 +169,32 @@ public final class OverviewComponentObserver { } } /** * @return {@code true} if the overview component is able to handle the configuration changes. */ boolean canHandleConfigChanges(ComponentName component, int changes) { final int orientationChange = ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_SCREEN_SIZE; if ((changes & orientationChange) == orientationChange) { // This is just an approximate guess for simple orientation change because the changes // may contain non-public bits (e.g. window configuration). return true; } int configMask = mConfigChangesMap.get(component.hashCode()); return configMask != 0 && (~configMask & changes) == 0; } /** * Get the intent for overview activity. It is used when lockscreen is shown and home was died * in background, we still want to restart the one that will be used after unlock. * * @return the overview intent */ Intent getOverviewIntentIgnoreSysUiState() { return mIsDefaultHome ? mMyHomeIntent : mOverviewIntent; } /** * Get the current intent for going to the overview activity. * Loading @@ -173,7 +208,7 @@ public final class OverviewComponentObserver { * Get the current intent for going to the home activity. */ public Intent getHomeIntent() { return mHomeIntent; return mCurrentHomeIntent; } /** Loading Loading
quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +1 −1 Original line number Diff line number Diff line Loading @@ -164,7 +164,7 @@ public abstract class RecentsUiFactory { } } if (FeatureFlags.PULL_DOWN_STATUS_BAR && Utilities.IS_DEBUG_DEVICE if (FeatureFlags.PULL_DOWN_STATUS_BAR && !launcher.getDeviceProfile().isMultiWindowMode && !launcher.getDeviceProfile().isVerticalBarLayout()) { list.add(new StatusBarTouchController(launcher)); Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +57 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.RectF; import android.graphics.Region; Loading Loading @@ -74,6 +76,8 @@ import com.android.launcher3.Utilities; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.logging.EventLogArray; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.UiThreadHelper; import com.android.quickstep.SysUINavigationMode.Mode; Loading @@ -91,6 +95,7 @@ import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.BackgroundExecutor; import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputMonitorCompat; Loading Loading @@ -152,6 +157,7 @@ public class TouchInteractionService extends Service implements .asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY)); MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor); MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet); MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */)); } @Override Loading Loading @@ -502,6 +508,9 @@ public class TouchInteractionService extends Service implements } private void onInputEvent(InputEvent ev) { if (TestProtocol.sDebugTracing) { Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onInputEvent " + ev); } if (!(ev instanceof MotionEvent)) { Log.e(TAG, "Unknown event " + ev); return; Loading Loading @@ -684,6 +693,54 @@ public class TouchInteractionService extends Service implements } } private void preloadOverview(boolean fromInit) { if (!mIsUserUnlocked) { return; } final ActivityControlHelper<BaseDraggingActivity> activityControl = mOverviewComponentObserver.getActivityControlHelper(); if (activityControl.getCreatedActivity() == null) { // Make sure that UI states will be initialized. activityControl.createActivityInitListener((activity, wasVisible) -> { AppLaunchTracker.INSTANCE.get(activity); return false; }).register(); } else if (fromInit) { // The activity has been created before the initialization of overview service. It is // usually happens when booting or launcher is the top activity, so we should already // have the latest state. return; } // Pass null animation handler to indicate this start is preload. BackgroundExecutor.get().submit( () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(), null /* assistDataReceiver */, null /* animationHandler */, null /* resultCallback */, null /* resultCallbackHandler */)); } @Override public void onConfigurationChanged(Configuration newConfig) { if (!mIsUserUnlocked) { return; } final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); final BaseDraggingActivity activity = activityControl.getCreatedActivity(); if (activity == null || activity.isStarted()) { // We only care about the existing background activity. return; } if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(), activity.getResources().getConfiguration().diff(newConfig))) { return; } preloadOverview(false /* fromInit */); } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) { if (rawArgs.length > 0 && Utilities.IS_DEBUG_DEVICE) { Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; Loading @@ -26,6 +27,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.OverviewCallbacks; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading Loading @@ -80,6 +82,9 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity> @Override public void onMotionEvent(MotionEvent ev) { if (TestProtocol.sDebugTracing) { Log.d(TestProtocol.EVENTS_TO_OVERVIEW_MISSING_TAG, "onMotionEvent " + ev); } if (!mProxyTouch) { return; } Loading
quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java +51 −17 Original line number Diff line number Diff line Loading @@ -17,17 +17,22 @@ package com.android.launcher3.uioverrides.touchcontrollers; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_CANCEL; import android.graphics.PointF; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.Window; import android.view.WindowManager; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.touch.TouchEventTranslator; import com.android.launcher3.util.TouchController; import com.android.quickstep.RecentsModel; import com.android.systemui.shared.recents.ISystemUiProxy; Loading @@ -36,18 +41,29 @@ import java.io.PrintWriter; /** * TouchController for handling touch events that get sent to the StatusBar. Once the * Once the event delta y passes the touch slop, the events start getting forwarded. * Once the event delta mDownY passes the touch slop, the events start getting forwarded. * All events are offset by initial Y value of the pointer. */ public class StatusBarTouchController implements TouchController { private static final String TAG = "StatusBarController"; /** * Window flag: Enable touches to slide out of a window into neighboring * windows in mid-gesture instead of being captured for the duration of * the gesture. * * This flag changes the behavior of touch focus for this window only. * Touches can slide out of the window but they cannot necessarily slide * back in (unless the other window with touch focus permits it). */ private static final int FLAG_SLIPPERY = 0x20000000; protected final Launcher mLauncher; protected final TouchEventTranslator mTranslator; private final float mTouchSlop; private ISystemUiProxy mSysUiProxy; private int mLastAction; private final SparseArray<PointF> mDownEvents; /* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/ private boolean mCanIntercept; Loading @@ -56,7 +72,7 @@ public class StatusBarTouchController implements TouchController { mLauncher = l; // Guard against TAPs by increasing the touch slop. mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop(); mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev)); mDownEvents = new SparseArray<>(); } @Override Loading @@ -64,7 +80,6 @@ public class StatusBarTouchController implements TouchController { writer.println(prefix + "mCanIntercept:" + mCanIntercept); writer.println(prefix + "mLastAction:" + MotionEvent.actionToString(mLastAction)); writer.println(prefix + "mSysUiProxy available:" + (mSysUiProxy != null)); } private void dispatchTouchEvent(MotionEvent ev) { Loading @@ -81,26 +96,31 @@ public class StatusBarTouchController implements TouchController { @Override public final boolean onControllerInterceptTouchEvent(MotionEvent ev) { int action = ev.getActionMasked(); int idx = ev.getActionIndex(); int pid = ev.getPointerId(idx); if (action == ACTION_DOWN) { mCanIntercept = canInterceptTouch(ev); if (!mCanIntercept) { return false; } mTranslator.reset(); mTranslator.setDownParameters(0, ev); mDownEvents.put(pid, new PointF(ev.getX(), ev.getY())); } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { // Check!! should only set it only when threshold is not entered. mTranslator.setDownParameters(ev.getActionIndex(), ev); mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx))); } if (!mCanIntercept) { return false; } if (action == ACTION_MOVE) { float dy = ev.getY() - mTranslator.getDownY(); float dx = ev.getX() - mTranslator.getDownX(); if (dy > mTouchSlop && dy > Math.abs(dx)) { mTranslator.dispatchDownEvents(ev); mTranslator.processMotionEvent(ev); float dy = ev.getY(idx) - mDownEvents.get(pid).y; float dx = ev.getX(idx) - mDownEvents.get(pid).x; // Currently input dispatcher will not do touch transfer if there are more than // one touch pointer. Hence, even if slope passed, only set the slippery flag // when there is single touch event. (context: InputDispatcher.cpp line 1445) if (dy > mTouchSlop && dy > Math.abs(dx) && ev.getPointerCount() == 1) { ev.setAction(ACTION_DOWN); dispatchTouchEvent(ev); setWindowSlippery(true); return true; } if (Math.abs(dx) > mTouchSlop) { Loading @@ -110,12 +130,26 @@ public class StatusBarTouchController implements TouchController { return false; } @Override public final boolean onControllerTouchEvent(MotionEvent ev) { mTranslator.processMotionEvent(ev); if (ev.getAction() == ACTION_UP || ev.getAction() == ACTION_CANCEL) { dispatchTouchEvent(ev); setWindowSlippery(false); return true; } return true; } private void setWindowSlippery(boolean enable) { Window w = mLauncher.getWindow(); WindowManager.LayoutParams wlp = w.getAttributes(); if (enable) { wlp.flags |= FLAG_SLIPPERY; } else { wlp.flags &= ~FLAG_SLIPPERY; } w.setAttributes(wlp); } private boolean canInterceptTouch(MotionEvent ev) { if (!mLauncher.isInState(LauncherState.NORMAL) || Loading
quickstep/src/com/android/quickstep/OverviewComponentObserver.java +63 −28 Original line number Diff line number Diff line Loading @@ -29,11 +29,15 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.util.SparseIntArray; import com.android.systemui.shared.system.PackageManagerWrapper; import java.util.ArrayList; import java.util.Objects; /** * Class to keep track of the current overview component based off user preferences and app updates Loading @@ -53,22 +57,41 @@ public final class OverviewComponentObserver { } }; private final Context mContext; private final ComponentName mMyHomeComponent; private final Intent mCurrentHomeIntent; private final Intent mMyHomeIntent; private final Intent mFallbackIntent; private final SparseIntArray mConfigChangesMap = new SparseIntArray(); private String mUpdateRegisteredPackage; private ActivityControlHelper mActivityControlHelper; private Intent mOverviewIntent; private Intent mHomeIntent; private int mSystemUiStateFlags; private boolean mIsHomeAndOverviewSame; private boolean mIsDefaultHome; public OverviewComponentObserver(Context context) { mContext = context; Intent myHomeIntent = new Intent(Intent.ACTION_MAIN) mCurrentHomeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) .setPackage(mContext.getPackageName()); ResolveInfo info = context.getPackageManager().resolveActivity(myHomeIntent, 0); mMyHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name); .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName()); ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0); ComponentName myHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name); mMyHomeIntent.setComponent(myHomeComponent); mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges); ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class); mFallbackIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_DEFAULT) .setComponent(fallbackComponent) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { ActivityInfo fallbackInfo = context.getPackageManager().getActivityInfo( mFallbackIntent.getComponent(), 0 /* flags */); mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges); } catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ } mContext.registerReceiver(mUserPreferenceChangeReceiver, new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED)); Loading @@ -92,17 +115,14 @@ public final class OverviewComponentObserver { ComponentName defaultHome = PackageManagerWrapper.getInstance() .getHomeActivities(new ArrayList<>()); final String overviewIntentCategory; ComponentName overviewComponent; mHomeIntent = null; if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 && (defaultHome == null || mMyHomeComponent.equals(defaultHome))) { mIsDefaultHome = Objects.equals(mMyHomeIntent.getComponent(), defaultHome); if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 && (defaultHome == null || mIsDefaultHome)) { // User default home is same as out home app. Use Overview integrated in Launcher. overviewComponent = mMyHomeComponent; mActivityControlHelper = new LauncherActivityControllerHelper(); mIsHomeAndOverviewSame = true; overviewIntentCategory = Intent.CATEGORY_HOME; mOverviewIntent = mMyHomeIntent; mCurrentHomeIntent.setComponent(mMyHomeIntent.getComponent()); if (mUpdateRegisteredPackage != null) { // Remove any update listener as we don't care about other packages. Loading @@ -111,14 +131,11 @@ public final class OverviewComponentObserver { } } else { // The default home app is a different launcher. Use the fallback Overview instead. overviewComponent = new ComponentName(mContext, RecentsActivity.class); mActivityControlHelper = new FallbackActivityControllerHelper(); mIsHomeAndOverviewSame = false; overviewIntentCategory = Intent.CATEGORY_DEFAULT; mOverviewIntent = mFallbackIntent; mCurrentHomeIntent.setComponent(defaultHome); mHomeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) .setComponent(defaultHome); // User's default home app can change as a result of package updates of this app (such // as uninstalling the app or removing the "Launcher" feature in an update). // Listen for package updates of this app (and remove any previously attached Loading @@ -138,14 +155,6 @@ public final class OverviewComponentObserver { ACTION_PACKAGE_REMOVED)); } } mOverviewIntent = new Intent(Intent.ACTION_MAIN) .addCategory(overviewIntentCategory) .setComponent(overviewComponent) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (mHomeIntent == null) { mHomeIntent = mOverviewIntent; } } /** Loading @@ -160,6 +169,32 @@ public final class OverviewComponentObserver { } } /** * @return {@code true} if the overview component is able to handle the configuration changes. */ boolean canHandleConfigChanges(ComponentName component, int changes) { final int orientationChange = ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_SCREEN_SIZE; if ((changes & orientationChange) == orientationChange) { // This is just an approximate guess for simple orientation change because the changes // may contain non-public bits (e.g. window configuration). return true; } int configMask = mConfigChangesMap.get(component.hashCode()); return configMask != 0 && (~configMask & changes) == 0; } /** * Get the intent for overview activity. It is used when lockscreen is shown and home was died * in background, we still want to restart the one that will be used after unlock. * * @return the overview intent */ Intent getOverviewIntentIgnoreSysUiState() { return mIsDefaultHome ? mMyHomeIntent : mOverviewIntent; } /** * Get the current intent for going to the overview activity. * Loading @@ -173,7 +208,7 @@ public final class OverviewComponentObserver { * Get the current intent for going to the home activity. */ public Intent getHomeIntent() { return mHomeIntent; return mCurrentHomeIntent; } /** Loading