|  | /* | 
|  | * Copyright (C) 2015 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License | 
|  | */ | 
|  | package android.provider; | 
|  |  | 
|  | import android.app.admin.DevicePolicyManager; | 
|  | import android.compat.annotation.UnsupportedAppUsage; | 
|  | import android.content.ActivityNotFoundException; | 
|  | import android.content.ContentUris; | 
|  | import android.content.Context; | 
|  | import android.content.Intent; | 
|  | import android.content.UriMatcher; | 
|  | import android.net.Uri; | 
|  | import android.os.UserHandle; | 
|  | import android.text.TextUtils; | 
|  | import android.widget.Toast; | 
|  |  | 
|  | import java.util.List; | 
|  |  | 
|  | /** | 
|  | * Contacts related internal methods. | 
|  | * | 
|  | * @hide | 
|  | */ | 
|  | public class ContactsInternal { | 
|  | private ContactsInternal() { | 
|  | } | 
|  |  | 
|  | /** URI matcher used to parse contact URIs. */ | 
|  | private static final UriMatcher sContactsUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); | 
|  |  | 
|  | private static final int CONTACTS_URI_LOOKUP_ID = 1000; | 
|  | private static final int CONTACTS_URI_LOOKUP = 1001; | 
|  |  | 
|  | static { | 
|  | // Contacts URI matching table | 
|  | final UriMatcher matcher = sContactsUriMatcher; | 
|  | matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_URI_LOOKUP); | 
|  | matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_URI_LOOKUP_ID); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Called by {@link ContactsContract} to star Quick Contact, possibly on the managed profile. | 
|  | */ | 
|  | @UnsupportedAppUsage | 
|  | public static void startQuickContactWithErrorToast(Context context, Intent intent) { | 
|  | final Uri uri = intent.getData(); | 
|  |  | 
|  | final int match = sContactsUriMatcher.match(uri); | 
|  | switch (match) { | 
|  | case CONTACTS_URI_LOOKUP: | 
|  | case CONTACTS_URI_LOOKUP_ID: { | 
|  | if (maybeStartManagedQuickContact(context, intent)) { | 
|  | return; // Request handled by DPM.  Just return here. | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | // Launch on the current profile. | 
|  | startQuickContactWithErrorToastForUser(context, intent, context.getUser()); | 
|  | } | 
|  |  | 
|  | public static void startQuickContactWithErrorToastForUser(Context context, Intent intent, | 
|  | UserHandle user) { | 
|  | try { | 
|  | context.startActivityAsUser(intent, user); | 
|  | } catch (ActivityNotFoundException e) { | 
|  | Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available, | 
|  | Toast.LENGTH_SHORT).show(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * If the URI in {@code intent} is of a corp contact, launch quick contact on the managed | 
|  | * profile. | 
|  | * | 
|  | * @return the URI in {@code intent} is of a corp contact thus launched on the managed profile. | 
|  | */ | 
|  | private static boolean maybeStartManagedQuickContact(Context context, Intent originalIntent) { | 
|  | final Uri uri = originalIntent.getData(); | 
|  |  | 
|  | // Decompose into an ID and a lookup key. | 
|  | final List<String> pathSegments = uri.getPathSegments(); | 
|  | final boolean isContactIdIgnored = pathSegments.size() < 4; | 
|  | final long contactId = isContactIdIgnored | 
|  | ? ContactsContract.Contacts.ENTERPRISE_CONTACT_ID_BASE //contact id will be ignored | 
|  | : ContentUris.parseId(uri); | 
|  | final String lookupKey = pathSegments.get(2); | 
|  | final String directoryIdStr = uri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY); | 
|  | final long directoryId = (directoryIdStr == null) | 
|  | ? ContactsContract.Directory.ENTERPRISE_DIRECTORY_ID_BASE | 
|  | : Long.parseLong(directoryIdStr); | 
|  |  | 
|  | // See if it has a corp lookupkey. | 
|  | if (TextUtils.isEmpty(lookupKey) | 
|  | || !lookupKey.startsWith( | 
|  | ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX)) { | 
|  | return false; // It's not a corp lookup key. | 
|  | } | 
|  |  | 
|  | if (!ContactsContract.Contacts.isEnterpriseContactId(contactId)) { | 
|  | throw new IllegalArgumentException("Invalid enterprise contact id: " + contactId); | 
|  | } | 
|  | if (!ContactsContract.Directory.isEnterpriseDirectoryId(directoryId)) { | 
|  | throw new IllegalArgumentException("Invalid enterprise directory id: " + directoryId); | 
|  | } | 
|  |  | 
|  | // Launch Quick Contact on the managed profile, if the policy allows. | 
|  | final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); | 
|  | final String actualLookupKey = lookupKey.substring( | 
|  | ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX.length()); | 
|  | final long actualContactId = | 
|  | (contactId - ContactsContract.Contacts.ENTERPRISE_CONTACT_ID_BASE); | 
|  | final long actualDirectoryId = (directoryId | 
|  | - ContactsContract.Directory.ENTERPRISE_DIRECTORY_ID_BASE); | 
|  |  | 
|  | dpm.startManagedQuickContact(actualLookupKey, actualContactId, isContactIdIgnored, | 
|  | actualDirectoryId, originalIntent); | 
|  | return true; | 
|  | } | 
|  | } |