Merge "PIP: Fix NPE when an activity is PIPed again immediately" into nyc-dev

This commit is contained in:
Jaewan Kim
2016-03-22 03:42:10 +00:00
committed by Android (Google) Code Review
6 changed files with 78 additions and 49 deletions

View File

@@ -38,16 +38,15 @@
android:id="@+id/pip_shade"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:visibility="gone"
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 -->
Size and positions will be adjusted to comply with the PIP bounds -->
<View
android:id="@+id/pip"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
android:visibility="gone"
android:focusable="true" />
</com.android.systemui.recents.tv.views.RecentsTvView>

View File

@@ -84,10 +84,14 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
private PipManager mPipManager;
private PipManager.Listener mPipListener = new PipManager.Listener() {
@Override
public void onPipEntered() {
updatePipUI();
}
@Override
public void onPipActivityClosed() {
mPipView.setVisibility(View.GONE);
mPipShadeView.setVisibility(View.GONE);
updatePipUI();
}
@Override
@@ -102,6 +106,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public void onMediaControllerChanged() { }
};
private boolean mHasPip;
/**
* A common Runnable to finish Recents by launching Home with an animation depending on the
@@ -266,6 +271,10 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
mHasPip = false;
updatePipUI();
mPipManager.addListener(mPipListener);
}
@Override
@@ -296,34 +305,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
SystemServicesProxy ssp = Recents.getSystemServices();
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, 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();
@@ -340,7 +321,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
super.onStop();
mPipManager.onRecentsStopped();
mPipManager.removeListener(mPipListener);
mIgnoreAltTabRelease = false;
// Notify that recents is now hidden
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
@@ -357,6 +337,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
protected void onDestroy() {
super.onDestroy();
mPipManager.removeListener(mPipListener);
// In the case that the activity finished on startup, just skip the unregistration below
if (mFinishedOnStartup) {
return;
@@ -480,4 +461,40 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
});
return true;
}
private void updatePipUI() {
if (mHasPip == mPipManager.isPipShown()) {
return;
}
mHasPip = mPipManager.isPipShown();
if (mHasPip) {
// 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);
}
});
mPipShadeView.setVisibility(View.GONE);
} else {
mPipView.setVisibility(View.GONE);
mPipShadeView.setVisibility(View.GONE);
}
}
}

View File

@@ -120,6 +120,14 @@ public class PipManager {
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() {
@@ -384,7 +392,7 @@ public class PipManager {
try {
mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds, true, true, true, -1);
} catch (RemoteException e) {
Log.e(TAG, "showPipMenu failed", e);
Log.e(TAG, "resizeStack failed", e);
}
}
@@ -482,17 +490,7 @@ 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);
return stackInfo != null;
} catch (RemoteException e) {
Log.e(TAG, "getStackInfo failed", e);
return false;
}
return mState != STATE_NO_PIP;
}
private void handleMediaResourceGranted(String[] packageNames) {
@@ -600,6 +598,13 @@ public class PipManager {
* A listener interface to receive notification on changes in PIP.
*/
public interface Listener {
/**
* Invoked when an activity is pinned and PIP manager is set corresponding information.
* Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
* because there's no guarantee for the PIP manager be return relavent information
* correctly. (e.g. {@link isPipShown}, {@link getPipBounds})
*/
void onPipEntered();
/** Invoked when a PIPed activity is closed. */
void onPipActivityClosed();
/** Invoked when the PIP menu gets shown. */

View File

@@ -197,6 +197,9 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
restorePipAndFinish();
}
@Override
public void onPipEntered() { }
@Override
public void onPipActivityClosed() {
finish();

View File

@@ -66,6 +66,9 @@ public class PipOnboardingActivity extends Activity implements PipManager.Listen
mPipManager.removeListener(this);
}
@Override
public void onPipEntered() { }
@Override
public void onPipActivityClosed() {
finish();

View File

@@ -108,6 +108,9 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
}
@Override
public void onPipEntered() { }
@Override
public void onPipActivityClosed() {
finish();
@@ -131,8 +134,7 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
}
@Override
public void onMediaControllerChanged() {
}
public void onMediaControllerChanged() { }
@Override
public void finish() {