diff options
Diffstat (limited to 'src/com/android/phone/CallLogger.java')
-rw-r--r-- | src/com/android/phone/CallLogger.java | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/com/android/phone/CallLogger.java b/src/com/android/phone/CallLogger.java new file mode 100644 index 00000000..644812f9 --- /dev/null +++ b/src/com/android/phone/CallLogger.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2013 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.phone; + +import com.android.internal.telephony.CallerInfo; +import com.android.internal.telephony.Connection; +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.TelephonyCapabilities; +import com.android.phone.common.CallLogAsync; + +import android.net.Uri; +import android.os.SystemProperties; +import android.provider.CallLog.Calls; +import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; +import android.util.Log; + +/** + * Helper class for interacting with the call log. + */ +class CallLogger { + private static final String LOG_TAG = CallLogger.class.getSimpleName(); + private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 1) && + (SystemProperties.getInt("ro.debuggable", 0) == 1); + private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2); + + private PhoneGlobals mApplication; + private CallLogAsync mCallLog; + + public CallLogger(PhoneGlobals application, CallLogAsync callLogAsync) { + mApplication = application; + mCallLog = callLogAsync; + } + + /** + * Logs a call to the call log based on the connection object passed in. + * + * @param c The connection object for the call being logged. + * @param callLogType The type of call log entry. + */ + public void logCall(Connection c, int callLogType) { + final String number = c.getAddress(); + final long date = c.getCreateTime(); + final long duration = c.getDurationMillis(); + final Phone phone = c.getCall().getPhone(); + + final CallerInfo ci = getCallerInfoFromConnection(c); // May be null. + final String logNumber = getLogNumber(c, ci); + + if (DBG) { + log("- onDisconnect(): logNumber set to:" + PhoneUtils.toLogSafePhoneNumber(logNumber) + + ", number set to: " + PhoneUtils.toLogSafePhoneNumber(number)); + } + + // TODO: In getLogNumber we use the presentation from + // the connection for the CNAP. Should we use the one + // below instead? (comes from caller info) + + // For international calls, 011 needs to be logged as + + final int presentation = getPresentation(c, ci); + + final boolean isOtaspNumber = TelephonyCapabilities.supportsOtasp(phone) + && phone.isOtaSpNumber(number); + + // Don't log OTASP calls. + if (!isOtaspNumber) { + logCall(ci, logNumber, presentation, callLogType, date, duration); + } + } + + /** + * Came as logCall(Connection,int) but calculates the call type from the connection object. + */ + public void logCall(Connection c) { + final Connection.DisconnectCause cause = c.getDisconnectCause(); + + // Set the "type" to be displayed in the call log (see constants in CallLog.Calls) + final int callLogType; + + if (c.isIncoming()) { + callLogType = (cause == Connection.DisconnectCause.INCOMING_MISSED ? + Calls.MISSED_TYPE : Calls.INCOMING_TYPE); + } else { + callLogType = Calls.OUTGOING_TYPE; + } + if (VDBG) log("- callLogType: " + callLogType + ", UserData: " + c.getUserData()); + + logCall(c, callLogType); + } + + /** + * Logs a call to the call from the parameters passed in. + */ + public void logCall(CallerInfo ci, String number, int presentation, int callType, long start, + long duration) { + final boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(number, + mApplication); + + // On some devices, to avoid accidental redialing of + // emergency numbers, we *never* log emergency calls to + // the Call Log. (This behavior is set on a per-product + // basis, based on carrier requirements.) + final boolean okToLogEmergencyNumber = + mApplication.getResources().getBoolean( + R.bool.allow_emergency_numbers_in_call_log); + + // Don't log emergency numbers if the device doesn't allow it, + boolean isOkToLogThisCall = !isEmergencyNumber || okToLogEmergencyNumber; + + if (isOkToLogThisCall) { + if (DBG) { + log("sending Calllog entry: " + ci + ", " + PhoneUtils.toLogSafePhoneNumber(number) + + "," + presentation + ", " + callType + ", " + start + ", " + duration); + } + + CallLogAsync.AddCallArgs args = new CallLogAsync.AddCallArgs(mApplication, ci, number, + presentation, callType, start, duration); + mCallLog.addCall(args); + } + } + + /** + * Get the caller info. + * + * @param conn The phone connection. + * @return The CallerInfo associated with the connection. Maybe null. + */ + private CallerInfo getCallerInfoFromConnection(Connection conn) { + CallerInfo ci = null; + Object o = conn.getUserData(); + + if ((o == null) || (o instanceof CallerInfo)) { + ci = (CallerInfo) o; + } else if (o instanceof Uri) { + ci = CallerInfo.getCallerInfo(mApplication.getApplicationContext(), (Uri) o); + } else { + ci = ((PhoneUtils.CallerInfoToken) o).currentInfo; + } + return ci; + } + + /** + * Retrieve the phone number from the caller info or the connection. + * + * For incoming call the number is in the Connection object. For + * outgoing call we use the CallerInfo phoneNumber field if + * present. All the processing should have been done already (CDMA vs GSM numbers). + * + * If CallerInfo is missing the phone number, get it from the connection. + * Apply the Call Name Presentation (CNAP) transform in the connection on the number. + * + * @param conn The phone connection. + * @param callerInfo The CallerInfo. Maybe null. + * @return the phone number. + */ + private String getLogNumber(Connection conn, CallerInfo callerInfo) { + String number = null; + + if (conn.isIncoming()) { + number = conn.getAddress(); + } else { + // For emergency and voicemail calls, + // CallerInfo.phoneNumber does *not* contain a valid phone + // number. Instead it contains an I18N'd string such as + // "Emergency Number" or "Voice Mail" so we get the number + // from the connection. + if (null == callerInfo || TextUtils.isEmpty(callerInfo.phoneNumber) || + callerInfo.isEmergencyNumber() || callerInfo.isVoiceMailNumber()) { + if (conn.getCall().getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { + // In cdma getAddress() is not always equals to getOrigDialString(). + number = conn.getOrigDialString(); + } else { + number = conn.getAddress(); + } + } else { + number = callerInfo.phoneNumber; + } + } + + if (null == number) { + return null; + } else { + int presentation = conn.getNumberPresentation(); + + // Do final CNAP modifications. + String newNumber = PhoneUtils.modifyForSpecialCnapCases(mApplication, callerInfo, + number, presentation); + + if (!PhoneNumberUtils.isUriNumber(number)) { + number = PhoneNumberUtils.stripSeparators(number); + } + if (VDBG) log("getLogNumber: " + number); + return number; + } + } + + /** + * Get the presentation from the callerinfo if not null otherwise, + * get it from the connection. + * + * @param conn The phone connection. + * @param callerInfo The CallerInfo. Maybe null. + * @return The presentation to use in the logs. + */ + private int getPresentation(Connection conn, CallerInfo callerInfo) { + int presentation; + + if (null == callerInfo) { + presentation = conn.getNumberPresentation(); + } else { + presentation = callerInfo.numberPresentation; + if (DBG) log("- getPresentation(): ignoring connection's presentation: " + + conn.getNumberPresentation()); + } + if (DBG) log("- getPresentation: presentation: " + presentation); + return presentation; + } + + private void log(String msg) { + Log.d(LOG_TAG, msg); + } +} |