Use BindCallback with ServiceBinder.bind().
Incoming calls sequence will need to know when the bind() succeeds so it no longer makes sense for the wrapper objects to have direct references to the finder. Changes included: - Making the handle* methods of ServiceBinder private implementations instead of astract. - Add overriden setServiceInterface() to the wrapper. - Add simple BindCallback interface used to get notified of bind() results. - Update CallServiceRepository to use BindCallback. Change-Id: I59300e16463e88626df6d055b7fd4be1d850c5f2
This commit is contained in:
parent
c195e3613a
commit
5c12c6e001
|
@ -55,26 +55,16 @@ public class CallServiceProviderWrapper extends ServiceBinder<ICallServiceProvid
|
|||
* @param componentName The component name of the service to bind to.
|
||||
* @param repository The call-service repository.
|
||||
*/
|
||||
public CallServiceProviderWrapper(ComponentName componentName, CallServiceRepository repository) {
|
||||
public CallServiceProviderWrapper(
|
||||
ComponentName componentName, CallServiceRepository repository) {
|
||||
|
||||
super(CALL_SERVICE_PROVIDER_ACTION, componentName);
|
||||
mRepository = repository;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void handleSuccessfulConnection(IBinder binder) {
|
||||
@Override protected void setServiceInterface(IBinder binder) {
|
||||
mServiceInterface = ICallServiceProvider.Stub.asInterface(binder);
|
||||
mRepository.processProvider(getComponentName(), this);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void handleFailedConnection() {
|
||||
mRepository.abortProvider(getComponentName());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void handleServiceDisconnected() {
|
||||
mServiceInterface = null;
|
||||
// TODO(santoscordon): fill in.
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@ import android.telecomm.ICallServiceLookupResponse;
|
|||
import android.telecomm.ICallServiceProvider;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.telecomm.ServiceBinder.BindCallback;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -151,11 +152,8 @@ final class CallServiceRepository {
|
|||
mOutstandingProviders = Sets.newHashSet();
|
||||
|
||||
for (ComponentName name : providerNames) {
|
||||
// Bind to each of the providers that were found. Some of the providers may already be
|
||||
// bound, and in those cases the provider wrapper will still invoke processProvider()
|
||||
// allowing us to treat bound and unbound providers the same.
|
||||
getProvider(name).bind();
|
||||
mOutstandingProviders.add(name);
|
||||
bindProvider(name);
|
||||
}
|
||||
|
||||
int providerCount = providerNames.size();
|
||||
|
@ -175,6 +173,29 @@ final class CallServiceRepository {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to bind to the specified provider before continuing to {@link #processProvider}.
|
||||
*
|
||||
* @param componentName The component name of the relevant provider.
|
||||
*/
|
||||
private void bindProvider(final ComponentName componentName) {
|
||||
final CallServiceProviderWrapper provider = getProvider(componentName);
|
||||
|
||||
BindCallback callback = new BindCallback() {
|
||||
@Override public void onSuccess() {
|
||||
processProvider(componentName, provider);
|
||||
}
|
||||
@Override public void onFailure() {
|
||||
abortProvider(componentName);
|
||||
}
|
||||
};
|
||||
|
||||
// Some of the providers may already be bound, and in those cases the provider wrapper will
|
||||
// still invoke BindCallback.onSuccess() allowing us to treat bound and unbound providers
|
||||
// the same way.
|
||||
provider.bind(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the all-inclusive list of call-service-provider names.
|
||||
*
|
||||
|
@ -206,7 +227,7 @@ final class CallServiceRepository {
|
|||
* @param providerName The component name of the relevant provider.
|
||||
* @param provider The provider object to process.
|
||||
*/
|
||||
void processProvider(
|
||||
private void processProvider(
|
||||
final ComponentName providerName, final CallServiceProviderWrapper provider) {
|
||||
Preconditions.checkNotNull(providerName);
|
||||
Preconditions.checkNotNull(provider);
|
||||
|
@ -234,7 +255,7 @@ final class CallServiceRepository {
|
|||
*
|
||||
* @param providerName The component name of the relevant provider.
|
||||
*/
|
||||
void abortProvider(ComponentName providerName) {
|
||||
private void abortProvider(ComponentName providerName) {
|
||||
Preconditions.checkNotNull(providerName);
|
||||
removeOutstandingProvider(providerName);
|
||||
}
|
||||
|
|
|
@ -65,27 +65,6 @@ public class CallServiceWrapper extends ServiceBinder<ICallService> {
|
|||
mAdapter = adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the underlying call-service implementation upon successful binding.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override public void handleSuccessfulConnection(IBinder binder) {
|
||||
mServiceInterface = ICallService.Stub.asInterface(binder);
|
||||
setCallServiceAdapter(mAdapter);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void handleFailedConnection() {
|
||||
// TODO(santoscordon): fill in
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public void handleServiceDisconnected() {
|
||||
mServiceInterface = null;
|
||||
// TODO(santoscordon): fill in.
|
||||
}
|
||||
|
||||
public CallServiceInfo getInfo() {
|
||||
return mCallServiceInfo;
|
||||
}
|
||||
|
@ -141,4 +120,10 @@ public class CallServiceWrapper extends ServiceBinder<ICallService> {
|
|||
Log.e(TAG, "Failed to disconnect call " + callId + ".", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override protected void setServiceInterface(IBinder binder) {
|
||||
mServiceInterface = ICallService.Stub.asInterface(binder);
|
||||
setCallServiceAdapter(mAdapter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ import android.os.IInterface;
|
|||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Abstract class to perform the work of binding and unbinding to the specified service interface.
|
||||
|
@ -33,6 +36,14 @@ import com.google.common.base.Strings;
|
|||
*/
|
||||
abstract class ServiceBinder<ServiceInterface extends IInterface> {
|
||||
|
||||
/**
|
||||
* Callback to notify after a binding succeeds or fails.
|
||||
*/
|
||||
interface BindCallback {
|
||||
public void onSuccess();
|
||||
public void onFailure();
|
||||
}
|
||||
|
||||
private final class ServiceBinderConnection implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName componentName, IBinder binder) {
|
||||
|
@ -42,6 +53,7 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
|
|||
if (mIsBindingAborted) {
|
||||
clearAbort();
|
||||
mContext.unbindService(this);
|
||||
handleFailedConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -68,6 +80,9 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
|
|||
/** The component name of the service to bind to. */
|
||||
private final ComponentName mComponentName;
|
||||
|
||||
/** The set of callbacks waiting for notification of the binding's success or failure. */
|
||||
private final Set<BindCallback> mCallbacks = Sets.newHashSet();
|
||||
|
||||
/** Used to bind and unbind from the service. */
|
||||
private ServiceConnection mServiceConnection;
|
||||
|
||||
|
@ -98,15 +113,24 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
|
|||
/**
|
||||
* Performs an asynchronous bind to the service if not already bound.
|
||||
*
|
||||
* @param callback The callback to notify of the binding's success or failure.
|
||||
* @return The result of {#link Context#bindService} or true if already bound.
|
||||
*/
|
||||
final boolean bind() {
|
||||
final boolean bind(BindCallback callback) {
|
||||
ThreadUtil.checkOnMainThread();
|
||||
|
||||
// Reset any abort request if we're asked to bind again.
|
||||
clearAbort();
|
||||
|
||||
// If we are already waiting on a binding request, simply append to the list of waiting
|
||||
// callbacks.
|
||||
if (!mCallbacks.isEmpty()) {
|
||||
mCallbacks.add(callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mServiceConnection == null) {
|
||||
mCallbacks.add(callback);
|
||||
Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
|
||||
ServiceConnection connection = new ServiceBinderConnection();
|
||||
|
||||
|
@ -143,23 +167,46 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Handles a successful attempt to bind to service. See {@link Context#bindService}.
|
||||
* Notifies all the outstanding callbacks that the service is successfully bound. The list of
|
||||
* outstanding callbacks is cleared afterwards.
|
||||
*
|
||||
* @param service The actual bound service implementation.
|
||||
* @param binder The actual bound service implementation.
|
||||
*/
|
||||
protected abstract void handleSuccessfulConnection(IBinder binder);
|
||||
private void handleSuccessfulConnection(IBinder binder) {
|
||||
setServiceInterface(binder);
|
||||
|
||||
for (BindCallback callback : mCallbacks) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
mCallbacks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a failed attempt to bind to service. See {@link Context#bindService}.
|
||||
* Notifies all the outstanding callbacks that the service failed to bind. The list of
|
||||
* outstanding callbacks is cleared afterwards.
|
||||
*/
|
||||
protected abstract void handleFailedConnection();
|
||||
private void handleFailedConnection() {
|
||||
for (BindCallback callback : mCallbacks) {
|
||||
callback.onFailure();
|
||||
}
|
||||
mCallbacks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a service disconnection.
|
||||
*/
|
||||
protected abstract void handleServiceDisconnected();
|
||||
private void handleServiceDisconnected() {
|
||||
setServiceInterface(null);
|
||||
}
|
||||
|
||||
private void clearAbort() {
|
||||
mIsBindingAborted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service interface after the service is bound or unbound.
|
||||
*
|
||||
* @param binder The actual bound service implementation.
|
||||
*/
|
||||
protected abstract void setServiceInterface(IBinder binder);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue