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

Commit a086c409 authored by Beverly's avatar Beverly
Browse files

Add KeyguardStatusViewController

Refactor KeyguardStatusView so that it has a controller that
NotificationPanelViewController can use to manipulate the view. This
CL untangles some of the logic in KeyguardStatusView that should be in
KeyguardClockSwitchController.

No functionality changes.

Test: atest KeyguardClockSwitchControllerTest
Test: atest NotificationPanelViewTest
Test: atest KeyguardStatusViewControllerTest
Test: atest SystemUITests
Change-Id: I52d0d887cb4ce734ec265b6357644ba1d1368460
Bug: 170228350
parent fb038e9b
Loading
Loading
Loading
Loading
+132 −32
Original line number Diff line number Diff line
@@ -17,24 +17,32 @@
package com.android.keyguard;

import android.app.WallpaperManager;
import android.view.View;
import android.content.res.Resources;
import android.text.format.DateFormat;
import android.util.TypedValue;
import android.view.ViewGroup;

import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.util.ViewController;

import java.util.Locale;
import java.util.TimeZone;

import javax.inject.Inject;

/**
 * Injectable controller for {@link KeyguardClockSwitch}.
 */
public class KeyguardClockSwitchController {
public class KeyguardClockSwitchController extends ViewController<KeyguardClockSwitch> {
    private static final boolean CUSTOM_CLOCKS_ENABLED = true;

