summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java')
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java241
1 files changed, 182 insertions, 59 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 570d351a8b71..1aff3949a74b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,9 +1,15 @@
package com.android.keyguard;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
import android.graphics.Paint;
import android.graphics.Paint.Style;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -12,18 +18,29 @@ import android.widget.TextClock;
import androidx.annotation.VisibleForTesting;
+import com.android.keyguard.clock.BubbleClockController;
+import com.android.keyguard.clock.StretchAnalogClockController;
+import com.android.keyguard.clock.TypeClockController;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
import java.util.Objects;
import java.util.TimeZone;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
/**
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
*/
public class KeyguardClockSwitch extends RelativeLayout {
+
+ private LayoutInflater mLayoutInflater;
+
+ private final ContentResolver mContentResolver;
/**
* Optional/alternative clock injected via plugin.
*/
@@ -45,43 +62,48 @@ public class KeyguardClockSwitch extends RelativeLayout {
* or not to show it below the alternate clock.
*/
private View mKeyguardStatusArea;
+ /**
+ * Used to select between plugin or default implementations of ClockPlugin interface.
+ */
+ private Extension<ClockPlugin> mClockExtension;
+ /**
+ * Consumer that accepts the a new ClockPlugin implementation when the Extension reloads.
+ */
+ private final Consumer<ClockPlugin> mClockPluginConsumer = plugin -> setClockPlugin(plugin);
+ /**
+ * Maintain state so that a newly connected plugin can be initialized.
+ */
+ private float mDarkAmount;
- private final PluginListener<ClockPlugin> mClockPluginListener =
- new PluginListener<ClockPlugin>() {
+ private final StatusBarStateController.StateListener mStateListener =
+ new StatusBarStateController.StateListener() {
@Override
- public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
- disconnectPlugin();
- View smallClockView = plugin.getView();
- if (smallClockView != null) {
- // For now, assume that the most recently connected plugin is the
- // selected clock face. In the future, the user should be able to
- // pick a clock face from the available plugins.
- mSmallClockFrame.addView(smallClockView, -1,
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- initPluginParams();
- mClockView.setVisibility(View.GONE);
- }
- View bigClockView = plugin.getBigClockView();
- if (bigClockView != null && mBigClockContainer != null) {
- mBigClockContainer.addView(bigClockView);
- mBigClockContainer.setVisibility(View.VISIBLE);
+ public void onStateChanged(int newState) {
+ if (mBigClockContainer == null) {
+ return;
}
- if (!plugin.shouldShowStatusArea()) {
- mKeyguardStatusArea.setVisibility(View.GONE);
+ if (newState == StatusBarState.SHADE) {
+ if (mBigClockContainer.getVisibility() == View.VISIBLE) {
+ mBigClockContainer.setVisibility(View.INVISIBLE);
+ }
+ } else {
+ if (mBigClockContainer.getVisibility() == View.INVISIBLE) {
+ mBigClockContainer.setVisibility(View.VISIBLE);
+ }
}
- mClockPlugin = plugin;
}
+ };
+ private final ContentObserver mContentObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
- public void onPluginDisconnected(ClockPlugin plugin) {
- if (Objects.equals(plugin, mClockPlugin)) {
- disconnectPlugin();
- mClockView.setVisibility(View.VISIBLE);
- mKeyguardStatusArea.setVisibility(View.VISIBLE);
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ if (mClockExtension != null) {
+ mClockExtension.reload();
}
}
- };
+ };
public KeyguardClockSwitch(Context context) {
this(context, null);
@@ -89,6 +111,15 @@ public class KeyguardClockSwitch extends RelativeLayout {
public KeyguardClockSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
+ mLayoutInflater = LayoutInflater.from(context);
+ mContentResolver = context.getContentResolver();
+ }
+
+ /**
+ * Returns if this view is presenting a custom clock, or the default implementation.
+ */
+ public boolean hasCustomClock() {
+ return mClockPlugin != null;
}
@Override
@@ -102,14 +133,88 @@ public class KeyguardClockSwitch extends RelativeLayout {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- Dependency.get(PluginManager.class).addPluginListener(mClockPluginListener,
- ClockPlugin.class);
+ mClockExtension = Dependency.get(ExtensionController.class).newExtension(ClockPlugin.class)
+ .withPlugin(ClockPlugin.class)
+ .withCallback(mClockPluginConsumer)
+ // Using withDefault even though this isn't the default as a workaround.
+ // ExtensionBulider doesn't provide the ability to supply a ClockPlugin
+ // instance based off of the value of a setting. Since multiple "default"
+ // can be provided, using a supplier that changes the settings value.
+ // A null return will cause Extension#reload to look at the next "default"
+ // supplier.
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ BubbleClockController.class.getName(),
+ () -> BubbleClockController.build(mLayoutInflater)))
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ StretchAnalogClockController.class.getName(),
+ () -> StretchAnalogClockController.build(mLayoutInflater)))
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ TypeClockController.class.getName(),
+ () -> TypeClockController.build(mLayoutInflater)))
+ .build();
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
+ false, mContentObserver);
+ Dependency.get(StatusBarStateController.class).addCallback(mStateListener);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- Dependency.get(PluginManager.class).removePluginListener(mClockPluginListener);
+ mClockExtension.destroy();
+ mContentResolver.unregisterContentObserver(mContentObserver);
+ Dependency.get(StatusBarStateController.class).removeCallback(mStateListener);
+ }
+
+ private void setClockPlugin(ClockPlugin plugin) {
+ // Disconnect from existing plugin.
+ if (mClockPlugin != null) {
+ View smallClockView = mClockPlugin.getView();
+ if (smallClockView != null && smallClockView.getParent() == mSmallClockFrame) {
+ mSmallClockFrame.removeView(smallClockView);
+ }
+ if (mBigClockContainer != null) {
+ mBigClockContainer.removeAllViews();
+ mBigClockContainer.setVisibility(View.GONE);
+ }
+ mClockPlugin = null;
+ }
+ if (plugin == null) {
+ mClockView.setVisibility(View.VISIBLE);
+ mKeyguardStatusArea.setVisibility(View.VISIBLE);
+ return;
+ }
+ // Attach small and big clock views to hierarchy.
+ View smallClockView = plugin.getView();
+ if (smallClockView != null) {
+ mSmallClockFrame.addView(smallClockView, -1,
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ mClockView.setVisibility(View.GONE);
+ }
+ View bigClockView = plugin.getBigClockView();
+ if (bigClockView != null && mBigClockContainer != null) {
+ mBigClockContainer.addView(bigClockView);
+ mBigClockContainer.setVisibility(View.VISIBLE);
+ }
+ // Hide default clock.
+ if (!plugin.shouldShowStatusArea()) {
+ mKeyguardStatusArea.setVisibility(View.GONE);
+ }
+ // Initialize plugin parameters.
+ mClockPlugin = plugin;
+ mClockPlugin.setStyle(getPaint().getStyle());
+ mClockPlugin.setTextColor(getCurrentTextColor());
+ mClockPlugin.setDarkAmount(mDarkAmount);
}
/**
@@ -150,10 +255,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
mClockView.setShowCurrentUserTime(showCurrentUserTime);
}
- public void setElegantTextHeight(boolean elegant) {
- mClockView.setElegantTextHeight(elegant);
- }
-
public void setTextSize(int unit, float size) {
mClockView.setTextSize(unit, size);
}
@@ -171,6 +272,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
* @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
*/
public void setDarkAmount(float darkAmount) {
+ mDarkAmount = darkAmount;
if (mClockPlugin != null) {
mClockPlugin.setDarkAmount(darkAmount);
}
@@ -210,32 +312,53 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
+ @VisibleForTesting (otherwise = VisibleForTesting.NONE)
+ Consumer<ClockPlugin> getClockPluginConsumer() {
+ return mClockPluginConsumer;
+ }
+
+ @VisibleForTesting (otherwise = VisibleForTesting.NONE)
+ StatusBarStateController.StateListener getStateListener() {
+ return mStateListener;
+ }
+
/**
- * When plugin changes, set all kept parameters into newer plugin.
+ * Supplier that only gets an instance when a settings value matches expected value.
*/
- private void initPluginParams() {
- if (mClockPlugin != null) {
- mClockPlugin.setStyle(getPaint().getStyle());
- mClockPlugin.setTextColor(getCurrentTextColor());
- }
- }
+ private static class SettingsGattedSupplier implements Supplier<ClockPlugin> {
- private void disconnectPlugin() {
- if (mClockPlugin != null) {
- View smallClockView = mClockPlugin.getView();
- if (smallClockView != null) {
- mSmallClockFrame.removeView(smallClockView);
- }
- if (mBigClockContainer != null) {
- mBigClockContainer.removeAllViews();
- mBigClockContainer.setVisibility(View.GONE);
- }
- mClockPlugin = null;
+ private final ContentResolver mContentResolver;
+ private final String mKey;
+ private final String mValue;
+ private final Supplier<ClockPlugin> mSupplier;
+
+ /**
+ * Constructs a supplier that changes secure setting key against value.
+ *
+ * @param contentResolver Used to look up settings value.
+ * @param key Settings key.
+ * @param value If the setting matches this values that get supplies a ClockPlugin
+ * instance.
+ * @param supplier Supplier of ClockPlugin instance, only used if the setting
+ * matches value.
+ */
+ SettingsGattedSupplier(ContentResolver contentResolver, String key, String value,
+ Supplier<ClockPlugin> supplier) {
+ mContentResolver = contentResolver;
+ mKey = key;
+ mValue = value;
+ mSupplier = supplier;
}
- }
- @VisibleForTesting (otherwise = VisibleForTesting.NONE)
- PluginListener getClockPluginListener() {
- return mClockPluginListener;
+ /**
+ * Returns null if the settings value doesn't match the expected value.
+ *
+ * A null return causes Extension#reload to skip this supplier and move to the next.
+ */
+ @Override
+ public ClockPlugin get() {
+ final String currentValue = Settings.Secure.getString(mContentResolver, mKey);
+ return Objects.equals(currentValue, mValue) ? mSupplier.get() : null;
+ }
}
}