IMS-VT: Low battery handling for calls that can change to VT

1. For outgoing upgrade requests, seek user confirmation and
   as per user input, place the outgoing upgrade request

2. For incoming upgrade requests, if user tries to accept as
   Video, seek user confirmation and accordingly handle the
   incoming upgrade request

Change-Id: I8ea12a81b70e8e08a113d3c27721b17da65f0926
CRs-Fixed: 1091387
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index de49fff..91a8e0b 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -355,9 +355,11 @@
         int currUnpausedVideoState = VideoUtils.getUnPausedVideoState(currVideoState);
         currUnpausedVideoState |= VideoProfile.STATE_BIDIRECTIONAL;
 
-        VideoProfile videoProfile = new VideoProfile(currUnpausedVideoState);
-        videoCall.sendSessionModifyRequest(videoProfile);
-        mCall.setSessionModificationState(Call.SessionModificationState.WAITING_FOR_RESPONSE);
+        if (!InCallLowBatteryListener.getInstance().onChangeToVideoCall(mCall)) {
+            VideoProfile videoProfile = new VideoProfile(currUnpausedVideoState);
+            videoCall.sendSessionModifyRequest(videoProfile);
+            mCall.setSessionModificationState(Call.SessionModificationState.WAITING_FOR_RESPONSE);
+        }
 
         if (QtiCallUtils.useCustomVideoUi(context)) {
             InCallAudioManager.getInstance().onModifyCallClicked(mCall,
diff --git a/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java b/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java
index c413b07..d835616 100644
--- a/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java
+++ b/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java
@@ -38,6 +38,7 @@
 import android.content.DialogInterface.OnDismissListener;
 import android.content.DialogInterface.OnKeyListener;
 import android.os.Bundle;
+import android.telecom.InCallService.VideoCall;
 import android.telecom.VideoProfile;
 import android.view.KeyEvent;
 import android.view.WindowManager;
@@ -73,7 +74,7 @@
  * signalling that low battery indication for the call can be processed now.
  */
 public class InCallLowBatteryListener implements CallList.Listener, InCallDetailsListener,
-        InCallUiListener {
+        InCallUiListener, CallList.CallUpdateListener {
 
     private static InCallLowBatteryListener sInCallLowBatteryListener;
     private PrimaryCallTracker mPrimaryCallTracker;
@@ -168,6 +169,11 @@
             return;
         }
 
+        /* Clean up callUpdateListener in case call is terminated during MT upgrade
+           request is in progress. */
+        if (isIncomingUpgradeReq(call.getSessionModificationState())) {
+            CallList.getInstance().removeCallUpdateListener(call.getId(), this);
+        }
         mLowBatteryMap.remove(call);
     }
 
@@ -206,10 +212,108 @@
             return;
         }
 
+        /* There can be chances to miss displaying low battery dialog when user tries to
+         * accept incoming VT upgrade request from HUN due to absence of InCallActivity.
+         * In such cases, show low battery dialog when InCallActivity is visible
+         */
         maybeProcessLowBatteryIndication(call);
     }
 
     /**
+     * This method overrides onCallChanged method of {@interface CallList.CallUpdateListener}
+     * Added for completeness. No implementation yet.
+     */
+     @Override
+     public void onCallChanged(Call call) {
+     }
+
+    /**
+     * This method overrides onLastForwardedNumberChange method of
+     * {@interface CallList.CallUpdateListener}. Added for completeness.
+     *  No implementation yet.
+     */
+     @Override
+     public void onLastForwardedNumberChange() {
+     }
+
+    /**
+     * This method overrides onChildNumberChange method of {@interface CallList.CallUpdateListener}
+     * Added for completeness. No implementation yet.
+     */
+     @Override
+     public void onChildNumberChange() {
+     }
+
+    /**
+     * This method overrides onSessionModificationStateChange method of
+     * {@interface CallList.CallUpdateListener}
+     * @param call The call object for which session modify change occurred
+     * @param sessionModificationState contains the session modification state change
+     */
+     @Override
+     public void onSessionModificationStateChange(Call call, int sessionModificationState) {
+         Log.d(this, "onSessionModificationStateChange call = " + call);
+
+         if (call == null) {
+             return;
+         }
+
+         if (!isIncomingUpgradeReq(sessionModificationState)) {
+             Log.d(this, "onSessionModificationStateChange removing call update listener");
+             CallList.getInstance().removeCallUpdateListener(call.getId(), this);
+             /*
+              * Dismiss low battery dialog (if any) for eg. when incoming upgrade request
+              * times-out possibly because there is no user input on low battery dialog or
+              * when user dismisses the MT upgrade request from HUN with low battery dialog
+              * showing etc.
+              */
+             dismissPendingDialogs();
+         }
+     }
+
+     private boolean isIncomingUpgradeReq(int sessionModificationState) {
+         return (sessionModificationState ==
+                 Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST);
+     }
+
+    /**
+     * When there is user action to modify call as Video call (for eg click on upgrade
+     * button or accepting incoming upgrade request as video), this API checks to see
+     * if UE is under low battery or not and accordingly processes the callType change
+     * to video and returns TRUE if the callType change is handled by this API else FALSE
+     *
+     * @param call The call that is undergoing a change to video call
+     */
+    public boolean onChangeToVideoCall(Call call) {
+        Log.d(this, "onChangeToVideoCall call = " + call);
+        if (call == null || !mPrimaryCallTracker.isPrimaryCall(call)) {
+            return false;
+        }
+
+        if (!isLowBattery(call.getTelecomCall().getDetails())) {
+           // Do not process if the call is changing to Video when UE is NOT under low battery
+           return false;
+        }
+
+        /* If user tries to change to Video call again, then remove the call from
+         * from lowbatterymap to ensure that the dialog will be shown again
+         */
+        if (mLowBatteryMap.replace(call, PROCESS_LOW_BATTERY) == null) {
+            Log.d(this, "this call is not present in the lowbatterymap. add it.");
+            mLowBatteryMap.put(call, PROCESS_LOW_BATTERY);
+        }
+
+        /* Listen to call updates only when there is a incoming upgrade request so that
+           low battery dialog can be dismissed if MT upgrade request times out */
+        if (isIncomingUpgradeReq(call.getSessionModificationState())) {
+            CallList.getInstance().addCallUpdateListener(call.getId(), this);
+        }
+
+        maybeProcessLowBatteryIndication(call);
+        return true;
+    }
+
+    /**
      * When call is answered, this API checks to see if UE is under low battery or not
      * and accordingly processes the low battery video call and returns TRUE if
      * user action to answer the call is handled by this API else FALSE.
@@ -360,10 +464,6 @@
     }
 
     private void maybeProcessLowBatteryIndication(Call call) {
-        if (!isLowBatteryVideoCall(call)) {
-            return;
-        }
-
         if (canProcessLowBatteryIndication(call)) {
             displayLowBatteryAlert(call);
             //mark against the call that the respective low battery indication is processed
@@ -477,6 +577,68 @@
                     }
                 });
             }
+        } else if (isIncomingUpgradeReq(call.getSessionModificationState())) {
+            // Incoming upgrade request handling
+            alertDialog.setPositiveButton(R.string.low_battery_convert, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    Log.d(this, "displayLowBatteryAlert decline upgrade request");
+                    CallList.getInstance().removeCallUpdateListener(call.getId(),
+                            InCallLowBatteryListener.this);
+                    InCallPresenter.getInstance().declineUpgradeRequest();
+                }
+            });
+
+            alertDialog.setMessage(R.string.low_battery_msg);
+            alertDialog.setNegativeButton(R.string.low_battery_yes, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    Log.d(this, "displayLowBatteryAlert accept upgrade request as Video Call");
+                    /* Control reached here means upgrade req can be accepted only as
+                       bidirectional video call */
+                    VideoProfile videoProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL);
+                    call.getVideoCall().sendSessionModifyResponse(videoProfile);
+                    call.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
+                    InCallAudioManager.getInstance().onAcceptUpgradeRequest(call,
+                            VideoProfile.STATE_BIDIRECTIONAL);
+                }
+            });
+        } else {
+            // Outgoing upgrade request handling
+            alertDialog.setPositiveButton(R.string.low_battery_convert, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    Log.d(this, "displayLowBatteryAlert change to Voice Call");
+
+                    // Change the audio route to earpiece
+                    InCallAudioManager.getInstance().onModifyCallClicked(call,
+                            VideoProfile.STATE_AUDIO_ONLY);
+                }
+            });
+
+            alertDialog.setMessage(R.string.low_battery_msg);
+            alertDialog.setNegativeButton(R.string.low_battery_yes, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    Log.d(this, "displayLowBatteryAlert change to Video Call");
+
+                    VideoCall videoCall = call.getVideoCall();
+                    if (videoCall == null) {
+                        Log.w(this, "displayLowBatteryAlert videocall is null");
+                        return;
+                    }
+
+                    int currUnpausedVideoState = VideoUtils.getUnPausedVideoState(
+                            call.getVideoState());
+                    // Send bidirectional modify request
+                    currUnpausedVideoState |= VideoProfile.STATE_BIDIRECTIONAL;
+
+                    VideoProfile videoProfile = new VideoProfile(currUnpausedVideoState);
+                    videoCall.sendSessionModifyRequest(videoProfile);
+                    call.setSessionModificationState(
+                            Call.SessionModificationState.WAITING_FOR_RESPONSE);
+                }
+            });
         }
 
         mAlert = alertDialog.create();
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 2a1ecab..fa8ddb5 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -1058,7 +1058,7 @@
         }
 
         Call call = mCallList.getVideoUpgradeRequestCall();
