Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82ac50d6 authored by Jaewan Kim's avatar Jaewan Kim
Browse files

PIP: Fix NPE when an activity is PIPed again immediately

More proper fix would be not showing Recents after an activity is PIPed,
but NPE shouldn't be happen so let me propose the CL as the first step.

Bug: 27634771
Change-Id: Ie98293b7dd2d206567ded08d54134164aa78ca9c
parent 07db6f39
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -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>
+48 −31
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+17 −12
Original line number Diff line number Diff line
@@ -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. */
+3 −0
Original line number Diff line number Diff line
@@ -197,6 +197,9 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
        restorePipAndFinish();
    }

    @Override
    public void onPipEntered() { }

    @Override
    public void onPipActivityClosed() {
        finish();
+3 −0
Original line number Diff line number Diff line
@@ -66,6 +66,9 @@ public class PipOnboardingActivity extends Activity implements PipManager.Listen
        mPipManager.removeListener(this);
    }

    @Override
    public void onPipEntered() { }

    @Override
    public void onPipActivityClosed() {
        finish();
Loading