summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/public.xml2
-rwxr-xr-xcore/res/res/values/strings.xml6
-rw-r--r--opengl/java/android/opengl/GLSurfaceView.java39
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java21
-rw-r--r--services/java/com/android/server/wm/WindowState.java31
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java13
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyCapabilities.java160
7 files changed, 226 insertions, 46 deletions
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9c5f4d6..7b4f50b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -850,6 +850,8 @@
<java-symbol type="string" name="wifi_watchdog_network_disabled" />
<java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
<java-symbol type="string" name="yesterday" />
+ <java-symbol type="string" name="imei" />
+ <java-symbol type="string" name="meid" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7799f74..6c9576f 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -97,6 +97,12 @@
the SIM card. -->
<string name="needPuk">Your SIM card is PUK-locked. Type the PUK code to unlock it.</string>
<string name="needPuk2">Type PUK2 to unblock SIM card.</string>
+ <!-- Title for the dialog used to display the user's IMEI number [CHAR LIMIT=10] -->
+ <string name="imei">IMEI</string>
+
+ <!-- Title for the dialog used to display the user's MEID number on CDMA network
+ [CHAR LIMIT=10] -->
+ <string name="meid">MEID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
<string name="ClipMmi">Incoming Caller ID</string>
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index b868049..c937a09 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -779,8 +779,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (LOG_THREADS) {
Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId());
}
- throw new RuntimeException("eglDestroyContext failed: "
- + EGLLogWrapper.getErrorString(egl.eglGetError()));
+ EglHelper.throwEglException("eglDestroyContex", egl.eglGetError());
}
}
}
@@ -1094,7 +1093,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* the context is current and bound to a surface.
*/
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- throwEglException("eglMakeCurrent");
+ /*
+ * Could not make the context current, probably because the underlying
+ * SurfaceView surface has been destroyed.
+ */
+ logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
+ return false;
}
return true;
@@ -1134,7 +1138,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
*/
public int swap() {
if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
- return mEgl.eglGetError();
+ return mEgl.eglGetError();
}
return EGL10.EGL_SUCCESS;
}
@@ -1180,14 +1184,23 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
throwEglException(function, mEgl.eglGetError());
}
- private void throwEglException(String function, int error) {
- String message = function + " failed: " + EGLLogWrapper.getErrorString(error);
+ public static void throwEglException(String function, int error) {
+ String message = formatEglError(function, error);
if (LOG_THREADS) {
- Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " + message);
+ Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " "
+ + message);
}
throw new RuntimeException(message);
}
+ public static void logEglErrorAsWarning(String tag, String function, int error) {
+ Log.w(tag, formatEglError(function, error));
+ }
+
+ public static String formatEglError(String function, int error) {
+ return function + " failed: " + EGLLogWrapper.getErrorString(error);
+ }
+
private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
EGL10 mEgl;
EGLDisplay mEglDisplay;
@@ -1334,7 +1347,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
}
- // Have we lost the surface view surface?
+ // Have we lost the SurfaceView surface?
if ((! mHasSurface) && (! mWaitingForSurface)) {
if (LOG_SURFACE) {
Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
@@ -1446,8 +1459,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
Log.w("GLThread", "egl createSurface");
}
if (!mEglHelper.createSurface()) {
- // Couldn't create a surface. Quit quietly.
- break;
+ mSurfaceIsBad = true;
+ continue;
}
createEglSurface = false;
}
@@ -1502,12 +1515,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
break;
default:
// Other errors typically mean that the current surface is bad,
- // probably because the surfaceview surface has been destroyed,
+ // probably because the SurfaceView surface has been destroyed,
// but we haven't been notified yet.
// Log the error to help developers understand why rendering stopped.
- Log.w("GLThread", "eglSwapBuffers error: " + swapError +
- ". Assume surfaceview surface is being destroyed. tid="
- + getId());
+ EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError);
mSurfaceIsBad = true;
break;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index cecc0a0..3d60c6b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -600,7 +600,6 @@ public class WindowManagerService extends IWindowManager.Stub
private boolean mSyswin = false;
private float mScreenBrightness = -1;
private float mButtonBrightness = -1;
- private boolean mUpdateRotation = false;
}
LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields();
@@ -8575,17 +8574,17 @@ public class WindowManagerService extends IWindowManager.Stub
mTurnOnScreen = false;
}
- if (mInnerFields.mUpdateRotation) {
+ if (mAnimator.mUpdateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
if (updateRotationUncheckedLocked(false)) {
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
} else {
- mInnerFields.mUpdateRotation = false;
+ mAnimator.mUpdateRotation = false;
}
}
if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded &&
- !mInnerFields.mUpdateRotation) {
+ !mAnimator.mUpdateRotation) {
checkDrawnWindowsLocked();
}
@@ -8924,11 +8923,11 @@ public class WindowManagerService extends IWindowManager.Stub
mAnimator.mScreenRotationAnimation.kill();
mAnimator.mScreenRotationAnimation = null;
}
- if (mAnimator.mScreenRotationAnimation == null) {
- mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
- mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
- mDisplay.getRotation());
- }
+
+ mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
+ mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
+ mDisplay.getRotation());
+
if (!mAnimator.mScreenRotationAnimation.hasScreenshot()) {
Surface.freezeDisplay(0);
}
@@ -8943,6 +8942,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
+ if (DEBUG_ORIENTATION) Slog.d(TAG,
+ "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
+ + ", mAppsFreezingScreen=" + mAppsFreezingScreen
+ + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen);
return;
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 789bfaa..d22b17c 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -24,8 +24,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import com.android.server.wm.WindowManagerService.H;
-
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
@@ -40,15 +38,10 @@ import android.view.Gravity;
import android.view.IApplicationToken;
import android.view.IWindow;
import android.view.InputChannel;
-import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
-import android.view.WindowManager.LayoutParams;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Transformation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -57,6 +50,8 @@ import java.util.ArrayList;
* A window in the window manager.
*/
final class WindowState implements WindowManagerPolicy.WindowState {
+ static final String TAG = "WindowState";
+
static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
@@ -276,7 +271,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mSeq = seq;
mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
+ TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")");
try {
c.asBinder().linkToDeath(deathRecipient, 0);
@@ -304,7 +299,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
+ WindowManagerService.TYPE_LAYER_OFFSET;
mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
mAttachedWindow = attachedWindow;
- if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow);
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
mAttachedWindow.mChildWindows.add(this);
mLayoutAttached = mAttrs.type !=
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -358,7 +353,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
- WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
+ TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
@@ -496,7 +491,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (WindowManagerService.localLOGV) {
//if ("com.google.android.youtube".equals(mAttrs.packageName)
// && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth="
+ Slog.v(TAG, "Resolving (mRequestedWidth="
+ mRequestedWidth + ", mRequestedheight="
+ mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ "): frame=" + mFrame.toShortString()
@@ -600,10 +595,11 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mAppToken != null ? mAppToken.firstWindowDrawn : false;
}
+ // TODO(cmautner): Move to WindowStateAnimator
boolean finishDrawingLocked() {
if (mDrawPending) {
if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
- WindowManagerService.TAG, "finishDrawingLocked: " + this + " in "
+ TAG, "finishDrawingLocked: " + this + " in "
+ mWinAnimator.mSurface);
mCommitDrawPending = true;
mDrawPending = false;
@@ -612,6 +608,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return false;
}
+ // TODO(cmautner): Move to WindowStateAnimator
// This must be called while inside a transaction.
boolean commitFinishDrawingLocked(long currentTime) {
//Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
@@ -820,7 +817,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
disposeInputChannel();
if (mAttachedWindow != null) {
- if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
mAttachedWindow.mChildWindows.remove(this);
}
mWinAnimator.destroyDeferredSurfaceLocked();
@@ -859,7 +856,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
try {
synchronized(mService.mWindowMap) {
WindowState win = mService.windowForClientLocked(mSession, mClient, false);
- Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win);
+ Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
mService.removeWindowLocked(mSession, win);
}
@@ -891,9 +888,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// Already showing.
return false;
}
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
if (doAnimation) {
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
+ mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation);
if (!mService.okToDisplay()) {
doAnimation = false;
@@ -940,7 +937,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (doAnimation) {
mPolicyVisibilityAfterAnim = false;
} else {
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this);
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
mPolicyVisibilityAfterAnim = false;
mPolicyVisibility = false;
// Window is no longer visible -- make sure if we were waiting
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 789e74b..d1539ba 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -554,7 +554,7 @@ class WindowStateAnimator {
mPendingDestroySurface.destroy();
}
} catch (RuntimeException e) {
- Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window "
+ Slog.w(TAG, "Exception thrown when destroying Window "
+ this + " surface " + mPendingDestroySurface
+ " session " + mSession + ": " + e.toString());
}
@@ -705,6 +705,7 @@ class WindowStateAnimator {
mDsDy = 0;
mDtDy = mWin.mGlobalScale;
}
+
public void prepareSurfaceLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
if (mSurface == null) {
@@ -892,7 +893,7 @@ class WindowStateAnimator {
e = new RuntimeException();
e.fillInStackTrace();
}
- Slog.v(WindowManagerService.TAG, "performShow on " + this
+ Slog.v(TAG, "performShow on " + this
+ ": readyToShow=" + mWin.mReadyToShow + " readyForDisplay="
+ mWin.isReadyForDisplay()
+ " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING), e);
@@ -900,7 +901,7 @@ class WindowStateAnimator {
if (mWin.mReadyToShow && mWin.isReadyForDisplay()) {
if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION)
WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null);
- if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during animation: policyVis=" + mWin.mPolicyVisibility
+ " attHidden=" + mWin.mAttachedHidden
+ " tok.hiddenRequested="
@@ -947,7 +948,7 @@ class WindowStateAnimator {
if (mWin.mAppToken.startingData != null) {
if (WindowManagerService.DEBUG_STARTING_WINDOW ||
- WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+ WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
"Finish starting " + mWin.mToken
+ ": first real window is shown, no animation");
// If this initial window is animating, stop it -- we
@@ -1059,7 +1060,7 @@ class WindowStateAnimator {
a = mService.loadAnimation(mWin.mAttrs, attr);
}
}
- if (WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
"applyAnimation: win=" + this
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ " mAnimation=" + mAnimation
@@ -1071,7 +1072,7 @@ class WindowStateAnimator {
e = new RuntimeException();
e.fillInStackTrace();
}
- Slog.v(WindowManagerService.TAG, "Loaded animation " + a + " for " + this, e);
+ Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
}
setAnimation(a);
mAnimationIsEntrance = isEntrance;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyCapabilities.java b/telephony/java/com/android/internal/telephony/TelephonyCapabilities.java
new file mode 100644
index 0000000..061a6cb
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+
+/**
+ * Utilities that check if the phone supports specified capabilities.
+ */
+public class TelephonyCapabilities {
+ private static final String LOG_TAG = "TelephonyCapabilities";
+
+ /** This class is never instantiated. */
+ private TelephonyCapabilities() {
+ }
+
+ /**
+ * Return true if the current phone supports ECM ("Emergency Callback
+ * Mode"), which is a feature where the device goes into a special
+ * state for a short period of time after making an outgoing emergency
+ * call.
+ *
+ * (On current devices, that state lasts 5 minutes. It prevents data
+ * usage by other apps, to avoid conflicts with any possible incoming
+ * calls. It also puts up a notification in the status bar, showing a
+ * countdown while ECM is active, and allowing the user to exit ECM.)
+ *
+ * Currently this is assumed to be true for CDMA phones, and false
+ * otherwise.
+ */
+ public static boolean supportsEcm(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+ }
+
+ /**
+ * Return true if the current phone supports Over The Air Service
+ * Provisioning (OTASP)
+ *
+ * Currently this is assumed to be true for CDMA phones, and false
+ * otherwise.
+ *
+ * TODO: Watch out: this is also highly carrier-specific, since the
+ * OTASP procedure is different from one carrier to the next, *and* the
+ * different carriers may want very different onscreen UI as well.
+ * The procedure may even be different for different devices with the
+ * same carrier.
+ *
+ * So we eventually will need a much more flexible, pluggable design.
+ * This method here is just a placeholder to reduce hardcoded
+ * "if (CDMA)" checks sprinkled throughout the phone app.
+ */
+ public static boolean supportsOtasp(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+ }
+
+ /**
+ * Return true if the current phone can retrieve the voice message count.
+ *
+ * Currently this is assumed to be true on CDMA phones and false otherwise.
+ */
+ public static boolean supportsVoiceMessageCount(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA);
+ }
+
+ /**
+ * Return true if this phone allows the user to select which
+ * network to use.
+ *
+ * Currently this is assumed to be true only on GSM phones.
+ *
+ * TODO: Should CDMA phones allow this as well?
+ */
+ public static boolean supportsNetworkSelection(Phone phone) {
+ return (phone.getPhoneType() == Phone.PHONE_TYPE_GSM);
+ }
+
+ /**
+ * Returns a resource ID for a label to use when displaying the
+ * "device id" of the current device. (This is currently used as the
+ * title of the "device id" dialog.)
+ *
+ * This is specific to the device's telephony technology: the device
+ * id is called "IMEI" on GSM phones and "MEID" on CDMA phones.
+ */
+ public static int getDeviceIdLabel(Phone phone) {
+ if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM) {
+ return com.android.internal.R.string.imei;
+ } else if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
+ return com.android.internal.R.string.meid;
+ } else {
+ Log.w(LOG_TAG, "getDeviceIdLabel: no known label for phone "
+ + phone.getPhoneName());
+ return 0;
+ }
+ }
+
+ /**
+ * Return true if the current phone supports the ability to explicitly
+ * manage the state of a conference call (i.e. view the participants,
+ * and hangup or separate individual callers.)
+ *
+ * The in-call screen's "Manage conference" UI is available only on
+ * devices that support this feature.
+ *
+ * Currently this is assumed to be true on GSM phones and false otherwise.
+ */
+ public static boolean supportsConferenceCallManagement(Phone phone) {
+ return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+ || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
+ }
+
+ /**
+ * Return true if the current phone supports explicit "Hold" and
+ * "Unhold" actions for an active call. (If so, the in-call UI will
+ * provide onscreen "Hold" / "Unhold" buttons.)
+ *
+ * Currently this is assumed to be true on GSM phones and false
+ * otherwise. (In particular, CDMA has no concept of "putting a call
+ * on hold.")
+ */
+ public static boolean supportsHoldAndUnhold(Phone phone) {
+ return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+ || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
+ }
+
+ /**
+ * Return true if the current phone supports distinct "Answer & Hold"
+ * and "Answer & End" behaviors in the call-waiting scenario. If so,
+ * the in-call UI may provide separate buttons or menu items for these
+ * two actions.
+ *
+ * Currently this is assumed to be true on GSM phones and false
+ * otherwise. (In particular, CDMA has no concept of explicitly
+ * managing the background call, or "putting a call on hold.")
+ *
+ * TODO: It might be better to expose this capability in a more
+ * generic form, like maybe "supportsExplicitMultipleLineManagement()"
+ * rather than focusing specifically on call-waiting behavior.
+ */
+ public static boolean supportsAnswerAndHold(Phone phone) {
+ return ((phone.getPhoneType() == Phone.PHONE_TYPE_GSM)
+ || (phone.getPhoneType() == Phone.PHONE_TYPE_SIP));
+ }
+}