-        if (call != null) {
+        if (call != null && !InCallLowBatteryListener.getInstance().onChangeToVideoCall(call)) {
             VideoProfile videoProfile = new VideoProfile(videoState);
             call.getVideoCall().sendSessionModifyResponse(videoProfile);
             call.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
diff --git a/InCallUI/src/com/android/incallui/NotificationBroadcastReceiver.java b/InCallUI/src/com/android/incallui/NotificationBroadcastReceiver.java
index 94a852b..08389ef 100644
--- a/InCallUI/src/com/android/incallui/NotificationBroadcastReceiver.java
+++ b/InCallUI/src/com/android/incallui/NotificationBroadcastReceiver.java
@@ -69,6 +69,7 @@
             InCallPresenter.getInstance().hangUpOngoingCall(context);
         } else if (action.equals(ACTION_ACCEPT_VIDEO_UPGRADE_REQUEST)) {
             InCallPresenter.getInstance().acceptUpgradeRequest(context);
+            InCallPresenter.getInstance().bringToForeground(false);
         } else if (action.equals(ACTION_DECLINE_VIDEO_UPGRADE_REQUEST)) {
             InCallPresenter.getInstance().declineUpgradeRequest(context);
         } else if (action.equals(ACTION_PULL_EXTERNAL_CALL)) {