<!-- Flags enabling default window features. See Window.java -->
<bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
+
+ <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
+ <string translatable="false" name="config_defaultPictureInPictureBounds">"1420 100 1820 325"</string>
+
+ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP
+ is located in center. -->
+ <string translatable="false" name="config_centeredPictureInPictureBounds">"600 331 1320 749"</string>
+
</resources>
<!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
<string translatable="false" name="config_defaultPictureInPictureBounds">"0 0 100 100"</string>
+ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP
+ is located in center. -->
+ <string translatable="false" name="config_centeredPictureInPictureBounds">"0 0 300 300"</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)
<java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
<java-symbol type="bool" name="config_freeformWindowManagement" />
<java-symbol type="string" name="config_defaultPictureInPictureBounds" />
+ <java-symbol type="string" name="config_centeredPictureInPictureBounds" />
<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" />
android:launchMode="singleTop"
android:excludeFromRecents="true" />
+ <!-- started from PipUI -->
+ <activity
+ android:name="com.android.systemui.tv.pip.PipMenuActivity"
+ android:exported="true"
+ android:theme="@style/PipTheme"
+ android:launchMode="singleTop"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|layoutDirection"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ androidprv:alwaysFocusable="true"
+ android:excludeFromRecents="true" />
+ <activity
+ android:name="com.android.systemui.tv.pip.PipOverlayActivity"
+ android:exported="true"
+ android:theme="@style/PipTheme"
+ android:launchMode="singleTop"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|layoutDirection"
+ android:resizeable="true"
+ android:supportsPictureInPicture="true"
+ android:excludeFromRecents="true" />
+
<!-- platform logo easter egg activity -->
<activity
android:name=".DessertCase"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <FrameLayout
+ android:layout_alignParentEnd="true"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:background="#88FFFFFF">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <Button android:id="@+id/full"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/pip_fullscreen"
+ android:textSize="10sp"
+ android:focusable="true" />
+
+ <Button android:id="@+id/exit"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/pip_exit"
+ android:textSize="10sp"
+ android:focusable="true" />
+
+ <Button android:id="@+id/cancel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/pip_cancel"
+ android:textSize="10sp"
+ android:focusable="true" />
+ </LinearLayout>
+ </FrameLayout>
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <TextView
+ android:id="@+id/guide_overlay"
+ 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" />
+</FrameLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Button to close PIP on PIP UI -->
+ <string name="pip_exit">Close PIP</string>
+ <!-- Button to move PIP screen to the fullscreen on PIP UI -->
+ <string name="pip_fullscreen">Full screen</string>
+ <!-- Button to play the current media on PIP UI -->
+ <string name="pip_play">Play</string>
+ <!-- Button to pause the current media on PIP UI -->
+ <string name="pip_pause">Pause</string>
+ <!-- Button to close PIP overlay menu on PIP UI -->
+ <string name="pip_cancel">Cancel</string>
+ <!-- Overlay text on PIP -->
+ <string name="pip_hold_home">Hold HOME to control PIP</string>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="PipTheme" parent="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ </style>
+</resources>
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.keyboard.KeyboardUI.class,
+ com.android.systemui.tv.pip.PipUI.class
};
/**
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.systemui.tv.pip;
+
+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.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+
+/**
+ * Manages the picture-in-picture (PIP) UI and states.
+ */
+public class PipManager {
+ private static final String TAG = "PipManager";
+ private static final boolean DEBUG = false;
+
+ private static PipManager sPipManager;
+
+ private static final int STATE_NO_PIP = 0;
+ private static final int STATE_PIP_OVERLAY = 1;
+ private static final int STATE_PIP_MENU = 2;
+
+ 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 boolean mInitialized;
+ 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, "There is no pinned stack");
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getStackInfo failed", e);
+ return;
+ }
+ if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
+ mState = STATE_PIP_OVERLAY;
+ launchPipOverlayActivity();
+ }
+ };
+ private final Runnable mOnTaskStackChanged = new Runnable() {
+ @Override
+ public void run() {
+ if (mState != STATE_NO_PIP) {
+ // TODO: check whether PIP task is closed.
+ }
+ }
+ };
+
+ private final BroadcastReceiver mPipButtonReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "PIP button pressed");
+ if (!hasPipTasks()) {
+ startPip();
+ } else if (mState == STATE_PIP_OVERLAY) {
+ showPipMenu();
+ }
+ }
+ };
+
+ private PipManager() { }
+
+ /**
+ * Initializes {@link PipManager}.
+ */
+ public void initialize(Context context) {
+ if (mInitialized) {
+ return;
+ }
+ mInitialized = true;
+ mContext = context;
+ Resources res = context.getResources();
+ mPipBound = Rect.unflattenFromString(res.getString(
+ com.android.internal.R.string.config_defaultPictureInPictureBounds));
+ mMenuModePipBound = Rect.unflattenFromString(res.getString(
+ com.android.internal.R.string.config_centeredPictureInPictureBounds));
+
+ mActivityManager = ActivityManagerNative.getDefault();
+ TaskStackListener taskStackListener = new TaskStackListener();
+ IActivityManager iam = ActivityManagerNative.getDefault();
+ try {
+ iam.registerTaskStackListener(taskStackListener);
+ } catch (RemoteException e) {
+ Log.e(TAG, "registerTaskStackListener failed", e);
+ }
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_PICTURE_IN_PICTURE_BUTTON);
+ mContext.registerReceiver(mPipButtonReceiver, intentFilter);
+ }
+
+ private void startPip() {
+ try {
+ mActivityManager.moveTopActivityToPinnedStack(FULLSCREEN_WORKSPACE_STACK_ID, mPipBound);
+ } catch (RemoteException|IllegalArgumentException e) {
+ Log.e(TAG, "moveTopActivityToPinnedStack failed", e);
+ }
+
+ }
+
+ /**
+ * Closes PIP (PIPped activity and PIP system UI).
+ */
+ public void closePip() {
+ mState = STATE_NO_PIP;
+ StackInfo stackInfo = null;
+ try {
+ stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (stackInfo == null) {
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getStackInfo failed", e);
+ return;
+ }
+ for (int taskId : stackInfo.taskIds) {
+ try {
+ mActivityManager.removeTask(taskId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "removeTask failed", e);
+ }
+ }
+ }
+
+ /**
+ * Moves the PIPped activity to the fullscreen and closes PIP system UI.
+ */
+ public void movePipToFullscreen() {
+ mState = STATE_NO_PIP;
+ for (int i = mListeners.size() - 1; i >= 0; --i) {
+ mListeners.get(i).onMoveToFullscreen();
+ }
+ try {
+ mActivityManager.moveTasksToFullscreenStack(PINNED_STACK_ID, true);
+ } catch (RemoteException e) {
+ Log.e(TAG, "moveTasksToFullscreenStack failed", e);
+ }
+ }
+
+ /**
+ * Shows PIP overlay UI by launching {@link PipOverlayActivity}. It also locates the pinned
+ * stack to the default PIP bound {@link com.android.internal.R.string
+ * .config_defaultPictureInPictureBounds}.
+ */
+ public void showPipOverlay() {
+ if (DEBUG) Log.d(TAG, "showPipOverlay()");
+ try {
+ mActivityManager.resizeStack(PINNED_STACK_ID, mPipBound, false);
+ } catch (Exception e) {
+ Log.e(TAG, "resizeStack failed", e);
+ closePip();
+ return;
+ }
+ mState = STATE_PIP_OVERLAY;
+ launchPipOverlayActivity();
+ }
+
+ /**
+ * 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
+ * .config_centeredPictureInPictureBounds}.
+ */
+ public void showPipMenu() {
+ if (DEBUG) Log.d(TAG, "showPipMenu()");
+ try {
+ mActivityManager.resizeStack(PINNED_STACK_ID, mMenuModePipBound, false);
+ } catch (Exception e) {
+ Log.e(TAG, "resizeStack failed", e);
+ closePip();
+ return;
+ }
+ mState = STATE_PIP_MENU;
+ for (int i = mListeners.size() - 1; i >= 0; --i) {
+ mListeners.get(i).onShowPipMenu();
+ }
+ Intent intent = new Intent(mContext, PipMenuActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchStackId(PINNED_STACK_ID);
+ mContext.startActivity(intent, options.toBundle());
+ }
+
+ /**
+ * Adds {@link Listener}.
+ */
+ public void addListener(Listener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Removes {@link Listener}.
+ */
+ public void removeListener(Listener listener) {
+ mListeners.remove(listener);
+ }
+
+ private void launchPipOverlayActivity() {
+ Intent intent = new Intent(mContext, PipOverlayActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchStackId(PINNED_STACK_ID);
+ mContext.startActivity(intent, options.toBundle());
+ }
+
+ private boolean hasPipTasks() {
+ try {
+ StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ return stackInfo != null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "getStackInfo failed", e);
+ return false;
+ }
+ }
+
+ private class TaskStackListener extends ITaskStackListener.Stub {
+ @Override
+ public void onTaskStackChanged() throws RemoteException {
+ // Post the message back to the UI thread.
+ mHandler.post(mOnTaskStackChanged);
+ }
+
+ @Override
+ public void onActivityPinned() throws RemoteException {
+ // Post the message back to the UI thread.
+ mHandler.post(mOnActivityPinnedRunnable);
+ }
+ }
+
+ /**
+ * A listener interface to receive notification on changes in PIP.
+ */
+ public interface Listener {
+ /**
+ * Invoked when a PIPped activity is closed.
+ */
+ void onPipActivityClosed();
+ /**
+ * Invoked when the PIP menu gets shown.
+ */
+ void onShowPipMenu();
+ /**
+ * Invoked when the PIPped activity is returned back to the fullscreen.
+ */
+ void onMoveToFullscreen();
+ }
+
+ /**
+ * Gets an instance of {@link PipManager}.
+ */
+ public static PipManager getInstance() {
+ if (sPipManager == null) {
+ sPipManager = new PipManager();
+ }
+ return sPipManager;
+ }
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.systemui.tv.pip;
+
+import android.app.Activity;
+import android.media.session.MediaController;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.R;
+
+/**
+ * Activity to show the PIP menu to control PIP.
+ */
+public class PipMenuActivity extends Activity implements PipManager.Listener {
+ private static final String TAG = "PipMenuActivity";
+ private static final boolean DEBUG = false;
+
+ private final PipManager mPipManager = PipManager.getInstance();
+ private MediaController mMediaController;
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.tv_pip_menu);
+ mPipManager.addListener(this);
+ findViewById(R.id.full).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPipManager.movePipToFullscreen();
+ }
+ });
+ findViewById(R.id.exit).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPipManager.closePip();
+ finish();
+ }
+ });
+ findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPipManager.showPipOverlay();
+ finish();
+ }
+ });
+ }
+
+ @Override
+ protected void onDestroy() {
+ mPipManager.removeListener(this);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onBackPressed() {
+ mPipManager.showPipOverlay();
+ finish();
+ }
+
+ @Override
+ public void onPipActivityClosed() {
+ finish();
+ }
+
+ @Override
+ public void onShowPipMenu() { }
+
+ @Override
+ public void onMoveToFullscreen() {
+ finish();
+ }
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.systemui.tv.pip;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.R;
+
+/**
+ * Activity to show an overlay on top of PIP activity to show how to pop up PIP menu.
+ */
+public class PipOverlayActivity extends Activity implements PipManager.Listener {
+ private static final String TAG = "PipOverlayActivity";
+ private static final boolean DEBUG = false;
+
+ private static final long SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS = 2000;
+
+ private final PipManager mPipManager = PipManager.getInstance();
+ private final Handler mHandler = new Handler();
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.tv_pip_overlay);
+ mPipManager.addListener(this);
+ final View overlayView = findViewById(R.id.guide_overlay);
+ // TODO: apply animation
+ overlayView.setVisibility(View.VISIBLE);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ overlayView.setVisibility(View.INVISIBLE);
+ }
+ }, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mHandler.removeCallbacksAndMessages(null);
+ mPipManager.removeListener(this);
+ }
+
+ @Override
+ public void onPipActivityClosed() {
+ finish();
+ }
+
+ @Override
+ public void onShowPipMenu() {
+ finish();
+ }
+
+ @Override
+ public void onMoveToFullscreen() {
+ finish();
+ }
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.systemui.tv.pip;
+
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+
+import com.android.systemui.SystemUI;
+
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+
+/**
+ * Controls the picture-in-picture window for TV devices.
+ */
+public class PipUI extends SystemUI {
+ private boolean mSupportPip;
+
+ @Override
+ public void start() {
+ PackageManager pm = mContext.getPackageManager();
+ mSupportPip = pm.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)
+ && pm.hasSystemFeature(FEATURE_LEANBACK);
+ if (!mSupportPip) {
+ return;
+ }
+ PipManager pipManager = PipManager.getInstance();
+ pipManager.initialize(mContext);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ if (!mSupportPip) {
+ return;
+ }
+ // TODO: handle configuration change.
+ }
+}