1313import android .content .pm .PackageManager ;
1414import android .os .Build ;
1515import android .os .Bundle ;
16- import android .os .PowerManager ;
1716import android .util .Log ;
1817import android .util .Rational ;
1918import android .view .View ;
@@ -30,14 +29,14 @@ public abstract class CallBaseActivity extends BaseActivity {
3029
3130 public PictureInPictureParams .Builder mPictureInPictureParamsBuilder ;
3231 public Boolean isInPipMode = Boolean .FALSE ;
33- long onCreateTime ;
3432
35-
36- private OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback (true ) {
33+ private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback (true ) {
3734 @ Override
3835 public void handleOnBackPressed () {
3936 if (isPipModePossible ()) {
4037 enterPipMode ();
38+ } else {
39+ moveTaskToBack (true );
4140 }
4241 }
4342 };
@@ -47,21 +46,25 @@ public void handleOnBackPressed() {
4746 public void onCreate (Bundle savedInstanceState ) {
4847 super .onCreate (savedInstanceState );
4948
50- onCreateTime = System .currentTimeMillis ();
51-
5249 requestWindowFeature (Window .FEATURE_NO_TITLE );
5350 dismissKeyguard ();
5451 getWindow ().addFlags (WindowManager .LayoutParams .FLAG_FULLSCREEN );
5552 getWindow ().addFlags (WindowManager .LayoutParams .FLAG_KEEP_SCREEN_ON );
5653
5754 if (isPipModePossible ()) {
5855 mPictureInPictureParamsBuilder = new PictureInPictureParams .Builder ();
56+ Rational pipRatio = new Rational (300 , 500 );
57+ mPictureInPictureParamsBuilder .setAspectRatio (pipRatio );
58+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
59+ mPictureInPictureParamsBuilder .setAutoEnterEnabled (true );
60+ }
61+ setPictureInPictureParams (mPictureInPictureParamsBuilder .build ());
5962 }
6063
6164 getOnBackPressedDispatcher ().addCallback (this , onBackPressedCallback );
6265 }
6366
64- public void hideNavigationIfNoPipAvailable (){
67+ public void hideNavigationIfNoPipAvailable () {
6568 if (!isPipModePossible ()) {
6669 getWindow ().getDecorView ().setSystemUiVisibility (View .SYSTEM_UI_FLAG_LAYOUT_STABLE |
6770 View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
@@ -91,39 +94,82 @@ void enableKeyguard() {
9194 }
9295 }
9396
97+ /**
98+ * On API 29+, fires BEFORE onPause while the window is still fully visible.
99+ *
100+ * On API 29-30: enter PIP immediately (no auto-enter available).
101+ *
102+ * On API 31+: auto-enter handles swipe-up/home gestures. Task switching
103+ * (left/right swipe) does NOT trigger auto-enter — we accept no PIP for
104+ * task switch since the call stays alive in the background via the ICE
105+ * failure guard in CallActivity.
106+ */
107+ @ Override
108+ public void onTopResumedActivityChanged (boolean isTopResumedActivity ) {
109+ super .onTopResumedActivityChanged (isTopResumedActivity );
110+ Log .d (TAG , "onTopResumedActivityChanged: isTopResumedActivity=" + isTopResumedActivity
111+ + " isInPictureInPictureMode=" + isInPictureInPictureMode ());
112+ if (isTopResumedActivity || isInPictureInPictureMode ()
113+ || !isPipModePossible ()
114+ || isChangingConfigurations ()
115+ || isFinishing ()) {
116+ return ;
117+ }
118+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .S ) {
119+ enterPipMode ();
120+ }
121+ }
122+
123+ @ Override
124+ public void onPause () {
125+ super .onPause ();
126+ Log .d (TAG , "onPause: isInPipMode=" + isInPipMode
127+ + " isInPictureInPictureMode=" + isInPictureInPictureMode ());
128+ // Fallback for API 26-28 where onTopResumedActivityChanged doesn't exist.
129+ // On API 29+, onTopResumedActivityChanged already handled this.
130+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .Q
131+ && !isInPictureInPictureMode ()
132+ && isPipModePossible ()
133+ && !isChangingConfigurations ()
134+ && !isFinishing ()) {
135+ enterPipMode ();
136+ }
137+ }
138+
94139 @ Override
95140 public void onStop () {
96141 super .onStop ();
97- if (shouldFinishOnStop ()) {
98- finish ();
99- }
142+ Log .d (TAG , "onStop: isInPipMode=" + isInPipMode + " isFinishing=" + isFinishing ());
100143 }
101144
102145 @ Override
103146 protected void onUserLeaveHint () {
104147 super .onUserLeaveHint ();
105- long onUserLeaveHintTime = System .currentTimeMillis ();
106- long diff = onUserLeaveHintTime - onCreateTime ;
107- Log .d (TAG , "onUserLeaveHintTime - onCreateTime: " + diff );
108-
109- if (diff < 3000 ) {
110- Log .d (TAG , "enterPipMode skipped" );
111- } else {
148+ Log .d (TAG , "onUserLeaveHint: isInPipMode=" + isInPipMode
149+ + " isInPictureInPictureMode=" + isInPictureInPictureMode ());
150+ // On API 26-30, enter PIP manually. On API 31+ auto-enter handles swipe-up/home, and plain
151+ // backgrounding (e.g. task switch) keeps the activity alive on its own. Deliberately no
152+ // moveTaskToBack here: onUserLeaveHint also fires when a transient overlay like the
153+ // permission dialog appears at call start, which would throw the call to the background.
154+ if (!isInPipMode
155+ && isPipModePossible ()
156+ && Build .VERSION .SDK_INT < Build .VERSION_CODES .S ) {
112157 enterPipMode ();
113158 }
114159 }
115160
116161 void enterPipMode () {
162+ Log .d (TAG , "enterPipMode: isPipModePossible=" + isPipModePossible () + " isInPipMode=" + isInPipMode );
117163 enableKeyguard ();
118164 if (isPipModePossible ()) {
119165 Rational pipRatio = new Rational (300 , 500 );
120166 mPictureInPictureParamsBuilder .setAspectRatio (pipRatio );
121- enterPictureInPictureMode (mPictureInPictureParamsBuilder .build ());
167+ boolean entered = enterPictureInPictureMode (mPictureInPictureParamsBuilder .build ());
168+ Log .d (TAG , "enterPictureInPictureMode returned: " + entered );
122169 } else {
123- // we don't support other solutions than PIP to have a call in the background.
124- // If PIP is not available the call is ended when user presses the home button.
125- Log .d (TAG , "Activity was finished because PIP is not available." );
126- finish ();
170+ // If PIP is not available, move to background instead of finishing
171+ Log .d (TAG , "PIP is not available, moving call to background." );
172+ moveTaskToBack (true );
127173 }
128174 }
129175
@@ -138,19 +184,6 @@ boolean isPipModePossible() {
138184 return deviceHasPipFeature && isPipFeatureGranted ;
139185 }
140186
141- private boolean shouldFinishOnStop () {
142- if (!isInPipMode ) {
143- return false ;
144- }
145-
146- PowerManager powerManager = (PowerManager ) getSystemService (Context .POWER_SERVICE );
147- if (powerManager == null ) {
148- return true ;
149- }
150-
151- return powerManager .isInteractive ();
152- }
153-
154187 public abstract void updateUiForPipMode ();
155188
156189 public abstract void updateUiForNormalMode ();
0 commit comments