Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f43dc04 authored by Adrian Roos's avatar Adrian Roos
Browse files

Assist disclosure

Add an animation that discloses delivery
of contextual data to the assist component.

Also fixes a bug where contextual data was
delivered to legacy assist activities even
though the user explicitly disabled context.

Bug: 21568059
Change-Id: I27dfaa36e2f677b0d73acfa4730f0f4ea3486919
parent cdca13c6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -64,5 +64,7 @@ oneway interface IStatusBar
     *        bar caused by this app transition in millis
     */
    void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);

    void showAssistDisclosure();
}
+6 −0
Original line number Diff line number Diff line
@@ -578,4 +578,10 @@

    <!-- Padding between icon and text for managed profile toast -->
    <dimen name="managed_profile_toast_padding">4dp</dimen>

    <!-- Thickness of the assist disclosure beams -->
    <dimen name="assist_disclosure_thickness">4dp</dimen>

    <!-- Thickness of the shadows of the assist disclosure beams -->
    <dimen name="assist_disclosure_shadow_thickness">1.5dp</dimen>
</resources>
+251 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.assist;

import com.android.systemui.R;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Handler;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;

/**
 * Visually discloses that contextual data was provided to an assistant.
 */
public class AssistDisclosure {
    private final Context mContext;
    private final WindowManager mWm;
    private final Handler mHandler;

    private AssistDisclosureView mView;
    private boolean mViewAdded;

    public AssistDisclosure(Context context, Handler handler) {
        mContext = context;
        mHandler = handler;
        mWm = mContext.getSystemService(WindowManager.class);
    }

    public void postShow() {
        mHandler.removeCallbacks(mShowRunnable);
        mHandler.post(mShowRunnable);
    }

