Phone app: Initial *minimal* set of Phone UI changes for CDMA.
David Brown [Thu, 14 May 2009 18:27:54 +0000 (11:27 -0700)]
Fix a couple of CDMA-specific issues in the in-call UI:

- Add a new mode to the CallCard for the "generic call" state, where the
  phone is in use but we don't know any specific details about the state
  of the call (like who you're talking to, or how many lines are in use.)

  NOTE this can't actually be enabled till the Call.isGeneric() API gets
  checked in.  (See the TODO comment in updateForegroundCall().)

- Make sure the "Manage conference" UI (which is GSM-specific) is never
  enabled on CDMA phones

These changes are mostly untested, since I don't have a CDMA phone with
working telephony yet.  (But the PhoneUtils/InCallScreen changes are
ultra-simple, and I was at least able to test the "generic call" UI by
temporarily hacking the code to pretend that Call.isGeneric() returned
true.)

I did at least make sure this doesn't break anything on GSM phones.

This change does NOT include:

- Automatically timing-out the "call waiting" connection if ignored by
  the user.  (The Moto team is already doing this, in the CallNotifier
  class.)

- Make sure the "Merge calls" and "Swap calls" menu items are enabled
  only when it's *really* possible to merge or swap.  (The current logic
  is GSM-specific.)  Added TODO comments in PhoneUtils.java for these.

src/com/android/phone/CallCard.java
src/com/android/phone/InCallScreen.java
src/com/android/phone/PhoneUtils.java

index 7480e13..ec216d1 100644 (file)
@@ -190,6 +190,10 @@ public class CallCard extends FrameLayout
         mMenuButtonHint = (TextView) findViewById(R.id.menuButtonHint);
     }
 
+    /**
+     * Updates the state of all UI elements on the CallCard, based on the
+     * current state of the phone.
+     */
     void updateState(Phone phone) {
         if (DBG) log("updateState(" + phone + ")...");
 
@@ -250,6 +254,14 @@ public class CallCard extends FrameLayout
         Call fgCall = phone.getForegroundCall();
         Call bgCall = phone.getBackgroundCall();
 
+        // Check for the "generic call" state.
+        if (false /* TODO(CDMA): use "fgCall.isGeneric()" here, once that API is checked in */ ) {
+            // Show the special "generic call" state instead of the regular
+            // in-call CallCard state.
+            updateGenericCall(phone);
+            return;
+        }
+
         if (fgCall.isIdle() && !fgCall.hasConnections()) {
             if (DBG) log("updateForegroundCall: no active call, show holding call");
             // TODO: make sure this case agrees with the latest UI spec.
@@ -270,6 +282,24 @@ public class CallCard extends FrameLayout
     }
 
     /**
+     * Updates the UI for the "generic call" state, where the phone is in
+     * use but we don't know any specific details about the state of the
+     * call (like who you're talking to, or how many lines are in use.)
+     */
+    private void updateGenericCall(Phone phone) {
+        if (DBG) log("updateForegroundCall()...");
+
+        Call fgCall = phone.getForegroundCall();
+
+        // Display the special "generic" state in the main call area:
+        displayMainCallGeneric(phone, fgCall);
+
+        // And hide the "other call" info areas:
+        displayOnHoldCallStatus(phone, null);
+        displayOngoingCallStatus(phone, null);
+    }
+
+    /**
      * Updates the UI for the state where an incoming call is ringing (or
      * call waiting), regardless of whether the phone's already offhook.
      */
@@ -347,7 +377,6 @@ public class CallCard extends FrameLayout
                             : R.drawable.incall_frame_connected_tall_port;
                 }
 
-
                 // update timer field
                 if (DBG) log("displayMainCallStatus: start periodicUpdateTimer");
                 mCallTime.setActiveCallMode(call);
@@ -439,6 +468,10 @@ public class CallCard extends FrameLayout
                 break;
         }
 
