diff options
12 files changed, 167 insertions, 45 deletions
diff --git a/api/current.txt b/api/current.txt index 8045c8326378..eb991ada0937 100644 --- a/api/current.txt +++ b/api/current.txt @@ -27774,9 +27774,8 @@ package android.service.voice { } public static class AlwaysOnHotwordDetector.EventPayload { - field public final android.media.AudioFormat audioFormat; - field public final byte[] data; - field public final boolean triggerAvailable; + method public android.media.AudioFormat getCaptureAudioFormat(); + method public byte[] getTriggerAudio(); } public class VoiceInteractionService extends android.app.Service { diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java index 2e9648714b34..0dbde6bfa29d 100644 --- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java +++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java @@ -33,6 +33,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.Arrays; import java.util.List; /** @@ -263,4 +264,11 @@ public class KeyphraseEnrollmentInfo { Slog.w(TAG, "Enrollment application doesn't support the given keyphrase/locale"); return null; } + + @Override + public String toString() { + return "KeyphraseEnrollmentInfo [Keyphrases=" + Arrays.toString(mKeyphrases) + + ", EnrollmentPackage=" + mEnrollmentPackage + ", ParseError=" + mParseError + + "]"; + } } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 47cfa7d44369..8db99a5265c2 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -510,9 +510,10 @@ public class CallLog { for (int i = 0; i < count; i++) { final UserInfo user = users.get(i); final UserHandle userHandle = user.getUserHandle(); - if (userManager.isUserRunning(userHandle) && - !userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, - userHandle)) { + if (userManager.isUserRunning(userHandle) + && !userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, + userHandle) + && !user.isManagedProfile()) { Uri uri = addEntryAndRemoveExpiredEntries(context, ContentProvider.maybeAddUserId(CONTENT_URI, user.id), values); if (user.id == currentUserId) { diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index f1e1943424f1..15e66a0f8fd7 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -39,6 +39,8 @@ import android.util.Slog; import com.android.internal.app.IVoiceInteractionManagerService; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -185,48 +187,77 @@ public class AlwaysOnHotwordDetector { * Additional payload for {@link Callback#onDetected}. */ public static class EventPayload { + private final boolean mTriggerAvailable; + // Indicates if {@code captureSession} can be used to continue capturing more audio + // from the DSP hardware. + private final boolean mCaptureAvailable; + // The session to use when attempting to capture more audio from the DSP hardware. + private final int mCaptureSession; + private final AudioFormat mAudioFormat; + // Raw data associated with the event. + // This is the audio that triggered the keyphrase if {@code isTriggerAudio} is true. + private final byte[] mData; + + private EventPayload(boolean triggerAvailable, boolean captureAvailable, + AudioFormat audioFormat, int captureSession, byte[] data) { + mTriggerAvailable = triggerAvailable; + mCaptureAvailable = captureAvailable; + mCaptureSession = captureSession; + mAudioFormat = audioFormat; + mData = data; + } + /** - * Indicates if {@code data} is the audio that triggered the keyphrase. + * Gets the format of the audio obtained using {@link #getTriggerAudio()}. + * May be null if there's no audio present. */ - public final boolean triggerAvailable; + @Nullable + public AudioFormat getCaptureAudioFormat() { + return mAudioFormat; + } + /** - * Indicates if {@code captureSession} can be used to continue capturing more audio from - * the DSP hardware. + * Gets the raw audio that triggered the keyphrase. + * This may be null if the trigger audio isn't available. + * If non-null, the format of the audio can be obtained by calling + * {@link #getCaptureAudioFormat()}. * - * Candidate for public API - * @hide + * @see AlwaysOnHotwordDetector#RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO */ - public final boolean captureAvailable; + @Nullable + public byte[] getTriggerAudio() { + if (mTriggerAvailable) { + return mData; + } else { + return null; + } + } + /** - * The session to use when attempting to capture more audio from the DSP hardware. + * Gets the session ID to start a capture from the DSP. + * This may be null if streaming capture isn't possible. + * If non-null, the format of the audio that can be captured can be + * obtained using {@link #getCaptureAudioFormat()}. + * + * TODO: Candidate for Public API when the API to start capture with a session ID + * is made public. + * + * TODO: Add this to {@link #getCaptureAudioFormat()}: + * "Gets the format of the audio obtained using {@link #getTriggerAudio()} + * or {@link #getCaptureSession()}. May be null if no audio can be obtained + * for either the trigger or a streaming session." + * + * TODO: Should this return a known invalid value instead? * - * Candidate for public API - * TODO: When unhiding, change javadoc of audioFormat to - - * "Format of {@code data} or the audio that may be captured using {@code captureSession}. - * May be null if {@code triggerAvailable} and {@code captureAvailable} are false." * @hide */ - public final int captureSession; - /** - * Format of {@code data}. - * May be null if {@code triggerAvailable} is false. - */ @Nullable - public final AudioFormat audioFormat; - /** - * Raw data associated with the event. - * This is the audio that triggered the keyphrase if {@code isTriggerAudio} is true. - */ - @Nullable - public final byte[] data; - - private EventPayload(boolean _triggerAvailable, boolean _captureAvailable, - AudioFormat _audioFormat, int _captureSession, byte[] _data) { - triggerAvailable = _triggerAvailable; - captureAvailable = _captureAvailable; - captureSession = _captureSession; - audioFormat = _audioFormat; - data = _data; + public Integer getCaptureSession() { + if (mCaptureAvailable) { + return mCaptureSession; + } else { + return null; + } } } @@ -490,7 +521,7 @@ public class AlwaysOnHotwordDetector { new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers, recognitionExtra, null /* additional data */)); } catch (RemoteException e) { - Slog.w(TAG, "RemoteException in startRecognition!"); + Slog.w(TAG, "RemoteException in startRecognition!", e); } if (code != STATUS_OK) { Slog.w(TAG, "startRecognition() failed with error code " + code); @@ -504,7 +535,7 @@ public class AlwaysOnHotwordDetector { code = mModelManagementService.stopRecognition( mVoiceInteractionService, mKeyphraseMetadata.id, mInternalCallback); } catch (RemoteException e) { - Slog.w(TAG, "RemoteException in stopRecognition!"); + Slog.w(TAG, "RemoteException in stopRecognition!", e); } if (code != STATUS_OK) { @@ -636,7 +667,7 @@ public class AlwaysOnHotwordDetector { dspModuleProperties = mModelManagementService.getDspModuleProperties(mVoiceInteractionService); } catch (RemoteException e) { - Slog.w(TAG, "RemoteException in getDspProperties!"); + Slog.w(TAG, "RemoteException in getDspProperties!", e); } // No DSP available if (dspModuleProperties == null) { @@ -657,9 +688,20 @@ public class AlwaysOnHotwordDetector { return mModelManagementService.isEnrolledForKeyphrase( mVoiceInteractionService, keyphraseId); } catch (RemoteException e) { - Slog.w(TAG, "RemoteException in listRegisteredKeyphraseSoundModels!"); + Slog.w(TAG, "RemoteException in listRegisteredKeyphraseSoundModels!", e); } return false; } } + + /** @hide */ + public void dump(String prefix, PrintWriter pw) { + synchronized (mLock) { + pw.print(prefix); pw.print("Text="); pw.println(mText); + pw.print(prefix); pw.print("Locale="); pw.println(mLocale); + pw.print(prefix); pw.print("Availability="); pw.println(mAvailability); + pw.print(prefix); pw.print("KeyphraseMetadata="); pw.println(mKeyphraseMetadata); + pw.print(prefix); pw.print("EnrollmentInfo="); pw.println(mKeyphraseEnrollmentInfo); + } + } } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 51894049661b..770d66cd5f25 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -33,6 +33,9 @@ import android.provider.Settings; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractionManagerService; +import java.io.FileDescriptor; +import java.io.PrintWriter; + /** * Top-level service of the current global voice interactor, which is providing @@ -244,4 +247,17 @@ public class VoiceInteractionService extends Service { // Ignore. } } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("VOICE INTERACTION"); + synchronized (mLock) { + pw.println(" AlwaysOnHotwordDetector"); + if (mHotwordDetector == null) { + pw.println(" NULL"); + } else { + mHotwordDetector.dump(" ", pw); + } + } + } } diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index c3ea8f841072..cd73527220a6 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -83,7 +83,7 @@ <color name="notification_material_background_dimmed_color">#d4ffffff</color> <!-- The color of the material notification background when low priority --> - <color name="notification_material_background_low_priority_color">#ffdcdcdc</color> + <color name="notification_material_background_low_priority_color">#ffe0e0e0</color> <!-- The color of the ripples on the untinted notifications --> <color name="notification_ripple_untinted_color">#20000000</color> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java index 1cd18a08cd22..6ac0bef3202c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java @@ -660,6 +660,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } public void reset() { + super.reset(); setTintColor(0); setShowingLegacyBackground(false); setBelowSpeedBump(false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 0960c0017b9b..a27557235cf6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -59,6 +59,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { private boolean mClearable; private ExpansionLogger mLogger; private String mLoggingKey; + private boolean mWasReset; public interface ExpansionLogger { public void logNotificationExpansion(String key, boolean userAction, boolean expanded); @@ -88,6 +89,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mPublicLayout.reset(); mPrivateLayout.reset(); mMaxExpandHeight = 0; + mWasReset = true; logExpansionEvent(false, wasExpanded); } @@ -246,11 +248,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - boolean updateExpandHeight = mMaxExpandHeight == 0; + boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset; mMaxExpandHeight = mPrivateLayout.getMaxHeight(); if (updateExpandHeight) { applyExpansionToLayout(); } + mWasReset = false; } public void setSensitive(boolean sensitive) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 46d4a9a7a1cc..df64edfbeb48 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -255,6 +255,10 @@ public abstract class ExpandableView extends FrameLayout { public void setBelowSpeedBump(boolean below) { } + public void reset() { + mOnHeightChangedListener.onReset(this); + } + /** * A listener notifying when {@link #getActualHeight} changes. */ @@ -265,5 +269,12 @@ public abstract class ExpandableView extends FrameLayout { * padding or the padding between the elements changed */ void onHeightChanged(ExpandableView view); + + /** + * Called when the view is reset and therefore the height will change abruptly + * + * @param view The view which was reset. + */ + void onReset(ExpandableView view); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index a07bc5c3b323..1d08658ccaf2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1469,6 +1469,10 @@ public class NotificationPanelView extends PanelView implements } @Override + public void onReset(ExpandableView view) { + } + + @Override public void onScrollChanged() { if (mQsExpanded) { requestScrollerTopPaddingUpdate(false /* animate */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index fec5e74b9d14..d2b97d1e4e36 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -163,6 +163,8 @@ public class NotificationStackScrollLayout extends ViewGroup private int mNotificationTopPadding; private float mTopPaddingOverflow; private boolean mDontReportNextOverScroll; + private boolean mRequestViewResizeAnimationOnLayout; + private boolean mNeedViewResizeAnimation; /** * The maximum scrollPosition which we are allowed to reach when a notification was expanded. @@ -319,9 +321,18 @@ public class NotificationStackScrollLayout extends ViewGroup setMaxLayoutHeight(getHeight()); updateContentHeight(); clampScrollPosition(); + requestAnimationOnViewResize(); requestChildrenUpdate(); } + private void requestAnimationOnViewResize() { + if (mRequestViewResizeAnimationOnLayout && mIsExpanded && mAnimationsEnabled) { + mNeedViewResizeAnimation = true; + mNeedsAnimation = true; + } + mRequestViewResizeAnimationOnLayout = false; + } + public void updateSpeedBumpIndex(int newIndex) { int currentIndex = indexOfChild(mSpeedBumpView); @@ -1598,9 +1609,18 @@ public class NotificationStackScrollLayout extends ViewGroup generateHideSensitiveEvent(); generateDarkEvent(); generateGoToFullShadeEvent(); + generateViewResizeEvent(); mNeedsAnimation = false; } + private void generateViewResizeEvent() { + if (mNeedViewResizeAnimation) { + mAnimationEvents.add( + new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_VIEW_RESIZE)); + } + mNeedViewResizeAnimation = false; + } + private void generateSnapBackEvents() { for (View child : mSnappedBackChildren) { mAnimationEvents.add(new AnimationEvent(child, @@ -1892,6 +1912,11 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); } + @Override + public void onReset(ExpandableView view) { + mRequestViewResizeAnimationOnLayout = true; + } + private void updateScrollPositionOnExpandInBottom(ExpandableView view) { if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; @@ -2258,6 +2283,14 @@ public class NotificationStackScrollLayout extends ViewGroup // ANIMATION_TYPE_HIDE_SENSITIVE new AnimationFilter() .animateHideSensitive(), + + // ANIMATION_TYPE_VIEW_RESIZE + new AnimationFilter() + .animateAlpha() + .animateHeight() + .animateTopInset() + .animateY() + .animateZ(), }; static int[] LENGTHS = new int[] { @@ -2297,6 +2330,9 @@ public class NotificationStackScrollLayout extends ViewGroup // ANIMATION_TYPE_HIDE_SENSITIVE StackStateAnimator.ANIMATION_DURATION_STANDARD, + + // ANIMATION_TYPE_VIEW_RESIZE + StackStateAnimator.ANIMATION_DURATION_STANDARD, }; static final int ANIMATION_TYPE_ADD = 0; @@ -2311,6 +2347,7 @@ public class NotificationStackScrollLayout extends ViewGroup static final int ANIMATION_TYPE_DARK = 9; static final int ANIMATION_TYPE_GO_TO_FULL_SHADE = 10; static final int ANIMATION_TYPE_HIDE_SENSITIVE = 11; + static final int ANIMATION_TYPE_VIEW_RESIZE = 12; final long eventStartTime; final View changingView; diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java index 994f758370b7..3a6498427461 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java @@ -159,7 +159,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { try { mActiveListener.onError(STATUS_ERROR); } catch (RemoteException e) { - Slog.w(TAG, "RemoteException in onDetectionStopped"); + Slog.w(TAG, "RemoteException in onDetectionStopped", e); } mActiveListener = null; } |