    private void show() {
        if (mView == null) {
            mView = new AssistDisclosureView(mContext);
        }
        if (!mViewAdded) {
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                            | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                            | WindowManager.LayoutParams.FLAG_FULLSCREEN
                            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
                    PixelFormat.TRANSLUCENT);
            lp.setTitle("AssistDisclosure");

            mWm.addView(mView, lp);
            mViewAdded = true;
        }
    }

    private void hide() {
        if (mViewAdded) {
            mWm.removeView(mView);
            mViewAdded = false;
        }
    }

    private Runnable mShowRunnable = new Runnable() {
        @Override
        public void run() {
            show();
        }
    };

    private class AssistDisclosureView extends View
            implements ValueAnimator.AnimatorUpdateListener {

        public static final int TRACING_ANIMATION_DURATION = 300;
        public static final int ALPHA_ANIMATION_DURATION = 200;

        private float mThickness;
        private float mShadowThickness;
        private final Paint mPaint = new Paint();
        private final Paint mShadowPaint = new Paint();

        private final ValueAnimator mTracingAnimator;
        private final ValueAnimator mAlphaAnimator;
        private final AnimatorSet mAnimator;

        private float mTracingProgress = 0;
        private int mAlpha = 255;

        public AssistDisclosureView(Context context) {
            super(context);

            mTracingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(TRACING_ANIMATION_DURATION);
            mTracingAnimator.addUpdateListener(this);
            mTracingAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
                    android.R.interpolator.fast_out_slow_in));
            mAlphaAnimator = ValueAnimator.ofInt(255, 0).setDuration(ALPHA_ANIMATION_DURATION);
            mAlphaAnimator.addUpdateListener(this);
            mAlphaAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
                    android.R.interpolator.fast_out_linear_in));
            mAnimator = new AnimatorSet();
            mAnimator.play(mTracingAnimator).before(mAlphaAnimator);
            mAnimator.addListener(new AnimatorListenerAdapter() {
                boolean mCancelled;

                @Override
                public void onAnimationStart(Animator animation) {
                    mCancelled = false;
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    mCancelled = true;
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    if (!mCancelled) {
                        hide();
                    }
                }
            });

            PorterDuffXfermode srcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
            mPaint.setColor(Color.WHITE);
            mPaint.setXfermode(srcMode);
            mShadowPaint.setColor(Color.DKGRAY);
            mShadowPaint.setXfermode(srcMode);

            mThickness = getResources().getDimension(R.dimen.assist_disclosure_thickness);
            mShadowThickness = getResources().getDimension(
                    R.dimen.assist_disclosure_shadow_thickness);
        }

        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();

            startAnimation();
        }

        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();

            mAnimator.cancel();

            mTracingProgress = 0;
            mAlpha = 255;
        }

        private void startAnimation() {
            mAnimator.cancel();
            mAnimator.start();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            mPaint.setAlpha(mAlpha);
            mShadowPaint.setAlpha(mAlpha / 4);

            drawGeometry(canvas, mShadowPaint, mShadowThickness);
            drawGeometry(canvas, mPaint, 0);
        }

        private void drawGeometry(Canvas canvas, Paint paint, float padding) {
            final int width = getWidth();
            final int height = getHeight();
            float thickness = mThickness;
            final float pixelProgress = mTracingProgress * (width + height - 2 * thickness);

            float bottomProgress = Math.min(pixelProgress, width / 2f);
            if (bottomProgress > 0) {
                drawBeam(canvas,
                        width / 2f - bottomProgress,
                        height - thickness,
                        width / 2f + bottomProgress,
                        height, paint, padding);
            }

            float sideProgress = Math.min(pixelProgress - bottomProgress, height - thickness);
            if (sideProgress > 0) {
                drawBeam(canvas,
                        0,
                        (height - thickness) - sideProgress,
                        thickness,
                        height - thickness, paint, padding);
                drawBeam(canvas,
                        width - thickness,
                        (height - thickness) - sideProgress,
                        width,
                        height - thickness, paint, padding);
            }

            float topProgress = Math.min(pixelProgress - bottomProgress - sideProgress,
                    width / 2 - thickness);
            if (sideProgress > 0 && topProgress > 0) {
                drawBeam(canvas,
                        thickness,
                        0,
                        thickness + topProgress,
                        thickness, paint, padding);
                drawBeam(canvas,
                        (width - thickness) - topProgress,
                        0,
                        width - thickness,
                        thickness, paint, padding);
            }
        }

        private void drawBeam(Canvas canvas, float left, float top, float right, float bottom,
                Paint paint, float padding) {
            canvas.drawRect(left - padding,
                    top - padding,
                    right + padding,
                    bottom + padding,
                    paint);
        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            if (animation == mAlphaAnimator) {
                mAlpha = (int) mAlphaAnimator.getAnimatedValue();
            } else if (animation == mTracingAnimator) {
                mTracingProgress = (float) mTracingAnimator.getAnimatedValue();
            }
            invalidate();
        }
    }
}
+15 −1
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ public class AssistManager {

    private final Context mContext;
    private final WindowManager mWindowManager;
    private final AssistDisclosure mAssistDisclosure;

    private AssistOrbContainer mView;
    private final PhoneStatusBar mBar;
    private final AssistUtils mAssistUtils;
@@ -100,6 +102,7 @@ public class AssistManager {
                Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false,
                mAssistSettingsObserver);
        mAssistSettingsObserver.onChange(false);
        mAssistDisclosure = new AssistDisclosure(context, new Handler());
    }

    public void onConfigurationChanged() {
@@ -187,8 +190,11 @@ public class AssistManager {
        mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL |
                CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL);

        boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;

        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
                .getAssistIntent(mContext, structureEnabled, UserHandle.USER_CURRENT);
        if (intent == null) {
            return;
        }
@@ -196,6 +202,10 @@ public class AssistManager {
            intent.setComponent(mAssistComponent);
        }

        if (structureEnabled) {
            showDisclosure();
        }

        try {
            final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
                    R.anim.search_launch_enter, R.anim.search_launch_exit);
@@ -297,4 +307,8 @@ public class AssistManager {
        pw.println("AssistManager state:");
        pw.print("  mAssistComponent="); pw.println(mAssistComponent);
    }

    public void showDisclosure() {
        mAssistDisclosure.postShow();
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -2101,4 +2101,11 @@ public abstract class BaseStatusBar extends SystemUI implements
        }
        return mStatusBarKeyguardViewManager.isSecure();
    }

    @Override
    public void showAssistDisclosure() {
        if (mAssistManager != null) {
            mAssistManager.showDisclosure();
        }
    }
}
Loading