ImsPhoneConnection.java revision 6a0fa4105fa8104a09b33a3403df5ae2711e0083
1d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright/* 2d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Copyright (C) 2013 The Android Open Source Project 3d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * 4d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Licensed under the Apache License, Version 2.0 (the "License"); 5d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * you may not use this file except in compliance with the License. 6d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * You may obtain a copy of the License at 7d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * 8d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * http://www.apache.org/licenses/LICENSE-2.0 9d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * 10d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * Unless required by applicable law or agreed to in writing, software 11d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * distributed under the License is distributed on an "AS IS" BASIS, 12d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * See the License for the specific language governing permissions and 14d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * limitations under the License. 15d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 16d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 17d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightpackage com.android.internal.telephony.imsphone; 18d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 19d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.content.Context; 20d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.net.Uri; 21d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.AsyncResult; 22d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Handler; 23d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Looper; 24d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Message; 25d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.PowerManager; 26d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.Registrant; 27d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.os.SystemClock; 28d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.telecom.Log; 29d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.telephony.DisconnectCause; 30d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.telephony.PhoneNumberUtils; 31d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport android.telephony.Rlog; 32d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 33d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.ims.ImsException; 34d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.ims.ImsStreamMediaProfile; 35d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.internal.telephony.CallStateException; 36d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.internal.telephony.Connection; 37d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.internal.telephony.Phone; 38d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.internal.telephony.PhoneConstants; 39d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.internal.telephony.UUSInfo; 40d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 41d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.ims.ImsCall; 42d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightimport com.android.ims.ImsCallProfile; 43d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 44d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright/** 45d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * {@hide} 46d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 47d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wrightpublic class ImsPhoneConnection extends Connection { 48d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final String LOG_TAG = "ImsPhoneConnection"; 49d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final boolean DBG = true; 50d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 51d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //***** Instance Variables 52d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 53d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private ImsPhoneCallTracker mOwner; 54d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private ImsPhoneCall mParent; 55d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private ImsCall mImsCall; 56d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 57d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private String mPostDialString; // outgoing calls only 58d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private boolean mDisconnected; 59d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 60d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /* 61d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright int mIndex; // index in ImsPhoneCallTracker.connections[], -1 if unassigned 62d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright // The GSM index is 1 + this 63d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 64d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 65d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /* 66d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * These time/timespan values are based on System.currentTimeMillis(), 67d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright * i.e., "wall clock" time. 68d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright */ 69d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private long mDisconnectTime; 70d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 71d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private int mNextPostDialChar; // index into postDialString 72d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 73d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private int mCause = DisconnectCause.NOT_DISCONNECTED; 74d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private PostDialState mPostDialState = PostDialState.NOT_STARTED; 75d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private UUSInfo mUusInfo; 76d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private Handler mHandler; 77d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 78d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private PowerManager.WakeLock mPartialWakeLock; 79d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 80d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //***** Event Constants 81d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int EVENT_DTMF_DONE = 1; 82d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int EVENT_PAUSE_DONE = 2; 83d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int EVENT_NEXT_POST_DIAL = 3; 84d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int EVENT_WAKE_LOCK_TIMEOUT = 4; 85d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 86d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //***** Constants 87d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int PAUSE_DELAY_MILLIS = 3 * 1000; 88d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000; 89d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 90d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //***** Inner Classes 91d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 92d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright class MyHandler extends Handler { 93d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright MyHandler(Looper l) {super(l);} 94d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 95d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 96d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public void 97d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright handleMessage(Message msg) { 98d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 99d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright switch (msg.what) { 100d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case EVENT_NEXT_POST_DIAL: 101d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case EVENT_DTMF_DONE: 102d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case EVENT_PAUSE_DONE: 103d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright processNextPostDialChar(); 104d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 105d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright case EVENT_WAKE_LOCK_TIMEOUT: 106d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright releaseWakeLock(); 107d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright break; 108d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 109d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 110d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 111d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 112d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //***** Constructors 113d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 114d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /** This is probably an MT call */ 115d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /*package*/ 116d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright ImsPhoneConnection(Context context, ImsCall imsCall, ImsPhoneCallTracker ct, ImsPhoneCall parent) { 117d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright createWakeLock(context); 118d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright acquireWakeLock(); 119d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 120d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mOwner = ct; 121d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler = new MyHandler(mOwner.getLooper()); 122d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mImsCall = imsCall; 123d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 124d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if ((imsCall != null) && (imsCall.getCallProfile() != null)) { 125d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI); 126d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA); 127d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mNumberPresentation = ImsCallProfile.OIRToPresentation( 128d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR)); 129d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCnapNamePresentation = ImsCallProfile.OIRToPresentation( 130d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP)); 131d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 132d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright updateMediaCapabilities(imsCall); 133d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else { 134d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN; 135d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN; 136d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 137d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 138d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mIsIncoming = true; 139d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCreateTime = System.currentTimeMillis(); 140d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mUusInfo = null; 141d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 142d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //mIndex = index; 143d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 144d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mParent = parent; 145d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mParent.attach(this, ImsPhoneCall.State.INCOMING); 146d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 147d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 148d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /** This is an MO call, created when dialing */ 149d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright /*package*/ 150d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright ImsPhoneConnection(Context context, String dialString, ImsPhoneCallTracker ct, ImsPhoneCall parent) { 151d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright createWakeLock(context); 152d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright acquireWakeLock(); 153d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 154d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mOwner = ct; 155d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mHandler = new MyHandler(mOwner.getLooper()); 156d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 157d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mDialString = dialString; 158d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 159d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString); 160d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString); 161d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 162d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright //mIndex = -1; 163d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 164d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mIsIncoming = false; 165d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCnapName = null; 166d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED; 167d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED; 168d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCreateTime = System.currentTimeMillis(); 169d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 170d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mParent = parent; 171d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright parent.attachFake(this, ImsPhoneCall.State.DIALING); 172d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 173d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 174d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public void dispose() { 175d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 176d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 177d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright static boolean 178d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright equalsHandlesNulls (Object a, Object b) { 179d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return (a == null) ? (b == null) : a.equals (b); 180d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 181d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 182d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 183d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public String getOrigDialString(){ 184d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mDialString; 185d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 186d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 187d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 188d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public ImsPhoneCall getCall() { 189d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mParent; 190d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 191d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 192d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 193d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public long getDisconnectTime() { 194d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mDisconnectTime; 195d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 196d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 197d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 198d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public long getHoldingStartTime() { 199d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mHoldingStartTime; 200d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 201d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 202d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 203d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public long getHoldDurationMillis() { 204d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (getState() != ImsPhoneCall.State.HOLDING) { 205d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright // If not holding, return 0 206d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return 0; 207d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else { 208d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return SystemClock.elapsedRealtime() - mHoldingStartTime; 209d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 210d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 211d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 212d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 213d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public int getDisconnectCause() { 214d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mCause; 215d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 216d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 217d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public void setDisconnectCause(int cause) { 218d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mCause = cause; 219d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 220d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 221d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public ImsPhoneCallTracker getOwner () { 222d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return mOwner; 223d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 224d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 225d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 226d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public ImsPhoneCall.State getState() { 227d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (mDisconnected) { 228d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return ImsPhoneCall.State.DISCONNECTED; 229d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else { 230d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright return super.getState(); 231d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 232d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 233d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 234d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 235d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public void hangup() throws CallStateException { 236d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright if (!mDisconnected) { 237d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright mOwner.hangup(this); 238d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } else { 239d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright throw new CallStateException ("disconnected"); 240d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 241d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 242d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 243d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright @Override 244d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright public void separate() throws CallStateException { 245d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright throw new CallStateException ("not supported"); 246d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright } 247d02c5b6aace05d9fd938e2d03705ac4f60f8da19Michael Wright 248 @Override 249 public PostDialState getPostDialState() { 250 return mPostDialState; 251 } 252 253 @Override 254 public void proceedAfterWaitChar() { 255 if (mPostDialState != PostDialState.WAIT) { 256 Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected " 257 + "getPostDialState() to be WAIT but was " + mPostDialState); 258 return; 259 } 260 261 setPostDialState(PostDialState.STARTED); 262 263 processNextPostDialChar(); 264 } 265 266 @Override 267 public void proceedAfterWildChar(String str) { 268 if (mPostDialState != PostDialState.WILD) { 269 Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected " 270 + "getPostDialState() to be WILD but was " + mPostDialState); 271 return; 272 } 273 274 setPostDialState(PostDialState.STARTED); 275 276 // make a new postDialString, with the wild char replacement string 277 // at the beginning, followed by the remaining postDialString. 278 279 StringBuilder buf = new StringBuilder(str); 280 buf.append(mPostDialString.substring(mNextPostDialChar)); 281 mPostDialString = buf.toString(); 282 mNextPostDialChar = 0; 283 if (Phone.DEBUG_PHONE) { 284 Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " + 285 mPostDialString); 286 } 287 288 processNextPostDialChar(); 289 } 290 291 @Override 292 public void cancelPostDial() { 293 setPostDialState(PostDialState.CANCELLED); 294 } 295 296 /** 297 * Called when this Connection is being hung up locally (eg, user pressed "end") 298 */ 299 void 300 onHangupLocal() { 301 mCause = DisconnectCause.LOCAL; 302 } 303 304 /** Called when the connection has been disconnected */ 305 /*package*/ boolean 306 onDisconnect(int cause) { 307 Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause); 308 if (mCause != DisconnectCause.LOCAL) mCause = cause; 309 return onDisconnect(); 310 } 311 312 /*package*/ boolean 313 onDisconnect() { 314 boolean changed = false; 315 316 if (!mDisconnected) { 317 //mIndex = -1; 318 319 mDisconnectTime = System.currentTimeMillis(); 320 mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal; 321 mDisconnected = true; 322 323 mOwner.mPhone.notifyDisconnect(this); 324 325 if (mParent != null) { 326 changed = mParent.connectionDisconnected(this); 327 } else { 328 Rlog.d(LOG_TAG, "onDisconnect: no parent"); 329 } 330 if (mImsCall != null) mImsCall.close(); 331 mImsCall = null; 332 } 333 releaseWakeLock(); 334 return changed; 335 } 336 337 /** 338 * An incoming or outgoing call has connected 339 */ 340 void 341 onConnectedInOrOut() { 342 mConnectTime = System.currentTimeMillis(); 343 mConnectTimeReal = SystemClock.elapsedRealtime(); 344 mDuration = 0; 345 346 if (Phone.DEBUG_PHONE) { 347 Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime); 348 } 349 350 if (!mIsIncoming) { 351 // outgoing calls only 352 processNextPostDialChar(); 353 } 354 releaseWakeLock(); 355 } 356 357 /*package*/ void 358 onStartedHolding() { 359 mHoldingStartTime = SystemClock.elapsedRealtime(); 360 } 361 /** 362 * Performs the appropriate action for a post-dial char, but does not 363 * notify application. returns false if the character is invalid and 364 * should be ignored 365 */ 366 private boolean 367 processPostDialChar(char c) { 368 if (PhoneNumberUtils.is12Key(c)) { 369 mOwner.mCi.sendDtmf(c, mHandler.obtainMessage(EVENT_DTMF_DONE)); 370 } else if (c == PhoneNumberUtils.PAUSE) { 371 // From TS 22.101: 372 // It continues... 373 // Upon the called party answering the UE shall send the DTMF digits 374 // automatically to the network after a delay of 3 seconds( 20 ). 375 // The digits shall be sent according to the procedures and timing 376 // specified in 3GPP TS 24.008 [13]. The first occurrence of the 377 // "DTMF Control Digits Separator" shall be used by the ME to 378 // distinguish between the addressing digits (i.e. the phone number) 379 // and the DTMF digits. Upon subsequent occurrences of the 380 // separator, 381 // the UE shall pause again for 3 seconds ( 20 ) before sending 382 // any further DTMF digits. 383 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE), 384 PAUSE_DELAY_MILLIS); 385 } else if (c == PhoneNumberUtils.WAIT) { 386 setPostDialState(PostDialState.WAIT); 387 } else if (c == PhoneNumberUtils.WILD) { 388 setPostDialState(PostDialState.WILD); 389 } else { 390 return false; 391 } 392 393 return true; 394 } 395 396 @Override 397 public String 398 getRemainingPostDialString() { 399 if (mPostDialState == PostDialState.CANCELLED 400 || mPostDialState == PostDialState.COMPLETE 401 || mPostDialString == null 402 || mPostDialString.length() <= mNextPostDialChar 403 ) { 404 return ""; 405 } 406 407 return mPostDialString.substring(mNextPostDialChar); 408 } 409 410 @Override 411 protected void finalize() 412 { 413 releaseWakeLock(); 414 } 415 416 private void 417 processNextPostDialChar() { 418 char c = 0; 419 Registrant postDialHandler; 420 421 if (mPostDialState == PostDialState.CANCELLED) { 422 //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail"); 423 return; 424 } 425 426 if (mPostDialString == null || 427 mPostDialString.length() <= mNextPostDialChar) { 428 setPostDialState(PostDialState.COMPLETE); 429 430 // notifyMessage.arg1 is 0 on complete 431 c = 0; 432 } else { 433 boolean isValid; 434 435 setPostDialState(PostDialState.STARTED); 436 437 c = mPostDialString.charAt(mNextPostDialChar++); 438 439 isValid = processPostDialChar(c); 440 441 if (!isValid) { 442 // Will call processNextPostDialChar 443 mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget(); 444 // Don't notify application 445 Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!"); 446 return; 447 } 448 } 449 450 postDialHandler = mOwner.mPhone.mPostDialHandler; 451 452 Message notifyMessage; 453 454 if (postDialHandler != null 455 && (notifyMessage = postDialHandler.messageForRegistrant()) != null) { 456 // The AsyncResult.result is the Connection object 457 PostDialState state = mPostDialState; 458 AsyncResult ar = AsyncResult.forMessage(notifyMessage); 459 ar.result = this; 460 ar.userObj = state; 461 462 // arg1 is the character that was/is being processed 463 notifyMessage.arg1 = c; 464 465 //Rlog.v(LOG_TAG, "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c); 466 notifyMessage.sendToTarget(); 467 } 468 } 469 470 /** 471 * Set post dial state and acquire wake lock while switching to "started" 472 * state, the wake lock will be released if state switches out of "started" 473 * state or after WAKE_LOCK_TIMEOUT_MILLIS. 474 * @param s new PostDialState 475 */ 476 private void setPostDialState(PostDialState s) { 477 if (mPostDialState != PostDialState.STARTED 478 && s == PostDialState.STARTED) { 479 acquireWakeLock(); 480 Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT); 481 mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS); 482 } else if (mPostDialState == PostDialState.STARTED 483 && s != PostDialState.STARTED) { 484 mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT); 485 releaseWakeLock(); 486 } 487 mPostDialState = s; 488 } 489 490 private void 491 createWakeLock(Context context) { 492 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 493 mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); 494 } 495 496 private void 497 acquireWakeLock() { 498 Rlog.d(LOG_TAG, "acquireWakeLock"); 499 mPartialWakeLock.acquire(); 500 } 501 502 void 503 releaseWakeLock() { 504 synchronized(mPartialWakeLock) { 505 if (mPartialWakeLock.isHeld()) { 506 Rlog.d(LOG_TAG, "releaseWakeLock"); 507 mPartialWakeLock.release(); 508 } 509 } 510 } 511 512 @Override 513 public int getNumberPresentation() { 514 return mNumberPresentation; 515 } 516 517 @Override 518 public UUSInfo getUUSInfo() { 519 return mUusInfo; 520 } 521 522 @Override 523 public Connection getOrigConnection() { 524 return null; 525 } 526 527 @Override 528 public boolean isMultiparty() { 529 return mImsCall != null && mImsCall.isMultiparty(); 530 } 531 532 /*package*/ ImsCall getImsCall() { 533 return mImsCall; 534 } 535 536 /*package*/ void setImsCall(ImsCall imsCall) { 537 mImsCall = imsCall; 538 } 539 540 /*package*/ void changeParent(ImsPhoneCall parent) { 541 mParent = parent; 542 } 543 544 /** 545 * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been 546 * changed, and {@code false} otherwise. 547 */ 548 /*package*/ boolean update(ImsCall imsCall, ImsPhoneCall.State state) { 549 if (state == ImsPhoneCall.State.ACTIVE) { 550 if (mParent.getState().isRinging() || mParent.getState().isDialing()) { 551 onConnectedInOrOut(); 552 } 553 554 if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) { 555 //mForegroundCall should be IDLE 556 //when accepting WAITING call 557 //before accept WAITING call, 558 //the ACTIVE call should be held ahead 559 mParent.detach(this); 560 mParent = mOwner.mForegroundCall; 561 mParent.attach(this); 562 } 563 } else if (state == ImsPhoneCall.State.HOLDING) { 564 onStartedHolding(); 565 } 566 567 return mParent.update(this, imsCall, state) || updateMediaCapabilities(imsCall); 568 } 569 570 @Override 571 public int getPreciseDisconnectCause() { 572 return 0; 573 } 574 575 /** 576 * Notifies this Connection of a request to disconnect a participant of the conference managed 577 * by the connection. 578 * 579 * @param endpoint the {@link android.net.Uri} of the participant to disconnect. 580 */ 581 @Override 582 public void onDisconnectConferenceParticipant(Uri endpoint) { 583 ImsCall imsCall = getImsCall(); 584 if (imsCall == null) { 585 return; 586 } 587 try { 588 imsCall.removeParticipants(new String[]{endpoint.toString()}); 589 } catch (ImsException e) { 590 // No session in place -- no change 591 Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+ 592 "Failed to disconnect endpoint = " + endpoint); 593 } 594 } 595 596 /** 597 * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and 598 * update the {@link ImsPhoneConnection} with this information. 599 * 600 * @param imsCall The call to check for changes in media capabilities. 601 * @return Whether the media capabilities have been changed. 602 */ 603 private boolean updateMediaCapabilities(ImsCall imsCall) { 604 if (imsCall == null) { 605 return false; 606 } 607 608 boolean changed = false; 609 610 try { 611 ImsCallProfile localCallProfile = imsCall.getLocalCallProfile(); 612 ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile(); 613 614 if (localCallProfile != null) { 615 int callType = localCallProfile.mCallType; 616 617 boolean newLocalVideoCapable = callType == ImsCallProfile.CALL_TYPE_VT; 618 if (isLocalVideoCapable() != newLocalVideoCapable) { 619 setLocalVideoCapable(newLocalVideoCapable); 620 changed = true; 621 } 622 623 int newVideoState = ImsCallProfile.getVideoStateFromCallType(callType); 624 if (getVideoState() != newVideoState) { 625 setVideoState(newVideoState); 626 changed = true; 627 } 628 } 629 630 int newAudioQuality = 631 getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile); 632 if (getAudioQuality() != newAudioQuality) { 633 setAudioQuality(newAudioQuality); 634 changed = true; 635 } 636 } catch (ImsException e) { 637 // No session in place -- no change 638 } 639 640 return changed; 641 } 642 643 /** 644 * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote 645 * {@link ImsCallProfile}. If indicate a HQ audio call if the local stream profile 646 * indicates AMR_WB or EVRC_WB and there is no remote restrict cause. 647 * 648 * @param localCallProfile The local call profile. 649 * @param remoteCallProfile The remote call profile. 650 * @return The audio quality. 651 */ 652 private int getAudioQualityFromCallProfile( 653 ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) { 654 if (localCallProfile == null || remoteCallProfile == null 655 || localCallProfile.mMediaProfile == null) { 656 return AUDIO_QUALITY_STANDARD; 657 } 658 659 boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality 660 == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB 661 || localCallProfile.mMediaProfile.mAudioQuality 662 == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB) 663 && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE; 664 return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD; 665 } 666 667 /** 668 * Provides a string representation of the {@link ImsPhoneConnection}. Primarily intended for 669 * use in log statements. 670 * 671 * @return String representation of call. 672 */ 673 @Override 674 public String toString() { 675 StringBuilder sb = new StringBuilder(); 676 sb.append("[ImsPhoneConnection objId: "); 677 sb.append(System.identityHashCode(this)); 678 sb.append(" address:"); 679 sb.append(Log.pii(getAddress())); 680 sb.append(" ImsCall:"); 681 if (mImsCall == null) { 682 sb.append("null"); 683 } else { 684 sb.append(mImsCall); 685 } 686 sb.append("]"); 687 return sb.toString(); 688 } 689} 690 691