Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19d4f4eb authored by Neil Fuller's avatar Neil Fuller Committed by android-build-merger
Browse files

Merge "Switch widgets away from android.text.format.Time" am: db31e6d0

am: 8d96e179

Change-Id: I497266b9a4805b356ebab6deca215020627cfd6e
parents 40b8170b 8d96e179
Loading
Loading
Loading
Loading
+24 −14
Original line number Diff line number Diff line
@@ -26,12 +26,14 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
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
@@ -45,7 +47,7 @@ import java.util.TimeZone;
@RemoteView
@Deprecated
public class AnalogClock extends View {
    private Time mCalendar;
    private Clock mClock;

    @UnsupportedAppUsage
    private Drawable mHourHand;
@@ -99,7 +101,7 @@ public class AnalogClock extends View {
            mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
        }

        mCalendar = new Time();
        mClock = Clock.systemDefaultZone();

        mDialWidth = mDial.getIntrinsicWidth();
        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.

        // 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
        onTimeChanged();
@@ -241,17 +243,18 @@ public class AnalogClock extends View {
    }

    private void onTimeChanged() {
        mCalendar.setToNow();
        long nowMillis = mClock.millis();
        LocalDateTime localDateTime = toLocalDateTime(nowMillis, mClock.getZone());

        int hour = mCalendar.hour;
        int minute = mCalendar.minute;
        int second = mCalendar.second;
        int hour = localDateTime.getHour();
        int minute = localDateTime.getMinute();
        int second = localDateTime.getSecond();

        mMinutes = minute + second / 60.0f;
        mHour = hour + mMinutes / 60.0f;
        mChanged = true;

        updateContentDescription(mCalendar);
        updateContentDescription(nowMillis);
    }

    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -259,7 +262,7 @@ public class AnalogClock extends View {
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
                String tz = intent.getStringExtra("time-zone");
                mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
                mClock = Clock.system(ZoneId.of(tz));
            }

            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;
        String contentDescription = DateUtils.formatDateTime(mContext,
                time.toMillis(false), flags);
        String contentDescription = DateUtils.formatDateTime(mContext, timeMillis, flags);
        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);
    }
}
+68 −57
Original line number Diff line number Diff line
@@ -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.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
import static android.text.format.Time.getJulianDay;

import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
@@ -32,7 +31,6 @@ import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inspector.InspectableProperty;
@@ -41,10 +39,14 @@ import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;

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.Calendar;
import java.util.Date;
import java.util.TimeZone;

