From 06c5f8a768bcd4f7b6441f7525bd5c639399fc76 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 4 Dec 2012 09:53:44 -0800 Subject: [PATCH] Examine widget hierarchy to find clocks. When switching to a widget, examine its hierarchy to determine if it contains TextClocks that show hour and minute for the local timezone. If so, hide the status bar clock. Doesn't fix closing walls. Bug: 7667638 Change-Id: I1e2c40345c9e5eb0193efd70838c7ca9f779190b --- core/java/android/text/format/DateFormat.java | 12 +++- core/java/android/widget/TextClock.java | 10 +++ .../android/text/format/DateFormatTest.java | 39 +++++++++++ .../impl/keyguard/KeyguardWidgetPager.java | 66 ++++++++++++++++++- 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 core/tests/coretests/src/android/text/format/DateFormatTest.java diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 3c984b51fa4d1..352cb22a3d6cb 100644 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -452,6 +452,16 @@ public class DateFormat { * @hide */ public static boolean hasSeconds(CharSequence inFormat) { + return hasDesignator(inFormat, SECONDS); + } + + /** + * Test if a format string contains the given designator. Always returns + * {@code false} if the input format is {@code null}. + * + * @hide + */ + public static boolean hasDesignator(CharSequence inFormat, char designator) { if (inFormat == null) return false; final int length = inFormat.length(); @@ -465,7 +475,7 @@ public class DateFormat { if (c == QUOTE) { count = skipQuotedText(inFormat, i, length); - } else if (c == SECONDS) { + } else if (c == designator) { return true; } } diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java index 290d9b5b4a52e..5bf21c0d82f7d 100644 --- a/core/java/android/widget/TextClock.java +++ b/core/java/android/widget/TextClock.java @@ -385,6 +385,16 @@ public class TextClock extends TextView { chooseFormat(true); } + /** + * Returns the current format string. Always valid after constructor has + * finished, and will never be {@code null}. + * + * @hide + */ + public CharSequence getFormat() { + return mFormat; + } + /** * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()} * depending on whether the user has selected 24-hour format. diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java new file mode 100644 index 0000000000000..5f36cfd12b22e --- /dev/null +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 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 android.text.format; + +import android.test.suitebuilder.annotation.SmallTest; + +import junit.framework.TestCase; + +public class DateFormatTest extends TestCase { + @SmallTest + public void testHasDesignator() throws Exception { + assertTrue(DateFormat.hasDesignator("hh:mm:ss", DateFormat.MINUTE)); + assertTrue(DateFormat.hasDesignator("myyyy", DateFormat.MINUTE)); + assertTrue(DateFormat.hasDesignator("mmm", DateFormat.MINUTE)); + + assertFalse(DateFormat.hasDesignator("hh:MM:ss", DateFormat.MINUTE)); + } + + @SmallTest + public void testHasDesignatorEscaped() throws Exception { + assertTrue(DateFormat.hasDesignator("hh:mm 'LOL'", DateFormat.MINUTE)); + + assertFalse(DateFormat.hasDesignator("hh:mm 'yyyy'", DateFormat.YEAR)); + } +} diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index b4fe0c7aaca48..ad5e25706ba8a 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -27,6 +27,7 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.os.Handler; import android.os.HandlerThread; +import android.text.format.DateFormat; import android.util.AttributeSet; import android.util.Slog; import android.view.Gravity; @@ -38,10 +39,12 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; +import android.widget.TextClock; import com.android.internal.widget.LockPatternUtils; import java.util.ArrayList; +import java.util.TimeZone; public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener, OnLongClickListener, ChallengeLayout.OnBouncerStateChangedListener { @@ -51,6 +54,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit protected static float OVERSCROLL_MAX_ROTATION = 30; private static final boolean PERFORM_OVERSCROLL_ROTATION = true; + private static final int FLAG_HAS_LOCAL_HOUR = 0x1; + private static final int FLAG_HAS_LOCAL_MINUTE = 0x2; + protected KeyguardViewStateManager mViewStateManager; private LockPatternUtils mLockPatternUtils; @@ -131,16 +137,21 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit @Override public void onPageSwitched(View newPage, int newPageIndex) { - boolean showingStatusWidget = false; + boolean showingClock = false; if (newPage instanceof ViewGroup) { ViewGroup vg = (ViewGroup) newPage; if (vg.getChildAt(0) instanceof KeyguardStatusView) { - showingStatusWidget = true; + showingClock = true; } } + if (newPage != null && + findClockInHierarchy(newPage) == (FLAG_HAS_LOCAL_HOUR | FLAG_HAS_LOCAL_MINUTE)) { + showingClock = true; + } + // Disable the status bar clock if we're showing the default status widget - if (showingStatusWidget) { + if (showingClock) { setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK); } else { setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK); @@ -857,4 +868,53 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) { return !isCameraPage(childIndex) && super.shouldSetTopAlignedPivotForWidget(childIndex); } + + /** + * Search given {@link View} hierarchy for {@link TextClock} instances that + * show various time components. Returns combination of + * {@link #FLAG_HAS_LOCAL_HOUR} and {@link #FLAG_HAS_LOCAL_MINUTE}. + */ + private static int findClockInHierarchy(View view) { + if (view instanceof TextClock) { + return getClockFlags((TextClock) view); + } else if (view instanceof ViewGroup) { + int flags = 0; + final ViewGroup group = (ViewGroup) view; + final int size = group.getChildCount(); + for (int i = 0; i < size; i++) { + flags |= findClockInHierarchy(group.getChildAt(i)); + } + return flags; + } else { + return 0; + } + } + + /** + * Return combination of {@link #FLAG_HAS_LOCAL_HOUR} and + * {@link #FLAG_HAS_LOCAL_MINUTE} describing the time represented described + * by the given {@link TextClock}. + */ + private static int getClockFlags(TextClock clock) { + int flags = 0; + + final String timeZone = clock.getTimeZone(); + if (timeZone != null && !TimeZone.getDefault().equals(TimeZone.getTimeZone(timeZone))) { + // Ignore clocks showing another timezone + return 0; + } + + final CharSequence format = clock.getFormat(); + final char hour = clock.is24HourModeEnabled() ? DateFormat.HOUR_OF_DAY + : DateFormat.HOUR; + + if (DateFormat.hasDesignator(format, hour)) { + flags |= FLAG_HAS_LOCAL_HOUR; + } + if (DateFormat.hasDesignator(format, DateFormat.MINUTE)) { + flags |= FLAG_HAS_LOCAL_MINUTE; + } + + return flags; + } }