Custom message in AoD
Optional message that lives under the clock and also
in AoD. Implemented using a slice.
Test: launch sysui, look at the date in AoD
Test: runtest -x packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
Change-Id: I9dbc827bd48c6a3d1b25b0a481ffaecc0dd37f25
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
new file mode 100644
index 0000000..03018f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.icu.text.DateFormat;
+import android.icu.text.DisplayContext;
+import android.net.Uri;
+import android.os.Handler;
+import android.app.slice.Slice;
+import android.app.slice.SliceProvider;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Simple Slice provider that shows the current date.
+ */
+public class KeyguardSliceProvider extends SliceProvider {
+
+ public static final String KEYGUARD_SLICE_URI = "content://com.android.systemui.keyguard/main";
+
+ private final Date mCurrentTime = new Date();
+ protected final Uri mSliceUri;
+ private final Handler mHandler;
+ private String mDatePattern;
+ private DateFormat mDateFormat;
+ private String mLastText;
+ private boolean mRegistered;
+ private boolean mRegisteredEveryMinute;
+
+ /**
+ * Receiver responsible for time ticking and updating the date format.
+ */
+ @VisibleForTesting
+ final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_TIME_TICK.equals(action)
+ || Intent.ACTION_DATE_CHANGED.equals(action)
+ || Intent.ACTION_TIME_CHANGED.equals(action)
+ || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
+ || Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+ if (Intent.ACTION_LOCALE_CHANGED.equals(action)
+ || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+ // need to get a fresh date format
+ mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
+ }
+ mHandler.post(KeyguardSliceProvider.this::updateClock);
+ }
+ }
+ };
+
+ public KeyguardSliceProvider() {
+ this(new Handler());
+ }
+
+ @VisibleForTesting
+ KeyguardSliceProvider(Handler handler) {
+ mHandler = handler;
+ mSliceUri = Uri.parse(KEYGUARD_SLICE_URI);
+ }
+
+ @Override
+ public Slice onBindSlice(Uri sliceUri) {
+ return new Slice.Builder(sliceUri).addText(mLastText, Slice.HINT_TITLE).build();
+ }
+
+ @Override
+ public boolean onCreate() {
+
+ mDatePattern = getContext().getString(R.string.system_ui_date_pattern);
+
+ registerClockUpdate(false /* everyMinute */);
+ updateClock();
+ return true;
+ }
+
+ protected void registerClockUpdate(boolean everyMinute) {
+ if (mRegistered) {
+ if (mRegisteredEveryMinute == everyMinute) {
+ return;
+ } else {
+ unregisterClockUpdate();
+ }
+ }
+
+ IntentFilter filter = new IntentFilter();
+ if (everyMinute) {
+ filter.addAction(Intent.ACTION_TIME_TICK);
+ }
+ filter.addAction(Intent.ACTION_DATE_CHANGED);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ filter.addAction(Intent.ACTION_LOCALE_CHANGED);
+ getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,
+ null /* scheduler */);
+ mRegistered = true;
+ mRegisteredEveryMinute = everyMinute;
+ }
+
+ protected void unregisterClockUpdate() {
+ if (!mRegistered) {
+ return;
+ }
+ getContext().unregisterReceiver(mIntentReceiver);
+ mRegistered = false;
+ }
+
+ @VisibleForTesting
+ boolean isRegistered() {
+ return mRegistered;
+ }
+
+ protected void updateClock() {
+ final String text = getFormattedDate();
+ if (!text.equals(mLastText)) {
+ mLastText = text;
+ getContext().getContentResolver().notifyChange(mSliceUri, null /* observer */);
+ }
+ }
+
+ protected String getFormattedDate() {
+ if (mDateFormat == null) {
+ final Locale l = Locale.getDefault();
+ DateFormat format = DateFormat.getInstanceForSkeleton(mDatePattern, l);
+ format.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE);
+ mDateFormat = format;
+ }
+ mCurrentTime.setTime(System.currentTimeMillis());
+ return mDateFormat.format(mCurrentTime);
+ }
+
+ @VisibleForTesting
+ void cleanDateFormat() {
+ mDateFormat = null;
+ }
+}