Merge "Switch widgets away from android.text.format.Time" am: db31e6d07a am: 8d96e17940

am: 19d4f4eb32

Change-Id: I65336bde8f7730cb3aea8f436d5e301d808c52e6
This commit is contained in:
Neil Fuller
2019-07-09 02:05:28 -07:00
committed by android-build-merger
2 changed files with 90 additions and 69 deletions

View File

@@ -26,12 +26,14 @@ import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.RemoteViews.RemoteView; import android.widget.RemoteViews.RemoteView;
import java.util.TimeZone; import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
/** /**
* This widget display an analogic clock with two hands for hours and * This widget display an analogic clock with two hands for hours and
@@ -45,7 +47,7 @@ import java.util.TimeZone;
@RemoteView @RemoteView
@Deprecated @Deprecated
public class AnalogClock extends View { public class AnalogClock extends View {
private Time mCalendar; private Clock mClock;
@UnsupportedAppUsage @UnsupportedAppUsage
private Drawable mHourHand; private Drawable mHourHand;
@@ -99,7 +101,7 @@ public class AnalogClock extends View {
mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute); mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
} }
mCalendar = new Time(); mClock = Clock.systemDefaultZone();
mDialWidth = mDial.getIntrinsicWidth(); mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight(); mDialHeight = mDial.getIntrinsicHeight();
@@ -132,7 +134,7 @@ public class AnalogClock extends View {
// in the main thread, therefore the receiver can't run before this method returns. // in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time // The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = new Time(); mClock = Clock.systemDefaultZone();
// Make sure we update to the current time // Make sure we update to the current time
onTimeChanged(); onTimeChanged();
@@ -241,17 +243,18 @@ public class AnalogClock extends View {
} }
private void onTimeChanged() { private void onTimeChanged() {
mCalendar.setToNow(); long nowMillis = mClock.millis();
LocalDateTime localDateTime = toLocalDateTime(nowMillis, mClock.getZone());
int hour = mCalendar.hour; int hour = localDateTime.getHour();
int minute = mCalendar.minute; int minute = localDateTime.getMinute();
int second = mCalendar.second; int second = localDateTime.getSecond();
mMinutes = minute + second / 60.0f; mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f; mHour = hour + mMinutes / 60.0f;
mChanged = true; mChanged = true;
updateContentDescription(mCalendar); updateContentDescription(nowMillis);
} }
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -259,7 +262,7 @@ public class AnalogClock extends View {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) { if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone"); String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID()); mClock = Clock.system(ZoneId.of(tz));
} }
onTimeChanged(); onTimeChanged();
@@ -268,10 +271,17 @@ public class AnalogClock extends View {
} }
}; };
private void updateContentDescription(Time time) { private void updateContentDescription(long timeMillis) {
final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR; final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR;
String contentDescription = DateUtils.formatDateTime(mContext, String contentDescription = DateUtils.formatDateTime(mContext, timeMillis, flags);
time.toMillis(false), flags);
setContentDescription(contentDescription); setContentDescription(contentDescription);
} }
private static LocalDateTime toLocalDateTime(long timeMillis, ZoneId zoneId) {
// java.time types like LocalDateTime / Instant can support the full range of "long millis"
// with room to spare so we do not need to worry about overflow / underflow and the
// resulting exceptions while the input to this class is a long.
Instant instant = Instant.ofEpochMilli(timeMillis);
return LocalDateTime.ofInstant(instant, zoneId);
}
} }

View File

@@ -20,7 +20,6 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.YEAR_IN_MILLIS; import static android.text.format.DateUtils.YEAR_IN_MILLIS;
import static android.text.format.Time.getJulianDay;
import android.annotation.UnsupportedAppUsage; import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread; import android.app.ActivityThread;
@@ -32,7 +31,6 @@ import android.content.res.Configuration;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.os.Handler; import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inspector.InspectableProperty; import android.view.inspector.InspectableProperty;
@@ -41,10 +39,14 @@ import android.widget.RemoteViews.RemoteView;
import com.android.internal.R; import com.android.internal.R;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.JulianFields;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.TimeZone;
// //
// TODO // TODO
@@ -63,8 +65,9 @@ public class DateTimeView extends TextView {
private static final int SHOW_TIME = 0; private static final int SHOW_TIME = 0;
private static final int SHOW_MONTH_DAY_YEAR = 1; private static final int SHOW_MONTH_DAY_YEAR = 1;
Date mTime; private long mTimeMillis;
long mTimeMillis; // The LocalDateTime equivalent of mTimeMillis but truncated to minute, i.e. no seconds / nanos.
private LocalDateTime mLocalTime;
int mLastDisplay = -1; int mLastDisplay = -1;
DateFormat mLastFormat; DateFormat mLastFormat;
@@ -128,11 +131,10 @@ public class DateTimeView extends TextView {
@android.view.RemotableViewMethod @android.view.RemotableViewMethod
@UnsupportedAppUsage @UnsupportedAppUsage
public void setTime(long time) { public void setTime(long timeMillis) {
Time t = new Time(); mTimeMillis = timeMillis;
t.set(time); LocalDateTime dateTime = toLocalDateTime(timeMillis, ZoneId.systemDefault());
mTimeMillis = t.toMillis(false); mLocalTime = dateTime.withSecond(0);
mTime = new Date(t.year-1900, t.month, t.monthDay, t.hour, t.minute, 0);
update(); update();
} }
@@ -165,7 +167,7 @@ public class DateTimeView extends TextView {
@UnsupportedAppUsage @UnsupportedAppUsage
void update() { void update() {
if (mTime == null || getVisibility() == GONE) { if (mLocalTime == null || getVisibility() == GONE) {
return; return;
} }
if (mShowRelativeTime) { if (mShowRelativeTime) {
@@ -174,31 +176,27 @@ public class DateTimeView extends TextView {
} }
int display; int display;
Date time = mTime; ZoneId zoneId = ZoneId.systemDefault();
Time t = new Time(); // localTime is the local time for mTimeMillis but at zero seconds past the minute.
t.set(mTimeMillis); LocalDateTime localTime = mLocalTime;
t.second = 0; LocalDateTime localStartOfDay =
LocalDateTime.of(localTime.toLocalDate(), LocalTime.MIDNIGHT);
LocalDateTime localTomorrowStartOfDay = localStartOfDay.plusDays(1);
// now is current local time but at zero seconds past the minute.
LocalDateTime localNow = LocalDateTime.now(zoneId).withSecond(0);
t.hour -= 12; long twelveHoursBefore = toEpochMillis(localTime.minusHours(12), zoneId);
long twelveHoursBefore = t.toMillis(false); long twelveHoursAfter = toEpochMillis(localTime.plusHours(12), zoneId);
t.hour += 12; long midnightBefore = toEpochMillis(localStartOfDay, zoneId);
long twelveHoursAfter = t.toMillis(false); long midnightAfter = toEpochMillis(localTomorrowStartOfDay, zoneId);
t.hour = 0; long time = toEpochMillis(localTime, zoneId);
t.minute = 0; long now = toEpochMillis(localNow, zoneId);
long midnightBefore = t.toMillis(false);
t.monthDay++;
long midnightAfter = t.toMillis(false);
long nowMillis = System.currentTimeMillis();
t.set(nowMillis);
t.second = 0;
nowMillis = t.normalize(false);
// Choose the display mode // Choose the display mode
choose_display: { choose_display: {
if ((nowMillis >= midnightBefore && nowMillis < midnightAfter) if ((now >= midnightBefore && now < midnightAfter)
|| (nowMillis >= twelveHoursBefore && nowMillis < twelveHoursAfter)) { || (now >= twelveHoursBefore && now < twelveHoursAfter)) {
display = SHOW_TIME; display = SHOW_TIME;
break choose_display; break choose_display;
} }
@@ -227,7 +225,7 @@ public class DateTimeView extends TextView {
} }
// Set the text // Set the text
String text = format.format(mTime); String text = format.format(new Date(time));
setText(text); setText(text);
// Schedule the next update // Schedule the next update
@@ -236,7 +234,7 @@ public class DateTimeView extends TextView {
mUpdateTimeMillis = twelveHoursAfter > midnightAfter ? twelveHoursAfter : midnightAfter; mUpdateTimeMillis = twelveHoursAfter > midnightAfter ? twelveHoursAfter : midnightAfter;
} else { } else {
// Currently showing the date // Currently showing the date
if (mTimeMillis < nowMillis) { if (mTimeMillis < now) {
// If the time is in the past, don't schedule an update // If the time is in the past, don't schedule an update
mUpdateTimeMillis = 0; mUpdateTimeMillis = 0;
} else { } else {
@@ -277,15 +275,18 @@ public class DateTimeView extends TextView {
millisIncrease = HOUR_IN_MILLIS; millisIncrease = HOUR_IN_MILLIS;
} else if (duration < YEAR_IN_MILLIS) { } else if (duration < YEAR_IN_MILLIS) {
// In weird cases it can become 0 because of daylight savings // In weird cases it can become 0 because of daylight savings
TimeZone timeZone = TimeZone.getDefault(); LocalDateTime localDateTime = mLocalTime;
count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1); ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localNow = toLocalDateTime(now, zoneId);
count = Math.max(Math.abs(dayDistance(localDateTime, localNow)), 1);
result = String.format(getContext().getResources().getQuantityString(past result = String.format(getContext().getResources().getQuantityString(past
? com.android.internal.R.plurals.duration_days_shortest ? com.android.internal.R.plurals.duration_days_shortest
: com.android.internal.R.plurals.duration_days_shortest_future, : com.android.internal.R.plurals.duration_days_shortest_future,
count), count),
count); count);
if (past || count != 1) { if (past || count != 1) {
mUpdateTimeMillis = computeNextMidnight(timeZone); mUpdateTimeMillis = computeNextMidnight(localNow, zoneId);
millisIncrease = -1; millisIncrease = -1;
} else { } else {
millisIncrease = DAY_IN_MILLIS; millisIncrease = DAY_IN_MILLIS;
@@ -311,18 +312,13 @@ public class DateTimeView extends TextView {
} }
/** /**
* @param timeZone the timezone we are in * Returns the epoch millis for the next midnight in the specified timezone.
* @return the timepoint in millis at UTC at midnight in the current timezone
*/ */
private long computeNextMidnight(TimeZone timeZone) { private static long computeNextMidnight(LocalDateTime time, ZoneId zoneId) {
Calendar c = Calendar.getInstance(); // This ignores the chance of overflow: it should never happen.
c.setTimeZone(timeZone); LocalDate tomorrow = time.toLocalDate().plusDays(1);
c.add(Calendar.DAY_OF_MONTH, 1); LocalDateTime nextMidnight = LocalDateTime.of(tomorrow, LocalTime.MIDNIGHT);
c.set(Calendar.HOUR_OF_DAY, 0); return toEpochMillis(nextMidnight, zoneId);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return c.getTimeInMillis();
} }
@Override @Override
@@ -340,11 +336,10 @@ public class DateTimeView extends TextView {
com.android.internal.R.string.now_string_shortest); com.android.internal.R.string.now_string_shortest);
} }
// Return the date difference for the two times in a given timezone. // Return the number of days between the two dates.
private static int dayDistance(TimeZone timeZone, long startTime, private static int dayDistance(LocalDateTime start, LocalDateTime end) {
long endTime) { return (int) (end.getLong(JulianFields.JULIAN_DAY)
return getJulianDay(endTime, timeZone.getOffset(endTime) / 1000) - start.getLong(JulianFields.JULIAN_DAY));
- getJulianDay(startTime, timeZone.getOffset(startTime) / 1000);
} }
private DateFormat getTimeFormat() { private DateFormat getTimeFormat() {
@@ -389,8 +384,11 @@ public class DateTimeView extends TextView {
count); count);
} else if (duration < YEAR_IN_MILLIS) { } else if (duration < YEAR_IN_MILLIS) {
// In weird cases it can become 0 because of daylight savings // In weird cases it can become 0 because of daylight savings
TimeZone timeZone = TimeZone.getDefault(); LocalDateTime localDateTime = mLocalTime;
count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1); ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localNow = toLocalDateTime(now, zoneId);
count = Math.max(Math.abs(dayDistance(localDateTime, localNow)), 1);
result = String.format(getContext().getResources().getQuantityString(past result = String.format(getContext().getResources().getQuantityString(past
? com.android.internal. ? com.android.internal.
R.plurals.duration_days_relative R.plurals.duration_days_relative
@@ -526,4 +524,17 @@ public class DateTimeView extends TextView {
} }
} }
} }
private static LocalDateTime toLocalDateTime(long timeMillis, ZoneId zoneId) {
// java.time types like LocalDateTime / Instant can support the full range of "long millis"
// with room to spare so we do not need to worry about overflow / underflow and the rsulting
// exceptions while the input to this class is a long.
Instant instant = Instant.ofEpochMilli(timeMillis);
return LocalDateTime.ofInstant(instant, zoneId);
}
private static long toEpochMillis(LocalDateTime time, ZoneId zoneId) {
Instant instant = time.toInstant(zoneId.getRules().getOffset(time));
return instant.toEpochMilli();
}
} }