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

Commit 19e458f4 authored by Utkarsh Gupta's avatar Utkarsh Gupta Committed by Gerrit Code Review
Browse files

SystemUI: use new visualizer from Eleven



Change-Id: I4441440868cac71caa32c91a0875f00a630fe596
Signed-off-by: default avatarUtkarsh Gupta <utkarsh.eminem@gmail.com>
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
parent 1d87c140
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -37,6 +37,10 @@

    <uses-permission android:name="cyanogenmod.permission.HARDWARE_ABSTRACTION_ACCESS" />

    <!-- Visualizer -->
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <application>
        <provider android:name=".cm.SpamMessageProvider"
                  android:permission="android.permission.INTERACT_ACROSS_USERS_FULL"
+23 −13
Original line number Diff line number Diff line
@@ -45,19 +45,29 @@
                   android:visibility="invisible" />
    </com.android.systemui.statusbar.BackDropView>

    <com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_behind"
    <FrameLayout android:id="@+id/scrimview"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
        android:importantForAccessibility="no"
        sysui:ignoreRightInset="true"
        />

                 android:visibility="visible">
        <com.android.systemui.statusbar.ScrimView
                android:id="@+id/scrim_behind"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:importantForAccessibility="no"/>
        <com.android.systemui.statusbar.AlphaOptimizedView
            android:id="@+id/heads_up_scrim"
            android:layout_width="match_parent"
            android:layout_height="@dimen/heads_up_scrim_height"
            android:background="@drawable/heads_up_scrim"
            android:importantForAccessibility="no"/>
        <com.android.systemui.statusbar.VisualizerView
                android:id="@+id/visualizerview"
                android:gravity="bottom"
                android:layout_gravity="bottom"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="visible"/>
    </FrameLayout>

    <include layout="@layout/status_bar"
        android:layout_width="match_parent"
