DefaultDialerManager.java revision 014de02dd2e050c36f7e0d4f57690bd5d023b4f2
1014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee/*
2014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * Copyright (C) 2015 The Android Open Source Project
3014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee *
4014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * in compliance with the License. You may obtain a copy of the License at
6014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee *
7014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * http://www.apache.org/licenses/LICENSE-2.0
8014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee *
9014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * Unless required by applicable law or agreed to in writing, software distributed under the License
10014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * or implied. See the License for the specific language governing permissions and limitations under
12014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * the License.
13014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee */
14014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
15014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leepackage android.telecom;
16014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
17014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.content.ComponentName;
18014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.content.Context;
19014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.content.Intent;
20014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.content.pm.ActivityInfo;
21014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.content.pm.PackageManager;
22014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.content.pm.ResolveInfo;
23014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.provider.Settings;
24014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport android.text.TextUtils;
25014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
26014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport java.util.ArrayList;
27014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leeimport java.util.List;
28014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
29014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee/**
30014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * Class for managing the default dialer application that will receive incoming calls, and be
31014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * allowed to make emergency outgoing calls.
32014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee *
33014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee * @hide
34014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee */
35014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Leepublic class DefaultDialerManager {
36014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    private static final String TAG = "DefaultDialerManager";
37014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
38014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    /**
39014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * Sets the specified package name as the default dialer application. The caller of this method
40014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * needs to have permission to write to secure settings.
41014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
42014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @hide
43014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * */
44014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    public static void setDefaultPhoneApplication(Context context, String packageName) {
45014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        // Get old package name
46014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        String oldPackageName = Settings.Secure.getString(context.getContentResolver(),
47014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                Settings.Secure.DIALER_DEFAULT_APPLICATION);
48014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
49014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
50014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            // No change
51014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            return;
52014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        }
53014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
54014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        // Only make the change if the new package belongs to a valid phone application
55014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        List<ComponentName> componentNames = getInstalledDialerApplications(context);
56014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        final ComponentName foundComponent = getComponentName(componentNames, packageName);
57014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
58014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        if (foundComponent != null) {
59014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            // Update the secure setting.
60014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            Settings.Secure.putString(context.getContentResolver(),
61014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                    Settings.Secure.DIALER_DEFAULT_APPLICATION, foundComponent.getPackageName());
62014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        }
63014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    }
64014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
65014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    /**
66014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * Returns the installed dialer application that will be used to receive incoming calls, and is
67014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * allowed to make emergency calls.
68014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
69014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * The application will be returned in order of preference:
70014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * 1) User selected phone application (if still installed)
71014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * 2) Pre-installed system dialer (if not disabled)
72014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * 3) Null
73014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
74014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @hide
75014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * */
76014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    public static ComponentName getDefaultDialerApplication(Context context) {
77014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        String defaultPackageName = Settings.Secure.getString(context.getContentResolver(),
78014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                Settings.Secure.DIALER_DEFAULT_APPLICATION);
79014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
80014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        final List<ComponentName> componentNames = getInstalledDialerApplications(context);
81014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        if (!TextUtils.isEmpty(defaultPackageName)) {
82014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            final ComponentName defaultDialer =
83014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                    getComponentName(componentNames, defaultPackageName);
84014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            if (defaultDialer != null) {
85014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                return defaultDialer;
86014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            }
87014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        }
88014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
89014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        // No user-set dialer found, fallback to system dialer
90014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        ComponentName systemDialer = getTelecomManager(context).getDefaultPhoneApp();
91014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
92014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        if (systemDialer == null) {
93014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            // No system dialer configured at build time
94014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            return null;
95014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        }
96014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
97014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        // Verify that the system dialer has not been disabled.
98014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        return getComponentName(componentNames, systemDialer.getPackageName());
99014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    }
100014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
101014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    /**
102014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * Returns a list of installed and available dialer applications.
103014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
104014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * In order to appear in the list, a dialer application must implement an intent-filter with
105014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * the DIAL intent for the following schemes:
106014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
107014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * 1) Empty scheme
108014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * 2) tel Uri scheme
109014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
110014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @hide
111014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     **/
112014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    public static List<ComponentName> getInstalledDialerApplications(Context context) {
113014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        PackageManager packageManager = context.getPackageManager();
114014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
115014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        // Get the list of apps registered for the DIAL intent with empty scheme
116014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        Intent intent = new Intent(Intent.ACTION_DIAL);
117014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
118014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
119014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        List<ComponentName> componentNames = new ArrayList<ComponentName> ();
120014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
121014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        for (ResolveInfo resolveInfo : resolveInfoList) {
122014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            final ActivityInfo activityInfo = resolveInfo.activityInfo;
123014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            if (activityInfo == null) {
124014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                continue;
125014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            }
126014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            final ComponentName componentName =
127014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                    new ComponentName(activityInfo.packageName, activityInfo.name);
128014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            componentNames.add(componentName);
129014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        }
130014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
131014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        // TODO: Filter for apps that don't handle DIAL intent with tel scheme
132014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        return componentNames;
133014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    }
134014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
135014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    /**
136014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * Returns the {@link ComponentName} for the installed dialer application for a given package
137014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * name.
138014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
139014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @param context A valid context.
140014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @param packageName to retrieve the {@link ComponentName} for.
141014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
142014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @return The {@link ComponentName} for the installed dialer application corresponding to the
143014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * package name, or null if none is found.
144014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
145014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @hide
146014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     */
147014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    public static ComponentName getDialerApplicationForPackageName(Context context,
148014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            String packageName) {
149014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        return getComponentName(getInstalledDialerApplications(context), packageName);
150014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    }
151014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
152014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    /**
153014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * Returns the component from a list of application components that corresponds to the package
154014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * name.
155014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *
156014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @param componentNames A list of component names
157014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @param packageName The package name to look for
158014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     * @return The {@link ComponentName} that matches the provided packageName, or null if not
159014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     *         found.
160014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee     */
161014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    private static ComponentName getComponentName(List<ComponentName> componentNames,
162014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            String packageName) {
163014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        for (ComponentName componentName : componentNames) {
164014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            if (TextUtils.equals(packageName, componentName.getPackageName())) {
165014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee                return componentName;
166014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee            }
167014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        }
168014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        return null;
169014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    }
170014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee
171014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    private static TelecomManager getTelecomManager(Context context) {
172014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee        return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
173014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee    }
174014de02dd2e050c36f7e0d4f57690bd5d023b4f2Yorke Lee}
175