diff options
Diffstat (limited to 'core/java/com/android/internal/app/ChooserActivity.java')
-rw-r--r-- | core/java/com/android/internal/app/ChooserActivity.java | 119 |
1 files changed, 91 insertions, 28 deletions
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index d9faece..2e0bf06 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -40,6 +40,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; import android.os.UserManager; +import android.provider.DocumentsContract; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; import android.service.chooser.IChooserTargetResult; @@ -104,6 +105,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 +210,8 @@ public class ChooserActivity extends ResolverActivity { mRefinementResultReceiver.destroy(); mRefinementResultReceiver = null; } + unbindRemainingServices(); + mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT); } @Override @@ -265,6 +269,24 @@ public class ChooserActivity extends ResolverActivity { return true; } + @Override + boolean shouldAutoLaunchSingleChoice(TargetInfo target) { + final Intent intent = target.getResolvedIntent(); + final ResolveInfo resolve = target.getResolveInfo(); + + // When GET_CONTENT is handled by the DocumentsUI system component, + // we're okay automatically launching it, since it offers it's own + // intent disambiguation UI. + if (intent != null && Intent.ACTION_GET_CONTENT.equals(intent.getAction()) + && resolve != null && resolve.priority > 0 + && resolve.activityInfo != null && DocumentsContract.PACKAGE_DOCUMENTS_UI + .equals(resolve.activityInfo.packageName)) { + return true; + } + + return false; + } + private void modifyTargetIntent(Intent in) { final String action = in.getAction(); if (Intent.ACTION_SEND.equals(action) || @@ -371,7 +393,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 +448,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); @@ -637,7 +661,8 @@ public class ChooserActivity extends ResolverActivity { @Override public CharSequence getExtendedInfo() { - return mSourceInfo != null ? mSourceInfo.getExtendedInfo() : null; + // ChooserTargets have badge icons, so we won't show the extended info to disambiguate. + return null; } @Override @@ -730,9 +755,8 @@ public class ChooserActivity extends ResolverActivity { @Override public boolean showsExtendedInfo(TargetInfo info) { - // Reserve space to show extended info if any one of the items in the adapter has - // extended info. This keeps grid item sizes uniform. - return hasExtendedInfo(); + // We have badges so we don't need this text shown. + return false; } @Override @@ -1024,54 +1048,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() + "}"; } } |