11040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki/* 21040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * Copyright (C) 2015 The Android Open Source Project 31040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * 41040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 51040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * you may not use this file except in compliance with the License. 61040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * You may obtain a copy of the License at 71040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * 81040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 91040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * 101040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * Unless required by applicable law or agreed to in writing, software 111040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 121040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * See the License for the specific language governing permissions and 141040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * limitations under the License 151040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki */ 161040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukipackage android.provider; 171040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 181040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.app.admin.DevicePolicyManager; 191040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.content.ActivityNotFoundException; 201040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.content.ContentUris; 211040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.content.Context; 221040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.content.Intent; 231040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.content.UriMatcher; 241040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.net.Uri; 251040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.os.Process; 261040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.os.UserHandle; 271040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.text.TextUtils; 281040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport android.widget.Toast; 291040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 301040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukiimport java.util.List; 311040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 321040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki/** 331040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * Contacts related internal methods. 341040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * 351040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * @hide 361040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki */ 371040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onukipublic class ContactsInternal { 381040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki private ContactsInternal() { 391040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 401040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 411040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki /** URI matcher used to parse contact URIs. */ 421040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki private static final UriMatcher sContactsUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 431040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 441040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki private static final int CONTACTS_URI_LOOKUP_ID = 1000; 451040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 461040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki static { 471040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki // Contacts URI matching table 481040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final UriMatcher matcher = sContactsUriMatcher; 491040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_URI_LOOKUP_ID); 501040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 511040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 521040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki /** 531040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * Called by {@link ContactsContract} to star Quick Contact, possibly on the managed profile. 541040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki */ 551040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki public static void startQuickContactWithErrorToast(Context context, Intent intent) { 561040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final Uri uri = intent.getData(); 571040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 581040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final int match = sContactsUriMatcher.match(uri); 591040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki switch (match) { 601040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki case CONTACTS_URI_LOOKUP_ID: { 611040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki if (maybeStartManagedQuickContact(context, intent)) { 621040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki return; // Request handled by DPM. Just return here. 631040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 641040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki break; 651040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 661040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 671040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki // Launch on the current profile. 681040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki startQuickContactWithErrorToastForUser(context, intent, Process.myUserHandle()); 691040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 701040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 711040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki public static void startQuickContactWithErrorToastForUser(Context context, Intent intent, 721040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki UserHandle user) { 731040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki try { 741040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki context.startActivityAsUser(intent, user); 751040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } catch (ActivityNotFoundException e) { 761040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available, 771040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki Toast.LENGTH_SHORT).show(); 781040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 791040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 801040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 811040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki /** 821040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * If the URI in {@code intent} is of a corp contact, launch quick contact on the managed 831040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * profile. 841040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * 851040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki * @return the URI in {@code intent} is of a corp contact thus launched on the managed profile. 861040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki */ 871040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki private static boolean maybeStartManagedQuickContact(Context context, Intent originalIntent) { 881040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final Uri uri = originalIntent.getData(); 891040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 901040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki // Decompose into an ID and a lookup key. 911040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final List<String> pathSegments = uri.getPathSegments(); 921040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final long contactId = ContentUris.parseId(uri); 931040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final String lookupKey = pathSegments.get(2); 941040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 951040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki // See if it has a corp lookupkey. 961040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki if (TextUtils.isEmpty(lookupKey) 971040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki || !lookupKey.startsWith( 981040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX)) { 991040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki return false; // It's not a corp lookup key. 1001040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 1011040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 1021040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki // Launch Quick Contact on the managed profile, if the policy allows. 1031040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 1041040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final String actualLookupKey = lookupKey.substring( 1051040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX.length()); 1061040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki final long actualContactId = 1071040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki (contactId - ContactsContract.Contacts.ENTERPRISE_CONTACT_ID_BASE); 1081040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki 1091040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki dpm.startManagedQuickContact(actualLookupKey, actualContactId, originalIntent); 1101040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki return true; 1111040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki } 1121040da1d4eb99fd2588e4c4d5b08b2e3fc0c7777Makoto Onuki} 113