Loading packages/SystemUI/src/com/android/systemui/recents/Recents.java +1 −1 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ public class Recents extends SystemUI @Override public void start() { sDebugFlags = new RecentsDebugFlags(mContext); sSystemServicesProxy = new SystemServicesProxy(mContext); sSystemServicesProxy = SystemServicesProxy.getInstance(mContext); sTaskLoader = new RecentsTaskLoader(mContext); sConfiguration = new RecentsConfiguration(mContext); mHandler = new Handler(); Loading packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +5 −29 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ITaskStackListener; import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; import android.content.Context; Loading Loading @@ -59,6 +58,7 @@ import com.android.systemui.recents.events.ui.DraggingInRecentsEvent; import com.android.systemui.recents.misc.DozeTrigger; import com.android.systemui.recents.misc.ForegroundThread; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.recents.model.RecentsTaskLoadPlan; import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; Loading Loading @@ -95,37 +95,13 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity"; /** * An implementation of ITaskStackListener, that allows us to listen for changes to the system * An implementation of TaskStackListener, that allows us to listen for changes to the system * task stacks and update recents accordingly. */ class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { Handler mHandler; public TaskStackListenerImpl(Handler handler) { mHandler = handler; } class TaskStackListenerImpl extends TaskStackListener { @Override public void onTaskStackChanged() { // Debounce any task stack changes mHandler.removeCallbacks(this); mHandler.post(this); } @Override public void onActivityPinned() { } @Override public void onPinnedActivityRestartAttempt() { } @Override public void onPinnedStackAnimationEnded() { } /** Preloads the next task */ public void run() { // Preloads the next task RecentsConfiguration config = Recents.getConfiguration(); if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { RecentsTaskLoader loader = Recents.getTaskLoader(); Loading Loading @@ -201,7 +177,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener ForegroundThread.get(); // Register the task stack listener mTaskStackListener = new TaskStackListenerImpl(mHandler); mTaskStackListener = new TaskStackListenerImpl(); SystemServicesProxy ssp = Recents.getSystemServices(); ssp.registerTaskStackListener(mTaskStackListener); Loading packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +120 −7 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemProperties; Loading Loading @@ -106,6 +109,8 @@ public class SystemServicesProxy { sRecentsBlacklist.add("com.android.systemui.tv.pip.PipMenuActivity"); } private static SystemServicesProxy sSystemServicesProxy; AccessibilityManager mAccm; ActivityManager mAm; IActivityManager mIam; Loading @@ -128,8 +133,58 @@ public class SystemServicesProxy { Paint mBgProtectionPaint; Canvas mBgProtectionCanvas; private final Handler mHandler = new H(); /** * An abstract class to track task stack changes. * Classes should implement this instead of {@link android.app.ITaskStackListener} * to reduce IPC calls from system services. These callbacks will be called on the main thread. */ public abstract static class TaskStackListener { public void onTaskStackChanged() { } public void onActivityPinned() { } public void onPinnedActivityRestartAttempt() { } public void onPinnedStackAnimationEnded() { } } /** * Implementation of {@link android.app.ITaskStackListener} to listen task stack changes from * ActivityManagerNative. * This simply passes callbacks to listeners through {@link H}. * */ private ITaskStackListener.Stub mTaskStackListener = new ITaskStackListener.Stub() { @Override public void onTaskStackChanged() throws RemoteException { mHandler.removeMessages(H.ON_TASK_STACK_CHANGED); mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED); } @Override public void onActivityPinned() throws RemoteException { mHandler.removeMessages(H.ON_ACTIVITY_PINNED); mHandler.sendEmptyMessage(H.ON_ACTIVITY_PINNED); } @Override public void onPinnedActivityRestartAttempt() throws RemoteException{ mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT); mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT); } @Override public void onPinnedStackAnimationEnded() throws RemoteException { mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED); mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED); } }; /** * List of {@link TaskStackListener} registered from {@link registerTaskStackListener}. */ private List<TaskStackListener> mTaskStackListeners = new ArrayList<>(); /** Private constructor */ public SystemServicesProxy(Context context) { private SystemServicesProxy(Context context) { mAccm = AccessibilityManager.getInstance(context); mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); mIam = ActivityManagerNative.getDefault(); Loading Loading @@ -170,6 +225,20 @@ public class SystemServicesProxy { } } /** * Returns the single instance of the {@link SystemServicesProxy}. * This should only be called on the main thread. */ public static SystemServicesProxy getInstance(Context context) { if (!Looper.getMainLooper().isCurrentThread()) { throw new RuntimeException("Must be called on the UI thread"); } if (sSystemServicesProxy == null) { sSystemServicesProxy = new SystemServicesProxy(context); } return sSystemServicesProxy; } /** Returns a list of the recents tasks */ public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId, boolean isTopTaskHome, ArraySet<Integer> quietProfileIds) { Loading Loading @@ -982,14 +1051,21 @@ public class SystemServicesProxy { } } /** Registers a task stack listener with the system. */ public void registerTaskStackListener(ITaskStackListener listener) { /** * Registers a task stack listener with the system. * This should be called on the main thread. */ public void registerTaskStackListener(TaskStackListener listener) { if (mIam == null) return; mTaskStackListeners.add(listener); if (mTaskStackListeners.size() == 1) { // Register mTaskStackListener to IActivityManager only once if needed. try { mIam.registerTaskStackListener(listener); mIam.registerTaskStackListener(mTaskStackListener); } catch (Exception e) { e.printStackTrace(); Log.w(TAG, "Failed to call registerTaskStackListener", e); } } } Loading Loading @@ -1039,4 +1115,41 @@ public class SystemServicesProxy { e.printStackTrace(); } } private final class H extends Handler { private static final int ON_TASK_STACK_CHANGED = 1; private static final int ON_ACTIVITY_PINNED = 2; private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 3; private static final int ON_PINNED_STACK_ANIMATION_ENDED = 4; @Override public void handleMessage(Message msg) { switch (msg.what) { case ON_TASK_STACK_CHANGED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onTaskStackChanged(); } break; } case ON_ACTIVITY_PINNED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onActivityPinned(); } break; } case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(); } break; } case ON_PINNED_STACK_ANIMATION_ENDED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onPinnedStackAnimationEnded(); } break; } } } } } packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +5 −40 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.car; import android.app.ActivityManager; import android.app.ITaskStackListener; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading @@ -33,6 +32,7 @@ import android.view.WindowManager; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.PhoneStatusBar; Loading @@ -40,9 +40,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; * A status bar (and navigation bar) tailored for the automotive use case. */ public class CarStatusBar extends PhoneStatusBar { private SystemServicesProxy mSystemServicesProxy; private TaskStackListenerImpl mTaskStackListener; private Handler mHandler; private CarNavigationBarView mCarNavigationBar; private CarNavigationBarController mController; Loading @@ -51,10 +49,8 @@ public class CarStatusBar extends PhoneStatusBar { @Override public void start() { super.start(); mHandler = new Handler(); mTaskStackListener = new TaskStackListenerImpl(mHandler); mSystemServicesProxy = new SystemServicesProxy(mContext); mSystemServicesProxy.registerTaskStackListener(mTaskStackListener); mTaskStackListener = new TaskStackListenerImpl(); SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener); registerPackageChangeReceivers(); } Loading Loading @@ -114,47 +110,16 @@ public class CarStatusBar extends PhoneStatusBar { } /** * An implementation of ITaskStackListener, that listens for changes in the system task * An implementation of TaskStackListener, that listens for changes in the system task * stack and notifies the navigation bar. */ private class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { private Handler mHandler; public TaskStackListenerImpl(Handler handler) { this.mHandler = handler; } @Override public void onActivityPinned() { } @Override public void onPinnedActivityRestartAttempt() { } @Override public void onPinnedStackAnimationEnded() { } private class TaskStackListenerImpl extends TaskStackListener { @Override public void onTaskStackChanged() { mHandler.removeCallbacks(this); mHandler.post(this); } @Override public void run() { ensureMainThread(); SystemServicesProxy ssp = Recents.getSystemServices(); ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask(); mController.taskChanged(runningTaskInfo.baseActivity.getPackageName()); } private void ensureMainThread() { if (!Looper.getMainLooper().isCurrentThread()) { throw new RuntimeException("Must be called on the UI thread"); } } } @Override Loading packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java +69 −102 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.IActivityManager; import android.app.ITaskStackListener; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading @@ -38,6 +37,8 @@ import android.os.SystemProperties; import android.util.Log; import com.android.systemui.Prefs; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import java.util.ArrayList; import java.util.List; Loading Loading @@ -95,89 +96,6 @@ public class PipManager { private boolean mIsRecentsShown; private boolean mIsPipFocusedInRecent; private final Runnable mOnActivityPinnedRunnable = new Runnable() { @Override public void run() { StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "Cannot find pinned stack"); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo); mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1]; mPipComponentName = ComponentName.unflattenFromString( stackInfo.taskNames[stackInfo.taskNames.length - 1]); // Set state to overlay so we show it when the pinned stack animation ends. mState = STATE_PIP_OVERLAY; mCurrentPipBounds = mPipBounds; launchPipOnboardingActivityIfNeeded(); mMediaSessionManager.addOnActiveSessionsChangedListener( mActiveMediaSessionListener, null); updateMediaController(mMediaSessionManager.getActiveSessions(null)); if (mIsRecentsShown) { // If an activity becomes PIPed again after the fullscreen, the Recents is shown // behind so we need to resize the pinned stack and show the correct overlay. resizePinnedStack(STATE_PIP_OVERLAY); } for (int i = mListeners.size() - 1; i >= 0; i--) { mListeners.get(i).onPipEntered(); } } }; private final Runnable mOnTaskStackChanged = new Runnable() { @Override public void run() { if (mState != STATE_NO_PIP) { StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "There is no pinned stack"); closePipInternal(false); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) { if (stackInfo.taskIds[i] == mPipTaskId) { // PIP task is still alive. return; } } // PIP task doesn't exist anymore in PINNED_STACK. closePipInternal(true); } } }; private final Runnable mOnPinnedActivityRestartAttempt = new Runnable() { @Override public void run() { // If PIPed activity is launched again by Launcher or intent, make it fullscreen. movePipToFullscreen(); } }; private final Runnable mOnPinnedStackAnimationEnded = new Runnable() { @Override public void run() { switch (mState) { case STATE_PIP_OVERLAY: showPipOverlay(); break; case STATE_PIP_MENU: showPipMenu(); break; } } }; private final Runnable mResizePinnedStackRunnable = new Runnable() { @Override public void run() { Loading Loading @@ -241,13 +159,7 @@ public class PipManager { (int) (mRecentsPipBounds.bottom + scaleBy * mRecentsPipBounds.height())); mActivityManager = ActivityManagerNative.getDefault(); TaskStackListener taskStackListener = new TaskStackListener(); IActivityManager iam = ActivityManagerNative.getDefault(); try { iam.registerTaskStackListener(taskStackListener); } catch (RemoteException e) { Log.e(TAG, "registerTaskStackListener failed", e); } SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED); mContext.registerReceiver(mBroadcastReceiver, intentFilter); Loading Loading @@ -566,33 +478,88 @@ public class PipManager { return mPipMediaController; } private class TaskStackListener extends ITaskStackListener.Stub { TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskStackChanged() throws RemoteException { // Post the message back to the UI thread. mHandler.post(mOnTaskStackChanged); public void onTaskStackChanged() { if (mState != STATE_NO_PIP) { StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "There is no pinned stack"); closePipInternal(false); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) { if (stackInfo.taskIds[i] == mPipTaskId) { // PIP task is still alive. return; } } // PIP task doesn't exist anymore in PINNED_STACK. closePipInternal(true); } } @Override public void onActivityPinned() throws RemoteException { // Post the message back to the UI thread. public void onActivityPinned() { if (DEBUG) Log.d(TAG, "onActivityPinned()"); mHandler.post(mOnActivityPinnedRunnable); StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "Cannot find pinned stack"); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo); mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1]; mPipComponentName = ComponentName.unflattenFromString( stackInfo.taskNames[stackInfo.taskNames.length - 1]); // Set state to overlay so we show it when the pinned stack animation ends. mState = STATE_PIP_OVERLAY; mCurrentPipBounds = mPipBounds; launchPipOnboardingActivityIfNeeded(); mMediaSessionManager.addOnActiveSessionsChangedListener( mActiveMediaSessionListener, null); updateMediaController(mMediaSessionManager.getActiveSessions(null)); if (mIsRecentsShown) { // If an activity becomes PIPed again after the fullscreen, the Recents is shown // behind so we need to resize the pinned stack and show the correct overlay. resizePinnedStack(STATE_PIP_OVERLAY); } for (int i = mListeners.size() - 1; i >= 0; i--) { mListeners.get(i).onPipEntered(); } } @Override public void onPinnedActivityRestartAttempt() { // Post the message back to the UI thread. if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()"); mHandler.post(mOnPinnedActivityRestartAttempt); // If PIPed activity is launched again by Launcher or intent, make it fullscreen. movePipToFullscreen(); } @Override public void onPinnedStackAnimationEnded() { if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()"); mHandler.post(mOnPinnedStackAnimationEnded); switch (mState) { case STATE_PIP_OVERLAY: showPipOverlay(); break; case STATE_PIP_MENU: showPipMenu(); break; } } }; /** * A listener interface to receive notification on changes in PIP. Loading Loading
packages/SystemUI/src/com/android/systemui/recents/Recents.java +1 −1 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ public class Recents extends SystemUI @Override public void start() { sDebugFlags = new RecentsDebugFlags(mContext); sSystemServicesProxy = new SystemServicesProxy(mContext); sSystemServicesProxy = SystemServicesProxy.getInstance(mContext); sTaskLoader = new RecentsTaskLoader(mContext); sConfiguration = new RecentsConfiguration(mContext); mHandler = new Handler(); Loading
packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +5 −29 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ITaskStackListener; import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; import android.content.Context; Loading Loading @@ -59,6 +58,7 @@ import com.android.systemui.recents.events.ui.DraggingInRecentsEvent; import com.android.systemui.recents.misc.DozeTrigger; import com.android.systemui.recents.misc.ForegroundThread; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.recents.model.RecentsTaskLoadPlan; import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; Loading Loading @@ -95,37 +95,13 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity"; /** * An implementation of ITaskStackListener, that allows us to listen for changes to the system * An implementation of TaskStackListener, that allows us to listen for changes to the system * task stacks and update recents accordingly. */ class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { Handler mHandler; public TaskStackListenerImpl(Handler handler) { mHandler = handler; } class TaskStackListenerImpl extends TaskStackListener { @Override public void onTaskStackChanged() { // Debounce any task stack changes mHandler.removeCallbacks(this); mHandler.post(this); } @Override public void onActivityPinned() { } @Override public void onPinnedActivityRestartAttempt() { } @Override public void onPinnedStackAnimationEnded() { } /** Preloads the next task */ public void run() { // Preloads the next task RecentsConfiguration config = Recents.getConfiguration(); if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { RecentsTaskLoader loader = Recents.getTaskLoader(); Loading Loading @@ -201,7 +177,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener ForegroundThread.get(); // Register the task stack listener mTaskStackListener = new TaskStackListenerImpl(mHandler); mTaskStackListener = new TaskStackListenerImpl(); SystemServicesProxy ssp = Recents.getSystemServices(); ssp.registerTaskStackListener(mTaskStackListener); Loading
packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +120 −7 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemProperties; Loading Loading @@ -106,6 +109,8 @@ public class SystemServicesProxy { sRecentsBlacklist.add("com.android.systemui.tv.pip.PipMenuActivity"); } private static SystemServicesProxy sSystemServicesProxy; AccessibilityManager mAccm; ActivityManager mAm; IActivityManager mIam; Loading @@ -128,8 +133,58 @@ public class SystemServicesProxy { Paint mBgProtectionPaint; Canvas mBgProtectionCanvas; private final Handler mHandler = new H(); /** * An abstract class to track task stack changes. * Classes should implement this instead of {@link android.app.ITaskStackListener} * to reduce IPC calls from system services. These callbacks will be called on the main thread. */ public abstract static class TaskStackListener { public void onTaskStackChanged() { } public void onActivityPinned() { } public void onPinnedActivityRestartAttempt() { } public void onPinnedStackAnimationEnded() { } } /** * Implementation of {@link android.app.ITaskStackListener} to listen task stack changes from * ActivityManagerNative. * This simply passes callbacks to listeners through {@link H}. * */ private ITaskStackListener.Stub mTaskStackListener = new ITaskStackListener.Stub() { @Override public void onTaskStackChanged() throws RemoteException { mHandler.removeMessages(H.ON_TASK_STACK_CHANGED); mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED); } @Override public void onActivityPinned() throws RemoteException { mHandler.removeMessages(H.ON_ACTIVITY_PINNED); mHandler.sendEmptyMessage(H.ON_ACTIVITY_PINNED); } @Override public void onPinnedActivityRestartAttempt() throws RemoteException{ mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT); mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT); } @Override public void onPinnedStackAnimationEnded() throws RemoteException { mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED); mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED); } }; /** * List of {@link TaskStackListener} registered from {@link registerTaskStackListener}. */ private List<TaskStackListener> mTaskStackListeners = new ArrayList<>(); /** Private constructor */ public SystemServicesProxy(Context context) { private SystemServicesProxy(Context context) { mAccm = AccessibilityManager.getInstance(context); mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); mIam = ActivityManagerNative.getDefault(); Loading Loading @@ -170,6 +225,20 @@ public class SystemServicesProxy { } } /** * Returns the single instance of the {@link SystemServicesProxy}. * This should only be called on the main thread. */ public static SystemServicesProxy getInstance(Context context) { if (!Looper.getMainLooper().isCurrentThread()) { throw new RuntimeException("Must be called on the UI thread"); } if (sSystemServicesProxy == null) { sSystemServicesProxy = new SystemServicesProxy(context); } return sSystemServicesProxy; } /** Returns a list of the recents tasks */ public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId, boolean isTopTaskHome, ArraySet<Integer> quietProfileIds) { Loading Loading @@ -982,14 +1051,21 @@ public class SystemServicesProxy { } } /** Registers a task stack listener with the system. */ public void registerTaskStackListener(ITaskStackListener listener) { /** * Registers a task stack listener with the system. * This should be called on the main thread. */ public void registerTaskStackListener(TaskStackListener listener) { if (mIam == null) return; mTaskStackListeners.add(listener); if (mTaskStackListeners.size() == 1) { // Register mTaskStackListener to IActivityManager only once if needed. try { mIam.registerTaskStackListener(listener); mIam.registerTaskStackListener(mTaskStackListener); } catch (Exception e) { e.printStackTrace(); Log.w(TAG, "Failed to call registerTaskStackListener", e); } } } Loading Loading @@ -1039,4 +1115,41 @@ public class SystemServicesProxy { e.printStackTrace(); } } private final class H extends Handler { private static final int ON_TASK_STACK_CHANGED = 1; private static final int ON_ACTIVITY_PINNED = 2; private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 3; private static final int ON_PINNED_STACK_ANIMATION_ENDED = 4; @Override public void handleMessage(Message msg) { switch (msg.what) { case ON_TASK_STACK_CHANGED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onTaskStackChanged(); } break; } case ON_ACTIVITY_PINNED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onActivityPinned(); } break; } case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(); } break; } case ON_PINNED_STACK_ANIMATION_ENDED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { mTaskStackListeners.get(i).onPinnedStackAnimationEnded(); } break; } } } } }
packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +5 −40 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.car; import android.app.ActivityManager; import android.app.ITaskStackListener; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading @@ -33,6 +32,7 @@ import android.view.WindowManager; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.PhoneStatusBar; Loading @@ -40,9 +40,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; * A status bar (and navigation bar) tailored for the automotive use case. */ public class CarStatusBar extends PhoneStatusBar { private SystemServicesProxy mSystemServicesProxy; private TaskStackListenerImpl mTaskStackListener; private Handler mHandler; private CarNavigationBarView mCarNavigationBar; private CarNavigationBarController mController; Loading @@ -51,10 +49,8 @@ public class CarStatusBar extends PhoneStatusBar { @Override public void start() { super.start(); mHandler = new Handler(); mTaskStackListener = new TaskStackListenerImpl(mHandler); mSystemServicesProxy = new SystemServicesProxy(mContext); mSystemServicesProxy.registerTaskStackListener(mTaskStackListener); mTaskStackListener = new TaskStackListenerImpl(); SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener); registerPackageChangeReceivers(); } Loading Loading @@ -114,47 +110,16 @@ public class CarStatusBar extends PhoneStatusBar { } /** * An implementation of ITaskStackListener, that listens for changes in the system task * An implementation of TaskStackListener, that listens for changes in the system task * stack and notifies the navigation bar. */ private class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { private Handler mHandler; public TaskStackListenerImpl(Handler handler) { this.mHandler = handler; } @Override public void onActivityPinned() { } @Override public void onPinnedActivityRestartAttempt() { } @Override public void onPinnedStackAnimationEnded() { } private class TaskStackListenerImpl extends TaskStackListener { @Override public void onTaskStackChanged() { mHandler.removeCallbacks(this); mHandler.post(this); } @Override public void run() { ensureMainThread(); SystemServicesProxy ssp = Recents.getSystemServices(); ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask(); mController.taskChanged(runningTaskInfo.baseActivity.getPackageName()); } private void ensureMainThread() { if (!Looper.getMainLooper().isCurrentThread()) { throw new RuntimeException("Must be called on the UI thread"); } } } @Override Loading
packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java +69 −102 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.IActivityManager; import android.app.ITaskStackListener; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; Loading @@ -38,6 +37,8 @@ import android.os.SystemProperties; import android.util.Log; import com.android.systemui.Prefs; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import java.util.ArrayList; import java.util.List; Loading Loading @@ -95,89 +96,6 @@ public class PipManager { private boolean mIsRecentsShown; private boolean mIsPipFocusedInRecent; private final Runnable mOnActivityPinnedRunnable = new Runnable() { @Override public void run() { StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "Cannot find pinned stack"); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo); mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1]; mPipComponentName = ComponentName.unflattenFromString( stackInfo.taskNames[stackInfo.taskNames.length - 1]); // Set state to overlay so we show it when the pinned stack animation ends. mState = STATE_PIP_OVERLAY; mCurrentPipBounds = mPipBounds; launchPipOnboardingActivityIfNeeded(); mMediaSessionManager.addOnActiveSessionsChangedListener( mActiveMediaSessionListener, null); updateMediaController(mMediaSessionManager.getActiveSessions(null)); if (mIsRecentsShown) { // If an activity becomes PIPed again after the fullscreen, the Recents is shown // behind so we need to resize the pinned stack and show the correct overlay. resizePinnedStack(STATE_PIP_OVERLAY); } for (int i = mListeners.size() - 1; i >= 0; i--) { mListeners.get(i).onPipEntered(); } } }; private final Runnable mOnTaskStackChanged = new Runnable() { @Override public void run() { if (mState != STATE_NO_PIP) { StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "There is no pinned stack"); closePipInternal(false); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) { if (stackInfo.taskIds[i] == mPipTaskId) { // PIP task is still alive. return; } } // PIP task doesn't exist anymore in PINNED_STACK. closePipInternal(true); } } }; private final Runnable mOnPinnedActivityRestartAttempt = new Runnable() { @Override public void run() { // If PIPed activity is launched again by Launcher or intent, make it fullscreen. movePipToFullscreen(); } }; private final Runnable mOnPinnedStackAnimationEnded = new Runnable() { @Override public void run() { switch (mState) { case STATE_PIP_OVERLAY: showPipOverlay(); break; case STATE_PIP_MENU: showPipMenu(); break; } } }; private final Runnable mResizePinnedStackRunnable = new Runnable() { @Override public void run() { Loading Loading @@ -241,13 +159,7 @@ public class PipManager { (int) (mRecentsPipBounds.bottom + scaleBy * mRecentsPipBounds.height())); mActivityManager = ActivityManagerNative.getDefault(); TaskStackListener taskStackListener = new TaskStackListener(); IActivityManager iam = ActivityManagerNative.getDefault(); try { iam.registerTaskStackListener(taskStackListener); } catch (RemoteException e) { Log.e(TAG, "registerTaskStackListener failed", e); } SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED); mContext.registerReceiver(mBroadcastReceiver, intentFilter); Loading Loading @@ -566,33 +478,88 @@ public class PipManager { return mPipMediaController; } private class TaskStackListener extends ITaskStackListener.Stub { TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskStackChanged() throws RemoteException { // Post the message back to the UI thread. mHandler.post(mOnTaskStackChanged); public void onTaskStackChanged() { if (mState != STATE_NO_PIP) { StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "There is no pinned stack"); closePipInternal(false); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) { if (stackInfo.taskIds[i] == mPipTaskId) { // PIP task is still alive. return; } } // PIP task doesn't exist anymore in PINNED_STACK. closePipInternal(true); } } @Override public void onActivityPinned() throws RemoteException { // Post the message back to the UI thread. public void onActivityPinned() { if (DEBUG) Log.d(TAG, "onActivityPinned()"); mHandler.post(mOnActivityPinnedRunnable); StackInfo stackInfo = null; try { stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); if (stackInfo == null) { Log.w(TAG, "Cannot find pinned stack"); return; } } catch (RemoteException e) { Log.e(TAG, "getStackInfo failed", e); return; } if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo); mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1]; mPipComponentName = ComponentName.unflattenFromString( stackInfo.taskNames[stackInfo.taskNames.length - 1]); // Set state to overlay so we show it when the pinned stack animation ends. mState = STATE_PIP_OVERLAY; mCurrentPipBounds = mPipBounds; launchPipOnboardingActivityIfNeeded(); mMediaSessionManager.addOnActiveSessionsChangedListener( mActiveMediaSessionListener, null); updateMediaController(mMediaSessionManager.getActiveSessions(null)); if (mIsRecentsShown) { // If an activity becomes PIPed again after the fullscreen, the Recents is shown // behind so we need to resize the pinned stack and show the correct overlay. resizePinnedStack(STATE_PIP_OVERLAY); } for (int i = mListeners.size() - 1; i >= 0; i--) { mListeners.get(i).onPipEntered(); } } @Override public void onPinnedActivityRestartAttempt() { // Post the message back to the UI thread. if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()"); mHandler.post(mOnPinnedActivityRestartAttempt); // If PIPed activity is launched again by Launcher or intent, make it fullscreen. movePipToFullscreen(); } @Override public void onPinnedStackAnimationEnded() { if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()"); mHandler.post(mOnPinnedStackAnimationEnded); switch (mState) { case STATE_PIP_OVERLAY: showPipOverlay(); break; case STATE_PIP_MENU: showPipMenu(); break; } } }; /** * A listener interface to receive notification on changes in PIP. Loading