1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16package android.provider;
17
18import android.app.admin.DevicePolicyManager;
19import android.content.ActivityNotFoundException;
20import android.content.ContentUris;
21import android.content.Context;
22import android.content.Intent;
23import android.content.UriMatcher;
24import android.net.Uri;
25import android.os.Process;
26import android.os.UserHandle;
27import android.text.TextUtils;
28import android.widget.Toast;
29
30import java.util.List;
31
32/**
33 * Contacts related internal methods.
34 *
35 * @hide
36 */
37public class ContactsInternal {
38    private ContactsInternal() {
39    }
40
41    /** URI matcher used to parse contact URIs. */
42    private static final UriMatcher sContactsUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
43
44    private static final int CONTACTS_URI_LOOKUP_ID = 1000;
45    private static final int CONTACTS_URI_LOOKUP = 1001;
46
47    static {
48        // Contacts URI matching table
49        final UriMatcher matcher = sContactsUriMatcher;
50        matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_URI_LOOKUP);
51        matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_URI_LOOKUP_ID);
52    }
53
54    /**
55     * Called by {@link ContactsContract} to star Quick Contact, possibly on the managed profile.
56     */
57    public static void startQuickContactWithErrorToast(Context context, Intent intent) {
58        final Uri uri = intent.getData();
59
60        final int match = sContactsUriMatcher.match(uri);
61        switch (match) {
62            case CONTACTS_URI_LOOKUP:
63            case CONTACTS_URI_LOOKUP_ID: {
64                if (maybeStartManagedQuickContact(context, intent)) {
65                    return; // Request handled by DPM.  Just return here.
66                }
67                break;
68            }
69        }
70        // Launch on the current profile.
71        startQuickContactWithErrorToastForUser(context, intent, Process.myUserHandle());
72    }
73
74    public static void startQuickContactWithErrorToastForUser(Context context, Intent intent,
75            UserHandle user) {
76        try {
77            context.startActivityAsUser(intent, user);
78        } catch (ActivityNotFoundException e) {
79            Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available,
80                    Toast.LENGTH_SHORT).show();
81        }
82    }
83
84    /**
85     * If the URI in {@code intent} is of a corp contact, launch quick contact on the managed
86     * profile.
87     *
88     * @return the URI in {@code intent} is of a corp contact thus launched on the managed profile.
89     */
90    private static boolean maybeStartManagedQuickContact(Context context, Intent originalIntent) {
91        final Uri uri = originalIntent.getData();
92
93        // Decompose into an ID and a lookup key.
94        final List<String> pathSegments = uri.getPathSegments();
95        final boolean isContactIdIgnored = pathSegments.size() < 4;
96        final long contactId = isContactIdIgnored
97                ? ContactsContract.Contacts.ENTERPRISE_CONTACT_ID_BASE //contact id will be ignored
98                : ContentUris.parseId(uri);
99        final String lookupKey = pathSegments.get(2);
100        final String directoryIdStr = uri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
101        final long directoryId = (directoryIdStr == null)
102                ? ContactsContract.Directory.ENTERPRISE_DIRECTORY_ID_BASE
103                : Long.parseLong(directoryIdStr);
104
105        // See if it has a corp lookupkey.
106        if (TextUtils.isEmpty(lookupKey)
107                || !lookupKey.startsWith(
108                        ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX)) {
109            return false; // It's not a corp lookup key.
110        }
111
112        if (!ContactsContract.Contacts.isEnterpriseContactId(contactId)) {
113            throw new IllegalArgumentException("Invalid enterprise contact id: " + contactId);
114        }
115        if (!ContactsContract.Directory.isEnterpriseDirectoryId(directoryId)) {
116            throw new IllegalArgumentException("Invalid enterprise directory id: " + directoryId);
117        }
118
119        // Launch Quick Contact on the managed profile, if the policy allows.
120        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
121        final String actualLookupKey = lookupKey.substring(
122                ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX.length());
123        final long actualContactId =
124                (contactId - ContactsContract.Contacts.ENTERPRISE_CONTACT_ID_BASE);
125        final long actualDirectoryId = (directoryId
126                - ContactsContract.Directory.ENTERPRISE_DIRECTORY_ID_BASE);
127
128        dpm.startManagedQuickContact(actualLookupKey, actualContactId, isContactIdIgnored,
129                actualDirectoryId, originalIntent);
130        return true;
131    }
132}
133