    private final KeyguardClockSwitch mView;
    private final Resources mResources;
    private final StatusBarStateController mStatusBarStateController;
    private final SysuiColorExtractor mColorExtractor;
    private final ClockManager mClockManager;
@@ -65,20 +73,43 @@ public class KeyguardClockSwitchController {

    private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;

    private final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
            new View.OnAttachStateChangeListener() {
    @Inject
    public KeyguardClockSwitchController(
            KeyguardClockSwitch keyguardClockSwitch,
            @Main Resources resources,
            StatusBarStateController statusBarStateController,
            SysuiColorExtractor colorExtractor, ClockManager clockManager,
            KeyguardSliceViewController keyguardSliceViewController) {
        super(keyguardClockSwitch);
        mResources = resources;
        mStatusBarStateController = statusBarStateController;
        mColorExtractor = colorExtractor;
        mClockManager = clockManager;
        mKeyguardSliceViewController = keyguardSliceViewController;
    }

    /**
     * Attach the controller to the view it relates to.
     */
    @Override
        public void onViewAttachedToWindow(View v) {
    public void init() {
        super.init();
        mKeyguardSliceViewController.init();
    }

    @Override
    protected void onViewAttached() {
        if (CUSTOM_CLOCKS_ENABLED) {
            mClockManager.addOnClockChangedListener(mClockChangedListener);
        }
        refreshFormat();
        mStatusBarStateController.addCallback(mStateListener);
        mColorExtractor.addOnColorsChangedListener(mColorsListener);
        mView.updateColors(getGradientColors());
    }

    @Override
        public void onViewDetachedFromWindow(View v) {
    protected void onViewDetached() {
        if (CUSTOM_CLOCKS_ENABLED) {
            mClockManager.removeOnClockChangedListener(mClockChangedListener);
        }
@@ -86,37 +117,75 @@ public class KeyguardClockSwitchController {
        mColorExtractor.removeOnColorsChangedListener(mColorsListener);
        mView.setClockPlugin(null, mStatusBarStateController.getState());
    }
    };

    @Inject
    public KeyguardClockSwitchController(KeyguardClockSwitch keyguardClockSwitch,
            StatusBarStateController statusBarStateController,
            SysuiColorExtractor colorExtractor, ClockManager clockManager,
            KeyguardSliceViewController keyguardSliceViewController) {
        mView = keyguardClockSwitch;
        mStatusBarStateController = statusBarStateController;
        mColorExtractor = colorExtractor;
        mClockManager = clockManager;
        mKeyguardSliceViewController = keyguardSliceViewController;
    /**
     * Updates clock's text
     */
    public void onDensityOrFontScaleChanged() {
        mView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                mResources.getDimensionPixelSize(R.dimen.widget_big_font_size));
    }

    /**
     * Attach the controller to the view it relates to.
     * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
     */
    public void init() {
        if (mView.isAttachedToWindow()) {
            mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
    public void setBigClockContainer(ViewGroup bigClockContainer) {
        mView.setBigClockContainer(bigClockContainer, mStatusBarStateController.getState());
    }
        mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);

        mKeyguardSliceViewController.init();
    /**
     * Set whether or not the lock screen is showing notifications.
     */
    public void setHasVisibleNotifications(boolean hasVisibleNotifications) {
        mView.setHasVisibleNotifications(hasVisibleNotifications);
    }

    /**
     * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
     * If we're presenting a custom clock of just the default one.
     */
    public void setBigClockContainer(ViewGroup bigClockContainer) {
        mView.setBigClockContainer(bigClockContainer, mStatusBarStateController.getState());
    public boolean hasCustomClock() {
        return mView.hasCustomClock();
    }

    /**
     * Get the clock text size.
     */
    public float getClockTextSize() {
        return mView.getTextSize();
    }

    /**
     * Returns the preferred Y position of the clock.
     *
     * @param totalHeight The height available to position the clock.
     * @return Y position of clock.
     */
    public int getClockPreferredY(int totalHeight) {
        return mView.getPreferredY(totalHeight);
    }

    /**
     * Refresh clock. Called in response to TIME_TICK broadcasts.
     */
    void refresh() {
        mView.refresh();
    }

    /**
     * Update lockscreen mode that may change clock display.
     */
    void updateLockScreenMode(int mode) {
        mView.updateLockScreenMode(mode);
    }

    void updateTimeZone(TimeZone timeZone) {
        mView.onTimeZoneChanged(timeZone);
    }

    void refreshFormat() {
        Patterns.update(mResources);
        mView.setFormat12Hour(Patterns.sClockView12);
        mView.setFormat24Hour(Patterns.sClockView24);
    }

    private void setClockPlugin(ClockPlugin plugin) {
@@ -126,4 +195,35 @@ public class KeyguardClockSwitchController {
    private ColorExtractor.GradientColors getGradientColors() {
        return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
    }

    // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
    // This is an optimization to ensure we only recompute the patterns when the inputs change.
    private static final class Patterns {
        static String sClockView12;
        static String sClockView24;
        static String sCacheKey;

        static void update(Resources res) {
            final Locale locale = Locale.getDefault();
            final String clockView12Skel = res.getString(R.string.clock_12hr_format);
            final String clockView24Skel = res.getString(R.string.clock_24hr_format);
            final String key = locale.toString() + clockView12Skel + clockView24Skel;
            if (key.equals(sCacheKey)) return;

            sClockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
            // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
            // format.  The following code removes the AM/PM indicator if we didn't want it.
            if (!clockView12Skel.contains("a")) {
                sClockView12 = sClockView12.replaceAll("a", "").trim();
            }

            sClockView24 = DateFormat.getBestDateTimePattern(locale, clockView24Skel);

            // Use fancy colon.
            sClockView24 = sClockView24.replace(':', '\uee01');
            sClockView12 = sClockView12.replace(':', '\uee01');

            sCacheKey = key;
        }
    }
}
+1 −7
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@ public class KeyguardSliceViewController implements Dumpable {
    private static final String TAG = "KeyguardSliceViewCtrl";

    private final KeyguardSliceView mView;
    private final KeyguardStatusView mKeyguardStatusView;
    private final ActivityStarter mActivityStarter;
    private final ConfigurationController mConfigurationController;
    private final TunerService mTunerService;
@@ -135,11 +134,10 @@ public class KeyguardSliceViewController implements Dumpable {

    @Inject
    public KeyguardSliceViewController(KeyguardSliceView keyguardSliceView,
            KeyguardStatusView keyguardStatusView, ActivityStarter activityStarter,
            ActivityStarter activityStarter,
            ConfigurationController configurationController, TunerService tunerService,
            DumpManager dumpManager) {
        mView = keyguardSliceView;
        mKeyguardStatusView = keyguardStatusView;
        mActivityStarter = activityStarter;
        mConfigurationController = configurationController;
        mTunerService = tunerService;
@@ -153,8 +151,6 @@ public class KeyguardSliceViewController implements Dumpable {
        }
        mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
        mView.setOnClickListener(mOnClickListener);
        // TODO: remove the line below.
        mKeyguardStatusView.setKeyguardSliceViewController(this);
    }

    /**
@@ -233,7 +229,5 @@ public class KeyguardSliceViewController implements Dumpable {
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("  mSlice: " + mSlice);
        pw.println("  mClickActions: " + mClickActions);

        mKeyguardStatusView.dump(fd, pw, args);
    }
}
+42 −214
Original line number Diff line number Diff line
@@ -19,16 +19,13 @@ package com.android.keyguard;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.util.TypedValue;
import android.view.View;
import android.widget.GridLayout;
@@ -39,15 +36,18 @@ import androidx.core.graphics.ColorUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ConfigurationController;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Locale;
import java.util.TimeZone;

public class KeyguardStatusView extends GridLayout implements
        ConfigurationController.ConfigurationListener {
/**
 * View consisting of:
 * - keyguard clock
 * - logout button (on certain managed devices)
 * - owner information (if set)
 * - notification icons (shown on AOD)
 */
public class KeyguardStatusView extends GridLayout {
    private static final boolean DEBUG = KeyguardConstants.DEBUG;
    private static final String TAG = "KeyguardStatusView";
    private static final int MARQUEE_DELAY_MS = 2000;
@@ -62,9 +62,7 @@ public class KeyguardStatusView extends GridLayout implements
    private View mNotificationIcons;
    private Runnable mPendingMarqueeStart;
    private Handler mHandler;
    private KeyguardSliceViewController mKeyguardSliceViewController;

    private boolean mPulsing;
    private float mDarkAmount = 0;
    private int mTextColor;

@@ -76,56 +74,6 @@ public class KeyguardStatusView extends GridLayout implements
    private int mIconTopMarginWithHeader;
    private boolean mShowingHeader;

    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {

        @Override
        public void onLockScreenModeChanged(int mode) {
            updateLockScreenMode(mode);
        }

        @Override
        public void onTimeChanged() {
            refreshTime();
        }

        @Override
        public void onTimeZoneChanged(TimeZone timeZone) {
            updateTimeZone(timeZone);
        }

        @Override
        public void onKeyguardVisibilityChanged(boolean showing) {
            if (showing) {
                if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
                refreshTime();
                updateOwnerInfo();
                updateLogoutView();
            }
        }

        @Override
        public void onStartedWakingUp() {
            setEnableMarquee(true);
        }

        @Override
        public void onFinishedGoingToSleep(int why) {
            setEnableMarquee(false);
        }

        @Override
        public void onUserSwitchComplete(int userId) {
            refreshFormat();
            updateOwnerInfo();
            updateLogoutView();
        }

        @Override
        public void onLogoutEnabledChanged() {
            updateLogoutView();
        }
    };

    public KeyguardStatusView(Context context) {
        this(context, null, 0);
    }
@@ -142,21 +90,7 @@ public class KeyguardStatusView extends GridLayout implements
        onDensityOrFontScaleChanged();
    }

    /**
     * If we're presenting a custom clock of just the default one.
     */
    public boolean hasCustomClock() {
        return mClockView.hasCustomClock();
    }

    /**
     * Set whether or not the lock screen is showing notifications.
     */
    public void setHasVisibleNotifications(boolean hasVisibleNotifications) {
        mClockView.setHasVisibleNotifications(hasVisibleNotifications);
    }

    private void setEnableMarquee(boolean enabled) {
    void setEnableMarquee(boolean enabled) {
        if (DEBUG) Log.v(TAG, "Schedule setEnableMarquee: " + (enabled ? "Enable" : "Disable"));
        if (enabled) {
            if (mPendingMarqueeStart == null) {
@@ -203,7 +137,6 @@ public class KeyguardStatusView extends GridLayout implements

        boolean shouldMarquee = Dependency.get(KeyguardUpdateMonitor.class).isDeviceInteractive();
        setEnableMarquee(shouldMarquee);
        refreshFormat();
        updateOwnerInfo();
        updateLogoutView();
        updateDark();
@@ -238,64 +171,14 @@ public class KeyguardStatusView extends GridLayout implements
        layoutOwnerInfo();
    }

    @Override
    public void onDensityOrFontScaleChanged() {
        if (mClockView != null) {
            mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                    getResources().getDimensionPixelSize(R.dimen.widget_big_font_size));
        }
        if (mOwnerInfo != null) {
            mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                    getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
        }
        loadBottomMargin();
    }

    public void dozeTimeTick() {
        refreshTime();
        mKeyguardSliceViewController.refresh();
    }

    private void refreshTime() {
        mClockView.refresh();
    }

    private void updateLockScreenMode(int mode) {
        mClockView.updateLockScreenMode(mode);
    }

    private void updateTimeZone(TimeZone timeZone) {
        mClockView.onTimeZoneChanged(timeZone);
    }

    private void refreshFormat() {
        Patterns.update(mContext);
        mClockView.setFormat12Hour(Patterns.clockView12);
        mClockView.setFormat24Hour(Patterns.clockView24);
    }

    public int getLogoutButtonHeight() {
    int getLogoutButtonHeight() {
        if (mLogoutView == null) {
            return 0;
        }
        return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
    }

    public float getClockTextSize() {
        return mClockView.getTextSize();
    }

    /**
     * Returns the preferred Y position of the clock.
     *
     * @param totalHeight The height available to position the clock.
     * @return Y position of clock.
     */
    public int getClockPreferredY(int totalHeight) {
        return mClockView.getPreferredY(totalHeight);
    }

    private void updateLogoutView() {
    void updateLogoutView() {
        if (mLogoutView == null) {
            return;
        }
@@ -305,7 +188,16 @@ public class KeyguardStatusView extends GridLayout implements
                com.android.internal.R.string.global_action_logout));
    }

    private void updateOwnerInfo() {
    void onDensityOrFontScaleChanged() {
        if (mOwnerInfo != null) {
            mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                    getResources().getDimensionPixelSize(
                            com.android.systemui.R.dimen.widget_label_font_size));
            loadBottomMargin();
        }
    }

    void updateOwnerInfo() {
        if (mOwnerInfo == null) return;
        String info = mLockPatternUtils.getDeviceOwnerInfo();
        if (info == null) {
@@ -320,30 +212,36 @@ public class KeyguardStatusView extends GridLayout implements
        updateDark();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mInfoCallback);
        Dependency.get(ConfigurationController.class).addCallback(this);
    void setDarkAmount(float darkAmount) {
        if (mDarkAmount == darkAmount) {
            return;
        }
        mDarkAmount = darkAmount;
        mClockView.setDarkAmount(darkAmount);
        updateDark();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mInfoCallback);
        Dependency.get(ConfigurationController.class).removeCallback(this);
    void updateDark() {
        boolean dark = mDarkAmount == 1;
        if (mLogoutView != null) {
            mLogoutView.setAlpha(dark ? 0 : 1);
        }

    @Override
    public void onLocaleListChanged() {
        refreshFormat();
        if (mOwnerInfo != null) {
            boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
            mOwnerInfo.setVisibility(hasText ? VISIBLE : GONE);
            layoutOwnerInfo();
        }

        final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
        mKeyguardSlice.setDarkAmount(mDarkAmount);
        mClockView.setTextColor(blendedTextColor);
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("KeyguardStatusView:");
        pw.println("  mOwnerInfo: " + (mOwnerInfo == null
                ? "null" : mOwnerInfo.getVisibility() == VISIBLE));
        pw.println("  mPulsing: " + mPulsing);
        pw.println("  mDarkAmount: " + mDarkAmount);
        pw.println("  mTextColor: " + Integer.toHexString(mTextColor));
        if (mLogoutView != null) {
@@ -363,64 +261,6 @@ public class KeyguardStatusView extends GridLayout implements
                R.dimen.widget_vertical_padding_with_header);
    }

    // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
    // This is an optimization to ensure we only recompute the patterns when the inputs change.
    private static final class Patterns {
        static String clockView12;
        static String clockView24;
        static String cacheKey;

        static void update(Context context) {
            final Locale locale = Locale.getDefault();
            final Resources res = context.getResources();
            final String clockView12Skel = res.getString(R.string.clock_12hr_format);
            final String clockView24Skel = res.getString(R.string.clock_24hr_format);
            final String key = locale.toString() + clockView12Skel + clockView24Skel;
            if (key.equals(cacheKey)) return;

            clockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
            // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
            // format.  The following code removes the AM/PM indicator if we didn't want it.
            if (!clockView12Skel.contains("a")) {
                clockView12 = clockView12.replaceAll("a", "").trim();
            }

            clockView24 = DateFormat.getBestDateTimePattern(locale, clockView24Skel);

            // Use fancy colon.
            clockView24 = clockView24.replace(':', '\uee01');
            clockView12 = clockView12.replace(':', '\uee01');

            cacheKey = key;
        }
    }

    public void setDarkAmount(float darkAmount) {
        if (mDarkAmount == darkAmount) {
            return;
        }
        mDarkAmount = darkAmount;
        mClockView.setDarkAmount(darkAmount);
        updateDark();
    }

    private void updateDark() {
        boolean dark = mDarkAmount == 1;
        if (mLogoutView != null) {
            mLogoutView.setAlpha(dark ? 0 : 1);
        }

        if (mOwnerInfo != null) {
            boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
            mOwnerInfo.setVisibility(hasText ? VISIBLE : GONE);
            layoutOwnerInfo();
        }

        final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
        mKeyguardSlice.setDarkAmount(mDarkAmount);
        mClockView.setTextColor(blendedTextColor);
    }

    private void layoutOwnerInfo() {
        if (mOwnerInfo != null && mOwnerInfo.getVisibility() != GONE) {
            // Animate owner info during wake-up transition
@@ -442,13 +282,6 @@ public class KeyguardStatusView extends GridLayout implements
        }
    }

    public void setPulsing(boolean pulsing) {
        if (mPulsing == pulsing) {
            return;
        }
        mPulsing = pulsing;
    }

    private boolean shouldShowLogout() {
        return Dependency.get(KeyguardUpdateMonitor.class).isLogoutEnabled()
                && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
@@ -463,9 +296,4 @@ public class KeyguardStatusView extends GridLayout implements
            Log.e(TAG, "Failed to logout user", re);
        }
    }

    // TODO: remove this method when a controller is available.
    void setKeyguardSliceViewController(KeyguardSliceViewController keyguardSliceViewController) {
        mKeyguardSliceViewController = keyguardSliceViewController;
    }
}
+329 −0

File added.

Preview size limit exceeded, changes collapsed.

+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.keyguard.dagger;

import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;

import dagger.BindsInstance;
import dagger.Subcomponent;
@@ -36,4 +37,7 @@ public interface KeyguardStatusViewComponent {

    /** Builds a {@link com.android.keyguard.KeyguardClockSwitchController}. */
    KeyguardClockSwitchController getKeyguardClockSwitchController();

    /** Builds a {@link com.android.keyguard.KeyguardStatusViewController}. */
    KeyguardStatusViewController getKeyguardStatusViewController();
}
Loading