13921359f3f01938768f0b0e731941542f0385787Yorke Lee/*
23921359f3f01938768f0b0e731941542f0385787Yorke Lee * Copyright (C) 2014 The Android Open Source Project
33921359f3f01938768f0b0e731941542f0385787Yorke Lee *
43921359f3f01938768f0b0e731941542f0385787Yorke Lee * Licensed under the Apache License, Version 2.0 (the "License");
53921359f3f01938768f0b0e731941542f0385787Yorke Lee * you may not use this file except in compliance with the License.
63921359f3f01938768f0b0e731941542f0385787Yorke Lee * You may obtain a copy of the License at
73921359f3f01938768f0b0e731941542f0385787Yorke Lee *
83921359f3f01938768f0b0e731941542f0385787Yorke Lee *      http://www.apache.org/licenses/LICENSE-2.0
93921359f3f01938768f0b0e731941542f0385787Yorke Lee *
103921359f3f01938768f0b0e731941542f0385787Yorke Lee * Unless required by applicable law or agreed to in writing, software
113921359f3f01938768f0b0e731941542f0385787Yorke Lee * distributed under the License is distributed on an "AS IS" BASIS,
123921359f3f01938768f0b0e731941542f0385787Yorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133921359f3f01938768f0b0e731941542f0385787Yorke Lee * See the License for the specific language governing permissions and
143921359f3f01938768f0b0e731941542f0385787Yorke Lee * limitations under the License.
153921359f3f01938768f0b0e731941542f0385787Yorke Lee */
163921359f3f01938768f0b0e731941542f0385787Yorke Leepackage com.android.dialer.util;
173921359f3f01938768f0b0e731941542f0385787Yorke Lee
1872d59616b7a491d41c9b127b777c63fe315ecd06Yorke Leeimport android.app.Activity;
193921359f3f01938768f0b0e731941542f0385787Yorke Leeimport android.content.ActivityNotFoundException;
2046fd712ad2896858d977274f94a08aef5bdf0e4cYorke Leeimport android.content.ComponentName;
213921359f3f01938768f0b0e731941542f0385787Yorke Leeimport android.content.Context;
223921359f3f01938768f0b0e731941542f0385787Yorke Leeimport android.content.Intent;
2346fd712ad2896858d977274f94a08aef5bdf0e4cYorke Leeimport android.content.pm.PackageManager;
2446fd712ad2896858d977274f94a08aef5bdf0e4cYorke Leeimport android.content.pm.ResolveInfo;
250a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Leeimport android.content.res.Resources;
260d3a73932a23cb07168d25ec331a9abf72817346Nancy Chenimport android.graphics.Point;
2746fd712ad2896858d977274f94a08aef5bdf0e4cYorke Leeimport android.net.Uri;
280d3a73932a23cb07168d25ec331a9abf72817346Nancy Chenimport android.os.Bundle;
2946fd712ad2896858d977274f94a08aef5bdf0e4cYorke Leeimport android.provider.Telephony;
309dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunnimport android.telecom.TelecomManager;
31f4cb047c49e061cd0590a53d0a176233019eb906Andrew Leeimport android.text.BidiFormatter;
32f4cb047c49e061cd0590a53d0a176233019eb906Andrew Leeimport android.text.TextDirectionHeuristics;
338b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunnimport android.text.TextUtils;
340a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Leeimport android.view.View;
35f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Leeimport android.view.inputmethod.InputMethodManager;
360a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Leeimport android.widget.ImageView;
370a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Leeimport android.widget.TextView;
383921359f3f01938768f0b0e731941542f0385787Yorke Leeimport android.widget.Toast;
393921359f3f01938768f0b0e731941542f0385787Yorke Lee
40ae274c05cdb6707ca9593bedf20c016cd8164c0bJay Shraunerimport com.android.contacts.common.ContactsUtils;
410d3a73932a23cb07168d25ec331a9abf72817346Nancy Chenimport com.android.contacts.common.interactions.TouchPointManager;
423921359f3f01938768f0b0e731941542f0385787Yorke Leeimport com.android.dialer.R;
4338019af70eb1ca084d36291390bbc54dc81027deYorke Leeimport com.android.dialer.widget.EmptyContentView;
440d3a73932a23cb07168d25ec331a9abf72817346Nancy Chenimport com.android.incallui.CallCardFragment;
450d3a73932a23cb07168d25ec331a9abf72817346Nancy Chenimport com.android.incallui.Log;
463921359f3f01938768f0b0e731941542f0385787Yorke Lee
47f4cb047c49e061cd0590a53d0a176233019eb906Andrew Leeimport java.util.ArrayList;
48f4cb047c49e061cd0590a53d0a176233019eb906Andrew Leeimport java.util.Iterator;
4946fd712ad2896858d977274f94a08aef5bdf0e4cYorke Leeimport java.util.List;
5069c247f619fd2f2474070bdbcec32b78f6444149Yorke Leeimport java.util.Locale;
5146fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee
523921359f3f01938768f0b0e731941542f0385787Yorke Lee/**
533921359f3f01938768f0b0e731941542f0385787Yorke Lee * General purpose utility methods for the Dialer.
543921359f3f01938768f0b0e731941542f0385787Yorke Lee */
553921359f3f01938768f0b0e731941542f0385787Yorke Leepublic class DialerUtils {
563921359f3f01938768f0b0e731941542f0385787Yorke Lee
573921359f3f01938768f0b0e731941542f0385787Yorke Lee    /**
583921359f3f01938768f0b0e731941542f0385787Yorke Lee     * Attempts to start an activity and displays a toast with the default error message if the
593921359f3f01938768f0b0e731941542f0385787Yorke Lee     * activity is not found, instead of throwing an exception.
603921359f3f01938768f0b0e731941542f0385787Yorke Lee     *
613921359f3f01938768f0b0e731941542f0385787Yorke Lee     * @param context to start the activity with.
623921359f3f01938768f0b0e731941542f0385787Yorke Lee     * @param intent to start the activity with.
633921359f3f01938768f0b0e731941542f0385787Yorke Lee     */
643921359f3f01938768f0b0e731941542f0385787Yorke Lee    public static void startActivityWithErrorToast(Context context, Intent intent) {
653921359f3f01938768f0b0e731941542f0385787Yorke Lee        startActivityWithErrorToast(context, intent, R.string.activity_not_available);
663921359f3f01938768f0b0e731941542f0385787Yorke Lee    }
673921359f3f01938768f0b0e731941542f0385787Yorke Lee
683921359f3f01938768f0b0e731941542f0385787Yorke Lee    /**
693921359f3f01938768f0b0e731941542f0385787Yorke Lee     * Attempts to start an activity and displays a toast with a provided error message if the
703921359f3f01938768f0b0e731941542f0385787Yorke Lee     * activity is not found, instead of throwing an exception.
713921359f3f01938768f0b0e731941542f0385787Yorke Lee     *
723921359f3f01938768f0b0e731941542f0385787Yorke Lee     * @param context to start the activity with.
733921359f3f01938768f0b0e731941542f0385787Yorke Lee     * @param intent to start the activity with.
743921359f3f01938768f0b0e731941542f0385787Yorke Lee     * @param msgId Resource ID of the string to display in an error message if the activity is
753921359f3f01938768f0b0e731941542f0385787Yorke Lee     *              not found.
763921359f3f01938768f0b0e731941542f0385787Yorke Lee     */
773921359f3f01938768f0b0e731941542f0385787Yorke Lee    public static void startActivityWithErrorToast(Context context, Intent intent, int msgId) {
783921359f3f01938768f0b0e731941542f0385787Yorke Lee        try {
79247df6ee4f43af916f7e7f339ed181a18807ef36Andrew Lee            if ((IntentUtil.CALL_ACTION.equals(intent.getAction())
80b82e8dae149a9f247e5c9fcae02ced460670b0e7Yorke Lee                            && context instanceof Activity)) {
810d3a73932a23cb07168d25ec331a9abf72817346Nancy Chen                // All dialer-initiated calls should pass the touch point to the InCallUI
820d3a73932a23cb07168d25ec331a9abf72817346Nancy Chen                Point touchPoint = TouchPointManager.getInstance().getPoint();
830d3a73932a23cb07168d25ec331a9abf72817346Nancy Chen                if (touchPoint.x != 0 || touchPoint.y != 0) {
840d3a73932a23cb07168d25ec331a9abf72817346Nancy Chen                    Bundle extras = new Bundle();
850d3a73932a23cb07168d25ec331a9abf72817346Nancy Chen                    extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint);
869dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunn                    intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
870d3a73932a23cb07168d25ec331a9abf72817346Nancy Chen                }
88b82e8dae149a9f247e5c9fcae02ced460670b0e7Yorke Lee                final TelecomManager tm =
89b82e8dae149a9f247e5c9fcae02ced460670b0e7Yorke Lee                        (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
90b82e8dae149a9f247e5c9fcae02ced460670b0e7Yorke Lee                tm.placeCall(intent.getData(), intent.getExtras());
9172d59616b7a491d41c9b127b777c63fe315ecd06Yorke Lee            } else {
9272d59616b7a491d41c9b127b777c63fe315ecd06Yorke Lee                context.startActivity(intent);
9372d59616b7a491d41c9b127b777c63fe315ecd06Yorke Lee            }
943921359f3f01938768f0b0e731941542f0385787Yorke Lee        } catch (ActivityNotFoundException e) {
953921359f3f01938768f0b0e731941542f0385787Yorke Lee            Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show();
963921359f3f01938768f0b0e731941542f0385787Yorke Lee        }
973921359f3f01938768f0b0e731941542f0385787Yorke Lee    }
9846fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee
9946fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee    /**
10046fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee     * Returns the component name to use in order to send an SMS using the default SMS application,
10146fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee     * or null if none exists.
10246fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee     */
10346fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee    public static ComponentName getSmsComponent(Context context) {
10446fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee        String smsPackage = Telephony.Sms.getDefaultSmsPackage(context);
10546fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee        if (smsPackage != null) {
10646fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee            final PackageManager packageManager = context.getPackageManager();
10746fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee            final Intent intent = new Intent(Intent.ACTION_SENDTO,
108ae274c05cdb6707ca9593bedf20c016cd8164c0bJay Shrauner                    Uri.fromParts(ContactsUtils.SCHEME_SMSTO, "", null));
10946fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee            final List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent, 0);
11046fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee            for (ResolveInfo resolveInfo : resolveInfos) {
11146fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee                if (smsPackage.equals(resolveInfo.activityInfo.packageName)) {
11246fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee                    return new ComponentName(smsPackage, resolveInfo.activityInfo.name);
11346fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee                }
11446fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee            }
11546fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee        }
11646fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee        return null;
11746fd712ad2896858d977274f94a08aef5bdf0e4cYorke Lee    }
1180a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Lee
1190a4327e6bfeedc23ddefb4df9f6e8041ebc87b59Andrew Lee    /**
12035ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee     * Closes an {@link AutoCloseable}, silently ignoring any checked exceptions. Does nothing if
12135ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee     * null.
12235ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee     *
12335ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee     * @param closeable to close.
12435ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee     */
12535ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee    public static void closeQuietly(AutoCloseable closeable) {
12635ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee        if (closeable != null) {
12735ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee            try {
12835ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee                closeable.close();
12935ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee            } catch (RuntimeException rethrown) {
13035ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee                throw rethrown;
13135ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee            } catch (Exception ignored) {
13235ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee            }
13335ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee        }
13435ee63feb37dcc38483a35e11fff3f16bb0bfe75Yorke Lee    }
1358b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn
1368b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn    /**
1378b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * Joins a list of {@link CharSequence} into a single {@link CharSequence} seperated by a
1388b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * localized delimiter such as ", ".
1398b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     *
1408b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * @param resources Resources used to get list delimiter.
1418b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * @param list List of char sequences to join.
1428b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * @return Joined char sequences.
1438b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     */
1448b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn    public static CharSequence join(Resources resources, Iterable<CharSequence> list) {
145f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        StringBuilder sb = new StringBuilder();
146f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        final BidiFormatter formatter = BidiFormatter.getInstance();
1478b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        final CharSequence separator = resources.getString(R.string.list_delimeter);
148f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee
149f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        Iterator<CharSequence> itr = list.iterator();
150f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        boolean firstTime = true;
151f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        while (itr.hasNext()) {
152f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee            if (firstTime) {
153f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee                firstTime = false;
154f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee            } else {
155f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee                sb.append(separator);
156f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee            }
157f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee            // Unicode wrap the elements of the list to respect RTL for individual strings.
158f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee            sb.append(formatter.unicodeWrap(
159f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee                    itr.next().toString(), TextDirectionHeuristics.FIRSTSTRONG_LTR));
160f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        }
161f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee
162f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        // Unicode wrap the joined value, to respect locale's RTL ordering for the whole list.
163f4cb047c49e061cd0590a53d0a176233019eb906Andrew Lee        return formatter.unicodeWrap(sb.toString());
1648b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn    }
16569c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee
16669c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee    /**
16769c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee     * @return True if the application is currently in RTL mode.
16869c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee     */
16969c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee    public static boolean isRtl() {
17069c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee        return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) ==
17169c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee            View.LAYOUT_DIRECTION_RTL;
17269c247f619fd2f2474070bdbcec32b78f6444149Yorke Lee    }
173f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee
174f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee    public static void showInputMethod(View view) {
175f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee        final InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(
176f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee                Context.INPUT_METHOD_SERVICE);
177f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee        if (imm != null) {
178f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee            imm.showSoftInput(view, 0);
179f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee        }
180f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee    }
181f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee
182f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee    public static void hideInputMethod(View view) {
183f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee        final InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(
184f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee                Context.INPUT_METHOD_SERVICE);
185f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee        if (imm != null) {
186f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
187f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee        }
188f543baadd1119bad7cd9ff7ed39e5598c6fc50d6Yorke Lee    }
1893921359f3f01938768f0b0e731941542f0385787Yorke Lee}
190