Loading packages/SystemUI/AndroidManifest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -427,6 +427,7 @@ android:supportsPictureInPicture="true" android:supportsPictureInPicture="true" android:stateNotNeeded="true" android:stateNotNeeded="true" android:taskAffinity="" android:taskAffinity="" android:launchMode="singleTop" androidprv:alwaysFocusable="true" /> androidprv:alwaysFocusable="true" /> <!-- platform logo easter egg activity --> <!-- platform logo easter egg activity --> Loading packages/SystemUI/res/layout/pip_menu_activity.xml +3 −3 Original line number Original line Diff line number Diff line Loading @@ -19,7 +19,7 @@ android:id="@+id/menu" android:id="@+id/menu" android:layout_width="match_parent" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_height="match_parent" android:background="#33000000"> android:background="#66000000"> <LinearLayout <LinearLayout android:id="@+id/actions" android:id="@+id/actions" Loading @@ -45,7 +45,7 @@ android:text="@string/pip_phone_dismiss" android:text="@string/pip_phone_dismiss" android:background="?android:selectableItemBackground" /> android:background="?android:selectableItemBackground" /> <TextView <TextView android:id="@+id/minimize" android:id="@+id/expand" android:layout_width="0dp" android:layout_width="0dp" android:layout_height="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:layout_weight="1" Loading @@ -53,7 +53,7 @@ android:textSize="12sp" android:textSize="12sp" android:textColor="#ffffffff" android:textColor="#ffffffff" android:fontFamily="sans-serif" android:fontFamily="sans-serif" android:text="@string/pip_phone_minimize" android:text="@string/pip_phone_expand" android:background="?android:selectableItemBackground" /> android:background="?android:selectableItemBackground" /> </LinearLayout> </LinearLayout> </FrameLayout> </FrameLayout> packages/SystemUI/res/values/styles.xml +1 −1 Original line number Original line Diff line number Diff line Loading @@ -68,7 +68,7 @@ <item name="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowBackground">@drawable/forced_resizable_background</item> <item name="android:windowBackground">@null</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:statusBarColor">@color/transparent</item> <item name="android:statusBarColor">@color/transparent</item> <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item> <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item> Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +143 −28 Original line number Original line Diff line number Diff line Loading @@ -16,13 +16,16 @@ package com.android.systemui.pip.phone; package com.android.systemui.pip.phone; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.Activity; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; import android.app.RemoteAction; import android.content.Intent; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice; import android.graphics.PointF; import android.os.Bundle; import android.os.Bundle; import android.os.Handler; import android.os.Handler; import android.os.Message; import android.os.Message; Loading @@ -30,11 +33,15 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.util.Log; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; import android.widget.ImageView; import android.widget.TextView; import android.widget.TextView; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.R; import java.util.ArrayList; import java.util.ArrayList; Loading @@ -47,28 +54,40 @@ public class PipMenuActivity extends Activity { private static final String TAG = "PipMenuActivity"; private static final String TAG = "PipMenuActivity"; public static final int MESSAGE_FINISH_SELF = 1; public static final int MESSAGE_SHOW_MENU = 1; public static final int MESSAGE_UPDATE_ACTIONS = 2; public static final int MESSAGE_HIDE_MENU = 2; public static final int MESSAGE_UPDATE_ACTIONS = 3; private static final long INITIAL_DISMISS_DELAY = 2000; private static final long INITIAL_DISMISS_DELAY = 2000; private static final long POST_INTERACTION_DISMISS_DELAY = 1500; private static final long POST_INTERACTION_DISMISS_DELAY = 1500; private static final long MENU_FADE_DURATION = 125; private List<RemoteAction> mActions = new ArrayList<>(); private boolean mMenuVisible; private final List<RemoteAction> mActions = new ArrayList<>(); private View mMenuContainer; private View mDismissButton; private View mDismissButton; private View mMinimizeButton; private View mExpandButton; private ObjectAnimator mMenuContainerAnimator; private PointF mDownPosition = new PointF(); private PointF mDownDelta = new PointF(); private ViewConfiguration mViewConfig; private Handler mHandler = new Handler(); private Handler mHandler = new Handler(); private Messenger mToControllerMessenger; private Messenger mToControllerMessenger; private Messenger mMessenger = new Messenger(new Handler() { private Messenger mMessenger = new Messenger(new Handler() { @Override @Override public void handleMessage(Message msg) { public void handleMessage(Message msg) { switch (msg.what) { switch (msg.what) { case MESSAGE_SHOW_MENU: showMenu(); break; case MESSAGE_HIDE_MENU: hideMenu(); break; case MESSAGE_UPDATE_ACTIONS: case MESSAGE_UPDATE_ACTIONS: setActions(((ParceledListSlice) msg.obj).getList()); setActions(((ParceledListSlice) msg.obj).getList()); break; break; case MESSAGE_FINISH_SELF: finish(); break; } } } } }); }); Loading @@ -76,12 +95,17 @@ public class PipMenuActivity extends Activity { private final Runnable mFinishRunnable = new Runnable() { private final Runnable mFinishRunnable = new Runnable() { @Override @Override public void run() { public void run() { finish(); hideMenu(); } } }; }; @Override @Override protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) { // Set the flags to allow us to watch for outside touches and also hide the menu and start // manipulating the PIP in the same touch gesture mViewConfig = ViewConfiguration.get(this); getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY); super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); setContentView(R.layout.pip_menu_activity); setContentView(R.layout.pip_menu_activity); Loading @@ -94,44 +118,74 @@ public class PipMenuActivity extends Activity { setActions(actions.getList()); setActions(actions.getList()); } } findViewById(R.id.menu).setOnClickListener((v) -> { mMenuContainer = findViewById(R.id.menu); mMenuContainer.setOnClickListener((v) -> { expandPip(); expandPip(); }); }); mDismissButton = findViewById(R.id.dismiss); mDismissButton = findViewById(R.id.dismiss); mDismissButton.setOnClickListener((v) -> { mDismissButton.setOnClickListener((v) -> { dismissPip(); dismissPip(); }); }); mMinimizeButton = findViewById(R.id.minimize); mExpandButton = findViewById(R.id.expand); mMinimizeButton.setOnClickListener((v) -> { mExpandButton.setOnClickListener((v) -> { minimizePip(); expandPip(); }); }); notifyActivityCallback(mMessenger); showMenu(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); showMenu(); } } @Override @Override protected void onStart() { protected void onStart() { super.onStart(); super.onStart(); notifyActivityVisibility(true); notifyMenuVisibility(true); repostDelayedFinish(INITIAL_DISMISS_DELAY); repostDelayedFinish(INITIAL_DISMISS_DELAY); } } @Override public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { if (!isInPictureInPictureMode) { finish(); } } @Override @Override public void onUserInteraction() { public void onUserInteraction() { repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); } } @Override @Override protected void onStop() { public boolean dispatchTouchEvent(MotionEvent ev) { super.onStop(); // On the first action outside the window, hide the menu finish(); switch (ev.getAction()) { case MotionEvent.ACTION_OUTSIDE: hideMenu(); break; case MotionEvent.ACTION_DOWN: mDownPosition.set(ev.getX(), ev.getY()); break; case MotionEvent.ACTION_MOVE: mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y); if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() && mMenuVisible) { hideMenu(); mMenuVisible = false; } } return super.dispatchTouchEvent(ev); } } @Override @Override public void finish() { public void finish() { View v = getWindow().getDecorView(); notifyActivityCallback(null); v.removeCallbacks(mFinishRunnable); notifyActivityVisibility(false); super.finish(); super.finish(); overridePendingTransition(0, R.anim.forced_resizable_exit); // Hide without an animation (the menu should already be invisible at this point) overridePendingTransition(0, 0); } } @Override @Override Loading @@ -139,6 +193,51 @@ public class PipMenuActivity extends Activity { // Do nothing // Do nothing } } private void showMenu() { if (!mMenuVisible) { if (mMenuContainerAnimator != null) { mMenuContainerAnimator.cancel(); } notifyMenuVisibility(true); mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA, mMenuContainer.getAlpha(), 1f); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN); mMenuContainerAnimator.setDuration(MENU_FADE_DURATION); mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { repostDelayedFinish(INITIAL_DISMISS_DELAY); } }); mMenuContainerAnimator.start(); } } private void hideMenu() { hideMenu(null /* animationFinishedRunnable */); } private void hideMenu(final Runnable animationFinishedRunnable) { if (mMenuVisible) { cancelDelayedFinish(); notifyMenuVisibility(false); mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA, mMenuContainer.getAlpha(), 0f); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT); mMenuContainerAnimator.setDuration(MENU_FADE_DURATION); mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animationFinishedRunnable != null) { animationFinishedRunnable.run(); } } }); mMenuContainerAnimator.start(); } } private void setActions(List<RemoteAction> actions) { private void setActions(List<RemoteAction> actions) { mActions.clear(); mActions.clear(); mActions.addAll(actions); mActions.addAll(actions); Loading Loading @@ -173,17 +272,19 @@ public class PipMenuActivity extends Activity { } } } } private void notifyActivityVisibility(boolean visible) { private void notifyMenuVisibility(boolean visible) { mMenuVisible = visible; Message m = Message.obtain(); Message m = Message.obtain(); m.what = PipMenuActivityController.MESSAGE_ACTIVITY_VISIBILITY_CHANGED; m.what = PipMenuActivityController.MESSAGE_MENU_VISIBILITY_CHANGED; m.arg1 = visible ? 1 : 0; m.arg1 = visible ? 1 : 0; m.replyTo = visible ? mMessenger : null; sendMessage(m, "Could not notify controller of PIP menu visibility"); sendMessage(m, "Could not notify controller of PIP menu visibility"); } } private void expandPip() { private void expandPip() { hideMenu(() -> { sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP, sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP, "Could not notify controller to expand PIP"); "Could not notify controller to expand PIP"); }); } } private void minimizePip() { private void minimizePip() { Loading @@ -192,8 +293,17 @@ public class PipMenuActivity extends Activity { } } private void dismissPip() { private void dismissPip() { hideMenu(() -> { sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP, sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP, "Could not notify controller to dismiss PIP"); "Could not notify controller to dismiss PIP"); }); } private void notifyActivityCallback(Messenger callback) { Message m = Message.obtain(); m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK; m.replyTo = callback; sendMessage(m, "Could not notify controller of activity finished"); } } private void sendEmptyMessage(int what, String errorMsg) { private void sendEmptyMessage(int what, String errorMsg) { Loading @@ -210,6 +320,11 @@ public class PipMenuActivity extends Activity { } } } } private void cancelDelayedFinish() { View v = getWindow().getDecorView(); v.removeCallbacks(mFinishRunnable); } private void repostDelayedFinish(long delay) { private void repostDelayedFinish(long delay) { View v = getWindow().getDecorView(); View v = getWindow().getDecorView(); v.removeCallbacks(mFinishRunnable); v.removeCallbacks(mFinishRunnable); Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +40 −39 Original line number Original line Diff line number Diff line Loading @@ -25,10 +25,11 @@ public class PipMenuActivityController { public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; public static final String EXTRA_ACTIONS = "actions"; public static final String EXTRA_ACTIONS = "actions"; public static final int MESSAGE_ACTIVITY_VISIBILITY_CHANGED = 100; public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100; public static final int MESSAGE_EXPAND_PIP = 101; public static final int MESSAGE_EXPAND_PIP = 101; public static final int MESSAGE_MINIMIZE_PIP = 102; public static final int MESSAGE_MINIMIZE_PIP = 102; public static final int MESSAGE_DISMISS_PIP = 103; public static final int MESSAGE_DISMISS_PIP = 103; public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104; /** /** * A listener interface to receive notification on changes in PIP. * A listener interface to receive notification on changes in PIP. Loading Loading @@ -67,34 +68,25 @@ public class PipMenuActivityController { @Override @Override public void handleMessage(Message msg) { public void handleMessage(Message msg) { switch (msg.what) { switch (msg.what) { case MESSAGE_ACTIVITY_VISIBILITY_CHANGED: { case MESSAGE_MENU_VISIBILITY_CHANGED: { boolean visible = msg.arg1 > 0; boolean visible = msg.arg1 > 0; int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible)); for (int i = 0; i < listenerCount; i++) { mListeners.get(i).onPipMenuVisibilityChanged(visible); } mToActivityMessenger = msg.replyTo; break; break; } } case MESSAGE_EXPAND_PIP: { case MESSAGE_EXPAND_PIP: { int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipExpand()); for (int i = 0; i < listenerCount; i++) { mListeners.get(i).onPipExpand(); } break; break; } } case MESSAGE_MINIMIZE_PIP: { case MESSAGE_MINIMIZE_PIP: { int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipMinimize()); for (int i = 0; i < listenerCount; i++) { mListeners.get(i).onPipMinimize(); } break; break; } } case MESSAGE_DISMISS_PIP: { case MESSAGE_DISMISS_PIP: { int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipDismiss()); for (int i = 0; i < listenerCount; i++) { break; mListeners.get(i).onPipDismiss(); } } case MESSAGE_UPDATE_ACTIVITY_CALLBACK: { mToActivityMessenger = msg.replyTo; break; break; } } } } Loading @@ -121,6 +113,15 @@ public class PipMenuActivityController { * Shows the menu activity. * Shows the menu activity. */ */ public void showMenu() { public void showMenu() { if (mToActivityMessenger != null) { Message m = Message.obtain(); m.what = PipMenuActivity.MESSAGE_SHOW_MENU; try { mToActivityMessenger.send(m); } catch (RemoteException e) { Log.e(TAG, "Could not notify menu to show", e); } } else { // Start the menu activity on the top task of the pinned stack // Start the menu activity on the top task of the pinned stack try { try { StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); Loading @@ -129,7 +130,7 @@ public class PipMenuActivityController { Intent intent = new Intent(mContext, PipMenuActivity.class); Intent intent = new Intent(mContext, PipMenuActivity.class); intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); intent.putExtra(EXTRA_ACTIONS, mActions); intent.putExtra(EXTRA_ACTIONS, mActions); ActivityOptions options = ActivityOptions.makeBasic(); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); options.setLaunchTaskId( options.setLaunchTaskId( pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); options.setTaskOverlay(true); options.setTaskOverlay(true); Loading @@ -141,6 +142,7 @@ public class PipMenuActivityController { Log.e(TAG, "Error showing PIP menu activity", e); Log.e(TAG, "Error showing PIP menu activity", e); } } } } } /** /** * Hides the menu activity. * Hides the menu activity. Loading @@ -148,13 +150,12 @@ public class PipMenuActivityController { public void hideMenu() { public void hideMenu() { if (mToActivityMessenger != null) { if (mToActivityMessenger != null) { Message m = Message.obtain(); Message m = Message.obtain(); m.what = PipMenuActivity.MESSAGE_FINISH_SELF; m.what = PipMenuActivity.MESSAGE_HIDE_MENU; try { try { mToActivityMessenger.send(m); mToActivityMessenger.send(m); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Could not notify menu activity to finish", e); Log.e(TAG, "Could not notify menu to hide", e); } } mToActivityMessenger = null; } } } } Loading Loading
packages/SystemUI/AndroidManifest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -427,6 +427,7 @@ android:supportsPictureInPicture="true" android:supportsPictureInPicture="true" android:stateNotNeeded="true" android:stateNotNeeded="true" android:taskAffinity="" android:taskAffinity="" android:launchMode="singleTop" androidprv:alwaysFocusable="true" /> androidprv:alwaysFocusable="true" /> <!-- platform logo easter egg activity --> <!-- platform logo easter egg activity --> Loading
packages/SystemUI/res/layout/pip_menu_activity.xml +3 −3 Original line number Original line Diff line number Diff line Loading @@ -19,7 +19,7 @@ android:id="@+id/menu" android:id="@+id/menu" android:layout_width="match_parent" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_height="match_parent" android:background="#33000000"> android:background="#66000000"> <LinearLayout <LinearLayout android:id="@+id/actions" android:id="@+id/actions" Loading @@ -45,7 +45,7 @@ android:text="@string/pip_phone_dismiss" android:text="@string/pip_phone_dismiss" android:background="?android:selectableItemBackground" /> android:background="?android:selectableItemBackground" /> <TextView <TextView android:id="@+id/minimize" android:id="@+id/expand" android:layout_width="0dp" android:layout_width="0dp" android:layout_height="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:layout_weight="1" Loading @@ -53,7 +53,7 @@ android:textSize="12sp" android:textSize="12sp" android:textColor="#ffffffff" android:textColor="#ffffffff" android:fontFamily="sans-serif" android:fontFamily="sans-serif" android:text="@string/pip_phone_minimize" android:text="@string/pip_phone_expand" android:background="?android:selectableItemBackground" /> android:background="?android:selectableItemBackground" /> </LinearLayout> </LinearLayout> </FrameLayout> </FrameLayout>
packages/SystemUI/res/values/styles.xml +1 −1 Original line number Original line Diff line number Diff line Loading @@ -68,7 +68,7 @@ <item name="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowBackground">@drawable/forced_resizable_background</item> <item name="android:windowBackground">@null</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:statusBarColor">@color/transparent</item> <item name="android:statusBarColor">@color/transparent</item> <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item> <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item> Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +143 −28 Original line number Original line Diff line number Diff line Loading @@ -16,13 +16,16 @@ package com.android.systemui.pip.phone; package com.android.systemui.pip.phone; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.Activity; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; import android.app.RemoteAction; import android.content.Intent; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice; import android.graphics.PointF; import android.os.Bundle; import android.os.Bundle; import android.os.Handler; import android.os.Handler; import android.os.Message; import android.os.Message; Loading @@ -30,11 +33,15 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.util.Log; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; import android.widget.ImageView; import android.widget.TextView; import android.widget.TextView; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.R; import java.util.ArrayList; import java.util.ArrayList; Loading @@ -47,28 +54,40 @@ public class PipMenuActivity extends Activity { private static final String TAG = "PipMenuActivity"; private static final String TAG = "PipMenuActivity"; public static final int MESSAGE_FINISH_SELF = 1; public static final int MESSAGE_SHOW_MENU = 1; public static final int MESSAGE_UPDATE_ACTIONS = 2; public static final int MESSAGE_HIDE_MENU = 2; public static final int MESSAGE_UPDATE_ACTIONS = 3; private static final long INITIAL_DISMISS_DELAY = 2000; private static final long INITIAL_DISMISS_DELAY = 2000; private static final long POST_INTERACTION_DISMISS_DELAY = 1500; private static final long POST_INTERACTION_DISMISS_DELAY = 1500; private static final long MENU_FADE_DURATION = 125; private List<RemoteAction> mActions = new ArrayList<>(); private boolean mMenuVisible; private final List<RemoteAction> mActions = new ArrayList<>(); private View mMenuContainer; private View mDismissButton; private View mDismissButton; private View mMinimizeButton; private View mExpandButton; private ObjectAnimator mMenuContainerAnimator; private PointF mDownPosition = new PointF(); private PointF mDownDelta = new PointF(); private ViewConfiguration mViewConfig; private Handler mHandler = new Handler(); private Handler mHandler = new Handler(); private Messenger mToControllerMessenger; private Messenger mToControllerMessenger; private Messenger mMessenger = new Messenger(new Handler() { private Messenger mMessenger = new Messenger(new Handler() { @Override @Override public void handleMessage(Message msg) { public void handleMessage(Message msg) { switch (msg.what) { switch (msg.what) { case MESSAGE_SHOW_MENU: showMenu(); break; case MESSAGE_HIDE_MENU: hideMenu(); break; case MESSAGE_UPDATE_ACTIONS: case MESSAGE_UPDATE_ACTIONS: setActions(((ParceledListSlice) msg.obj).getList()); setActions(((ParceledListSlice) msg.obj).getList()); break; break; case MESSAGE_FINISH_SELF: finish(); break; } } } } }); }); Loading @@ -76,12 +95,17 @@ public class PipMenuActivity extends Activity { private final Runnable mFinishRunnable = new Runnable() { private final Runnable mFinishRunnable = new Runnable() { @Override @Override public void run() { public void run() { finish(); hideMenu(); } } }; }; @Override @Override protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) { // Set the flags to allow us to watch for outside touches and also hide the menu and start // manipulating the PIP in the same touch gesture mViewConfig = ViewConfiguration.get(this); getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY); super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); setContentView(R.layout.pip_menu_activity); setContentView(R.layout.pip_menu_activity); Loading @@ -94,44 +118,74 @@ public class PipMenuActivity extends Activity { setActions(actions.getList()); setActions(actions.getList()); } } findViewById(R.id.menu).setOnClickListener((v) -> { mMenuContainer = findViewById(R.id.menu); mMenuContainer.setOnClickListener((v) -> { expandPip(); expandPip(); }); }); mDismissButton = findViewById(R.id.dismiss); mDismissButton = findViewById(R.id.dismiss); mDismissButton.setOnClickListener((v) -> { mDismissButton.setOnClickListener((v) -> { dismissPip(); dismissPip(); }); }); mMinimizeButton = findViewById(R.id.minimize); mExpandButton = findViewById(R.id.expand); mMinimizeButton.setOnClickListener((v) -> { mExpandButton.setOnClickListener((v) -> { minimizePip(); expandPip(); }); }); notifyActivityCallback(mMessenger); showMenu(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); showMenu(); } } @Override @Override protected void onStart() { protected void onStart() { super.onStart(); super.onStart(); notifyActivityVisibility(true); notifyMenuVisibility(true); repostDelayedFinish(INITIAL_DISMISS_DELAY); repostDelayedFinish(INITIAL_DISMISS_DELAY); } } @Override public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { if (!isInPictureInPictureMode) { finish(); } } @Override @Override public void onUserInteraction() { public void onUserInteraction() { repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); } } @Override @Override protected void onStop() { public boolean dispatchTouchEvent(MotionEvent ev) { super.onStop(); // On the first action outside the window, hide the menu finish(); switch (ev.getAction()) { case MotionEvent.ACTION_OUTSIDE: hideMenu(); break; case MotionEvent.ACTION_DOWN: mDownPosition.set(ev.getX(), ev.getY()); break; case MotionEvent.ACTION_MOVE: mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y); if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() && mMenuVisible) { hideMenu(); mMenuVisible = false; } } return super.dispatchTouchEvent(ev); } } @Override @Override public void finish() { public void finish() { View v = getWindow().getDecorView(); notifyActivityCallback(null); v.removeCallbacks(mFinishRunnable); notifyActivityVisibility(false); super.finish(); super.finish(); overridePendingTransition(0, R.anim.forced_resizable_exit); // Hide without an animation (the menu should already be invisible at this point) overridePendingTransition(0, 0); } } @Override @Override Loading @@ -139,6 +193,51 @@ public class PipMenuActivity extends Activity { // Do nothing // Do nothing } } private void showMenu() { if (!mMenuVisible) { if (mMenuContainerAnimator != null) { mMenuContainerAnimator.cancel(); } notifyMenuVisibility(true); mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA, mMenuContainer.getAlpha(), 1f); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN); mMenuContainerAnimator.setDuration(MENU_FADE_DURATION); mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { repostDelayedFinish(INITIAL_DISMISS_DELAY); } }); mMenuContainerAnimator.start(); } } private void hideMenu() { hideMenu(null /* animationFinishedRunnable */); } private void hideMenu(final Runnable animationFinishedRunnable) { if (mMenuVisible) { cancelDelayedFinish(); notifyMenuVisibility(false); mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA, mMenuContainer.getAlpha(), 0f); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT); mMenuContainerAnimator.setDuration(MENU_FADE_DURATION); mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animationFinishedRunnable != null) { animationFinishedRunnable.run(); } } }); mMenuContainerAnimator.start(); } } private void setActions(List<RemoteAction> actions) { private void setActions(List<RemoteAction> actions) { mActions.clear(); mActions.clear(); mActions.addAll(actions); mActions.addAll(actions); Loading Loading @@ -173,17 +272,19 @@ public class PipMenuActivity extends Activity { } } } } private void notifyActivityVisibility(boolean visible) { private void notifyMenuVisibility(boolean visible) { mMenuVisible = visible; Message m = Message.obtain(); Message m = Message.obtain(); m.what = PipMenuActivityController.MESSAGE_ACTIVITY_VISIBILITY_CHANGED; m.what = PipMenuActivityController.MESSAGE_MENU_VISIBILITY_CHANGED; m.arg1 = visible ? 1 : 0; m.arg1 = visible ? 1 : 0; m.replyTo = visible ? mMessenger : null; sendMessage(m, "Could not notify controller of PIP menu visibility"); sendMessage(m, "Could not notify controller of PIP menu visibility"); } } private void expandPip() { private void expandPip() { hideMenu(() -> { sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP, sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP, "Could not notify controller to expand PIP"); "Could not notify controller to expand PIP"); }); } } private void minimizePip() { private void minimizePip() { Loading @@ -192,8 +293,17 @@ public class PipMenuActivity extends Activity { } } private void dismissPip() { private void dismissPip() { hideMenu(() -> { sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP, sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP, "Could not notify controller to dismiss PIP"); "Could not notify controller to dismiss PIP"); }); } private void notifyActivityCallback(Messenger callback) { Message m = Message.obtain(); m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK; m.replyTo = callback; sendMessage(m, "Could not notify controller of activity finished"); } } private void sendEmptyMessage(int what, String errorMsg) { private void sendEmptyMessage(int what, String errorMsg) { Loading @@ -210,6 +320,11 @@ public class PipMenuActivity extends Activity { } } } } private void cancelDelayedFinish() { View v = getWindow().getDecorView(); v.removeCallbacks(mFinishRunnable); } private void repostDelayedFinish(long delay) { private void repostDelayedFinish(long delay) { View v = getWindow().getDecorView(); View v = getWindow().getDecorView(); v.removeCallbacks(mFinishRunnable); v.removeCallbacks(mFinishRunnable); Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +40 −39 Original line number Original line Diff line number Diff line Loading @@ -25,10 +25,11 @@ public class PipMenuActivityController { public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; public static final String EXTRA_ACTIONS = "actions"; public static final String EXTRA_ACTIONS = "actions"; public static final int MESSAGE_ACTIVITY_VISIBILITY_CHANGED = 100; public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100; public static final int MESSAGE_EXPAND_PIP = 101; public static final int MESSAGE_EXPAND_PIP = 101; public static final int MESSAGE_MINIMIZE_PIP = 102; public static final int MESSAGE_MINIMIZE_PIP = 102; public static final int MESSAGE_DISMISS_PIP = 103; public static final int MESSAGE_DISMISS_PIP = 103; public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104; /** /** * A listener interface to receive notification on changes in PIP. * A listener interface to receive notification on changes in PIP. Loading Loading @@ -67,34 +68,25 @@ public class PipMenuActivityController { @Override @Override public void handleMessage(Message msg) { public void handleMessage(Message msg) { switch (msg.what) { switch (msg.what) { case MESSAGE_ACTIVITY_VISIBILITY_CHANGED: { case MESSAGE_MENU_VISIBILITY_CHANGED: { boolean visible = msg.arg1 > 0; boolean visible = msg.arg1 > 0; int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible)); for (int i = 0; i < listenerCount; i++) { mListeners.get(i).onPipMenuVisibilityChanged(visible); } mToActivityMessenger = msg.replyTo; break; break; } } case MESSAGE_EXPAND_PIP: { case MESSAGE_EXPAND_PIP: { int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipExpand()); for (int i = 0; i < listenerCount; i++) { mListeners.get(i).onPipExpand(); } break; break; } } case MESSAGE_MINIMIZE_PIP: { case MESSAGE_MINIMIZE_PIP: { int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipMinimize()); for (int i = 0; i < listenerCount; i++) { mListeners.get(i).onPipMinimize(); } break; break; } } case MESSAGE_DISMISS_PIP: { case MESSAGE_DISMISS_PIP: { int listenerCount = mListeners.size(); mListeners.forEach(l -> l.onPipDismiss()); for (int i = 0; i < listenerCount; i++) { break; mListeners.get(i).onPipDismiss(); } } case MESSAGE_UPDATE_ACTIVITY_CALLBACK: { mToActivityMessenger = msg.replyTo; break; break; } } } } Loading @@ -121,6 +113,15 @@ public class PipMenuActivityController { * Shows the menu activity. * Shows the menu activity. */ */ public void showMenu() { public void showMenu() { if (mToActivityMessenger != null) { Message m = Message.obtain(); m.what = PipMenuActivity.MESSAGE_SHOW_MENU; try { mToActivityMessenger.send(m); } catch (RemoteException e) { Log.e(TAG, "Could not notify menu to show", e); } } else { // Start the menu activity on the top task of the pinned stack // Start the menu activity on the top task of the pinned stack try { try { StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); Loading @@ -129,7 +130,7 @@ public class PipMenuActivityController { Intent intent = new Intent(mContext, PipMenuActivity.class); Intent intent = new Intent(mContext, PipMenuActivity.class); intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); intent.putExtra(EXTRA_ACTIONS, mActions); intent.putExtra(EXTRA_ACTIONS, mActions); ActivityOptions options = ActivityOptions.makeBasic(); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); options.setLaunchTaskId( options.setLaunchTaskId( pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); options.setTaskOverlay(true); options.setTaskOverlay(true); Loading @@ -141,6 +142,7 @@ public class PipMenuActivityController { Log.e(TAG, "Error showing PIP menu activity", e); Log.e(TAG, "Error showing PIP menu activity", e); } } } } } /** /** * Hides the menu activity. * Hides the menu activity. Loading @@ -148,13 +150,12 @@ public class PipMenuActivityController { public void hideMenu() { public void hideMenu() { if (mToActivityMessenger != null) { if (mToActivityMessenger != null) { Message m = Message.obtain(); Message m = Message.obtain(); m.what = PipMenuActivity.MESSAGE_FINISH_SELF; m.what = PipMenuActivity.MESSAGE_HIDE_MENU; try { try { mToActivityMessenger.send(m); mToActivityMessenger.send(m); } catch (RemoteException e) { } catch (RemoteException e) { Log.e(TAG, "Could not notify menu activity to finish", e); Log.e(TAG, "Could not notify menu to hide", e); } } mToActivityMessenger = null; } } } } Loading