diff options
author | Xin Li <delphij@google.com> | 2018-08-06 16:51:15 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2018-08-06 16:51:15 -0700 |
commit | bc0a323aa825030c639b2f85c5f1171e385fa217 (patch) | |
tree | 425350d783f248ea11209938273ce0d214ffc07d | |
parent | d56ef7d13feb6a3c43f9b2235dd64ebabc3d5d5d (diff) | |
parent | dce3f073732f0e94ee623669fd53e42129809889 (diff) | |
download | Messenger-master-cuttlefish-testing-release.tar.gz |
Merge Android Pie into masterandroid-o-mr1-iot-release-smart-display-r3android-o-mr1-iot-release-1.0.5android-o-mr1-iot-release-1.0.4android-o-mr1-iot-release-1.0.3oreo-mr1-1.2-iot-releasemaster-cuttlefish-testing-release
Bug: 112104996
Change-Id: If7bba1133ed2fef69205ab44f390a079e8136b05
-rw-r--r-- | Android.mk | 19 | ||||
-rw-r--r-- | res/drawable/circle_bg.xml | 4 | ||||
-rw-r--r-- | res/drawable/rounded_corner_btn_bg.xml | 2 | ||||
-rw-r--r-- | res/layout/play_message_layout.xml | 111 | ||||
-rw-r--r-- | res/values/dimens.xml | 1 | ||||
-rw-r--r-- | res/values/styles.xml | 9 | ||||
-rw-r--r-- | src/com/android/car/messenger/MapMessage.java | 3 | ||||
-rw-r--r-- | src/com/android/car/messenger/MapMessageMonitor.java | 56 | ||||
-rw-r--r-- | src/com/android/car/messenger/PlayMessageActivity.java | 25 | ||||
-rw-r--r-- | src/com/android/car/messenger/tts/AndroidTTSEngine.java | 9 | ||||
-rw-r--r-- | src/com/android/car/messenger/tts/FakeTTSEngine.java | 5 | ||||
-rw-r--r-- | src/com/android/car/messenger/tts/TTSEngine.java | 5 | ||||
-rw-r--r-- | src/com/android/car/messenger/tts/TTSHelper.java | 41 | ||||
-rw-r--r-- | tests/robotests/Android.mk | 10 | ||||
-rw-r--r-- | tests/robotests/src/com/android/car/messenger/tts/TTSHelperTest.java | 6 |
15 files changed, 184 insertions, 122 deletions
@@ -38,15 +38,17 @@ LOCAL_PRIVILEGED_MODULE := true LOCAL_USE_AAPT2 := true -LOCAL_STATIC_ANDROID_LIBRARIES += android-support-v4 -LOCAL_STATIC_JAVA_LIBRARIES += car-messenger-glide-target -LOCAL_STATIC_JAVA_LIBRARIES += car-massenger-gifdecoder-target -LOCAL_STATIC_JAVA_LIBRARIES += car-messenger-disklrucache-target +LOCAL_STATIC_ANDROID_LIBRARIES += \ + androidx.car_car \ + car-apps-common -LOCAL_DEX_PREOPT := false +LOCAL_STATIC_JAVA_LIBRARIES += \ + androidx.annotation_annotation \ + car-messenger-glide-target \ + car-massenger-gifdecoder-target \ + car-messenger-disklrucache-target -include packages/apps/Car/libs/car-stream-ui-lib/car-stream-ui-lib.mk -include packages/apps/Car/libs/car-apps-common/car-apps-common.mk +LOCAL_DEX_PREOPT := false include $(BUILD_PACKAGE) @@ -56,6 +58,7 @@ LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE := car-messenger-disklrucache-target LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := ../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/disklrucache/SNAPSHOT/disklrucache-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_JETIFIER_ENABLED := true LOCAL_UNINSTALLABLE_MODULE := true include $(BUILD_PREBUILT) @@ -66,6 +69,7 @@ LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE := car-massenger-gifdecoder-target LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := ../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/gifdecoder/SNAPSHOT/gifdecoder-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_JETIFIER_ENABLED := true LOCAL_UNINSTALLABLE_MODULE := true include $(BUILD_PREBUILT) @@ -76,6 +80,7 @@ LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE := car-messenger-glide-target LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := ../../../../prebuilts/maven_repo/bumptech/com/github/bumptech/glide/glide/SNAPSHOT/glide-SNAPSHOT$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_JETIFIER_ENABLED := true LOCAL_UNINSTALLABLE_MODULE := true include $(BUILD_PREBUILT) diff --git a/res/drawable/circle_bg.xml b/res/drawable/circle_bg.xml index 1770aab..9bdfa0f 100644 --- a/res/drawable/circle_bg.xml +++ b/res/drawable/circle_bg.xml @@ -19,6 +19,6 @@ android:shape="oval"> <solid android:color="@color/car_blue_grey_900" /> <size - android:height="@dimen/car_touch_target" - android:width="@dimen/car_touch_target" /> + android:height="@dimen/car_touch_target_size" + android:width="@dimen/car_touch_target_size" /> </shape>
\ No newline at end of file diff --git a/res/drawable/rounded_corner_btn_bg.xml b/res/drawable/rounded_corner_btn_bg.xml index dba56a6..27762ee 100644 --- a/res/drawable/rounded_corner_btn_bg.xml +++ b/res/drawable/rounded_corner_btn_bg.xml @@ -20,6 +20,6 @@ <solid android:color="@color/car_blue_grey_900" /> <corners android:radius="55dp"/> <size - android:height="@dimen/car_touch_target" + android:height="@dimen/car_touch_target_size" android:width="@dimen/big_btn_bg_width" /> </shape>
\ No newline at end of file diff --git a/res/layout/play_message_layout.xml b/res/layout/play_message_layout.xml index 058414d..452adb1 100644 --- a/res/layout/play_message_layout.xml +++ b/res/layout/play_message_layout.xml @@ -24,67 +24,82 @@ android:background="@drawable/round_corner" android:animateLayoutChanges="true" android:alpha="0" - android:layout_marginStart="@dimen/side_margin" - android:layout_marginEnd="@dimen/side_margin" + android:layout_marginStart="@dimen/car_margin" + android:layout_marginEnd="@dimen/car_margin" android:layout_width="match_parent" android:layout_height="wrap_content"> - <GridLayout + <LinearLayout android:id="@+id/message_container" android:visibility="gone" + android:layout_marginStart="@dimen/car_keyline_3" + android:layout_marginEnd="@dimen/car_keyline_3" + android:orientation="vertical" android:layout_weight="1" - android:layout_marginStart="@dimen/stream_card_keyline_3" - android:layout_marginEnd="@dimen/stream_card_keyline_3" android:layout_height="0dp" - android:layout_width="match_parent" - android:useDefaultMargins="true" - android:alignmentMode="alignBounds" - android:columnOrderPreserved="false" - android:columnCount="4" - > - <TextView - android:id="@+id/emoji1" - style="@style/MessageEmoji"> - </TextView> - <TextView - android:id="@+id/emoji2" - style="@style/MessageEmoji"> - </TextView> - <TextView - android:id="@+id/emoji3" - style="@style/MessageEmoji"> - </TextView> - <TextView - android:id="@+id/emoji4" - style="@style/MessageEmoji"> - </TextView> - <TextView - android:id="@+id/emoji5" - style="@style/MessageEmoji"> - </TextView> + android:layout_width="match_parent" > + <!-- expandable spacing --> + <View + android:layout_height="0dp" + android:layout_width="match_parent" + android:layout_weight="1"/> + <LinearLayout + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:orientation="horizontal"> + <TextView + android:id="@+id/emoji1" + style="@style/MessageEmoji"> + </TextView> + <!-- expandable spacing --> + <View + android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_weight="1"/> + <TextView + android:id="@+id/emoji2" + style="@style/MessageEmoji"> + </TextView> + <!-- expandable spacing --> + <View + android:layout_height="match_parent" + android:layout_width="0dp" + android:layout_weight="1"/> + <TextView + android:id="@+id/emoji3" + style="@style/MessageEmoji"> + </TextView> + </LinearLayout> + <!-- expandable spacing --> + <View + android:layout_height="0dp" + android:layout_width="match_parent" + android:layout_weight="1"/> <TextView android:id="@+id/canned_message" - style="@style/CarBody1.Light" - android:layout_column="1" - android:layout_rowSpan="1" - android:layout_columnSpan="3" + style="@style/TextAppearance.Car.Body1.Light" android:gravity="center" android:textStyle="italic" android:layout_gravity="center" android:background="@drawable/rounded_corner_btn_bg" android:text="@string/caned_message_driving_right_now" - android:layout_width="614dp" - android:layout_height="@dimen/car_touch_target"> + android:layout_width="match_parent" + android:layout_height="@dimen/car_touch_target_size"> </TextView> - </GridLayout> + <!-- expandable spacing --> + <View + android:layout_height="0dp" + android:layout_width="match_parent" + android:layout_weight="1"/> + </LinearLayout> <TextView android:id="@+id/reply_notice" - style="@style/CarBody1" + style="@style/TextAppearance.Car.Body1" android:layout_gravity="center" android:gravity="center" android:visibility="gone" android:layout_width="match_parent" - android:layout_height="@dimen/single_line_item_height"> + android:layout_height="@dimen/car_single_line_list_item_height"> </TextView> <LinearLayout @@ -92,16 +107,16 @@ android:background="@color/car_card" android:orientation="horizontal" android:layout_width="match_parent" - android:layout_height="@dimen/single_line_item_height"> + android:layout_height="@dimen/car_single_line_list_item_height"> <TextView android:id="@+id/left_btn" - style="@style/CarBody1" + style="@style/TextAppearance.Car.Body1" android:layout_weight="1" android:gravity="center" android:layout_gravity="center_vertical" android:textAllCaps="true" android:maxLines="1" - android:layout_marginStart="@dimen/stream_content_keyline_1" + android:layout_marginStart="@dimen/car_keyline_1" android:layout_marginEnd="@dimen/voice_plate_button_margin" android:layout_width="0dp" android:layout_height="wrap_content"> @@ -109,8 +124,8 @@ <ImageView android:id="@+id/voice_icon" - android:layout_width="@dimen/stream_button_icon_size" - android:layout_height="@dimen/stream_button_icon_size" + android:layout_width="@dimen/car_primary_icon_size" + android:layout_height="@dimen/car_primary_icon_size" android:layout_gravity="center" android:src="@drawable/ic_voice_out" android:scaleType="fitCenter"> @@ -118,16 +133,16 @@ <TextView android:id="@+id/right_btn" - style="@style/CarBody1" + style="@style/TextAppearance.Car.Body1" android:layout_weight="1" android:gravity="center" android:layout_gravity="center_vertical" android:textAllCaps="true" android:maxLines="1" android:layout_marginStart="@dimen/voice_plate_button_margin" - android:layout_marginEnd="@dimen/stream_content_keyline_1" + android:layout_marginEnd="@dimen/car_keyline_1" android:layout_width="0dp" android:layout_height="wrap_content"> </TextView> </LinearLayout> -</LinearLayout>
\ No newline at end of file +</LinearLayout> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index b0eafa5..1fb98d7 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -15,6 +15,7 @@ ~ limitations under the License --> <resources> + <dimen name="car_card_view_elevation">8dp</dimen> <dimen name="notification_contact_photo_size">300dp</dimen> <dimen name="voice_plate_button_margin">32dp</dimen> <dimen name="big_btn_bg_width">614dp</dimen> diff --git a/res/values/styles.xml b/res/values/styles.xml index c9ae141..05912be 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -26,13 +26,12 @@ <item name="android:windowNoTitle">true</item> </style> - <style name="MessageEmoji" parent="@style/CarBody1"> + <style name="MessageEmoji" parent="@style/TextAppearance.Car.Body1"> <item name="android:background">@drawable/circle_bg</item> <item name="android:textSize">@dimen/car_emoji_size</item> <item name="android:gravity">center</item> <item name="android:layout_gravity">center</item> - <item name="android:layout_columnWeight">1</item> - <item name="android:layout_rowWeight">1</item> - <item name="android:layout_height">@dimen/car_touch_target</item> + <item name="android:layout_height">@dimen/car_touch_target_size</item> + <item name="android:layout_width">@dimen/car_touch_target_size</item> </style> -</resources>
\ No newline at end of file +</resources> diff --git a/src/com/android/car/messenger/MapMessage.java b/src/com/android/car/messenger/MapMessage.java index 2bca390..998e933 100644 --- a/src/com/android/car/messenger/MapMessage.java +++ b/src/com/android/car/messenger/MapMessage.java @@ -19,7 +19,8 @@ package com.android.car.messenger; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothMapClient; import android.content.Intent; -import android.support.annotation.Nullable; + +import androidx.annotation.Nullable; /** * Represents a message obtained via MAP service from a connected Bluetooth device. diff --git a/src/com/android/car/messenger/MapMessageMonitor.java b/src/com/android/car/messenger/MapMessageMonitor.java index b07d263..3c427dd 100644 --- a/src/com/android/car/messenger/MapMessageMonitor.java +++ b/src/com/android/car/messenger/MapMessageMonitor.java @@ -35,20 +35,19 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; -import android.media.AudioManager; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.provider.ContactsContract; import android.provider.Settings; -import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.android.car.apps.common.LetterTileDrawable; import com.android.car.messenger.tts.TTSHelper; - import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.SimpleTarget; @@ -93,8 +92,6 @@ class MapMessageMonitor { private final Map<SenderKey, NotificationInfo> mNotificationInfos = new HashMap<>(); private final TTSHelper mTTSHelper; private final HashMap<String, Boolean> mReplyFeatureMap = new HashMap<>(); - private final AudioManager mAudioManager; - private final AudioManager.OnAudioFocusChangeListener mNoOpAFChangeListener = (f) -> {}; MapMessageMonitor(Context context) { mContext = context; @@ -103,8 +100,6 @@ class MapMessageMonitor { mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); mTTSHelper = new TTSHelper(mContext); - - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); } public boolean isPlaying() { @@ -347,34 +342,29 @@ class MapMessageMonitor { ttsMessages.add(mContext.getString(R.string.tts_sender_says, notificationInfo.mSenderName)); ttsMessages.add(ttsMessage); - int result = mAudioManager.requestAudioFocus(mNoOpAFChangeListener, - // Use the music stream. - AudioManager.STREAM_MUSIC, - // Request permanent focus. - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); - if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { - mTTSHelper.requestPlay(ttsMessages, - new TTSHelper.Listener() { - @Override - public void onTTSStarted() { - Intent intent = new Intent(ACTION_MESSAGE_PLAY_START); - mContext.sendBroadcast(intent); - } + mTTSHelper.requestPlay(ttsMessages, + new TTSHelper.Listener() { + @Override + public void onTTSStarted() { + Intent intent = new Intent(ACTION_MESSAGE_PLAY_START); + mContext.sendBroadcast(intent); + } - @Override - public void onTTSStopped(boolean error) { - mAudioManager.abandonAudioFocus(mNoOpAFChangeListener); - Intent intent = new Intent(ACTION_MESSAGE_PLAY_STOP); - mContext.sendBroadcast(intent); - if (error) { - Toast.makeText(mContext, R.string.tts_failed_toast, - Toast.LENGTH_SHORT).show(); - } + @Override + public void onTTSStopped(boolean error) { + Intent intent = new Intent(ACTION_MESSAGE_PLAY_STOP); + mContext.sendBroadcast(intent); + if (error) { + Toast.makeText(mContext, R.string.tts_failed_toast, + Toast.LENGTH_SHORT).show(); } - }); - } else { - Log.w(TAG, "failed to require audio focus."); - } + } + + @Override + public void onAudioFocusFailed() { + Log.w(TAG, "failed to require audio focus."); + } + }); } void stopPlayout() { diff --git a/src/com/android/car/messenger/PlayMessageActivity.java b/src/com/android/car/messenger/PlayMessageActivity.java index 0381c15..7bfc5f9 100644 --- a/src/com/android/car/messenger/PlayMessageActivity.java +++ b/src/com/android/car/messenger/PlayMessageActivity.java @@ -91,15 +91,11 @@ public class PlayMessageActivity extends Activity { private void setupEmojis() { TextView emoji1 = (TextView) findViewById(R.id.emoji1); - emoji1.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_ok_hand_sign))); + emoji1.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_up))); TextView emoji2 = (TextView) findViewById(R.id.emoji2); - emoji2.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_up))); + emoji2.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_down))); TextView emoji3 = (TextView) findViewById(R.id.emoji3); - emoji3.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_thumb_down))); - TextView emoji4 = (TextView) findViewById(R.id.emoji4); - emoji4.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_heart))); - TextView emoji5 = (TextView) findViewById(R.id.emoji5); - emoji5.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_smiling_face))); + emoji3.setText(getEmojiByUnicode(getResources().getInteger(R.integer.emoji_smiling_face))); } private String getEmojiByUnicode(int unicode){ @@ -115,8 +111,6 @@ public class PlayMessageActivity extends Activity { findViewById(R.id.emoji1).setOnClickListener(this::sendReply); findViewById(R.id.emoji2).setOnClickListener(this::sendReply); findViewById(R.id.emoji3).setOnClickListener(this::sendReply); - findViewById(R.id.emoji4).setOnClickListener(this::sendReply); - findViewById(R.id.emoji5).setOnClickListener(this::sendReply); } /** @@ -165,6 +159,11 @@ public class PlayMessageActivity extends Activity { } finish(); } + + @Override + public void onAudioFocusFailed() { + Log.w(TAG, "failed to require audio focus."); + } }); } @@ -199,7 +198,6 @@ public class PlayMessageActivity extends Activity { || event.getY() < mContainer.getY() || event.getY() > mContainer.getY() + mContainer.getHeight()) { finish(); - } } return super.onTouchEvent(event); @@ -245,6 +243,7 @@ public class PlayMessageActivity extends Activity { @Override protected void onStop() { super.onStop(); + stopMessage(); mTTSHelper.cleanup(); mMessengerServiceBroadcastReceiver.cleanup(); unbindService(mConnection); @@ -270,7 +269,7 @@ public class PlayMessageActivity extends Activity { mVoiceIcon.setVisibility(View.VISIBLE); } - private void updateViewFoeMessageStopped() { + private void updateViewForMessageStopped() { mRightButton.setText(getString(R.string.action_repeat)); mRightButton.setOnClickListener(v -> playMessage()); mVoiceIcon.setVisibility(View.INVISIBLE); @@ -299,7 +298,7 @@ public class PlayMessageActivity extends Activity { updateViewForMessagePlaying(); break; case MapMessageMonitor.ACTION_MESSAGE_PLAY_STOP: - updateViewFoeMessageStopped(); + updateViewForMessageStopped(); break; default: break; @@ -315,7 +314,7 @@ public class PlayMessageActivity extends Activity { if (mMessengerService.isPlaying()) { updateViewForMessagePlaying(); } else { - updateViewFoeMessageStopped(); + updateViewForMessageStopped(); } } diff --git a/src/com/android/car/messenger/tts/AndroidTTSEngine.java b/src/com/android/car/messenger/tts/AndroidTTSEngine.java index 1428f4a..70d0aff 100644 --- a/src/com/android/car/messenger/tts/AndroidTTSEngine.java +++ b/src/com/android/car/messenger/tts/AndroidTTSEngine.java @@ -39,7 +39,9 @@ class AndroidTTSEngine implements TTSEngine { @Override public void stop() { - mTextToSpeech.stop(); + if (mTextToSpeech != null) { + mTextToSpeech.stop(); + } } @Override @@ -52,4 +54,9 @@ class AndroidTTSEngine implements TTSEngine { mTextToSpeech.shutdown(); mTextToSpeech = null; } + + @Override + public int getStream() { + return TextToSpeech.Engine.DEFAULT_STREAM; + } } diff --git a/src/com/android/car/messenger/tts/FakeTTSEngine.java b/src/com/android/car/messenger/tts/FakeTTSEngine.java index 0870379..6af64e4 100644 --- a/src/com/android/car/messenger/tts/FakeTTSEngine.java +++ b/src/com/android/car/messenger/tts/FakeTTSEngine.java @@ -53,6 +53,11 @@ class FakeTTSEngine implements TTSEngine { mOnInitListener = null; } + @Override + public int getStream() { + return TextToSpeech.Engine.DEFAULT_STREAM; + } + void startRequest(String utteranceId) { mProgressListener.onStart(utteranceId); } diff --git a/src/com/android/car/messenger/tts/TTSEngine.java b/src/com/android/car/messenger/tts/TTSEngine.java index ed1313f..e789327 100644 --- a/src/com/android/car/messenger/tts/TTSEngine.java +++ b/src/com/android/car/messenger/tts/TTSEngine.java @@ -48,4 +48,9 @@ public interface TTSEngine { * using this engine. */ void shutdown(); + + /** + * Returns the stream used by this TTS engine. + */ + int getStream(); } diff --git a/src/com/android/car/messenger/tts/TTSHelper.java b/src/com/android/car/messenger/tts/TTSHelper.java index 08dfcd6..aef20d7 100644 --- a/src/com/android/car/messenger/tts/TTSHelper.java +++ b/src/com/android/car/messenger/tts/TTSHelper.java @@ -17,13 +17,15 @@ package com.android.car.messenger.tts; import android.content.Context; +import android.media.AudioManager; import android.os.Handler; import android.speech.tts.TextToSpeech; import android.speech.tts.UtteranceProgressListener; -import android.support.annotation.VisibleForTesting; import android.util.Log; import android.util.Pair; +import androidx.annotation.VisibleForTesting; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -56,6 +58,12 @@ public class TTSHelper { * not considered an error. */ void onTTSStopped(boolean error); + + /** + * Called when request to get audio focus failed. This happens before the requested TTS + * is played. + */ + void onAudioFocusFailed(); } private static final String TAG = "Messenger.TTSHelper"; @@ -66,6 +74,8 @@ public class TTSHelper { private final Handler mHandler = new Handler(); private final Context mContext; + private final AudioManager mAudioManager; + private final AudioManager.OnAudioFocusChangeListener mNoOpAFChangeListener = (f) -> {}; private final long mShutdownDelayMillis; private TTSEngine mTTSEngine; private int mInitStatus; @@ -83,6 +93,7 @@ public class TTSHelper { @VisibleForTesting TTSHelper(Context context, TTSEngine ttsEngine, long shutdownDelayMillis) { mContext = context; + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mTTSEngine = ttsEngine; mShutdownDelayMillis = shutdownDelayMillis; // OnInitListener will only set to SUCCESS/ERROR. So we initialize to STOPPED. @@ -129,6 +140,7 @@ public class TTSHelper { * until then. Only one batch is supported at a time; If a previous batch is waiting engine * setup, that batch is dropped. If a previous batch is playing, the play-out is stopped and * next one is passed to the TTS Engine. Callbacks are issued on the provided {@code listener}. + * Will request audio focus first, failure will trigger onAudioFocusFailed in listener. * * NOTE: Underlying engine may have limit on length of text in each element of the batch; it * will reject anything longer. See {@link TextToSpeech#getMaxSpeechInputLength()}. @@ -137,16 +149,23 @@ public class TTSHelper { * @param listener Observer that will receive callbacks about play-out progress. */ public void requestPlay(List<CharSequence> textToSpeak, Listener listener) { - if (textToSpeak == null || textToSpeak.size() < 1) { + if (textToSpeak == null || textToSpeak.isEmpty()) { throw new IllegalArgumentException("Empty/null textToSpeak"); } + int result = mAudioManager.requestAudioFocus(mNoOpAFChangeListener, + getStream(), + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); + if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { + listener.onAudioFocusFailed(); + return; + } initMaybeAndKeepAlive(); // Check if its still initializing. if (mInitStatus == TextToSpeech.STOPPED) { // Squash any already queued request. if (mPendingRequest != null) { - mPendingRequest.mListener.onTTSStopped(false /* error */); + onTtsStopped(mPendingRequest.mListener, false /* error */); } mPendingRequest = new SpeechRequest(textToSpeak, listener); } else { @@ -163,10 +182,16 @@ public class TTSHelper { return mTTSEngine.isSpeaking(); } + // wrap call back to listener.onTTSStopped with adandonAudioFocus. + private void onTtsStopped(Listener listener, boolean error) { + mAudioManager.abandonAudioFocus(mNoOpAFChangeListener); + mHandler.post(() -> listener.onTTSStopped(error)); + } + private void playInternal(List<CharSequence> textToSpeak, Listener listener) { if (mInitStatus == TextToSpeech.ERROR) { Log.e(TAG, "TTS setup failed!"); - mHandler.post(() -> listener.onTTSStopped(true /* error */)); + onTtsStopped(listener, true /* error */); return; } @@ -188,7 +213,7 @@ public class TTSHelper { mTTSEngine.stop(); currentBatchId = null; Log.e(TAG, "Queuing text failed!"); - mHandler.post(() -> listener.onTTSStopped(true /* error */)); + onTtsStopped(listener, true /* error */); return; } index--; @@ -206,6 +231,10 @@ public class TTSHelper { shutdownEngine(); } + public int getStream() { + return mTTSEngine.getStream(); + } + private void shutdownEngine() { if (mTTSEngine.isInitialized()) { if (DBG) { @@ -324,7 +353,7 @@ public class TTSHelper { // Handles terminal callbacks for the batch. We invoke stopped and remove ourselves. // No further callbacks will be handled for the batch. private void handleBatchFinished(Pair<String, Integer> parsedId, boolean error) { - mListener.onTTSStopped(error); + onTtsStopped(mListener, error); mListeners.remove(parsedId.first); } } diff --git a/tests/robotests/Android.mk b/tests/robotests/Android.mk index 357eb80..77c65f7 100644 --- a/tests/robotests/Android.mk +++ b/tests/robotests/Android.mk @@ -8,12 +8,12 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) # Include the testing libraries (JUnit4 + Robolectric libs). LOCAL_STATIC_JAVA_LIBRARIES := \ - platform-system-robolectric \ - truth-prebuilt + truth-prebuilt \ + mockito-robolectric-prebuilt LOCAL_JAVA_LIBRARIES := \ junit \ - platform-robolectric-prebuilt + platform-robolectric-3.6.1-prebuilt LOCAL_INSTRUMENTATION_FOR := CarMessengerApp LOCAL_MODULE := CarMessengerRoboTests @@ -36,4 +36,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ LOCAL_TEST_PACKAGE := CarMessengerApp -include prebuilts/misc/common/robolectric/run_robotests.mk +LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src + +include prebuilts/misc/common/robolectric/3.6.1/run_robotests.mk diff --git a/tests/robotests/src/com/android/car/messenger/tts/TTSHelperTest.java b/tests/robotests/src/com/android/car/messenger/tts/TTSHelperTest.java index f9745f4..dbbb5e4 100644 --- a/tests/robotests/src/com/android/car/messenger/tts/TTSHelperTest.java +++ b/tests/robotests/src/com/android/car/messenger/tts/TTSHelperTest.java @@ -156,5 +156,9 @@ public class TTSHelperTest { mStopped = true; mError = error; } + + @Override + public void onAudioFocusFailed() { + } } -}
\ No newline at end of file +} |