summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.pngbin0 -> 6315 bytes
-rw-r--r--packages/SystemUI/res-keyguard/layout/type_aod_clock.xml23
-rw-r--r--packages/SystemUI/res-keyguard/layout/typographic_clock.xml26
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml102
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java211
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java130
8 files changed, 501 insertions, 0 deletions
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png
new file mode 100644
index 000000000000..2bfd655e37de
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml b/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml
new file mode 100644
index 000000000000..28ff5a253317
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/type_aod_clock.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+ -->
+<com.android.keyguard.clock.ClockLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <include layout="@layout/typographic_clock" />
+</com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/typographic_clock.xml b/packages/SystemUI/res-keyguard/layout/typographic_clock.xml
new file mode 100644
index 000000000000..73bb4b9a0fc9
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/typographic_clock.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+ -->
+<com.android.keyguard.clock.TypographicClock
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/type_clock"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="50dp"
+ android:textAlignment="viewStart"
+ style="@style/widget_big"
+ android:textSize="40dp"
+ />
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 4b6621379b44..91df39056849 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -318,11 +318,113 @@ number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable.
number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
</plurals>
+ <!-- Time displayed on typographic clock face, which displays the time in words.
+ Example:
+
+ It's
+ Four
+ Twenty
+ Nine
+
+ This string requires two arguments: the first in the hours of the time and
+ the second is the minutes of the time. The hours string is obtained from
+ string-array type_clock_hours below and the minutes string is obtained
+ from string-array type_clock_minutes below.
+
+ [CHAR LIMIT=8] -->
+ <plurals name="type_clock_header">
+ <item quantity="one"><annotation name="color">It\u2019s</annotation>\n^1\n^2</item>
+ <item quantity="few"><annotation name="color">It\u2019s</annotation>\n^1\n^2</item>
+ <item quantity="other"><annotation name="color">It\u2019s</annotation>\n^1\n^2</item>
+ </plurals>
+
+ <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=12] -->
+ <string-array name="type_clock_hours">
+ <item>Twelve</item>
+ <item>One</item>
+ <item>Two</item>
+ <item>Three</item>
+ <item>Four</item>
+ <item>Five</item>
+ <item>Six</item>
+ <item>Seven</item>
+ <item>Eight</item>
+ <item>Nine</item>
+ <item>Ten</item>
+ <item>Eleven</item>
+ </string-array>
+
+ <!-- Minutes displayed in words on the typographic clock face. [CHAR LIMIT=20] -->
+ <string-array name="type_clock_minutes">
+ <item>O\u2019Clock</item>
+ <item>Oh One</item>
+ <item>Oh Two</item>
+ <item>Oh Three</item>
+ <item>Oh Four</item>
+ <item>Oh Five</item>
+ <item>Oh Six</item>
+ <item>Oh Seven</item>
+ <item>Oh Eight</item>
+ <item>Oh Nine</item>
+ <item>Ten</item>
+ <item>Eleven</item>
+ <item>Twelve</item>
+ <item>Thirteen</item>
+ <item>Fourteen</item>
+ <item>Fifteen</item>
+ <item>Sixteen</item>
+ <item>Seventeen</item>
+ <item>Eighteen</item>
+ <item>Nineteen</item>
+ <item>Twenty</item>
+ <item>Twenty\nOne</item>
+ <item>Twenty\nTwo</item>
+ <item>Twenty\nThree</item>
+ <item>Twenty\nFour</item>
+ <item>Twenty\nFive</item>
+ <item>Twenty\nSix</item>
+ <item>Twenty\nSeven</item>
+ <item>Twenty\nEight</item>
+ <item>Twenty\nNine</item>
+ <item>Thirty</item>
+ <item>Thirty\nOne</item>
+ <item>Thirty\nTwo</item>
+ <item>Thirty\nThree</item>
+ <item>Thirty\nFour</item>
+ <item>Thirty\nFive</item>
+ <item>Thirty\nSix</item>
+ <item>Thirty\nSeven</item>
+ <item>Thirty\nEight</item>
+ <item>Thirty\nNine</item>
+ <item>Forty</item>
+ <item>Forty\nOne</item>
+ <item>Forty\nTwo</item>
+ <item>Forty\nThree</item>
+ <item>Forty\nFour</item>
+ <item>Forty\nFive</item>
+ <item>Forty\nSix</item>
+ <item>Forty\nSeven</item>
+ <item>Forty\nEight</item>
+ <item>Forty\nNine</item>
+ <item>Fifty</item>
+ <item>Fifty\nOne</item>
+ <item>Fifty\nTwo</item>
+ <item>Fifty\nThree</item>
+ <item>Fifty\nFour</item>
+ <item>Fifty\nFive</item>
+ <item>Fifty\nSix</item>
+ <item>Fifty\nSeven</item>
+ <item>Fifty\nEight</item>
+ <item>Fifty\nNine</item>
+ </string-array>
+
<!-- Name of the "Default" clock face, which is the clock face that will be shown by default. [CHAR LIMIT=15]-->
<string name="clock_title_default">Default</string>
<!-- Name of the "Bubble" clock face, which is an analog clock with hands shaped like large bubbles [CHAR LIMIT=15]-->
<string name="clock_title_bubble">Bubble</string>
<!-- Name of the "Analog" clock face [CHAR LIMIT=15]-->
<string name="clock_title_analog">Analog</string>
+ <!-- Name of the "Typographic" clock face [CHAR LIMIT=15]-->
+ <string name="clock_title_type">Type</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index d44d89e63e8f..ccb495fcec28 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -37,6 +37,7 @@ public class ClockLayout extends FrameLayout {
* Clock face views.
*/
private View mAnalogClock;
+ private View mTypeClock;
/**
* Pixel shifting amplitudes used to prevent screen burn-in.
@@ -62,6 +63,7 @@ public class ClockLayout extends FrameLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mAnalogClock = findViewById(R.id.analog_clock);
+ mTypeClock = findViewById(R.id.type_clock);
// Get pixel shifting X, Y amplitudes from resources.
Resources resources = getResources();
@@ -105,5 +107,11 @@ public class ClockLayout extends FrameLayout {
mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
+ ANALOG_CLOCK_SHIFT_FACTOR * offsetY);
}
+
+ // Put the typographic clock part way down the screen.
+ if (mTypeClock != null) {
+ mTypeClock.setX(offsetX);
+ mTypeClock.setY(0.2f * getHeight() + offsetY);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 2200b22b8b27..fd5c99e75a1f 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -150,6 +150,7 @@ public final class ClockManager {
LayoutInflater layoutInflater = injectionInflater.injectable(LayoutInflater.from(context));
addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
+ addBuiltinClock(() -> new TypeClockController(res, layoutInflater, colorExtractor));
// Store the size of the display for generation of clock preview.
DisplayMetrics dm = res.getDisplayMetrics();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
new file mode 100644
index 000000000000..890ba1da0911
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2019 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.keyguard.clock;
+
+import android.app.WallpaperManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Paint.Style;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.R;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.ClockPlugin;
+
+import java.util.TimeZone;
+
+/**
+ * Plugin for a custom Typographic clock face that displays the time in words.
+ */
+public class TypeClockController implements ClockPlugin {
+
+ /**
+ * Resources used to get title and thumbnail.
+ */
+ private final Resources mResources;
+
+ /**
+ * LayoutInflater used to inflate custom clock views.
+ */
+ private final LayoutInflater mLayoutInflater;
+
+ /**
+ * Extracts accent color from wallpaper.
+ */
+ private final SysuiColorExtractor mColorExtractor;
+
+ /**
+ * Computes preferred position of clock.
+ */
+ private final SmallClockPosition mClockPosition;
+
+ /**
+ * Renders preview from clock view.
+ */
+ private final ViewPreviewer mRenderer = new ViewPreviewer();
+
+ /**
+ * Custom clock shown on AOD screen and behind stack scroller on lock.
+ */
+ private View mView;
+ private TypographicClock mTypeClock;
+
+ /**
+ * Small clock shown on lock screen above stack scroller.
+ */
+ private TypographicClock mLockClock;
+
+ /**
+ * Controller for transition into dark state.
+ */
+ private CrossFadeDarkController mDarkController;
+
+ /**
+ * Create a TypeClockController instance.
+ *
+ * @param res Resources contains title and thumbnail.
+ * @param inflater Inflater used to inflate custom clock views.
+ * @param colorExtractor Extracts accent color from wallpaper.
+ */
+ TypeClockController(Resources res, LayoutInflater inflater,
+ SysuiColorExtractor colorExtractor) {
+ mResources = res;
+ mLayoutInflater = inflater;
+ mColorExtractor = colorExtractor;
+ mClockPosition = new SmallClockPosition(res);
+ }
+
+ private void createViews() {
+ mView = mLayoutInflater.inflate(R.layout.type_aod_clock, null);
+ mTypeClock = mView.findViewById(R.id.type_clock);
+
+ // For now, this view is used to hide the default digital clock.
+ // Need better transition to lock screen.
+ mLockClock = (TypographicClock) mLayoutInflater.inflate(R.layout.typographic_clock, null);
+ mLockClock.setVisibility(View.GONE);
+
+ mDarkController = new CrossFadeDarkController(mView, mLockClock);
+ }
+
+ @Override
+ public void onDestroyView() {
+ mView = null;
+ mTypeClock = null;
+ mLockClock = null;
+ mDarkController = null;
+ }
+
+ @Override
+ public String getName() {
+ return "type";
+ }
+
+ @Override
+ public String getTitle() {
+ return mResources.getString(R.string.clock_title_type);
+ }
+
+ @Override
+ public Bitmap getThumbnail() {
+ return BitmapFactory.decodeResource(mResources, R.drawable.type_thumbnail);
+ }
+
+ @Override
+ public Bitmap getPreview(int width, int height) {
+
+ // Use the big clock view for the preview
+ View view = getBigClockView();
+
+ // Initialize state of plugin before generating preview.
+ setDarkAmount(1f);
+ setTextColor(Color.WHITE);
+ ColorExtractor.GradientColors colors = mColorExtractor.getColors(
+ WallpaperManager.FLAG_LOCK);
+ setColorPalette(colors.supportsDarkText(), colors.getColorPalette());
+ onTimeTick();
+
+ return mRenderer.createPreview(view, width, height);
+ }
+
+ @Override
+ public View getView() {
+ if (mLockClock == null) {
+ createViews();
+ }
+ return mLockClock;
+ }
+
+ @Override
+ public View getBigClockView() {
+ if (mView == null) {
+ createViews();
+ }
+ return mView;
+ }
+
+ @Override
+ public int getPreferredY(int totalHeight) {
+ return mClockPosition.getPreferredY();
+ }
+
+ @Override
+ public void setStyle(Style style) {}
+
+ @Override
+ public void setTextColor(int color) {
+ mTypeClock.setTextColor(color);
+ mLockClock.setTextColor(color);
+ }
+
+ @Override
+ public void setColorPalette(boolean supportsDarkText, int[] colorPalette) {
+ if (colorPalette == null || colorPalette.length == 0) {
+ return;
+ }
+ final int color = colorPalette[Math.max(0, colorPalette.length - 5)];
+ mTypeClock.setClockColor(color);
+ mLockClock.setClockColor(color);
+ }
+
+ @Override
+ public void onTimeTick() {
+ mTypeClock.onTimeChanged();
+ mLockClock.onTimeChanged();
+ }
+
+ @Override
+ public void setDarkAmount(float darkAmount) {
+ if (mDarkController != null) {
+ mDarkController.setDarkAmount(darkAmount);
+ }
+ mClockPosition.setDarkAmount(darkAmount);
+ }
+
+ @Override
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mTypeClock.onTimeZoneChanged(timeZone);
+ mLockClock.onTimeZoneChanged(timeZone);
+ }
+
+ @Override
+ public boolean shouldShowStatusArea() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
new file mode 100644
index 000000000000..c84c598498d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 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.keyguard.clock;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.text.Annotation;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannedString;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.text.style.ForegroundColorSpan;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Clock that presents the time in words.
+ */
+public class TypographicClock extends TextView {
+
+ private static final String ANNOTATION_COLOR = "color";
+
+ private final Resources mResources;
+ private final String[] mHours;
+ private final String[] mMinutes;
+ private int mAccentColor;
+ private final Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
+ private String mDescFormat;
+ private TimeZone mTimeZone;
+
+ public TypographicClock(Context context) {
+ this(context, null);
+ }
+
+ public TypographicClock(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern();
+ mResources = context.getResources();
+ mHours = mResources.getStringArray(R.array.type_clock_hours);
+ mMinutes = mResources.getStringArray(R.array.type_clock_minutes);
+ mAccentColor = mResources.getColor(R.color.typeClockAccentColor, null);
+ }
+
+ /**
+ * Call when the time changes to update the text of the time.
+ */
+ public void onTimeChanged() {
+ mTime.setTimeInMillis(System.currentTimeMillis());
+ setContentDescription(DateFormat.format(mDescFormat, mTime));
+ final int hour = mTime.get(Calendar.HOUR) % 12;
+ final int minute = mTime.get(Calendar.MINUTE) % 60;
+
+ // Get the quantity based on the hour for languages like Portuguese and Czech.
+ SpannedString typeTemplate = (SpannedString) mResources.getQuantityText(
+ R.plurals.type_clock_header, hour);
+
+ // Find the "color" annotation and set the foreground color to the accent color.
+ Annotation[] annotations = typeTemplate.getSpans(0, typeTemplate.length(),
+ Annotation.class);
+ SpannableString spanType = new SpannableString(typeTemplate);
+ for (int i = 0; i < annotations.length; i++) {
+ Annotation annotation = annotations[i];
+ String key = annotation.getValue();
+ if (ANNOTATION_COLOR.equals(key)) {
+ spanType.setSpan(new ForegroundColorSpan(mAccentColor),
+ spanType.getSpanStart(annotation), spanType.getSpanEnd(annotation),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+
+ setText(TextUtils.expandTemplate(spanType, mHours[hour], mMinutes[minute]));
+ }
+
+ /**
+ * Call when the time zone has changed to update clock time.
+ *
+ * @param timeZone The updated time zone that will be used.
+ */
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mTimeZone = timeZone;
+ mTime.setTimeZone(timeZone);
+ }
+
+ /**
+ * Sets the accent color used on the clock face.
+ */
+ public void setClockColor(int color) {
+ mAccentColor = color;
+ onTimeChanged();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+ onTimeChanged();
+ }
+
+ /**
+ * Overriding hasOverlappingRendering as false to improve performance of crossfading.
+ */
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+}