//
// TODO
@@ -63,8 +65,9 @@ public class DateTimeView extends TextView {
    private static final int SHOW_TIME = 0;
    private static final int SHOW_MONTH_DAY_YEAR = 1;

    Date mTime;
    long mTimeMillis;
    private long mTimeMillis;
    // The LocalDateTime equivalent of mTimeMillis but truncated to minute, i.e. no seconds / nanos.
    private LocalDateTime mLocalTime;

    int mLastDisplay = -1;
    DateFormat mLastFormat;
@@ -128,11 +131,10 @@ public class DateTimeView extends TextView {

    @android.view.RemotableViewMethod
    @UnsupportedAppUsage
    public void setTime(long time) {
        Time t = new Time();
        t.set(time);
        mTimeMillis = t.toMillis(false);
        mTime = new Date(t.year-1900, t.month, t.monthDay, t.hour, t.minute, 0);
    public void setTime(long timeMillis) {
        mTimeMillis = timeMillis;
        LocalDateTime dateTime = toLocalDateTime(timeMillis, ZoneId.systemDefault());
        mLocalTime = dateTime.withSecond(0);
        update();
    }

@@ -165,7 +167,7 @@ public class DateTimeView extends TextView {

    @UnsupportedAppUsage
    void update() {
        if (mTime == null || getVisibility() == GONE) {
        if (mLocalTime == null || getVisibility() == GONE) {
            return;
        }
        if (mShowRelativeTime) {
@@ -174,31 +176,27 @@ public class DateTimeView extends TextView {
        }

        int display;
        Date time = mTime;

        Time t = new Time();
        t.set(mTimeMillis);
        t.second = 0;

        t.hour -= 12;
        long twelveHoursBefore = t.toMillis(false);
        t.hour += 12;
        long twelveHoursAfter = t.toMillis(false);
        t.hour = 0;
        t.minute = 0;
        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);
        ZoneId zoneId = ZoneId.systemDefault();

        // localTime is the local time for mTimeMillis but at zero seconds past the minute.
        LocalDateTime localTime = mLocalTime;
        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);

        long twelveHoursBefore = toEpochMillis(localTime.minusHours(12), zoneId);
        long twelveHoursAfter = toEpochMillis(localTime.plusHours(12), zoneId);
        long midnightBefore = toEpochMillis(localStartOfDay, zoneId);
        long midnightAfter = toEpochMillis(localTomorrowStartOfDay, zoneId);
        long time = toEpochMillis(localTime, zoneId);
        long now = toEpochMillis(localNow, zoneId);

        // Choose the display mode
        choose_display: {
            if ((nowMillis >= midnightBefore && nowMillis < midnightAfter)
                    || (nowMillis >= twelveHoursBefore && nowMillis < twelveHoursAfter)) {
            if ((now >= midnightBefore && now < midnightAfter)
                    || (now >= twelveHoursBefore && now < twelveHoursAfter)) {
                display = SHOW_TIME;
                break choose_display;
            }
@@ -227,7 +225,7 @@ public class DateTimeView extends TextView {
        }

        // Set the text
        String text = format.format(mTime);
        String text = format.format(new Date(time));
        setText(text);

        // Schedule the next update
@@ -236,7 +234,7 @@ public class DateTimeView extends TextView {
            mUpdateTimeMillis = twelveHoursAfter > midnightAfter ? twelveHoursAfter : midnightAfter;
        } else {
            // Currently showing the date
            if (mTimeMillis < nowMillis) {
            if (mTimeMillis < now) {
                // If the time is in the past, don't schedule an update
                mUpdateTimeMillis = 0;
            } else {
@@ -277,15 +275,18 @@ public class DateTimeView extends TextView {
            millisIncrease = HOUR_IN_MILLIS;
        } else if (duration < YEAR_IN_MILLIS) {
            // In weird cases it can become 0 because of daylight savings
            TimeZone timeZone = TimeZone.getDefault();
            count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1);
            LocalDateTime localDateTime = mLocalTime;
            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
                            ? com.android.internal.R.plurals.duration_days_shortest
                            : com.android.internal.R.plurals.duration_days_shortest_future,
                            count),
                    count);
            if (past || count != 1) {
                mUpdateTimeMillis = computeNextMidnight(timeZone);
                mUpdateTimeMillis = computeNextMidnight(localNow, zoneId);
                millisIncrease = -1;
            } else {
                millisIncrease = DAY_IN_MILLIS;
@@ -311,18 +312,13 @@ public class DateTimeView extends TextView {
    }

    /**
     * @param timeZone the timezone we are in
     * @return the timepoint in millis at UTC at midnight in the current timezone
     * Returns the epoch millis for the next midnight in the specified timezone.
     */
    private long computeNextMidnight(TimeZone timeZone) {
        Calendar c = Calendar.getInstance();
        c.setTimeZone(timeZone);
        c.add(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTimeInMillis();
    private static long computeNextMidnight(LocalDateTime time, ZoneId zoneId) {
        // This ignores the chance of overflow: it should never happen.
        LocalDate tomorrow = time.toLocalDate().plusDays(1);
        LocalDateTime nextMidnight = LocalDateTime.of(tomorrow, LocalTime.MIDNIGHT);
        return toEpochMillis(nextMidnight, zoneId);
    }

    @Override
@@ -340,11 +336,10 @@ public class DateTimeView extends TextView {
                com.android.internal.R.string.now_string_shortest);
    }

    // Return the date difference for the two times in a given timezone.
    private static int dayDistance(TimeZone timeZone, long startTime,
            long endTime) {
        return getJulianDay(endTime, timeZone.getOffset(endTime) / 1000)
                - getJulianDay(startTime, timeZone.getOffset(startTime) / 1000);
    // Return the number of days between the two dates.
    private static int dayDistance(LocalDateTime start, LocalDateTime end) {
        return (int) (end.getLong(JulianFields.JULIAN_DAY)
                - start.getLong(JulianFields.JULIAN_DAY));
    }

    private DateFormat getTimeFormat() {
@@ -389,8 +384,11 @@ public class DateTimeView extends TextView {
                        count);
            } else if (duration < YEAR_IN_MILLIS) {
                // In weird cases it can become 0 because of daylight savings
                TimeZone timeZone = TimeZone.getDefault();
                count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1);
                LocalDateTime localDateTime = mLocalTime;
                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
                                ? com.android.internal.
                                        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();
    }
}