sri.resultTargets);
}
unbindService(sri.connection);
+ sri.connection.destroy();
mServiceConnections.remove(sri.connection);
if (mServiceConnections.isEmpty()) {
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
mRefinementResultReceiver.destroy();
mRefinementResultReceiver = null;
}
+ unbindRemainingServices();
+ mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT);
}
@Override
return true;
}
+ @Override
+ boolean shouldAutoLaunchSingleChoice() {
+ return false;
+ }
+
private void modifyTargetIntent(Intent in) {
final String action = in.getAction();
if (Intent.ACTION_SEND.equals(action) ||
continue;
}
- final ChooserTargetServiceConnection conn = new ChooserTargetServiceConnection(dri);
+ final ChooserTargetServiceConnection conn =
+ new ChooserTargetServiceConnection(this, dri);
if (bindServiceAsUser(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND,
UserHandle.CURRENT)) {
if (DEBUG) {
final ChooserTargetServiceConnection conn = mServiceConnections.get(i);
if (DEBUG) Log.d(TAG, "unbinding " + conn);
unbindService(conn);
+ conn.destroy();
}
mServiceConnections.clear();
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
}
}
- class ChooserTargetServiceConnection implements ServiceConnection {
+ static class ChooserTargetServiceConnection implements ServiceConnection {
private final DisplayResolveInfo mOriginalTarget;
+ private ComponentName mConnectedComponent;
+ private ChooserActivity mChooserActivity;
+ private final Object mLock = new Object();
private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() {
@Override
public void sendResult(List<ChooserTarget> targets) throws RemoteException {
- filterServiceTargets(mOriginalTarget.getResolveInfo().activityInfo.packageName,
- targets);
- final Message msg = Message.obtain();
- msg.what = CHOOSER_TARGET_SERVICE_RESULT;
- msg.obj = new ServiceResultInfo(mOriginalTarget, targets,
- ChooserTargetServiceConnection.this);
- mChooserHandler.sendMessage(msg);
+ synchronized (mLock) {
+ if (mChooserActivity == null) {
+ Log.e(TAG, "destroyed ChooserTargetServiceConnection received result from "
+ + mConnectedComponent + "; ignoring...");
+ return;
+ }
+ mChooserActivity.filterServiceTargets(
+ mOriginalTarget.getResolveInfo().activityInfo.packageName, targets);
+ final Message msg = Message.obtain();
+ msg.what = CHOOSER_TARGET_SERVICE_RESULT;
+ msg.obj = new ServiceResultInfo(mOriginalTarget, targets,
+ ChooserTargetServiceConnection.this);
+ mChooserActivity.mChooserHandler.sendMessage(msg);
+ }
}
};
- public ChooserTargetServiceConnection(DisplayResolveInfo dri) {
+ public ChooserTargetServiceConnection(ChooserActivity chooserActivity,
+ DisplayResolveInfo dri) {
+ mChooserActivity = chooserActivity;
mOriginalTarget = dri;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.d(TAG, "onServiceConnected: " + name);
- final IChooserTargetService icts = IChooserTargetService.Stub.asInterface(service);
- try {
- icts.getChooserTargets(mOriginalTarget.getResolvedComponentName(),
- mOriginalTarget.getResolveInfo().filter, mChooserTargetResult);
- } catch (RemoteException e) {
- Log.e(TAG, "Querying ChooserTargetService " + name + " failed.", e);
- unbindService(this);
- mServiceConnections.remove(this);
+ synchronized (mLock) {
+ if (mChooserActivity == null) {
+ Log.e(TAG, "destroyed ChooserTargetServiceConnection got onServiceConnected");
+ return;
+ }
+
+ final IChooserTargetService icts = IChooserTargetService.Stub.asInterface(service);
+ try {
+ icts.getChooserTargets(mOriginalTarget.getResolvedComponentName(),
+ mOriginalTarget.getResolveInfo().filter, mChooserTargetResult);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Querying ChooserTargetService " + name + " failed.", e);
+ mChooserActivity.unbindService(this);
+ destroy();
+ mChooserActivity.mServiceConnections.remove(this);
+ }
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.d(TAG, "onServiceDisconnected: " + name);
- unbindService(this);
- mServiceConnections.remove(this);
- if (mServiceConnections.isEmpty()) {
- mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
- sendVoiceChoicesIfNeeded();
+ synchronized (mLock) {
+ if (mChooserActivity == null) {
+ Log.e(TAG,
+ "destroyed ChooserTargetServiceConnection got onServiceDisconnected");
+ return;
+ }
+
+ mChooserActivity.unbindService(this);
+ destroy();
+ mChooserActivity.mServiceConnections.remove(this);
+ if (mChooserActivity.mServiceConnections.isEmpty()) {
+ mChooserActivity.mChooserHandler.removeMessages(
+ CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
+ mChooserActivity.sendVoiceChoicesIfNeeded();
+ }
+ mConnectedComponent = null;
+ }
+ }
+
+ public void destroy() {
+ synchronized (mLock) {
+ mChooserActivity = null;
}
}
@Override
public String toString() {
- return mOriginalTarget.getResolveInfo().activityInfo.toString();
+ return "ChooserTargetServiceConnection{service="
+ + mConnectedComponent + ", activity="
+ + mOriginalTarget.getResolveInfo().activityInfo.toString() + "}";
}
}
mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage);
- configureContentView(mIntents, initialIntents, rList, alwaysUseOption);
+ if (configureContentView(mIntents, initialIntents, rList, alwaysUseOption)) {
+ return;
+ }
// Prevent the Resolver window from becoming the top fullscreen window and thus from taking
// control of the system bars.
return false;
}
+ boolean shouldAutoLaunchSingleChoice() {
+ return true;
+ }
+
void showAppDetails(ResolveInfo ri) {
Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
launchedFromUid, filterLastUsed);
}
- void configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
+ /**
+ * Returns true if the activity is finishing and creation should halt
+ */
+ boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
List<ResolveInfo> rList, boolean alwaysUseOption) {
// The last argument of createAdapter is whether to do special handling
// of the last used choice to highlight it in the list. We need to always
mAlwaysUseOption = alwaysUseOption;
int count = mAdapter.getUnfilteredCount();
- if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {
+ if ((!shouldAutoLaunchSingleChoice() && count > 0)
+ || count > 1
+ || (count == 1 && mAdapter.getOtherProfile() != null)) {
setContentView(layoutId);
mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption);
mPackageMonitor.unregister();
mRegistered = false;
finish();
- return;
+ return true;
} else {
setContentView(R.layout.resolver_list);
mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
mAdapterView.setVisibility(View.GONE);
}
+ return false;
}
void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,