+365 −0
Original line number Diff line number Diff line
/*
* Copyright (C) 2015 The CyanogenMod 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;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.audiofx.Visualizer;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.support.v7.graphics.Palette;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.cm.UserContentObserver;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import cyanogenmod.providers.CMSettings;

import java.util.Arrays;

public class VisualizerView extends View implements Palette.PaletteAsyncListener,
        KeyguardMonitor.Callback {

    private Paint mPaint;
    private Visualizer mVisualizer;
    private ObjectAnimator mVisualizerColorAnimator;

    private ValueAnimator[] mValueAnimators;
    private float[] mFFTPoints;

    private boolean mVisualizerEnabled = false;
    private boolean mVisible = false;
    private boolean mPlaying = false;
    private boolean mPowerSaveMode = false;
    private boolean mDisplaying = false; // the state we're animating to
    private boolean mDozing = false;

    private int mColor;
    private Bitmap mCurrentBitmap;

    private KeyguardMonitor mKeyguardMonitor;
    private SettingsObserver mObserver;

    private Visualizer.OnDataCaptureListener mVisualizerListener =
            new Visualizer.OnDataCaptureListener() {
        byte rfk, ifk;
        int dbValue;
        float magnitude;

        @Override
        public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {
        }

        @Override
        public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
            for (int i = 0; i < 32; i++) {
                mValueAnimators[i].cancel();
                rfk = fft[i * 2 + 2];
                ifk = fft[i * 2 + 3];
                magnitude = rfk * rfk + ifk * ifk;
                dbValue = magnitude > 0 ? (int) (10 * Math.log10(magnitude)) : 0;

                mValueAnimators[i].setFloatValues(mFFTPoints[i * 4 + 1],
                        mFFTPoints[3] - (dbValue * 16f));
                mValueAnimators[i].start();
            }
        }
    };

    private final Runnable mLinkVisualizer = new Runnable() {
        @Override
        public void run() {
            try {
                mVisualizer = new Visualizer(0);
            } catch (Exception e) {
                return;
            }

            mVisualizer.setEnabled(false);
            mVisualizer.setCaptureSize(66);
            mVisualizer.setDataCaptureListener(mVisualizerListener,Visualizer.getMaxCaptureRate(),
                    false, true);
            mVisualizer.setEnabled(true);

        }
    };

    private final Runnable mUnlinkVisualizer = new Runnable() {
        @Override
        public void run() {
            mVisualizer.setEnabled(false);
            mVisualizer.release();
            mVisualizer = null;
        }
    };

    public VisualizerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mColor = Color.TRANSPARENT;

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(mColor);

        mFFTPoints = new float[128];
        mValueAnimators = new ValueAnimator[32];
        for (int i = 0; i < 32; i++) {
            final int j = i * 4 + 1;
            mValueAnimators[i] = new ValueAnimator();
            mValueAnimators[i].setDuration(128);
            mValueAnimators[i].addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mFFTPoints[j] = (float) animation.getAnimatedValue();
                    postInvalidate();
                }
            });
        }
    }

    public VisualizerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VisualizerView(Context context) {
        this(context, null, 0);
    }

    @Override
    public void onKeyguardChanged() {
        updateViewVisibility();
    }

    private void updateViewVisibility() {
        setVisibility(mKeyguardMonitor != null && mKeyguardMonitor.isShowing()
                && mVisualizerEnabled ? View.VISIBLE : View.GONE);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mKeyguardMonitor != null) {
            mKeyguardMonitor.addCallback(this);
        }
        mObserver = new SettingsObserver(new Handler());
        mObserver.observe();
        mObserver.update();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mKeyguardMonitor != null) {
            mKeyguardMonitor.removeCallback(this);
        }
        mObserver.unobserve();
        mObserver = null;
        mCurrentBitmap = null;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
        setMeasuredDimension(size, size);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        float barUnit = w / 32f;
        float barWidth = barUnit * 8f / 9f;
        barUnit = barWidth + (barUnit - barWidth) * 32f / 31f;
        mPaint.setStrokeWidth(barWidth);

        for (int i = 0; i < 32; i++) {
            mFFTPoints[i * 4] = mFFTPoints[i * 4 + 2] = i * barUnit + (barWidth / 2);
            mFFTPoints[i * 4 + 1] = h;
            mFFTPoints[i * 4 + 3] = h;
        }
    }

    @Override
    public boolean hasOverlappingRendering() {
        return mVisualizerEnabled && mDisplaying;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mVisualizer != null) {
            canvas.drawLines(mFFTPoints, mPaint);
        }
    }

    public void setKeyguardMonitor(KeyguardMonitor kgm) {
        mKeyguardMonitor = kgm;
        if (isAttachedToWindow()) {
            // otherwise we might never register ourselves
            mKeyguardMonitor.addCallback(this);
            updateViewVisibility();
        }
    }

    public void setVisible(boolean visible) {
        if (mVisible != visible) {
            mVisible = visible;
            checkStateChanged();
        }
    }

    public void setDozing(boolean dozing) {
        if (mDozing != dozing) {
            mDozing = dozing;
            checkStateChanged();
        }
    }

    public void setPlaying(boolean playing) {
        if (mPlaying != playing) {
            mPlaying = playing;
            checkStateChanged();
        }
    }

    public void setPowerSaveMode(boolean powerSaveMode) {
        if (mPowerSaveMode != powerSaveMode) {
            mPowerSaveMode = powerSaveMode;
            checkStateChanged();
        }
    }

    public void setBitmap(Bitmap bitmap) {
        if (mCurrentBitmap == bitmap) {
            return;
        }
        mCurrentBitmap = bitmap;
        if (bitmap != null) {
            Palette.generateAsync(bitmap, this);
        } else {
            setColor(Color.TRANSPARENT);
        }
    }

    @Override
    public void onGenerated(Palette palette) {
        int color = Color.TRANSPARENT;

        color = palette.getVibrantColor(color);
        if (color == Color.TRANSPARENT) {
            color = palette.getLightVibrantColor(color);
            if (color == Color.TRANSPARENT) {
                color = palette.getDarkVibrantColor(color);
            }
        }

        setColor(color);
    }

    private void setColor(int color) {
        if (color == Color.TRANSPARENT) {
            color = Color.WHITE;
        }

        color = Color.argb(140, Color.red(color), Color.green(color), Color.blue(color));

        if (mColor != color) {
            mColor = color;

            if (mVisualizer != null) {
                if (mVisualizerColorAnimator != null) {
                    mVisualizerColorAnimator.cancel();
                }

                mVisualizerColorAnimator = ObjectAnimator.ofArgb(mPaint, "color",
                        mPaint.getColor(), mColor);
                mVisualizerColorAnimator.setStartDelay(600);
                mVisualizerColorAnimator.setDuration(1200);
                mVisualizerColorAnimator.start();
            } else {
                mPaint.setColor(mColor);
            }
        }
    }

    private void checkStateChanged() {
        if (mVisible && mPlaying && !mDozing && !mPowerSaveMode && mVisualizerEnabled) {
            if (!mDisplaying) {
                mDisplaying = true;
                AsyncTask.execute(mLinkVisualizer);
                animate()
                        .alpha(1f)
                        .withEndAction(null)
                        .setDuration(800);
            }
        } else {
            if (mDisplaying) {
                mDisplaying = false;
                if (mVisible) {
                    animate()
                            .alpha(0f)
                            .withEndAction(mUnlinkVisualizer)
                            .setDuration(600);
                } else {
                    AsyncTask.execute(mUnlinkVisualizer);
                    animate().
                            alpha(0f)
                            .withEndAction(null)
                            .setDuration(0);
                }
            }
        }
    }

    private class SettingsObserver extends UserContentObserver {

        public SettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        protected void update() {
            mVisualizerEnabled = CMSettings.Secure.getInt(getContext().getContentResolver(),
                    CMSettings.Secure.LOCKSCREEN_VISUALIZER_ENABLED, 1) != 0;
            checkStateChanged();
            updateViewVisibility();
        }

        @Override
        protected void observe() {
            super.observe();
            getContext().getContentResolver().registerContentObserver(
                    CMSettings.Secure.getUriFor(CMSettings.Secure.LOCKSCREEN_VISUALIZER_ENABLED),
                    false, this, UserHandle.USER_CURRENT);
        }

        @Override
        protected void unobserve() {
            super.unobserve();
            getContext().getContentResolver().unregisterContentObserver(this);
        }
    }
}
+37 −2
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.SpeedBumpView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VisualizerView;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -614,6 +615,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    private PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
    private PorterDuffXfermode mSrcOverXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);

    private VisualizerView mVisualizerView;
    private boolean mScreenOn;

    private MediaSessionManager mMediaSessionManager;
    private MediaController mMediaController;
    private String mMediaNotificationKey;
@@ -629,6 +633,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
                    clearCurrentMediaNotification();
                    updateMediaMetaData(true);
                }
                mVisualizerView.setPlaying(state.getState() == PlaybackState.STATE_PLAYING);
            }
        }

@@ -994,8 +999,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
        mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);

        ScrimView scrimBehind = (ScrimView) mStatusBarWindowContent.findViewById(R.id.scrim_behind);
        ScrimView scrimInFront = (ScrimView) mStatusBarWindowContent.findViewById(R.id.scrim_in_front);
        FrameLayout scrimView = (FrameLayout) mStatusBarWindowContent.findViewById(R.id.scrimview);
        ScrimView scrimBehind = (ScrimView) scrimView.findViewById(R.id.scrim_behind);
        ScrimView scrimInFront =
                (ScrimView) mStatusBarWindowContent.findViewById(R.id.scrim_in_front);
        View headsUpScrim = mStatusBarWindowContent.findViewById(R.id.heads_up_scrim);
        mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim,
                mScrimSrcModeEnabled);
@@ -1004,6 +1011,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        mScrimController.setBackDropView(mBackdrop);
        mStatusBarView.setScrimController(mScrimController);
        mDozeScrimController = new DozeScrimController(mScrimController, context);
        mVisualizerView = (VisualizerView) scrimView.findViewById(R.id.visualizerview);

        mHeader = (StatusBarHeaderView) mStatusBarWindowContent.findViewById(R.id.header);
        mHeader.setActivityStarter(this);
@@ -1182,6 +1190,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.battery_level_text))
                .setBatteryController(mBatteryController);
        mKeyguardStatusBar.setBatteryController(mBatteryController);
        mVisualizerView.setKeyguardMonitor(mKeyguardMonitor);
        mHeader.setNextAlarmController(mNextAlarmController);
        mHeader.setWeatherController(mWeatherController);

@@ -2058,6 +2067,26 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
            backdropBitmap = mKeyguardWallpaper;
        }

        boolean keyguardVisible = (mState != StatusBarState.SHADE);

        if (!mKeyguardFadingAway && keyguardVisible && backdropBitmap != null && mScreenOn) {
            // if there's album art, ensure visualizer is visible
            mVisualizerView.setVisible(true);
            mVisualizerView.setPlaying(mMediaController != null
                    && mMediaController.getPlaybackState() != null
                    && mMediaController.getPlaybackState().getState()
                            == PlaybackState.STATE_PLAYING);
        }

        if (backdropBitmap == null && mMediaMetadata == null) {
            backdropBitmap = mKeyguardWallpaper;
        }

        if (keyguardVisible) {
            // always use current backdrop to color eq
            mVisualizerView.setBitmap(backdropBitmap);
        }

        final boolean hasBackdrop = backdropBitmap != null;
        mKeyguardShowingMedia = hasBackdrop;
        if (mStatusBarWindowManager != null) {
@@ -3396,12 +3425,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
                }
            }
            else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                mScreenOn = false;
                notifyNavigationBarScreenOn(false);
                notifyHeadsUpScreenOff();
                finishBarAnimations();
                resetUserExpandedStates();
            }
            else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                mScreenOn = true;
                notifyNavigationBarScreenOn(true);
            }
        }
@@ -4290,6 +4321,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
                        - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
                StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
        disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */);
        mVisualizerView.setVisible(false);
    }

    public boolean isKeyguardFadingAway() {
@@ -4354,6 +4386,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        mDozeScrimController.setDozing(mDozing &&
                mFingerprintUnlockController.getMode()
                        != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, animate);
        mVisualizerView.setDozing(mDozing);
    }

    public void updateStackScrollerState(boolean goingToFullShade) {
@@ -4627,6 +4660,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        mWakeUpTouchLocation = null;
        mStackScroller.setAnimationsEnabled(false);
        updateVisibleToUser();
        mVisualizerView.setVisible(false);
        if (mLaunchCameraOnFinishedGoingToSleep) {
            mLaunchCameraOnFinishedGoingToSleep = false;

@@ -4665,6 +4699,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    public void onScreenTurnedOn() {
        mScreenTurningOn = false;
        mDozeScrimController.onScreenTurnedOn();
        mVisualizerView.setVisible(true);
    }

    /**