am 39e94ebe: Handle single-choice ChooserActivities and bound ChooserTargetServices

* commit '39e94ebe22d4959facea4c3621a0a5377242a570':
  Handle single-choice ChooserActivities and bound ChooserTargetServices
This commit is contained in:
Adam Powell
2015-09-16 21:02:58 +00:00
committed by Android Git Automerger
2 changed files with 89 additions and 28 deletions

View File

@@ -104,6 +104,7 @@ public class ChooserActivity extends ResolverActivity {
sri.resultTargets);
}
unbindService(sri.connection);
sri.connection.destroy();
mServiceConnections.remove(sri.connection);
if (mServiceConnections.isEmpty()) {
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
@@ -208,6 +209,8 @@ public class ChooserActivity extends ResolverActivity {
mRefinementResultReceiver.destroy();
mRefinementResultReceiver = null;
}
unbindRemainingServices();
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT);
}
@Override
@@ -265,6 +268,11 @@ public class ChooserActivity extends ResolverActivity {
return true;
}
@Override
boolean shouldAutoLaunchSingleChoice() {
return false;
}
private void modifyTargetIntent(Intent in) {
final String action = in.getAction();
if (Intent.ACTION_SEND.equals(action) ||
@@ -371,7 +379,8 @@ public class ChooserActivity extends ResolverActivity {
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) {
@@ -425,6 +434,7 @@ public class ChooserActivity extends ResolverActivity {
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);
@@ -1024,54 +1034,93 @@ public class ChooserActivity extends ResolverActivity {
}
}
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() + "}";
}
}

View File

@@ -234,7 +234,9 @@ public class ResolverActivity extends Activity {
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.
@@ -794,6 +796,10 @@ public class ResolverActivity extends Activity {
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))
@@ -808,7 +814,10 @@ public class ResolverActivity extends Activity {
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
@@ -828,7 +837,9 @@ public class ResolverActivity extends Activity {
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);
@@ -837,7 +848,7 @@ public class ResolverActivity extends Activity {
mPackageMonitor.unregister();
mRegistered = false;
finish();
return;
return true;
} else {
setContentView(R.layout.resolver_list);
@@ -847,6 +858,7 @@ public class ResolverActivity extends Activity {
mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
mAdapterView.setVisibility(View.GONE);
}
return false;
}
void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,