+        // Set the background frame color based on the state of the call.
+        setMainCallCardBackgroundResource(callCardBackgroundResid);
+        // (Text colors are set in updateCardTitleWidgets().)
+
         updateCardTitleWidgets(phone, call);
 
         if (PhoneUtils.isConferenceCall(call)) {
@@ -506,10 +539,56 @@ public class CallCard extends FrameLayout
         // indication of the current state, rather than displaying the
         // regular photo as set above.
         updatePhotoForCallState(call);
+    }
+
+    /**
+     * Version of displayMainCallStatus() that sets the main call area
+     * into the "generic" state.
+     * @see displayMainCallStatus
+     */
+    private void displayMainCallGeneric(Phone phone, Call call) {
+        if (DBG) log("displayMainCallGeneric(phone " + phone
+                     + ", call " + call + ")...");
+
+        mMainCallCard.setVisibility(View.VISIBLE);
+
+        // Background frame resources are different between portrait/landscape.
+        // TODO: Don't do this manually.  Instead let the resource system do
+        // it: just move the *_land assets over to the res/drawable-land
+        // directory (but with the same filename as the corresponding
+        // portrait asset.)
+        boolean landscapeMode = InCallScreen.ConfigurationHelper.isLandscape();
+
+        // Background images are also different if Bluetooth is active.
+        final boolean bluetoothActive = PhoneApp.getInstance().showBluetoothIndication();
+
+        showCallConnected();
+
+        int callCardBackgroundResid = 0;
+        if (bluetoothActive) {
+            callCardBackgroundResid =
+                    landscapeMode ? R.drawable.incall_frame_bluetooth_tall_land
+                    : R.drawable.incall_frame_bluetooth_tall_port;
+        } else {
+            callCardBackgroundResid =
+                    landscapeMode ? R.drawable.incall_frame_connected_tall_land
+                    : R.drawable.incall_frame_connected_tall_port;
+        }
 
         // Set the background frame color based on the state of the call.
         setMainCallCardBackgroundResource(callCardBackgroundResid);
         // (Text colors are set in updateCardTitleWidgets().)
+
+        // Update timer field:
+        // TODO(CDMA): Need to confirm that we can trust the time info
+        // from the passed-in Call object, even though the call is "generic".
+        if (DBG) log("displayMainCallStatus: start periodicUpdateTimer");
+        mCallTime.setActiveCallMode(call);
+        mCallTime.reset();
+        mCallTime.periodicUpdateTimer();
+
+        updateCardTitleWidgets(phone, call);
+        updateDisplayForGenericCall();
     }
 
     /**
@@ -885,6 +964,9 @@ public class CallCard extends FrameLayout
      *
      * If the current call is a conference call, use
      * updateDisplayForConference() instead.
+     *
+     * If the phone is in the "generic call" state, use
+     * updateDisplayForGenericCall() instead.
      */
     private void updateDisplayForPerson(CallerInfo info,
                                         int presentation,
@@ -1016,6 +1098,25 @@ public class CallCard extends FrameLayout
     }
 
     /**
+     * Updates the name / photo / number / label fields
+     * for the special "generic call" state.
+     * @see updateDisplayForPerson
+     * @see updateDisplayForConference
+     */
+    private void updateDisplayForGenericCall() {
+        if (DBG) log("updateDisplayForGenericCall()...");
+
+        // Display a generic "in-call" image in the photo slot, with no
+        // other information.
+
+        showImage(mPhoto, R.drawable.picture_dialing);
+
+        mName.setVisibility(View.GONE);
+        mPhoneNumber.setVisibility(View.GONE);
+        mLabel.setVisibility(View.GONE);
+    }
+
+    /**
      * Updates the CallCard "photo" IFF the specified Call is in a state
      * that needs a special photo (like "busy" or "dialing".)
      *
index f723b6d..2e30ac8 100644 (file)
@@ -1040,13 +1040,20 @@ public class InCallScreen extends Activity
         if (mPhone.getPhoneName().equals("CDMA")) {
             // The green CALL button means either "Answer", "Swap calls/On Hold", or
             // "Add to 3WC", depending on the current state of the Phone.
-
             if (hasRingingCall) {
                 if (VDBG) log("handleCallKey: ringing ==> answer!");
                 internalAnswerCall();  // Automatically holds the current active call,
                                        // if there is one
             } else {
-                // send an empty CDMA flash string
+                // On a CDMA phone, if there's no ringing call, CALL means
+                // "flash" in any context.  (Depending on the state of the
+                // network, this could mean "hold", "swap calls", or
+                // "merge into 3-way call".)
+
+                // TODO: It's ugly to call switchHoldingAndActive() here,
+                // since we're not *really* trying to swap calls.  (We just
+                // want to send a flash command.)  Instead, consider having
+                // the telephony layer provide an explicit "flash" API.
                 PhoneUtils.switchHoldingAndActive(mPhone);
             }
         } else {
index 3af1072..7648948 100644 (file)
@@ -1125,7 +1125,10 @@ public class PhoneUtils {
 
     /**
      * Returns true if the specified Call is a "conference call", meaning
-     * that it owns more than one Connection object.
+     * that it owns more than one Connection object.  This information is
+     * used to trigger certain UI changes that appear when a conference
+     * call is active (like displaying the label "Conference call", and
+     * enabling the "Manage conference" UI.)
      *
      * Watch out: This method simply checks the number of Connections,
      * *not* their states.  So if a Call has (for example) one ACTIVE
@@ -1136,6 +1139,16 @@ public class PhoneUtils {
      * @return true if the specified call has more than one connection (in any state.)
      */
     static boolean isConferenceCall(Call call) {
+        // CDMA phones don't have the same concept of "conference call" as
+        // GSM phones do; there's no special "conference call" state of
+        // the UI or a "manage conference" function.  (Instead, when
+        // you're in a 3-way call, all we can do is display the "generic"
+        // state of the UI.)  So as far as the in-call UI is concerned,
+        // CDMA calls are *never* "conference calls".
+        if (PhoneApp.getInstance().phone.getPhoneName().equals("CDMA")) {
+            return false;
+        }
+
         List<Connection> connections = call.getConnections();
         if (connections != null && connections.size() > 1) {
             return true;
@@ -1494,6 +1507,7 @@ public class PhoneUtils {
         // call really is in the ACTIVE state and the holding call really
         // is in the HOLDING state, since you *can't* actually swap calls
         // when the foreground call is DIALING or ALERTING.)
+        // TODO(CDMA): Need to handle the CDMA case too.
         return phone.getRingingCall().isIdle()
                 && (phone.getForegroundCall().getState() == Call.State.ACTIVE)
                 && (phone.getBackgroundCall().getState() == Call.State.HOLDING);
@@ -1507,6 +1521,7 @@ public class PhoneUtils {
         // "Merge" is available if both lines are in use and there's no
         // incoming call, *and* the current conference isn't already
         // "full".
+        // TODO(CDMA): Need to handle the CDMA case too.
         return phone.getRingingCall().isIdle() && phone.canConference();
     }
 
@@ -1521,6 +1536,8 @@ public class PhoneUtils {
         // - The foreground call is ACTIVE or IDLE or DISCONNECTED.
         //   (We mainly need to make sure it *isn't* DIALING or ALERTING.)
 
+        // TODO(CDMA): Need to handle the CDMA case too.
+
         final boolean hasRingingCall = !phone.getRingingCall().isIdle();
         final boolean hasActiveCall = !phone.getForegroundCall().isIdle();
         final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle();
@@ -1541,7 +1558,8 @@ public class PhoneUtils {
 
     /* package */ static void dumpCallState(Phone phone) {
         Log.d(LOG_TAG, "##### dumpCallState()");
-        Log.d(LOG_TAG, "- Phone: " + phone + ", state = " + phone.getState());
+        Log.d(LOG_TAG, "- Phone: " + phone + ", name = " + phone.getPhoneName()
+              + ", state = " + phone.getState());
         Log.d(LOG_TAG, "-");
 
         Call fgCall = phone.getForegroundCall();