diff options
| author | 2015-06-23 01:18:27 +0000 | |
|---|---|---|
| committer | 2015-06-23 01:18:28 +0000 | |
| commit | 9f49dcda24ea63efc8b16d0c7d69cc697cdf20d7 (patch) | |
| tree | 969c896175e4f40c6c2bb50838799029eeb2a0e7 | |
| parent | 6d2268a57603e1c60329b93fb853ac2c134cb932 (diff) | |
| parent | 4c470d641c6906a742b63273b305695ba575b3e1 (diff) | |
Merge "Add voice interaction support to ResolverActivity/ChooserActivity" into mnc-dev
4 files changed, 119 insertions, 6 deletions
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 678e92b35db8..1b55557e8dd7 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -100,6 +100,10 @@ public class ChooserActivity extends ResolverActivity { mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets); unbindService(sri.connection); mServiceConnections.remove(sri.connection); + if (mServiceConnections.isEmpty()) { + mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); + sendVoiceChoicesIfNeeded(); + } break; case CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT: @@ -107,6 +111,7 @@ public class ChooserActivity extends ResolverActivity { Log.d(TAG, "CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT; unbinding services"); } unbindRemainingServices(); + sendVoiceChoicesIfNeeded(); break; default: @@ -384,6 +389,8 @@ public class ChooserActivity extends ResolverActivity { + WATCHDOG_TIMEOUT_MILLIS + "ms"); mChooserHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT, WATCHDOG_TIMEOUT_MILLIS); + } else { + sendVoiceChoicesIfNeeded(); } } @@ -418,6 +425,10 @@ public class ChooserActivity extends ResolverActivity { mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); } + void onSetupVoiceInteraction() { + // Do nothing. We'll send the voice stuff ourselves. + } + void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) { if (mRefinementResultReceiver != null) { mRefinementResultReceiver.destroy(); @@ -956,6 +967,10 @@ public class ChooserActivity extends ResolverActivity { if (DEBUG) Log.d(TAG, "onServiceDisconnected: " + name); unbindService(this); mServiceConnections.remove(this); + if (mServiceConnections.isEmpty()) { + mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); + sendVoiceChoicesIfNeeded(); + } } @Override diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index e14f0584a0b8..fe3ab9e49743 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -16,10 +16,17 @@ package com.android.internal.app; +import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityThread; +import android.app.VoiceInteractor; +import android.app.VoiceInteractor.PickOptionRequest; +import android.app.VoiceInteractor.PickOptionRequest.Option; +import android.app.VoiceInteractor.Prompt; +import android.app.VoiceInteractor.Request; import android.os.AsyncTask; import android.provider.Settings; +import android.service.chooser.ChooserTarget; import android.text.TextUtils; import android.util.Slog; import android.widget.AbsListView; @@ -96,6 +103,7 @@ public class ResolverActivity extends Activity { private int mProfileSwitchMessageId = -1; private final ArrayList<Intent> mIntents = new ArrayList<>(); private ResolverComparator mResolverComparator; + private PickTargetOptionRequest mPickOptionRequest; private boolean mRegistered; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @@ -242,6 +250,9 @@ public class ResolverActivity extends Activity { finish(); } }); + if (isVoiceInteraction()) { + rdl.setCollapsed(false); + } } if (title == null) { @@ -313,6 +324,39 @@ public class ResolverActivity extends Activity { }); bindProfileView(); } + + if (isVoiceInteraction()) { + onSetupVoiceInteraction(); + } + } + + /** + * Perform any initialization needed for voice interaction. + */ + void onSetupVoiceInteraction() { + // Do it right now. Subclasses may delay this and send it later. + sendVoiceChoicesIfNeeded(); + } + + void sendVoiceChoicesIfNeeded() { + if (!isVoiceInteraction()) { + // Clearly not needed. + return; + } + + + final Option[] options = new Option[mAdapter.getCount()]; + for (int i = 0, N = options.length; i < N; i++) { + options[i] = optionForChooserTarget(mAdapter.getItem(i), i); + } + + mPickOptionRequest = new PickTargetOptionRequest( + new Prompt(getTitle()), options, null); + getVoiceInteractor().submitRequest(mPickOptionRequest); + } + + Option optionForChooserTarget(TargetInfo target, int index) { + return new Option(target.getDisplayLabel(), index); } protected final void setAdditionalTargets(Intent[] intents) { @@ -473,6 +517,14 @@ public class ResolverActivity extends Activity { } @Override + protected void onDestroy() { + super.onDestroy(); + if (!isChangingConfigurations() && mPickOptionRequest != null) { + mPickOptionRequest.cancel(); + } + } + + @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); if (mAlwaysUseOption) { @@ -510,16 +562,12 @@ public class ResolverActivity extends Activity { try { ApplicationInfo appInfo = getPackageManager().getApplicationInfo( resolveInfo.activityInfo.packageName, 0 /* default flags */); - return versionNumberAtLeastL(appInfo.targetSdkVersion); + return appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP; } catch (NameNotFoundException e) { return false; } } - private boolean versionNumberAtLeastL(int versionNumber) { - return versionNumber >= Build.VERSION_CODES.LOLLIPOP; - } - private void setAlwaysButtonEnabled(boolean hasValidSelection, int checkedPos, boolean filtered) { boolean enabled = false; @@ -1644,4 +1692,39 @@ public class ResolverActivity extends Activity { && match <= IntentFilter.MATCH_CATEGORY_PATH; } + static class PickTargetOptionRequest extends PickOptionRequest { + public PickTargetOptionRequest(@Nullable Prompt prompt, Option[] options, + @Nullable Bundle extras) { + super(prompt, options, extras); + } + + @Override + public void onCancel() { + super.onCancel(); + final ResolverActivity ra = (ResolverActivity) getActivity(); + if (ra != null) { + ra.mPickOptionRequest = null; + ra.finish(); + } + } + + @Override + public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) { + super.onPickOptionResult(finished, selections, result); + if (selections.length != 1) { + // TODO In a better world we would filter the UI presented here and let the + // user refine. Maybe later. + return; + } + + final ResolverActivity ra = (ResolverActivity) getActivity(); + if (ra != null) { + final TargetInfo ti = ra.mAdapter.getItem(selections[0].getIndex()); + if (ra.onTargetSelected(ti, false)) { + ra.mPickOptionRequest = null; + ra.finish(); + } + } + } + } } diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index 585cbc943788..1071e12cb6e3 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -144,6 +144,14 @@ public class ResolverDrawerLayout extends ViewGroup { return mCollapseOffset > 0; } + public void setCollapsed(boolean collapsed) { + if (!isLaidOut()) { + mOpenOnLayout = collapsed; + } else { + smoothScrollTo(collapsed ? mCollapsibleHeight : 0, 0); + } + } + private boolean isMoving() { return mIsDragging || !mScroller.isFinished(); } @@ -575,7 +583,13 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) { - smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY); + if (mOnDismissedListener != null + && velocityY < 0 && mCollapseOffset > mCollapsibleHeight) { + smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY); + mDismissOnScrollerFinished = true; + } else { + smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY); + } return true; } return false; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index b1b772ae7e7e..f9b41a9324d4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2457,6 +2457,7 @@ <intent-filter> <action android:name="android.intent.action.CHOOSER" /> <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.VOICE" /> </intent-filter> </activity> <activity android:name="com.android.internal.app.IntentForwarderActivity" |