diff options
| author | 2018-11-26 15:27:34 -0800 | |
|---|---|---|
| committer | 2018-11-27 08:37:56 -0800 | |
| commit | 599f76b43dbd70d6b1c59ad5a39f81dbb7b9e50d (patch) | |
| tree | abeb530e32944c86979beac8cf8c39a6b4e887e6 | |
| parent | 490db5dda0f147fd1dd689fde136d2214d7f3315 (diff) | |
Making on-screen mic to use VoiceInteraction
Test: Manual
Bug: 114705441
Change-Id: Ib2f77e1df166aa2073c5cbf11d2465d861f2136c
(cherry picked from commit 92e98e3d7aa32ae40fcc09efbb525bce5972a8a0)
| -rw-r--r-- | packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java | 72 | ||||
| -rw-r--r-- | packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java | 204 |
2 files changed, 276 insertions, 0 deletions
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java new file mode 100644 index 000000000000..5bf30ca10694 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.car; + +import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.Log; + +import com.android.internal.app.AssistUtils; +import com.android.internal.app.IVoiceInteractionSessionShowCallback; + +/** + * AssitantButton is a ui component that will trigger the Voice Interaction Service. + */ +public class AssitantButton extends CarFacetButton { + + private static final String TAG = "CarFacetButton"; + private IVoiceInteractionSessionShowCallback mShowCallback = + new IVoiceInteractionSessionShowCallback.Stub() { + @Override + public void onFailed() { + Log.w(TAG, "Failed to show VoiceInteractionSession"); + } + + @Override + public void onShown() { + Log.d(TAG, "IVoiceInteractionSessionShowCallback onShown()"); + } + }; + + private static final String EXTRA_CAR_PUSH_TO_TALK = + "com.android.car.input.EXTRA_CAR_PUSH_TO_TALK"; + private final AssistUtils mAssistUtils; + + public AssitantButton(Context context, AttributeSet attrs) { + super(context, attrs); + mAssistUtils = new AssistUtils(context); + setOnClickListener(v -> { + showAssistant(); + }); + } + + private void showAssistant() { + final Bundle args = new Bundle(); + args.putBoolean(EXTRA_CAR_PUSH_TO_TALK, true); + mAssistUtils.showSessionForActiveService(args, + SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, /*activityToken=*/ null); + } + + @Override + protected void setupIntents(TypedArray typedArray){ + // left blank because for the assistant button Intent will not be passed from the layout. + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java new file mode 100644 index 000000000000..cea4ab0e4992 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.car; + +import android.content.Context; +import android.content.Intent; +import android.content.res.TypedArray; +import android.os.UserHandle; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.android.keyguard.AlphaOptimizedImageButton; +import com.android.systemui.Dependency; +import com.android.systemui.R; + +/** + * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined + * category. It can also render a indicator impling that there are more options of apps to launch + * using this component. This is done with a "More icon" currently an arrow as defined in the layout + * file. The class is to serve as an example. + * Usage example: A button that allows a user to select a music app and indicate that there are + * other music apps installed. + */ +public class CarFacetButton extends LinearLayout { + private static final String FACET_FILTER_DELIMITER = ";"; + /** + * Extra information to be sent to a helper to make the decision of what app to launch when + * clicked. + */ + private static final String EXTRA_FACET_CATEGORIES = "categories"; + private static final String EXTRA_FACET_PACKAGES = "packages"; + private static final String EXTRA_FACET_ID = "filter_id"; + private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker"; + private static final String TAG = "CarFacetButton"; + + private Context mContext; + private AlphaOptimizedImageButton mIcon; + private AlphaOptimizedImageButton mMoreIcon; + private boolean mSelected = false; + private String[] mComponentNames; + /** App categories that are to be used with this widget */ + private String[] mFacetCategories; + /** App packages that are allowed to be used with this widget */ + private String[] mFacetPackages; + private int mIconResourceId; + /** + * If defined in the xml this will be the icon that's rendered when the button is marked as + * selected + */ + private int mSelectedIconResourceId; + private boolean mUseMoreIcon = true; + private float mSelectedAlpha = 1f; + private float mUnselectedAlpha = 1f; + + public CarFacetButton(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + View.inflate(context, R.layout.car_facet_button, this); + // extract custom attributes + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton); + setupIntents(typedArray); + setupIcons(typedArray); + CarFacetButtonController carFacetButtonController = Dependency.get( + CarFacetButtonController.class); + carFacetButtonController.addFacetButton(this); + } + + /** + * Reads the custom attributes to setup click handlers for this component. + */ + protected void setupIntents(TypedArray typedArray) { + String intentString = typedArray.getString(R.styleable.CarFacetButton_intent); + String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent); + String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories); + String packageString = typedArray.getString(R.styleable.CarFacetButton_packages); + String componentNameString = + typedArray.getString(R.styleable.CarFacetButton_componentNames); + try { + final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME); + intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId())); + + if (packageString != null) { + mFacetPackages = packageString.split(FACET_FILTER_DELIMITER); + intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages); + } + if (categoryString != null) { + mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER); + intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories); + } + if (componentNameString != null) { + mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER); + } + + setOnClickListener(v -> { + intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); + }); + + if (longPressIntentString != null) { + final Intent longPressIntent = Intent.parseUri(longPressIntentString, + Intent.URI_INTENT_SCHEME); + setOnLongClickListener(v -> { + mContext.startActivityAsUser(longPressIntent, UserHandle.CURRENT); + return true; + }); + } + } catch (Exception e) { + throw new RuntimeException("Failed to attach intent", e); + } + } + + private void setupIcons(TypedArray styledAttributes) { + mSelectedAlpha = styledAttributes.getFloat( + R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha); + mUnselectedAlpha = styledAttributes.getFloat( + R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha); + mIcon = findViewById(R.id.car_nav_button_icon); + mIcon.setScaleType(ImageView.ScaleType.CENTER); + mIcon.setClickable(false); + mIcon.setAlpha(mUnselectedAlpha); + mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0); + mIcon.setImageResource(mIconResourceId); + mSelectedIconResourceId = styledAttributes.getResourceId( + R.styleable.CarFacetButton_selectedIcon, mIconResourceId); + + mMoreIcon = findViewById(R.id.car_nav_button_more_icon); + mMoreIcon.setClickable(false); + mMoreIcon.setAlpha(mSelectedAlpha); + mMoreIcon.setVisibility(GONE); + mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true); + } + + /** + * @return The app categories the component represents + */ + public String[] getCategories() { + if (mFacetCategories == null) { + return new String[0]; + } + return mFacetCategories; + } + + /** + * @return The valid packages that should be considered. + */ + public String[] getFacetPackages() { + if (mFacetPackages == null) { + return new String[0]; + } + return mFacetPackages; + } + + /** + * @return The list of component names. + */ + public String[] getComponentName() { + if (mComponentNames == null) { + return new String[0]; + } + return mComponentNames; + } + + /** + * Updates the alpha of the icons to "selected" and shows the "More icon" + * + * @param selected true if the view must be selected, false otherwise + */ + public void setSelected(boolean selected) { + super.setSelected(selected); + setSelected(selected, selected); + } + + /** + * Updates the visual state to let the user know if it's been selected. + * + * @param selected true if should update the alpha of the icon to selected, false otherwise + * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this + * is ignored if the attribute useMoreIcon is set to false + */ + public void setSelected(boolean selected, boolean showMoreIcon) { + mSelected = selected; + mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha); + mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId); + if (mUseMoreIcon) { + mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE); + } + } +} |