diff options
Diffstat (limited to 'java/com/android')
14 files changed, 271 insertions, 127 deletions
diff --git a/java/com/android/dialer/app/AndroidManifest.xml b/java/com/android/dialer/app/AndroidManifest.xml index 12abaa6a9..3652c95ca 100644 --- a/java/com/android/dialer/app/AndroidManifest.xml +++ b/java/com/android/dialer/app/AndroidManifest.xml @@ -56,7 +56,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> + android:targetSdkVersion="27"/> <application android:theme="@style/Theme.AppCompat"> diff --git a/java/com/android/dialer/assisteddialing/AndroidManifest.xml b/java/com/android/dialer/assisteddialing/AndroidManifest.xml index 6625dff07..a19af3b72 100644 --- a/java/com/android/dialer/assisteddialing/AndroidManifest.xml +++ b/java/com/android/dialer/assisteddialing/AndroidManifest.xml @@ -17,6 +17,6 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="24"/> + android:targetSdkVersion="27"/> -</manifest>
\ No newline at end of file +</manifest> diff --git a/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml b/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml index 5266b1376..3e79de38a 100644 --- a/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml +++ b/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml @@ -17,7 +17,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="24"/> + android:targetSdkVersion="27"/> <application> <activity @@ -32,4 +32,4 @@ </activity> </application> -</manifest>
\ No newline at end of file +</manifest> diff --git a/java/com/android/dialer/binary/google/AndroidManifest.xml b/java/com/android/dialer/binary/google/AndroidManifest.xml index 018c2a73c..86f6bcb81 100644 --- a/java/com/android/dialer/binary/google/AndroidManifest.xml +++ b/java/com/android/dialer/binary/google/AndroidManifest.xml @@ -21,7 +21,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> + android:targetSdkVersion="27"/> <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> diff --git a/java/com/android/dialer/shortcuts/AndroidManifest.xml b/java/com/android/dialer/shortcuts/AndroidManifest.xml index 15f77944e..117005841 100644 --- a/java/com/android/dialer/shortcuts/AndroidManifest.xml +++ b/java/com/android/dialer/shortcuts/AndroidManifest.xml @@ -18,7 +18,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> + android:targetSdkVersion="27"/> <application android:theme="@style/Theme.AppCompat"> diff --git a/java/com/android/dialer/smartdial/LatinSmartDialMap.java b/java/com/android/dialer/smartdial/LatinSmartDialMap.java index c512c5d4a..656fd12b2 100644 --- a/java/com/android/dialer/smartdial/LatinSmartDialMap.java +++ b/java/com/android/dialer/smartdial/LatinSmartDialMap.java @@ -16,6 +16,7 @@ package com.android.dialer.smartdial; +/** {@link SmartDialMap} for Latin based T9 dialpad searching. */ public class LatinSmartDialMap implements SmartDialMap { private static final char[] LATIN_LETTERS_TO_DIGITS = { diff --git a/java/com/android/incallui/AndroidManifest.xml b/java/com/android/incallui/AndroidManifest.xml index d854a7fc8..af9970056 100644 --- a/java/com/android/incallui/AndroidManifest.xml +++ b/java/com/android/incallui/AndroidManifest.xml @@ -19,7 +19,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> + android:targetSdkVersion="27"/> <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/> <!-- We use this to disable the status bar buttons of home, back and recent diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java index 95da1c65e..d3d993027 100644 --- a/java/com/android/incallui/NewReturnToCallController.java +++ b/java/com/android/incallui/NewReturnToCallController.java @@ -219,11 +219,15 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au } private void onPhotoAvatarReceived(@NonNull Drawable photo) { - bubble.updatePhotoAvatar(photo); + if (bubble != null) { + bubble.updatePhotoAvatar(photo); + } } private void onLetterTileAvatarReceived(@NonNull Drawable photo) { - bubble.updateAvatar(photo); + if (bubble != null) { + bubble.updateAvatar(photo); + } } private NewBubbleInfo generateBubbleInfo() { diff --git a/java/com/android/incallui/autoresizetext/AndroidManifest.xml b/java/com/android/incallui/autoresizetext/AndroidManifest.xml index 1b5c19355..e26670e52 100644 --- a/java/com/android/incallui/autoresizetext/AndroidManifest.xml +++ b/java/com/android/incallui/autoresizetext/AndroidManifest.xml @@ -19,7 +19,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> + android:targetSdkVersion="27"/> <application /> </manifest> diff --git a/java/com/android/incallui/video/protocol/AndroidManifest.xml b/java/com/android/incallui/video/protocol/AndroidManifest.xml index cfb6b27ad..6f6558278 100644 --- a/java/com/android/incallui/video/protocol/AndroidManifest.xml +++ b/java/com/android/incallui/video/protocol/AndroidManifest.xml @@ -18,5 +18,5 @@ package="com.android.incallui.video.protocol"> <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> -</manifest>
\ No newline at end of file + android:targetSdkVersion="27"/> +</manifest> diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java index 34a9585c1..d13952ba5 100644 --- a/java/com/android/newbubble/NewBubble.java +++ b/java/com/android/newbubble/NewBubble.java @@ -25,8 +25,8 @@ import android.annotation.SuppressLint; import android.app.PendingIntent.CanceledException; import android.content.Context; import android.content.Intent; -import android.graphics.Path; import android.graphics.PixelFormat; +import android.graphics.Rect; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -38,7 +38,6 @@ import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v4.graphics.ColorUtils; import android.support.v4.os.BuildCompat; -import android.support.v4.view.animation.FastOutLinearInInterpolator; import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.transition.TransitionManager; import android.transition.TransitionValues; @@ -55,6 +54,7 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AnticipateInterpolator; import android.view.animation.OvershootInterpolator; import android.widget.ImageView; @@ -87,8 +87,13 @@ public class NewBubble { // This ensures the new window has had time to draw first. private static final int WINDOW_REDRAW_DELAY_MILLIS = 50; + private static final int EXPAND_AND_COLLAPSE_ANIMATION_DURATION = 200; + private static Boolean canShowBubblesForTesting = null; + private final AccelerateDecelerateInterpolator accelerateDecelerateInterpolator = + new AccelerateDecelerateInterpolator(); + private final Context context; private final WindowManager windowManager; @@ -233,7 +238,12 @@ public class NewBubble { } setPrimaryButtonAccessibilityAction( context.getString(R.string.a11y_bubble_primary_button_collapse_action)); + viewHolder.setDrawerVisibility(View.INVISIBLE); + viewHolder.getArrow().setVisibility(View.INVISIBLE); + // No click during animation to avoid jank. + viewHolder.setPrimaryButtonClickable(false); + View expandedView = viewHolder.getExpandedView(); expandedView .getViewTreeObserver() @@ -247,47 +257,46 @@ public class NewBubble { savedYPosition = windowParams.y; } - // Calculate the move-to-middle distance + // Animation 1: animate x-move and y-move (if needed) together int deltaX = (int) viewHolder.getRoot().findViewById(R.id.bubble_primary_container).getX(); - float k = (float) moveUpDistance / deltaX; + float k = -(float) moveUpDistance / deltaX; if (isDrawingFromRight()) { deltaX = -deltaX; } - - // Do X-move and Y-move together - - final int startX = windowParams.x - deltaX; - final int startY = windowParams.y; - ValueAnimator animator = ValueAnimator.ofFloat(startX, windowParams.x); - animator.setInterpolator(new LinearOutSlowInInterpolator()); - animator.addUpdateListener( - (valueAnimator) -> { - // Update windowParams and the root layout. - // We can't do ViewPropertyAnimation since it clips children. - float newX = (float) valueAnimator.getAnimatedValue(); - if (moveUpDistance != 0) { - windowParams.y = startY - (int) (Math.abs(newX - (float) startX) * k); - } - windowParams.x = (int) newX; - windowManager.updateViewLayout(viewHolder.getRoot(), windowParams); - }); - animator.addListener( + ValueAnimator xValueAnimator = + createBubbleMoveAnimator( + windowParams.x - deltaX, windowParams.x, windowParams.y, k); + + // Show expanded view + expandedView.setVisibility(View.VISIBLE); + + // Animator 2: reveal expanded view from top left or top right + View expandedMenu = viewHolder.getRoot().findViewById(R.id.bubble_expanded_menu); + ValueAnimator revealAnim = + createOpenCloseOutlineProvider(expandedMenu) + .createRevealAnimator(expandedMenu, false); + revealAnim.setInterpolator(accelerateDecelerateInterpolator); + + // Animator 3: expanded view fade in + Animator fadeIn = ObjectAnimator.ofFloat(expandedView, "alpha", 0, 1); + fadeIn.setInterpolator(accelerateDecelerateInterpolator); + + // Play all animation together + AnimatorSet expandAnimatorSet = new AnimatorSet(); + expandAnimatorSet.playTogether(revealAnim, fadeIn, xValueAnimator); + expandAnimatorSet.setDuration(EXPAND_AND_COLLAPSE_ANIMATION_DURATION); + expandAnimatorSet.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - // Show expanded view - expandedView.setVisibility(View.VISIBLE); - expandedView.setTranslationY(-expandedView.getHeight()); - expandedView.setAlpha(0); - expandedView - .animate() - .setInterpolator(new LinearOutSlowInInterpolator()) - .translationY(0) - .alpha(1); + // Show arrow after animation + viewHolder.getArrow().setVisibility(View.VISIBLE); + // Safe to click primary button now + viewHolder.setPrimaryButtonClickable(true); } }); - animator.start(); + expandAnimatorSet.start(); expandedView.getViewTreeObserver().removeOnPreDrawListener(this); return false; @@ -315,89 +324,79 @@ public class NewBubble { if (isUserAction && collapseEndAction == CollapseEnd.NOTHING) { logBasicOrCallImpression(DialerImpression.Type.BUBBLE_COLLAPSE_BY_USER); } + setPrimaryButtonAccessibilityAction( context.getString(R.string.a11y_bubble_primary_button_expand_action)); - // Animate expanded view to move from its position to above primary button and hide - collapseAnimation = - expandedView - .animate() - .translationY(-expandedView.getHeight()) - .alpha(0) - .setInterpolator(new FastOutLinearInInterpolator()) - .withEndAction( - () -> { - collapseAnimation = null; - expanded = false; - if (textShowing) { - // Will do resize once the text is done. - return; - } + // Hide arrow before animation + viewHolder.getArrow().setVisibility(View.INVISIBLE); + + // No click during animation to avoid jank. + viewHolder.setPrimaryButtonClickable(false); - // Set drawer visibility to INVISIBLE instead of GONE to keep primary button fixed - viewHolder.setDrawerVisibility(View.INVISIBLE); - - // Do X-move and Y-move together - int deltaX = - (int) viewHolder.getRoot().findViewById(R.id.bubble_primary_container).getX(); - int startX = windowParams.x; - int startY = windowParams.y; - float k = - (savedYPosition != -1 && shouldRecoverYPosition) - ? (savedYPosition - startY) / (float) deltaX - : 0; - Path path = new Path(); - path.moveTo(windowParams.x, windowParams.y); - path.lineTo( - windowParams.x - deltaX, - (savedYPosition != -1 && shouldRecoverYPosition) - ? savedYPosition - : windowParams.y); - // The position is not useful after collapse - savedYPosition = -1; - - ValueAnimator animator = ValueAnimator.ofFloat(startX, startX - deltaX); - animator.setInterpolator(new LinearOutSlowInInterpolator()); - animator.addUpdateListener( - (valueAnimator) -> { - // Update windowParams and the root layout. - // We can't do ViewPropertyAnimation since it clips children. - float newX = (float) valueAnimator.getAnimatedValue(); - if (k != 0) { - windowParams.y = startY + (int) (Math.abs(newX - (float) startX) * k); - } - windowParams.x = (int) newX; - windowManager.updateViewLayout(viewHolder.getRoot(), windowParams); - }); - animator.addListener( - new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // If collapse on the right side, the primary button move left a bit after - // drawer - // visibility becoming GONE. To avoid it, we create a new ViewHolder. - replaceViewHolder(); - } - }); - animator.start(); - - // If this collapse was to come before a hide, do it now. - if (collapseEndAction == CollapseEnd.HIDE) { - hide(); + // Calculate animation values + int deltaX = (int) viewHolder.getRoot().findViewById(R.id.bubble_primary_container).getX(); + float k = + (savedYPosition != -1 && shouldRecoverYPosition) + ? (savedYPosition - windowParams.y) / (float) deltaX + : 0; + // The position is not useful after collapse + savedYPosition = -1; + + // Animation 1: animate x-move and y-move (if needed) together + ValueAnimator xValueAnimator = + createBubbleMoveAnimator(windowParams.x, windowParams.x - deltaX, windowParams.y, k); + + // Animator 2: hide expanded view to top left or top right + View expandedMenu = viewHolder.getRoot().findViewById(R.id.bubble_expanded_menu); + ValueAnimator revealAnim = + createOpenCloseOutlineProvider(expandedMenu).createRevealAnimator(expandedMenu, true); + revealAnim.setInterpolator(accelerateDecelerateInterpolator); + + // Animator 3: expanded view fade out + Animator fadeOut = ObjectAnimator.ofFloat(expandedView, "alpha", 1, 0); + fadeOut.setInterpolator(accelerateDecelerateInterpolator); + + // Play all animation together + AnimatorSet collapseAnimatorSet = new AnimatorSet(); + collapseAnimatorSet.setDuration(EXPAND_AND_COLLAPSE_ANIMATION_DURATION); + collapseAnimatorSet.playTogether(revealAnim, fadeOut, xValueAnimator); + collapseAnimatorSet.addListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + collapseAnimation = null; + expanded = false; + + if (textShowing) { + // Will do resize once the text is done. + return; + } + + // If this collapse was to come before a hide, do it now. + if (collapseEndAction == CollapseEnd.HIDE) { + hide(); + } + collapseEndAction = CollapseEnd.NOTHING; + + // If collapse on the right side, the primary button move left a bit after drawer + // visibility becoming GONE. To avoid it, we create a new ViewHolder. + // It also set primary button clickable back to true, so no need to reset manually. + replaceViewHolder(); + + // Resume normal gravity after any resizing is done. + handler.postDelayed( + () -> { + overrideGravity = null; + if (!viewHolder.isMoving()) { + viewHolder.undoGravityOverride(); } - collapseEndAction = CollapseEnd.NOTHING; - - // Resume normal gravity after any resizing is done. - handler.postDelayed( - () -> { - overrideGravity = null; - if (!viewHolder.isMoving()) { - viewHolder.undoGravityOverride(); - } - }, - // Need to wait twice as long for resize and layout - WINDOW_REDRAW_DELAY_MILLIS * 2); - }); + }, + // Need to wait twice as long for resize and layout + WINDOW_REDRAW_DELAY_MILLIS * 2); + } + }); + collapseAnimatorSet.start(); } /** @@ -917,18 +916,45 @@ public class NewBubble { }); } + private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider(View view) { + int startRectX = isDrawingFromRight() ? view.getMeasuredWidth() : 0; + Rect startRect = new Rect(startRectX, 0, startRectX, 0); + Rect endRect = new Rect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + + float bubbleRadius = context.getResources().getDimension(R.dimen.bubble_radius); + return new RoundedRectRevealOutlineProvider(bubbleRadius, bubbleRadius, startRect, endRect); + } + + private ValueAnimator createBubbleMoveAnimator(int startX, int endX, int startY, float k) { + ValueAnimator xValueAnimator = ValueAnimator.ofFloat(startX, endX); + xValueAnimator.setInterpolator(new LinearOutSlowInInterpolator()); + xValueAnimator.addUpdateListener( + (valueAnimator) -> { + // Update windowParams and the root layout. + // We can't do ViewPropertyAnimation since it clips children. + float newX = (float) valueAnimator.getAnimatedValue(); + if (k != 0) { + windowParams.y = startY + (int) (Math.abs(newX - (float) startX) * k); + } + windowParams.x = (int) newX; + windowManager.updateViewLayout(viewHolder.getRoot(), windowParams); + }); + return xValueAnimator; + } + @VisibleForTesting class ViewHolder { public static final int CHILD_INDEX_AVATAR_AND_ICON = 0; public static final int CHILD_INDEX_TEXT = 1; - private final NewMoveHandler moveHandler; + private NewMoveHandler moveHandler; private final NewWindowRoot root; private final ViewAnimator primaryButton; private final ImageView primaryIcon; private final ImageView primaryAvatar; private final TextView primaryText; + private final View arrow; private final NewCheckableButton fullScreenButton; private final NewCheckableButton muteButton; @@ -946,6 +972,7 @@ public class NewBubble { primaryAvatar = contentView.findViewById(R.id.bubble_icon_avatar); primaryIcon = contentView.findViewById(R.id.bubble_icon_primary); primaryText = contentView.findViewById(R.id.bubble_text); + arrow = contentView.findViewById(R.id.bubble_triangle); fullScreenButton = contentView.findViewById(R.id.bubble_button_full_screen); muteButton = contentView.findViewById(R.id.bubble_button_mute); @@ -985,8 +1012,10 @@ public class NewBubble { muteButton.setClickable(clickable); audioRouteButton.setClickable(clickable); endCallButton.setClickable(clickable); + setPrimaryButtonClickable(clickable); + } - // For primaryButton + private void setPrimaryButtonClickable(boolean clickable) { moveHandler.setClickable(clickable); } @@ -1024,6 +1053,10 @@ public class NewBubble { return expandedView; } + public View getArrow() { + return arrow; + } + public NewCheckableButton getFullScreenButton() { return fullScreenButton; } diff --git a/java/com/android/newbubble/RoundedRectRevealOutlineProvider.java b/java/com/android/newbubble/RoundedRectRevealOutlineProvider.java new file mode 100644 index 000000000..d204e0f1c --- /dev/null +++ b/java/com/android/newbubble/RoundedRectRevealOutlineProvider.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017 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.newbubble; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.graphics.Outline; +import android.graphics.Rect; +import android.view.View; +import android.view.ViewOutlineProvider; + +/** + * A {@link ViewOutlineProvider} that provides an outline that interpolates between two radii and + * two {@link Rect}s. + * + * <p>An example usage of this provider is an outline that starts out as a circle and ends as a + * rounded rectangle. + */ +public class RoundedRectRevealOutlineProvider extends ViewOutlineProvider { + private final float mStartRadius; + private final float mEndRadius; + + private final Rect mStartRect; + private final Rect mEndRect; + + private final Rect mOutline; + private float mOutlineRadius; + + public RoundedRectRevealOutlineProvider( + float startRadius, float endRadius, Rect startRect, Rect endRect) { + mStartRadius = startRadius; + mEndRadius = endRadius; + mStartRect = startRect; + mEndRect = endRect; + + mOutline = new Rect(); + } + + @Override + public void getOutline(View v, Outline outline) { + outline.setRoundRect(mOutline, mOutlineRadius); + } + + /** Sets the progress, from 0 to 1, of the reveal animation. */ + public void setProgress(float progress) { + mOutlineRadius = (1 - progress) * mStartRadius + progress * mEndRadius; + + mOutline.left = (int) ((1 - progress) * mStartRect.left + progress * mEndRect.left); + mOutline.top = (int) ((1 - progress) * mStartRect.top + progress * mEndRect.top); + mOutline.right = (int) ((1 - progress) * mStartRect.right + progress * mEndRect.right); + mOutline.bottom = (int) ((1 - progress) * mStartRect.bottom + progress * mEndRect.bottom); + } + + ValueAnimator createRevealAnimator(final View revealView, boolean isReversed) { + ValueAnimator valueAnimator = + isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f); + + valueAnimator.addListener( + new AnimatorListenerAdapter() { + private boolean mWasCanceled = false; + + @Override + public void onAnimationStart(Animator animation) { + revealView.setOutlineProvider(RoundedRectRevealOutlineProvider.this); + revealView.setClipToOutline(true); + } + + @Override + public void onAnimationCancel(Animator animation) { + mWasCanceled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (!mWasCanceled) { + revealView.setOutlineProvider(ViewOutlineProvider.BACKGROUND); + revealView.setClipToOutline(false); + } + } + }); + + valueAnimator.addUpdateListener( + (currentValueAnimator) -> { + float progress = (Float) currentValueAnimator.getAnimatedValue(); + setProgress(progress); + revealView.invalidateOutline(); + }); + return valueAnimator; + } +} diff --git a/java/com/android/newbubble/res/layout/new_bubble_base.xml b/java/com/android/newbubble/res/layout/new_bubble_base.xml index 216dce0d2..f83b75395 100644 --- a/java/com/android/newbubble/res/layout/new_bubble_base.xml +++ b/java/com/android/newbubble/res/layout/new_bubble_base.xml @@ -108,6 +108,7 @@ android:rotation="45"> </RelativeLayout> <RelativeLayout + android:id="@+id/bubble_expanded_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/bubble_triangle" diff --git a/java/com/android/voicemail/AndroidManifest.xml b/java/com/android/voicemail/AndroidManifest.xml index 817cf1b55..d64fb2504 100644 --- a/java/com/android/voicemail/AndroidManifest.xml +++ b/java/com/android/voicemail/AndroidManifest.xml @@ -18,7 +18,7 @@ <uses-sdk android:minSdkVersion="23" - android:targetSdkVersion="26"/> + android:targetSdkVersion="27"/> <!-- Applications using this module should merge these permissions using android_manifest_merge --> |