blob: cdef1300e286e87f2b8c70d51efa008d99f69fa1 [file] [log] [blame]
/*
* Copyright (C) 2013 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 com.android.telecomm;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.telecomm.CallServiceDescriptor;
import android.telecomm.TelecommConstants;
import com.android.internal.telecomm.ICallServiceLookupResponse;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Set;
/**
* Searches for and returns connection services.
*/
class CallServiceRepository extends BaseRepository<ConnectionServiceWrapper> {
/**
* The representation of a single lookup. Maintains lookup state and invokes the "complete"
* callback when finished.
*/
private final class CallServiceLookup {
final Set<ComponentName> mOutstandingProviders = Sets.newHashSet();
final Set<ConnectionServiceWrapper> mServices = Sets.newHashSet();
final LookupCallback<ConnectionServiceWrapper> mCallback;
CallServiceLookup(LookupCallback<ConnectionServiceWrapper> callback) {
mCallback = callback;
}
/** Starts the lookup. */
void start() {
List<ComponentName> providerNames = getProviderNames();
if (providerNames.isEmpty()) {
finishLookup();
return;
}
for (ComponentName name : providerNames) {
mOutstandingProviders.add(name);
queryProviderForCallServices(name);
}
Log.i(this, "Found %d implementations of ICallServiceProvider.",
mOutstandingProviders.size());
}
/**
* Returns the all-inclusive list of call-service-provider names.
*
* @return The list containing the (component) names of all known ICallServiceProvider
* implementations or the empty list upon no available providers.
*/
private List<ComponentName> getProviderNames() {
// The list of provider names to return to the caller, may be populated below.
List<ComponentName> providerNames = Lists.newArrayList();
PackageManager packageManager = TelecommApp.getInstance().getPackageManager();
Intent intent = new Intent(TelecommConstants.ACTION_CALL_SERVICE_PROVIDER);
for (ResolveInfo entry : packageManager.queryIntentServices(intent, 0)) {
ServiceInfo serviceInfo = entry.serviceInfo;
if (serviceInfo != null) {
// The entry resolves to a proper service, add it to the list of provider names.
providerNames.add(
new ComponentName(serviceInfo.packageName, serviceInfo.name));
}
}
return providerNames;
}
/**
* Attempts to obtain call-service descriptors from the specified provider (asynchronously)
* and passes the list through to {@link #processCallServices}, which then relinquishes
* control back to the switchboard.
*
* @param providerName The component name of the relevant provider.
*/
private void queryProviderForCallServices(final ComponentName providerName) {
final CallServiceProviderWrapper provider = new CallServiceProviderWrapper(
providerName);
provider.lookupCallServices(new CallServiceProviderWrapper.LookupResponse() {
@Override
public void setCallServiceDescriptors(List<CallServiceDescriptor> descriptors) {
processCallServices(provider, descriptors);
}
});
}
/**
* Processes the call-service descriptors provided by the specified provider.
*
* @param provider The call-service provider.
* @param callServiceDescriptors The set of descriptors to process.
*/
private void processCallServices(
CallServiceProviderWrapper provider,
List<CallServiceDescriptor> descriptors) {
// Descriptor lookup finished, we no longer need the provider.
provider.unbind();
ComponentName providerName = provider.getComponentName();
if (mOutstandingProviders.remove(providerName)) {
if (descriptors != null) {
// Add all the connection services from this provider to the connection-service
// cache.
for (CallServiceDescriptor descriptor : descriptors) {
mServices.add(getService(descriptor.getServiceComponent(), descriptor));
}
}
if (mOutstandingProviders.isEmpty()) {
finishLookup();
}
} else {
Log.i(this, "Unexpected connection services from %s in lookup.", providerName);
}
}
void finishLookup() {
mCallback.onComplete(mServices);
}
}
private final IncomingCallsManager mIncomingCallsManager;
/** Persists specified parameters. */
CallServiceRepository(IncomingCallsManager incomingCallsManager) {
mIncomingCallsManager = incomingCallsManager;
}
/**
* Returns the connection service implementation specified by the descriptor.
*
* @param descriptor The call-service descriptor.
*/
ConnectionServiceWrapper getService(CallServiceDescriptor descriptor) {
return getService(descriptor.getServiceComponent(), descriptor);
}
/** {@inheritDoc} */
@Override
protected void onLookupServices(LookupCallback<ConnectionServiceWrapper> callback) {
new CallServiceLookup(callback).start();
}
@Override
protected ConnectionServiceWrapper onCreateNewServiceWrapper(ComponentName componentName,
Object param) {
return new ConnectionServiceWrapper(
(CallServiceDescriptor) param, mIncomingCallsManager, this);
}
}