CallerInfoUtils.java revision 1a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87
17ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Leepackage com.android.incallui;
27ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
37ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Leeimport android.content.Context;
47ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Leeimport android.text.TextUtils;
57ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
67ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Leeimport com.android.services.telephony.common.Call;
77ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
87ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Leeimport java.util.Arrays;
97ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
107ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee/**
117ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee * TODO: Insert description here. (generated by yorkelee)
127ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee */
137ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Leepublic class CallerInfoUtils {
147ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
157ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    private static final String TAG = CallerInfoUtils.class.getSimpleName();
167ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
177ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    /** Define for not a special CNAP string */
187ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    private static final int CNAP_SPECIAL_CASE_NO = -1;
197ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
207ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    public CallerInfoUtils() {
217ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    }
227ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
237ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    private static final int QUERY_TOKEN = -1;
247ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
257ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    /**
264bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon     * This is called to get caller info for a call. This will return a CallerInfo
274bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon     * object immediately based off information in the call, but
287ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * more information is returned to the OnQueryCompleteListener (which contains
297ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * information about the phone number label, user's name, etc).
307ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     */
314bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon    public static CallerInfo getCallerInfoForCall(Context context, Call call,
327ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            CallerInfoAsyncQuery.OnQueryCompleteListener listener) {
337ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        CallerInfo info = new CallerInfo();
347ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        String number = call.getNumber();
357ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
367ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // Store CNAP information retrieved from the Connection (we want to do this
377ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // here regardless of whether the number is empty or not).
387ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        info.cnapName = call.getCnapName();
397ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        info.name = info.cnapName;
407ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        info.numberPresentation = call.getNumberPresentation();
417ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        info.namePresentation = call.getCnapNamePresentation();
427ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
434bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        // TODO: Have phoneapp send a Uri when it knows the contact that triggered this call.
447ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
454bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        if (!TextUtils.isEmpty(number)) {
464bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            number = modifyForSpecialCnapCases(context, info, number, info.numberPresentation);
474bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            info.phoneNumber = number;
484bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon
494bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            // For scenarios where we may receive a valid number from the network but a
504bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            // restricted/unavailable presentation, we do not want to perform a contact query,
514bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            // so just return the existing caller info.
524bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            if (info.numberPresentation != Call.PRESENTATION_ALLOWED) {
537ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                return info;
544bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            } else {
554bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon                // Start the query with the number provided from the call.
561a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng                Log.d(TAG, "==> Actually starting CallerInfoAsyncQuery.startQuery()...");
574bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon                CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, number, listener, call);
587ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            }
594bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon        } else {
604bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            // The number is null or empty (Blocked caller id or empty). Just return the
614bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            // caller info object as is, without starting a query.
624bbe4c6900dfe3584f674161dbe15e248d5adbe7Santos Cordon            return info;
637ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
647ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
657ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        return info;
667ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    }
677ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
687ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    /**
697ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * Handles certain "corner cases" for CNAP. When we receive weird phone numbers
707ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * from the network to indicate different number presentations, convert them to
717ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * expected number and presentation values within the CallerInfo object.
727ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * @param number number we use to verify if we are in a corner case
737ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * @param presentation presentation value used to verify if we are in a corner case
747ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * @return the new String that should be used for the phone number
757ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     */
767ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    /* package */static String modifyForSpecialCnapCases(Context context, CallerInfo ci,
777ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            String number, int presentation) {
787ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // Obviously we return number if ci == null, but still return number if
797ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // number == null, because in these cases the correct string will still be
807ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // displayed/logged after this function returns based on the presentation value.
817ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        if (ci == null || number == null) return number;
827ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
831a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(TAG, "modifyForSpecialCnapCases: initially, number="
847ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                + toLogSafePhoneNumber(number)
857ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                + ", presentation=" + presentation + " ci " + ci);
867ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
877ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // "ABSENT NUMBER" is a possible value we could get from the network as the
887ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // phone number, so if this happens, change it to "Unknown" in the CallerInfo
897ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // and fix the presentation to be the same.
907ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        final String[] absentNumberValues =
917ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                context.getResources().getStringArray(R.array.absent_num);
927ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        if (Arrays.asList(absentNumberValues).contains(number)
937ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                && presentation == Call.PRESENTATION_ALLOWED) {
947ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            number = context.getString(R.string.unknown);
957ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            ci.numberPresentation = Call.PRESENTATION_UNKNOWN;
967ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
977ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
987ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // Check for other special "corner cases" for CNAP and fix them similarly. Corner
997ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // cases only apply if we received an allowed presentation from the network, so check
1007ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // if we think we have an allowed presentation, or if the CallerInfo presentation doesn't
1017ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // match the presentation passed in for verification (meaning we changed it previously
1027ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // because it's a corner case and we're being called from a different entry point).
1037ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        if (ci.numberPresentation == Call.PRESENTATION_ALLOWED
1047ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                || (ci.numberPresentation != presentation
1057ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                        && presentation == Call.PRESENTATION_ALLOWED)) {
1067ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            int cnapSpecialCase = checkCnapSpecialCases(number);
1077ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            if (cnapSpecialCase != CNAP_SPECIAL_CASE_NO) {
1087ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                // For all special strings, change number & numberPresentation.
1097ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                if (cnapSpecialCase == Call.PRESENTATION_RESTRICTED) {
1107ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                    number = context.getString(R.string.private_num);
1117ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                } else if (cnapSpecialCase == Call.PRESENTATION_UNKNOWN) {
1127ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                    number = context.getString(R.string.unknown);
1137ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                }
1141a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng                Log.d(TAG, "SpecialCnap: number=" + toLogSafePhoneNumber(number)
1157ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                        + "; presentation now=" + cnapSpecialCase);
1167ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                ci.numberPresentation = cnapSpecialCase;
1177ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            }
1187ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
1191a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng        Log.d(TAG, "modifyForSpecialCnapCases: returning number string="
1207ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                + toLogSafePhoneNumber(number));
1217ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        return number;
1227ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    }
1237ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
1247ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    /**
1257ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * Based on the input CNAP number string,
1267ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * @return _RESTRICTED or _UNKNOWN for all the special CNAP strings.
1277ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     * Otherwise, return CNAP_SPECIAL_CASE_NO.
1287ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee     */
1297ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    private static int checkCnapSpecialCases(String n) {
1307ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        if (n.equals("PRIVATE") ||
1317ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                n.equals("P") ||
1327ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                n.equals("RES")) {
1331a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng            Log.d(TAG, "checkCnapSpecialCases, PRIVATE string: " + n);
1347ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            return Call.PRESENTATION_RESTRICTED;
1357ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        } else if (n.equals("UNAVAILABLE") ||
1367ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                n.equals("UNKNOWN") ||
1377ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                n.equals("UNA") ||
1387ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                n.equals("U")) {
1391a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng            Log.d(TAG, "checkCnapSpecialCases, UNKNOWN string: " + n);
1407ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            return Call.PRESENTATION_UNKNOWN;
1417ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        } else {
1421a7f2bcab2d2023f2ee4cfb0bc57bc265b5aab87Chiao Cheng            Log.d(TAG, "checkCnapSpecialCases, normal str. number: " + n);
1437ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            return CNAP_SPECIAL_CASE_NO;
1447ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
1457ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    }
1467ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
1477ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    /* package */static String toLogSafePhoneNumber(String number) {
1487ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // For unknown number, log empty string.
1497ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        if (number == null) {
1507ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            return "";
1517ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
1527ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
1537ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // Todo (klp): Figure out an equivalent for VDBG
1547ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        if (false) {
1557ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            // When VDBG is true we emit PII.
1567ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            return number;
1577ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
1587ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee
1597ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare
1607ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        // sanitized phone numbers.
1617ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        StringBuilder builder = new StringBuilder();
1627ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        for (int i = 0; i < number.length(); i++) {
1637ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            char c = number.charAt(i);
1647ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            if (c == '-' || c == '@' || c == '.') {
1657ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                builder.append(c);
1667ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            } else {
1677ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee                builder.append('x');
1687ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee            }
1697ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        }
1707ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee        return builder.toString();
1717ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee    }
1727ef707319c0e3563ff92a772ba53cb5dca0e3ae1Yorke Lee}
173