blob: aa9f05814976cdb62159aea2855561fccc91692d [file] [log] [blame]
Santos Cordon8e8b8d22013-12-19 14:14:05 -08001/*
2 * Copyright (C) 2013 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 */
16
17package com.android.telecomm;
18
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.PackageManager;
23import android.content.pm.ResolveInfo;
24import android.content.pm.ServiceInfo;
25import android.telecomm.ICallService;
26import android.telecomm.ICallServiceProvider;
27import android.util.Log;
28
29import com.android.telecomm.CallServiceProviderProxy.CallServiceProviderConnectionCallback;
30import com.google.common.collect.Lists;
31
32import java.util.List;
33
34/**
35 * Finds {@link ICallService} and {@link ICallServiceProvider} implementations on the device.
36 * Uses binder APIs to find ICallServiceProviders and calls method on ICallServiceProvider to
37 * find ICallService implementations.
38 * TODO(santoscordon): Add performance timing to async calls.
39 */
40final class CallServiceFinder {
41 /**
42 * Implemented by classes which want to receive the final list of {@link CallService}s found.
43 */
44 interface CallServiceSearchCallback {
45 /**
46 * Method called after search has completed.
47 *
48 * @param callServices List of {@link ICallServices} found in the search.
49 */
50 public void onSearchComplete(List<ICallService> callServices);
51 }
52
53 /** Used to identify log entries by this class */
54 static final String TAG = CallServiceFinder.class.getSimpleName();
55
56 /** Private constructor to prevent instances being made. */
57 private CallServiceFinder() {}
58
59 /**
60 * Asynchronously finds {@link ICallService} implementations and returns them asynchronously
61 * through the callback parameter.
62 *
63 * @param searchCallback The callback executed when the search is complete.
64 */
65 public static void findCallServices(Context context,
66 final CallServiceSearchCallback searchCallback) {
67 List<ComponentName> components = getAllProviderComponents(context);
68
69 Log.i(TAG, "Found " + components.size() + " implementations for ICallServiceProvider");
70
71 for (ComponentName componentName : components) {
72 CallServiceProviderProxy proxy = new CallServiceProviderProxy(componentName, context);
73 CallServiceProviderConnectionCallback onProviderFoundCallback =
74 new CallServiceProviderConnectionCallback() {
75 @Override public void onConnected(ICallServiceProvider serviceProvider) {
76 onProviderFound(serviceProvider, searchCallback);
77 }
78 };
79
80 proxy.connect(onProviderFoundCallback);
81 }
82 }
83
84 /**
85 * Called after a {@link CallServiceProviderProxy} attempts to bind to its
86 * {@link ICallServiceProvider} counterpart. When this method is called, the proxy should
87 * have either made a successful connection or an error occurred.
88 *
89 * @param serviceProvider The instance of ICallServiceProvider.
90 */
91 private static void onProviderFound(ICallServiceProvider serviceProvider,
92 CallServiceSearchCallback searchCallback) {
93 if (serviceProvider == null) {
94 // TODO(santoscordon): Handle error.
95 }
96
97 Log.i(TAG, "Found a service Provider: " + serviceProvider);
98
99 // TODO(santoscordon): asynchronously retrieve ICallService interfaces.
100 // TODO(santoscordon): Filter the list by only those which the user has allowed.
101 }
102
103 private static List<ComponentName> getAllProviderComponents(Context context) {
104 Intent serviceIntent = getICallServiceProviderIntent();
105
106 PackageManager packageManager = context.getPackageManager();
107 List<ResolveInfo> resolveInfos = packageManager.queryIntentServices(serviceIntent, 0);
108
109 List<ComponentName> components = Lists.newArrayList();
110 for (ResolveInfo resolveInfo : resolveInfos) {
111 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
112 // Ignore anything that didn't resolve to a proper service.
113 if (serviceInfo == null) {
114 continue;
115 }
116
117 ComponentName componentName = new ComponentName(serviceInfo.packageName,
118 serviceInfo.name);
119 components.add(componentName);
120 }
121
122 return components;
123 }
124
125 /**
126 * Returns the intent used to resolve all registered {@link ICallService}s.
127 */
128 private static Intent getICallServiceProviderIntent() {
129 return new Intent(ICallServiceProvider.class.getName());
130 }
131}