PIP: Make PIPed activity to be focused from Recents
This makes PIPed activity to look like part of the Recents. Bug: 26946155 Change-Id: Ic0ac441e57af5594c06701fa9d30400f0f7cc5a5
This commit is contained in:
@@ -31,4 +31,8 @@
|
||||
is located in center. -->
|
||||
<string translatable="false" name="config_centeredPictureInPictureBounds">"596 280 1324 690"</string>
|
||||
|
||||
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
|
||||
when the PIP is shown with Recents. -->
|
||||
<string translatable="false" name="config_pictureInPictureBoundsInRecents">"1480 123 1760 303"</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -2444,6 +2444,10 @@
|
||||
is located in center. -->
|
||||
<string translatable="false" name="config_centeredPictureInPictureBounds">"0 0 300 300"</string>
|
||||
|
||||
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
|
||||
when the PIP is shown with Recents. -->
|
||||
<string translatable="false" name="config_pictureInPictureBoundsInRecents">"0 0 100 100"</string>
|
||||
|
||||
<!-- Controls the snap mode for the docked stack divider
|
||||
0 - 3 snap targets: left/top has 16:9 ratio, 1:1, and right/bottom has 16:9 ratio
|
||||
1 - 3 snap targets: fixed ratio, 1:1, (1 - fixed ratio)
|
||||
|
||||
@@ -306,6 +306,7 @@
|
||||
<java-symbol type="bool" name="config_guestUserEphemeral" />
|
||||
<java-symbol type="string" name="config_defaultPictureInPictureBounds" />
|
||||
<java-symbol type="string" name="config_centeredPictureInPictureBounds" />
|
||||
<java-symbol type="string" name="config_pictureInPictureBoundsInRecents" />
|
||||
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
|
||||
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
|
||||
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
|
||||
|
||||
27
packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml
Normal file
27
packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:pathData="M0 0h24v24H0z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
|
||||
</vector>
|
||||
27
packages/SystemUI/res/drawable/ic_pause_white_24dp.xml
Normal file
27
packages/SystemUI/res/drawable/ic_pause_white_24dp.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
|
||||
<path
|
||||
android:pathData="M0 0h24v24H0z" />
|
||||
</vector>
|
||||
27
packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml
Normal file
27
packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M8 5v14l11-7z" />
|
||||
<path
|
||||
android:pathData="M0 0h24v24H0z" />
|
||||
</vector>
|
||||
@@ -28,10 +28,26 @@
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="beforeDescendants"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:paddingStart="@dimen/recents_tv_grid_row_padding"
|
||||
android:paddingEnd="@dimen/recents_tv_grid_row_padding"
|
||||
android:focusable="true"/>
|
||||
android:focusable="true" />
|
||||
|
||||
<View
|
||||
android:id="@+id/pip_shade"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible"
|
||||
android:background="#76000000"/>
|
||||
|
||||
<!-- Placeholder view to handle key events for PIP when it's focused.
|
||||
Size and positions will be adjusted to comply with
|
||||
config_pictureInPictureBoundsInRecents -->
|
||||
<View
|
||||
android:id="@+id/pip"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="invisible"
|
||||
android:focusable="true" />
|
||||
</com.android.systemui.recents.tv.views.RecentsTvView>
|
||||
|
||||
|
||||
@@ -17,13 +17,38 @@
|
||||
*/
|
||||
-->
|
||||
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/guide_overlay"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:padding="3dp"
|
||||
android:textSize="13sp"
|
||||
android:textColor="#111111"
|
||||
android:background="#99EEEEEE"
|
||||
android:text="@string/pip_hold_home" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/guide_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:padding="3dp"
|
||||
android:textSize="13sp"
|
||||
android:textColor="#111111"
|
||||
android:background="#99EEEEEE"
|
||||
android:text="@string/pip_hold_home" />
|
||||
<LinearLayout
|
||||
android:id="@+id/guide_buttons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="horizontal">
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_fullscreen_white_24dp" />
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_pause_white_24dp" />
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_close_white" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -998,20 +998,4 @@ public class SystemServicesProxy {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void focusPinnedStack() {
|
||||
try {
|
||||
mIam.setFocusedStack(PINNED_STACK_ID);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void focusHomeStack() {
|
||||
try {
|
||||
mIam.setFocusedStack(HOME_STACK_ID);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.recents.tv;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
@@ -25,6 +26,7 @@ import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout.LayoutParams;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.recents.Recents;
|
||||
@@ -58,6 +60,7 @@ import com.android.systemui.statusbar.BaseStatusBar;
|
||||
import com.android.systemui.tv.pip.PipManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* The main TV recents activity started by the RecentsImpl.
|
||||
*/
|
||||
@@ -73,9 +76,28 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
private boolean mIgnoreAltTabRelease;
|
||||
|
||||
private RecentsTvView mRecentsView;
|
||||
private View mPipView;
|
||||
private View mPipShadeView;
|
||||
private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
|
||||
private FinishRecentsRunnable mFinishLaunchHomeRunnable;
|
||||
|
||||
private PipManager mPipManager;
|
||||
private PipManager.Listener mPipListener = new PipManager.Listener() {
|
||||
@Override
|
||||
public void onPipActivityClosed() {
|
||||
mPipView.setVisibility(View.GONE);
|
||||
mPipShadeView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowPipMenu() { }
|
||||
|
||||
@Override
|
||||
public void onMoveToFullscreen() { }
|
||||
|
||||
@Override
|
||||
public void onPipResizeAboutToStart() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* A common Runnable to finish Recents by launching Home with an animation depending on the
|
||||
@@ -212,6 +234,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
mPipManager = PipManager.getInstance();
|
||||
|
||||
// Register this activity with the event bus
|
||||
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
|
||||
@@ -226,7 +249,8 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
|
||||
mPipView = findViewById(R.id.pip);
|
||||
mPipShadeView = findViewById(R.id.pip_shade);
|
||||
getWindow().getAttributes().privateFlags |=
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
|
||||
|
||||
@@ -265,6 +289,38 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
// Notify that recents is now visible
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
|
||||
|
||||
if (mPipManager.isPipShown()) {
|
||||
// Place mPipView at the PIP bounds for fine tuned focus handling.
|
||||
Rect pipBounds = mPipManager.getPipBounds();
|
||||
LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
|
||||
lp.width = pipBounds.width();
|
||||
lp.height = pipBounds.height();
|
||||
lp.leftMargin = pipBounds.left;
|
||||
lp.topMargin = pipBounds.top;
|
||||
mPipView.setLayoutParams(lp);
|
||||
|
||||
mPipView.setVisibility(View.VISIBLE);
|
||||
mPipView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mPipManager.resizePinnedStack(PipManager.STATE_PIP_MENU);
|
||||
}
|
||||
});
|
||||
mPipView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
mPipManager.onPipViewFocusChangedInRecents(hasFocus);
|
||||
mPipShadeView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
mPipManager.addListener(mPipListener);
|
||||
} else {
|
||||
mPipView.setVisibility(View.GONE);
|
||||
}
|
||||
mPipManager.onRecentsStarted();
|
||||
// Give focus to the recents row whenever its visible to an user.
|
||||
mRecentsView.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,6 +333,8 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
mPipManager.onRecentsStopped();
|
||||
mPipManager.removeListener(mPipListener);
|
||||
mIgnoreAltTabRelease = false;
|
||||
// Notify that recents is now hidden
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
@@ -316,18 +374,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_DPAD_UP: {
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
PipManager.getInstance().resizePinnedStack(PipManager.STATE_PIP_MENU);
|
||||
ssp.focusPinnedStack();
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN: {
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
PipManager.getInstance().resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
|
||||
ssp.focusHomeStack();
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DEL:
|
||||
case KeyEvent.KEYCODE_FORWARD_DEL: {
|
||||
EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
|
||||
|
||||
@@ -200,19 +200,6 @@ public class RecentsTvView extends FrameLayout {
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called with the full size of the window since we are handling our own insets.
|
||||
*/
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (mTaskStackHorizontalView != null && mTaskStackHorizontalView.getVisibility() != GONE) {
|
||||
mTaskStackHorizontalView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
|
||||
}
|
||||
|
||||
// Layout the empty view
|
||||
mEmptyView.layout(left, top, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
||||
mSystemInsets.set(insets.getSystemWindowInsets());
|
||||
|
||||
@@ -65,17 +65,25 @@ public class PipManager {
|
||||
public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH = 0x2;
|
||||
private int mSuspendPipResizingReason;
|
||||
|
||||
private static final float SCALE_FACTOR = 1.1f;
|
||||
|
||||
private Context mContext;
|
||||
private IActivityManager mActivityManager;
|
||||
private int mState = STATE_NO_PIP;
|
||||
private final Handler mHandler = new Handler();
|
||||
private List<Listener> mListeners = new ArrayList<>();
|
||||
private Rect mPipBound;
|
||||
private Rect mMenuModePipBound;
|
||||
private Rect mCurrentPipBounds;
|
||||
private Rect mPipBounds;
|
||||
private Rect mMenuModePipBounds;
|
||||
private Rect mRecentsPipBounds;
|
||||
private Rect mRecentsFocusedPipBounds;
|
||||
private boolean mInitialized;
|
||||
private int mPipTaskId = TASK_ID_NO_PIP;
|
||||
private boolean mOnboardingShown;
|
||||
|
||||
private boolean mIsRecentsShown;
|
||||
private boolean mIsPipFocusedInRecent;
|
||||
|
||||
private final Runnable mOnActivityPinnedRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -83,7 +91,7 @@ public class PipManager {
|
||||
try {
|
||||
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
|
||||
if (stackInfo == null) {
|
||||
Log.w(TAG, "There is no pinned stack");
|
||||
Log.w(TAG, "Cannot find pinned stack");
|
||||
return;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
@@ -94,6 +102,7 @@ public class PipManager {
|
||||
mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
|
||||
// Set state to overlay so we show it when the pinned stack animation ends.
|
||||
mState = STATE_PIP_OVERLAY;
|
||||
mCurrentPipBounds = mPipBounds;
|
||||
launchPipOnboardingActivityIfNeeded();
|
||||
}
|
||||
};
|
||||
@@ -133,10 +142,13 @@ public class PipManager {
|
||||
private final Runnable mOnPinnedStackAnimationEnded = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mState == STATE_PIP_OVERLAY) {
|
||||
showPipOverlay();
|
||||
} else if (mState == STATE_PIP_MENU) {
|
||||
showPipMenu();
|
||||
switch (mState) {
|
||||
case STATE_PIP_OVERLAY:
|
||||
showPipOverlay();
|
||||
break;
|
||||
case STATE_PIP_MENU:
|
||||
showPipMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -177,10 +189,18 @@ public class PipManager {
|
||||
mInitialized = true;
|
||||
mContext = context;
|
||||
Resources res = context.getResources();
|
||||
mPipBound = Rect.unflattenFromString(res.getString(
|
||||
mPipBounds = Rect.unflattenFromString(res.getString(
|
||||
com.android.internal.R.string.config_defaultPictureInPictureBounds));
|
||||
mMenuModePipBound = Rect.unflattenFromString(res.getString(
|
||||
mMenuModePipBounds = Rect.unflattenFromString(res.getString(
|
||||
com.android.internal.R.string.config_centeredPictureInPictureBounds));
|
||||
mRecentsPipBounds = Rect.unflattenFromString(res.getString(
|
||||
com.android.internal.R.string.config_pictureInPictureBoundsInRecents));
|
||||
float scaleBy = (SCALE_FACTOR - 1.0f) / 2;
|
||||
mRecentsFocusedPipBounds = new Rect(
|
||||
(int) (mRecentsPipBounds.left - scaleBy * mRecentsPipBounds.width()),
|
||||
(int) (mRecentsPipBounds.top - scaleBy * mRecentsPipBounds.height()),
|
||||
(int) (mRecentsPipBounds.right + scaleBy * mRecentsPipBounds.width()),
|
||||
(int) (mRecentsPipBounds.bottom + scaleBy * mRecentsPipBounds.height()));
|
||||
|
||||
mActivityManager = ActivityManagerNative.getDefault();
|
||||
TaskStackListener taskStackListener = new TaskStackListener();
|
||||
@@ -203,7 +223,7 @@ public class PipManager {
|
||||
*/
|
||||
public void requestTvPictureInPicture() {
|
||||
if (DEBUG) Log.d(TAG, "requestTvPictureInPicture()");
|
||||
if (!hasPipTasks()) {
|
||||
if (!isPipShown()) {
|
||||
startPip();
|
||||
} else if (mState == STATE_PIP_OVERLAY) {
|
||||
resizePinnedStack(STATE_PIP_MENU);
|
||||
@@ -212,7 +232,7 @@ public class PipManager {
|
||||
|
||||
private void startPip() {
|
||||
try {
|
||||
mActivityManager.moveTopActivityToPinnedStack(FULLSCREEN_WORKSPACE_STACK_ID, mPipBound);
|
||||
mActivityManager.moveTopActivityToPinnedStack(FULLSCREEN_WORKSPACE_STACK_ID, mPipBounds);
|
||||
} catch (RemoteException|IllegalArgumentException e) {
|
||||
Log.e(TAG, "moveTopActivityToPinnedStack failed", e);
|
||||
}
|
||||
@@ -235,6 +255,9 @@ public class PipManager {
|
||||
Log.e(TAG, "removeStack failed", e);
|
||||
}
|
||||
}
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onPipActivityClosed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,36 +318,99 @@ public class PipManager {
|
||||
public void resizePinnedStack(int state) {
|
||||
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
|
||||
mState = state;
|
||||
Rect bounds;
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onPipResizeAboutToStart();
|
||||
}
|
||||
switch (mState) {
|
||||
case STATE_PIP_MENU:
|
||||
bounds = mMenuModePipBound;
|
||||
break;
|
||||
case STATE_NO_PIP:
|
||||
bounds = null;
|
||||
break;
|
||||
default:
|
||||
bounds = mPipBound;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mSuspendPipResizingReason != 0) {
|
||||
if (DEBUG) Log.d(TAG,
|
||||
"resizePinnedStack() deferring mSuspendPipResizingReason=" +
|
||||
mSuspendPipResizingReason);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case STATE_NO_PIP:
|
||||
mCurrentPipBounds = null;
|
||||
break;
|
||||
case STATE_PIP_MENU:
|
||||
mCurrentPipBounds = mMenuModePipBounds;
|
||||
break;
|
||||
case STATE_PIP_OVERLAY:
|
||||
if (mIsRecentsShown) {
|
||||
if (mIsPipFocusedInRecent) {
|
||||
mCurrentPipBounds = mRecentsFocusedPipBounds;
|
||||
} else {
|
||||
mCurrentPipBounds = mRecentsPipBounds;
|
||||
}
|
||||
} else {
|
||||
mCurrentPipBounds = mPipBounds;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mCurrentPipBounds = mPipBounds;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
mActivityManager.resizeStack(PINNED_STACK_ID, bounds, true, true, true);
|
||||
mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds, true, true, true);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "showPipMenu failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current PIP bound for activities to sync their UI with PIP.
|
||||
*/
|
||||
public Rect getPipBounds() {
|
||||
return mCurrentPipBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when Recents is started.
|
||||
* PIPed activity will be resized accordingly and overlay will show available buttons.
|
||||
*/
|
||||
public void onRecentsStarted() {
|
||||
mIsRecentsShown = true;
|
||||
mIsPipFocusedInRecent = false;
|
||||
if (mState == STATE_NO_PIP) {
|
||||
return;
|
||||
}
|
||||
resizePinnedStack(STATE_PIP_OVERLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when Recents is stopped.
|
||||
* PIPed activity will be resized accordingly and overlay will hide available buttons.
|
||||
*/
|
||||
public void onRecentsStopped() {
|
||||
mIsRecentsShown = false;
|
||||
mIsPipFocusedInRecent = false;
|
||||
if (mState == STATE_NO_PIP) {
|
||||
return;
|
||||
}
|
||||
resizePinnedStack(STATE_PIP_OVERLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if recents is shown.
|
||||
*/
|
||||
boolean isRecentsShown() {
|
||||
return mIsRecentsShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
|
||||
* is focused.
|
||||
* This only resizes pinned stack so it looks like it's in Recents.
|
||||
* This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
|
||||
*/
|
||||
public void onPipViewFocusChangedInRecents(boolean hasFocus) {
|
||||
mIsPipFocusedInRecent = hasFocus;
|
||||
if (mState != STATE_PIP_OVERLAY) {
|
||||
Log.w(TAG, "There is no pinned stack to handle focus change.");
|
||||
return;
|
||||
}
|
||||
resizePinnedStack(STATE_PIP_OVERLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows PIP menu UI by launching {@link PipMenuActivity}. It also locates the pinned
|
||||
* stack to the centered PIP bound {@link com.android.internal.R.string
|
||||
@@ -362,6 +448,13 @@ public class PipManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if PIP is shown.
|
||||
*/
|
||||
public boolean isPipShown() {
|
||||
return hasPipTasks();
|
||||
}
|
||||
|
||||
private boolean hasPipTasks() {
|
||||
try {
|
||||
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
|
||||
|
||||
@@ -35,6 +35,7 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
|
||||
private final PipManager mPipManager = PipManager.getInstance();
|
||||
private final Handler mHandler = new Handler();
|
||||
private View mGuideOverlayView;
|
||||
private View mGuideButtonsView;
|
||||
private final Runnable mHideGuideOverlayRunnable = new Runnable() {
|
||||
public void run() {
|
||||
mGuideOverlayView.setVisibility(View.INVISIBLE);
|
||||
@@ -46,13 +47,21 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.tv_pip_overlay);
|
||||
mGuideOverlayView = findViewById(R.id.guide_overlay);
|
||||
mGuideButtonsView = findViewById(R.id.guide_buttons);
|
||||
mPipManager.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mGuideOverlayView.setVisibility(View.VISIBLE);
|
||||
// TODO: Implement animation for this
|
||||
if (!mPipManager.isRecentsShown()) {
|
||||
mGuideOverlayView.setVisibility(View.VISIBLE);
|
||||
mGuideButtonsView.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
mGuideOverlayView.setVisibility(View.INVISIBLE);
|
||||
mGuideButtonsView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
mHandler.removeCallbacks(mHideGuideOverlayRunnable);
|
||||
mHandler.postDelayed(mHideGuideOverlayRunnable, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user