15ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee/*
25ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Copyright (C) 2009 The Android Open Source Project
35ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
45ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Licensed under the Apache License, Version 2.0 (the "License");
55ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * you may not use this file except in compliance with the License.
65ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * You may obtain a copy of the License at
75ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
85ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *      http://www.apache.org/licenses/LICENSE-2.0
95ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Unless required by applicable law or agreed to in writing, software
115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * distributed under the License is distributed on an "AS IS" BASIS,
125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * See the License for the specific language governing permissions and
145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * limitations under the License.
155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee */
165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leepackage com.android.contacts.common;
185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.Context;
205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.Intent;
215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.database.Cursor;
2235408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulosimport android.net.Uri;
235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract.CommonDataKinds.Im;
245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract.DisplayPhoto;
255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.telephony.PhoneNumberUtils;
265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.text.TextUtils;
27c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulosimport android.util.Pair;
285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.android.contacts.common.model.account.AccountWithDataSet;
3035408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulosimport com.android.contacts.common.model.dataitem.ImDataItem;
3188bede3df22a27296afcec83c2f2f430d1bc1372Yorke Leeimport com.android.contacts.common.testing.NeededForTesting;
325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.android.contacts.common.model.AccountTypeManager;
335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport java.util.List;
355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leepublic class ContactsUtils {
375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    private static final String TAG = "ContactsUtils";
385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
39382b6dacb5d1582fa198c84825489d846ba9e5bcJay Shrauner    // Telecomm related schemes are in CallUtil
40382b6dacb5d1582fa198c84825489d846ba9e5bcJay Shrauner    public static final String SCHEME_IMTO = "imto";
41382b6dacb5d1582fa198c84825489d846ba9e5bcJay Shrauner    public static final String SCHEME_MAILTO = "mailto";
42382b6dacb5d1582fa198c84825489d846ba9e5bcJay Shrauner    public static final String SCHEME_SMSTO = "smsto";
43382b6dacb5d1582fa198c84825489d846ba9e5bcJay Shrauner
44114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner    private static final int DEFAULT_THUMBNAIL_SIZE = 96;
45114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner
465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    private static int sThumbnailSize = -1;
475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    // TODO find a proper place for the canonical version of these
495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public interface ProviderNames {
505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String YAHOO = "Yahoo";
515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String GTALK = "GTalk";
525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String MSN = "MSN";
535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String ICQ = "ICQ";
545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String AIM = "AIM";
555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String XMPP = "XMPP";
565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String JABBER = "JABBER";
575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String SKYPE = "SKYPE";
585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String QQ = "QQ";
595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * This looks up the provider name defined in
635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * ProviderNames from the predefined IM protocol id.
645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * This is used for interacting with the IM application.
655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     *
665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param protocol the protocol ID
675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @return the provider name the IM app uses for the given protocol, or null if no
685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * provider is defined for the given protocol
695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @hide
705ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
715ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static String lookupProviderNameFromId(int protocol) {
725ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        switch (protocol) {
735ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_GOOGLE_TALK:
745ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.GTALK;
755ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_AIM:
765ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.AIM;
775ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_MSN:
785ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.MSN;
795ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_YAHOO:
805ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.YAHOO;
815ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_ICQ:
825ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.ICQ;
835ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_JABBER:
845ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.JABBER;
855ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_SKYPE:
865ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.SKYPE;
875ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            case Im.PROTOCOL_QQ:
885ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                return ProviderNames.QQ;
895ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
905ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return null;
915ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
925ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
935ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
945ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Test if the given {@link CharSequence} contains any graphic characters,
955ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * first checking {@link TextUtils#isEmpty(CharSequence)} to handle null.
965ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
975ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static boolean isGraphic(CharSequence str) {
985ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return !TextUtils.isEmpty(str) && TextUtils.isGraphic(str);
995ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1005ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1015ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1025ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Returns true if two objects are considered equal.  Two null references are equal here.
1035ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1045ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    @NeededForTesting
1055ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static boolean areObjectsEqual(Object a, Object b) {
1065ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return a == b || (a != null && a.equals(b));
1075ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1085ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1095ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Returns true if two {@link Intent}s are both null, or have the same action.
1115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final boolean areIntentActionEqual(Intent a, Intent b) {
1135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (a == b) {
1145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            return true;
1155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (a == null || b == null) {
1175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            return false;
1185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return TextUtils.equals(a.getAction(), b.getAction());
1205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static boolean areContactWritableAccountsAvailable(Context context) {
1235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final List<AccountWithDataSet> accounts =
1245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                AccountTypeManager.getInstance(context).getAccounts(true /* writeable */);
1255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return !accounts.isEmpty();
1265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static boolean areGroupWritableAccountsAvailable(Context context) {
1295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final List<AccountWithDataSet> accounts =
1305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                AccountTypeManager.getInstance(context).getGroupWritableAccounts();
1315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return !accounts.isEmpty();
1325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Returns the size (width and height) of thumbnail pictures as configured in the provider. This
1365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * can safely be called from the UI thread, as the provider can serve this without performing
1375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * a database access
1385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static int getThumbnailSize(Context context) {
1405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (sThumbnailSize == -1) {
1415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final Cursor c = context.getContentResolver().query(
1425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
1435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    new String[] { DisplayPhoto.THUMBNAIL_MAX_DIM }, null, null, null);
144114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner            if (c != null) {
145114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                try {
146114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                    if (c.moveToFirst()) {
147114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                        sThumbnailSize = c.getInt(0);
148114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                    }
149114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                } finally {
150114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                    c.close();
151114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner                }
1525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
1535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
154114c36573f4860ccbc2d4fd041228b95576d89beJay Shrauner        return sThumbnailSize != -1 ? sThumbnailSize : DEFAULT_THUMBNAIL_SIZE;
1555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
157c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos    private static Intent getCustomImIntent(ImDataItem im, int protocol) {
15835408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        String host = im.getCustomProtocol();
15935408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        final String data = im.getData();
16035408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        if (TextUtils.isEmpty(data)) {
16135408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos            return null;
16235408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        }
16335408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        if (protocol != Im.PROTOCOL_CUSTOM) {
16435408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos            // Try bringing in a well-known host for specific protocols
16535408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos            host = ContactsUtils.lookupProviderNameFromId(protocol);
16635408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        }
16735408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        if (TextUtils.isEmpty(host)) {
16835408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos            return null;
16935408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        }
17035408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        final String authority = host.toLowerCase();
171382b6dacb5d1582fa198c84825489d846ba9e5bcJay Shrauner        final Uri imUri = new Uri.Builder().scheme(SCHEME_IMTO).authority(
17235408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos                authority).appendPath(data).build();
17335408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        final Intent intent = new Intent(Intent.ACTION_SENDTO, imUri);
17435408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos        return intent;
17535408bef2b7a180dfa5860e87d4d62209d9d1e09Paul Soulos    }
176c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos
177c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos    /**
178c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos     * Returns the proper Intent for an ImDatItem. If available, a secondary intent is stored
179c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos     * in the second Pair slot
180c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos     */
181c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos    public static Pair<Intent, Intent> buildImIntent(Context context, ImDataItem im) {
182c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        Intent intent = null;
183c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        Intent secondaryIntent = null;
184c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        final boolean isEmail = im.isCreatedFromEmail();
185c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos
186c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        if (!isEmail && !im.isProtocolValid()) {
187ca2ae1848c20aced422c44249b57e9dd3a1353ebJay Shrauner            return new Pair<>(null, null);
188c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        }
189c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos
190c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        final String data = im.getData();
191c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        if (TextUtils.isEmpty(data)) {
192ca2ae1848c20aced422c44249b57e9dd3a1353ebJay Shrauner            return new Pair<>(null, null);
193c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        }
194c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos
195c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
196c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos
197c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        if (protocol == Im.PROTOCOL_GOOGLE_TALK) {
198c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            final int chatCapability = im.getChatCapability();
199c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
200c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                intent = new Intent(Intent.ACTION_SENDTO,
201c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                                Uri.parse("xmpp:" + data + "?message"));
202c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                secondaryIntent = new Intent(Intent.ACTION_SENDTO,
203c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                        Uri.parse("xmpp:" + data + "?call"));
204c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            } else if ((chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
205c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                // Allow Talking and Texting
206c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                intent =
207c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                    new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
208c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                secondaryIntent =
209c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                    new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
210c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            } else {
211c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                intent =
212c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos                    new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
213c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            }
214c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        } else {
215c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            // Build an IM Intent
216c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos            intent = getCustomImIntent(im, protocol);
217c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        }
218c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos        return new Pair<>(intent, secondaryIntent);
219c219d047ada3c8f7a43e850baa7c7acb71252870Paul Soulos    }
2205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee}
221