Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.phone;
     18 
     19 import com.android.internal.telephony.CallerInfo;
     20 import com.android.internal.telephony.Connection;
     21 import com.android.internal.telephony.Phone;
     22 import com.android.internal.telephony.PhoneConstants;
     23 import com.android.internal.telephony.TelephonyCapabilities;
     24 import com.android.phone.common.CallLogAsync;
     25 
     26 import android.net.Uri;
     27 import android.os.SystemProperties;
     28 import android.provider.CallLog.Calls;
     29 import android.telephony.DisconnectCause;
     30 import android.telephony.PhoneNumberUtils;
     31 import android.text.TextUtils;
     32 import android.util.Log;
     33 
     34 /**
     35  * Helper class for interacting with the call log.
     36  */
     37 class CallLogger {
     38     private static final String LOG_TAG = CallLogger.class.getSimpleName();
     39     private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 1) &&
     40         (SystemProperties.getInt("ro.debuggable", 0) == 1);
     41     private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);
     42 
     43     private PhoneGlobals mApplication;
     44     private CallLogAsync mCallLog;
     45 
     46     public CallLogger(PhoneGlobals application, CallLogAsync callLogAsync) {
     47         mApplication = application;
     48         mCallLog = callLogAsync;
     49     }
     50 
     51     /**
     52      * Logs a call to the call log based on the connection object passed in.
     53      *
     54      * @param c The connection object for the call being logged.
     55      * @param callLogType The type of call log entry.
     56      */
     57     public void logCall(Connection c, int callLogType) {
     58         final String number = c.getAddress();
     59         final long date = c.getCreateTime();
     60         final long duration = c.getDurationMillis();
     61         final Phone phone = c.getCall().getPhone();
     62 
     63         final CallerInfo ci = getCallerInfoFromConnection(c);  // May be null.
     64         final String logNumber = getLogNumber(c, ci);
     65 
     66         if (DBG) {
     67             log("- onDisconnect(): logNumber set to:" + PhoneUtils.toLogSafePhoneNumber(logNumber) +
     68                 ", number set to: " + PhoneUtils.toLogSafePhoneNumber(number));
     69         }
     70 
     71         // TODO: In getLogNumber we use the presentation from
     72         // the connection for the CNAP. Should we use the one
     73         // below instead? (comes from caller info)
     74 
     75         // For international calls, 011 needs to be logged as +
     76         final int presentation = getPresentation(c, ci);
     77 
     78         final boolean isOtaspNumber = TelephonyCapabilities.supportsOtasp(phone)
     79                 && phone.isOtaSpNumber(number);
     80 
     81         // Don't log OTASP calls.
     82         if (!isOtaspNumber) {
     83             logCall(ci, logNumber, presentation, callLogType, date, duration);
     84         }
     85     }
     86 
     87     /**
     88      * Came as logCall(Connection,int) but calculates the call type from the connection object.
     89      */
     90     public void logCall(Connection c) {
     91         final int cause = c.getDisconnectCause();
     92 
     93         // Set the "type" to be displayed in the call log (see constants in CallLog.Calls)
     94         final int callLogType;
     95 
     96         if (c.isIncoming()) {
     97             callLogType = (cause == DisconnectCause.INCOMING_MISSED ?
     98                            Calls.MISSED_TYPE : Calls.INCOMING_TYPE);
     99         } else {
    100             callLogType = Calls.OUTGOING_TYPE;
    101         }
    102         if (VDBG) log("- callLogType: " + callLogType + ", UserData: " + c.getUserData());
    103 
    104         logCall(c, callLogType);
    105     }
    106 
    107     /**
    108      * Logs a call to the call from the parameters passed in.
    109      */
    110     public void logCall(CallerInfo ci, String number, int presentation, int callType, long start,
    111                         long duration) {
    112         // no-op
    113     }
    114 
    115     /**
    116      * Get the caller info.
    117      *
    118      * @param conn The phone connection.
    119      * @return The CallerInfo associated with the connection. Maybe null.
    120      */
    121     private CallerInfo getCallerInfoFromConnection(Connection conn) {
    122         CallerInfo ci = null;
    123         Object o = conn.getUserData();
    124 
    125         if ((o == null) || (o instanceof CallerInfo)) {
    126             ci = (CallerInfo) o;
    127         } else if (o instanceof Uri) {
    128             ci = CallerInfo.getCallerInfo(mApplication.getApplicationContext(), (Uri) o);
    129         } else {
    130             ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
    131         }
    132         return ci;
    133     }
    134 
    135     /**
    136      * Retrieve the phone number from the caller info or the connection.
    137      *
    138      * For incoming call the number is in the Connection object. For
    139      * outgoing call we use the CallerInfo phoneNumber field if
    140      * present. All the processing should have been done already (CDMA vs GSM numbers).
    141      *
    142      * If CallerInfo is missing the phone number, get it from the connection.
    143      * Apply the Call Name Presentation (CNAP) transform in the connection on the number.
    144      *
    145      * @param conn The phone connection.
    146      * @param callerInfo The CallerInfo. Maybe null.
    147      * @return the phone number.
    148      */
    149     private String getLogNumber(Connection conn, CallerInfo callerInfo) {
    150         String number = null;
    151 
    152         if (conn.isIncoming()) {
    153             number = conn.getAddress();
    154         } else {
    155             // For emergency and voicemail calls,
    156             // CallerInfo.phoneNumber does *not* contain a valid phone
    157             // number.  Instead it contains an I18N'd string such as
    158             // "Emergency Number" or "Voice Mail" so we get the number
    159             // from the connection.
    160             if (null == callerInfo || TextUtils.isEmpty(callerInfo.phoneNumber) ||
    161                 callerInfo.isEmergencyNumber() || callerInfo.isVoiceMailNumber()) {
    162                 if (conn.getCall().getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
    163                     // In cdma getAddress() is not always equals to getOrigDialString().
    164                     number = conn.getOrigDialString();
    165                 } else {
    166                     number = conn.getAddress();
    167                 }
    168             } else {
    169                 number = callerInfo.phoneNumber;
    170             }
    171         }
    172 
    173         if (null == number) {
    174             return null;
    175         } else {
    176             int presentation = conn.getNumberPresentation();
    177 
    178             // Do final CNAP modifications.
    179             String newNumber = PhoneUtils.modifyForSpecialCnapCases(mApplication, callerInfo,
    180                                                           number, presentation);
    181 
    182             if (!PhoneNumberUtils.isUriNumber(number)) {
    183                 number = PhoneNumberUtils.stripSeparators(number);
    184             }
    185             if (VDBG) log("getLogNumber: " + number);
    186             return number;
    187         }
    188     }
    189 
    190     /**
    191      * Get the presentation from the callerinfo if not null otherwise,
    192      * get it from the connection.
    193      *
    194      * @param conn The phone connection.
    195      * @param callerInfo The CallerInfo. Maybe null.
    196      * @return The presentation to use in the logs.
    197      */
    198     private int getPresentation(Connection conn, CallerInfo callerInfo) {
    199         int presentation;
    200 
    201         if (null == callerInfo) {
    202             presentation = conn.getNumberPresentation();
    203         } else {
    204             presentation = callerInfo.numberPresentation;
    205             if (DBG) log("- getPresentation(): ignoring connection's presentation: " +
    206                          conn.getNumberPresentation());
    207         }
    208         if (DBG) log("- getPresentation: presentation: " + presentation);
    209         return presentation;
    210     }
    211 
    212     private void log(String msg) {
    213         Log.d(LOG_TAG, msg);
    214     }
    215 }
    216