/* * 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.DisconnectCause; 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 int 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 == 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) { // no-op } /** * 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); } }