mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-10 14:24:34 -05:00
Implement WebView via Playwright (#1434)
* Implement Android's Looper Looper handles thread messaging. This is used by extensions when they want to enqueue actions e.g. for sleeping while WebView does someting * Stub WebView * Continue stubbing ViewGroup for WebView * Implement WebView via Playwright * Lint * Implement request interception Supports Yidan * Support WebChromeClient For Bokugen * Fix onPageStarted * Make Playwright configurable * Subscribe to config changes * Fix exposing of functions * Support data urls * Looper: Fix infinite sleep * Looper: Avoid killing the loop on exception Just log it and continue * Pump playwright's message queue periodically https://playwright.dev/java/docs/multithreading#pagewaitfortimeout-vs-threadsleep * Update server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SettingsType.kt Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> * Stub a KCef WebViewProvider * Initial Kcef Webview implementation Still buggy, on the second call it just seems to fall over * Format, restructure to create browser on load This is much more consistent, before we would sometimes see errors from about:blank, which block the actual page * Implement some small useful properties * Move inline objects to class * Handle requests in Kcef * Move Playwright implementation * Document Playwright settings, fix deprecated warnings * Inject default user agent from NetworkHelper * Move playwright to libs.versions.toml * Lint * Fix missing imports after lint * Update server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> * Fix default user agent set/get Use System.getProperty instead of SystemProperties.get * Configurable WebView provider implementation * Simplify Playwright settings init * Minor cleanup and improvements * Remove playwright WebView impl * Document WebView for Linux --------- Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
This commit is contained in:
@@ -136,4 +136,4 @@ public final class Log {
|
||||
first.append(msg);
|
||||
return first.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
270
AndroidCompat/src/main/java/android/util/Slog.java
Normal file
270
AndroidCompat/src/main/java/android/util/Slog.java
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.util;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Build;
|
||||
|
||||
/**
|
||||
* API for sending log output to the {@link Log#LOG_ID_SYSTEM} buffer.
|
||||
*
|
||||
* <p>Should be used by system components. Use {@code adb logcat --buffer=system} to fetch the logs.
|
||||
*
|
||||
* @see Log
|
||||
* @hide
|
||||
*/
|
||||
public final class Slog {
|
||||
|
||||
private Slog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#VERBOSE} level.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#v(String, String)
|
||||
*/
|
||||
public static int v(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.println(Log.VERBOSE, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#VERBOSE} level, attaching stack trace of the {@code tr} to
|
||||
* the end of the log statement.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#v(String, String, Throwable)
|
||||
*/
|
||||
public static int v(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
|
||||
return Log.println(Log.VERBOSE, tag,
|
||||
msg + '\n' + Log.getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#DEBUG} level.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#d(String, String)
|
||||
*/
|
||||
public static int d(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.println(Log.DEBUG, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#DEBUG} level, attaching stack trace of the {@code tr} to
|
||||
* the end of the log statement.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#d(String, String, Throwable)
|
||||
*/
|
||||
public static int d(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
|
||||
return Log.println(Log.DEBUG, tag,
|
||||
msg + '\n' + Log.getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#INFO} level.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#i(String, String)
|
||||
*/
|
||||
public static int i(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.println(Log.INFO, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#INFO} level, attaching stack trace of the {@code tr} to
|
||||
* the end of the log statement.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#i(String, String, Throwable)
|
||||
*/
|
||||
public static int i(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
|
||||
return Log.println(Log.INFO, tag,
|
||||
msg + '\n' + Log.getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#WARN} level.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#w(String, String)
|
||||
*/
|
||||
public static int w(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.println(Log.WARN, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#WARN} level, attaching stack trace of the {@code tr} to
|
||||
* the end of the log statement.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#w(String, String, Throwable)
|
||||
*/
|
||||
public static int w(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
|
||||
return Log.println(Log.WARN, tag,
|
||||
msg + '\n' + Log.getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs stack trace of {@code tr} at {@link Log#WARN} level.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#w(String, Throwable)
|
||||
*/
|
||||
public static int w(@Nullable String tag, @Nullable Throwable tr) {
|
||||
return Log.println(Log.WARN, tag, Log.getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#ERROR} level.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#e(String, String)
|
||||
*/
|
||||
public static int e(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.println(Log.ERROR, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs {@code msg} at {@link Log#ERROR} level, attaching stack trace of the {@code tr} to
|
||||
* the end of the log statement.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#e(String, String, Throwable)
|
||||
*/
|
||||
public static int e(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
|
||||
return Log.println(Log.ERROR, tag,
|
||||
msg + '\n' + Log.getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a condition that should never happen.
|
||||
*
|
||||
* <p>
|
||||
* Similar to {@link Log#wtf(String, String)}, but will never cause the caller to crash, and
|
||||
* will always be handled asynchronously. Primarily to be used by the system server.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#wtf(String, String)
|
||||
*/
|
||||
public static int wtf(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.wtf(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a condition that should never happen, attaching the full call stack to the log.
|
||||
*
|
||||
* <p>
|
||||
* Similar to {@link Log#wtfStack(String, String)}, but will never cause the caller to crash,
|
||||
* and will always be handled asynchronously. Primarily to be used by the system server.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
*
|
||||
* @see Log#wtfStack(String, String)
|
||||
*/
|
||||
public static int wtfStack(@Nullable String tag, @NonNull String msg) {
|
||||
return Log.wtf(tag, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a condition that should never happen, attaching stack trace of the {@code tr} to the
|
||||
* end of the log statement.
|
||||
*
|
||||
* <p>
|
||||
* Similar to {@link Log#wtf(String, Throwable)}, but will never cause the caller to crash,
|
||||
* and will always be handled asynchronously. Primarily to be used by the system server.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#wtf(String, Throwable)
|
||||
*/
|
||||
public static int wtf(@Nullable String tag, @Nullable Throwable tr) {
|
||||
return Log.wtf(tag, tr.getMessage(), tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a condition that should never happen, attaching stack trace of the {@code tr} to the
|
||||
* end of the log statement.
|
||||
*
|
||||
* <p>
|
||||
* Similar to {@link Log#wtf(String, String, Throwable)}, but will never cause the caller to
|
||||
* crash, and will always be handled asynchronously. Primarily to be used by the system server.
|
||||
*
|
||||
* @param tag identifies the source of a log message. It usually represents system service,
|
||||
* e.g. {@code PackageManager}.
|
||||
* @param msg the message to log.
|
||||
* @param tr an exception to log.
|
||||
*
|
||||
* @see Log#wtf(String, String, Throwable)
|
||||
*/
|
||||
public static int wtf(@Nullable String tag, @NonNull String msg, @Nullable Throwable tr) {
|
||||
return Log.wtf(tag, msg, tr);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static int println(int priority, @Nullable String tag, @NonNull String msg) {
|
||||
return Log.println(priority, tag, msg);
|
||||
}
|
||||
}
|
||||
371
AndroidCompat/src/main/java/android/util/TimeUtils.java
Normal file
371
AndroidCompat/src/main/java/android/util/TimeUtils.java
Normal file
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.util;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class containing utility methods related to time zones.
|
||||
*/
|
||||
public class TimeUtils {
|
||||
/** @hide */ public TimeUtils() {}
|
||||
/** {@hide} */
|
||||
private static final SimpleDateFormat sLoggingFormat =
|
||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
/** @hide */
|
||||
public static final SimpleDateFormat sDumpDateFormat =
|
||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
|
||||
/**
|
||||
* This timestamp is used in TimeUtils methods and by the SettingsUI to filter time zones
|
||||
* to only "effective" ones in a country. It is compared against the notUsedAfter metadata that
|
||||
* Android records for some time zones.
|
||||
*
|
||||
* <p>What is notUsedAfter?</p>
|
||||
* Android chooses to avoid making users choose between functionally identical time zones at the
|
||||
* expense of not being able to represent local times in the past.
|
||||
*
|
||||
* notUsedAfter exists because some time zones can "merge" with other time zones after a given
|
||||
* point in time (i.e. they change to have identical transitions, offsets, display names, etc.).
|
||||
* From the notUsedAfter time, the zone will express the same local time as the one it merged
|
||||
* with.
|
||||
*
|
||||
* <p>Why hardcoded?</p>
|
||||
* Rather than using System.currentTimeMillis(), a timestamp known to be in the recent past is
|
||||
* used to ensure consistent behavior across devices and time, and avoid assumptions that the
|
||||
* system clock on a device is currently set correctly. The fixed value should be updated
|
||||
* occasionally, but it doesn't have to be very often as effective time zones for a country
|
||||
* don't change very often.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final Instant MIN_USE_DATE_OF_TIMEZONE =
|
||||
Instant.ofEpochMilli(1546300800000L); // 1/1/2019 00:00 UTC
|
||||
|
||||
/** @hide Field length that can hold 999 days of time */
|
||||
public static final int HUNDRED_DAY_FIELD_LEN = 19;
|
||||
|
||||
private static final int SECONDS_PER_MINUTE = 60;
|
||||
private static final int SECONDS_PER_HOUR = 60 * 60;
|
||||
private static final int SECONDS_PER_DAY = 24 * 60 * 60;
|
||||
|
||||
/** @hide */
|
||||
public static final long NANOS_PER_MS = 1000000;
|
||||
|
||||
private static final Object sFormatSync = new Object();
|
||||
private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
|
||||
private static char[] sTmpFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
|
||||
|
||||
static private int accumField(int amt, int suffix, boolean always, int zeropad) {
|
||||
if (amt > 999) {
|
||||
int num = 0;
|
||||
while (amt != 0) {
|
||||
num++;
|
||||
amt /= 10;
|
||||
}
|
||||
return num + suffix;
|
||||
} else {
|
||||
if (amt > 99 || (always && zeropad >= 3)) {
|
||||
return 3+suffix;
|
||||
}
|
||||
if (amt > 9 || (always && zeropad >= 2)) {
|
||||
return 2+suffix;
|
||||
}
|
||||
if (always || amt > 0) {
|
||||
return 1+suffix;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static private int printFieldLocked(char[] formatStr, int amt, char suffix, int pos,
|
||||
boolean always, int zeropad) {
|
||||
if (always || amt > 0) {
|
||||
final int startPos = pos;
|
||||
if (amt > 999) {
|
||||
int tmp = 0;
|
||||
while (amt != 0 && tmp < sTmpFormatStr.length) {
|
||||
int dig = amt % 10;
|
||||
sTmpFormatStr[tmp] = (char)(dig + '0');
|
||||
tmp++;
|
||||
amt /= 10;
|
||||
}
|
||||
tmp--;
|
||||
while (tmp >= 0) {
|
||||
formatStr[pos] = sTmpFormatStr[tmp];
|
||||
pos++;
|
||||
tmp--;
|
||||
}
|
||||
} else {
|
||||
if ((always && zeropad >= 3) || amt > 99) {
|
||||
int dig = amt/100;
|
||||
formatStr[pos] = (char)(dig + '0');
|
||||
pos++;
|
||||
amt -= (dig*100);
|
||||
}
|
||||
if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
|
||||
int dig = amt/10;
|
||||
formatStr[pos] = (char)(dig + '0');
|
||||
pos++;
|
||||
amt -= (dig*10);
|
||||
}
|
||||
formatStr[pos] = (char)(amt + '0');
|
||||
pos++;
|
||||
}
|
||||
formatStr[pos] = suffix;
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private static int formatDurationLocked(long duration, int fieldLen) {
|
||||
if (sFormatStr.length < fieldLen) {
|
||||
sFormatStr = new char[fieldLen];
|
||||
}
|
||||
|
||||
char[] formatStr = sFormatStr;
|
||||
|
||||
if (duration == 0) {
|
||||
int pos = 0;
|
||||
fieldLen -= 1;
|
||||
while (pos < fieldLen) {
|
||||
formatStr[pos++] = ' ';
|
||||
}
|
||||
formatStr[pos] = '0';
|
||||
return pos+1;
|
||||
}
|
||||
|
||||
char prefix;
|
||||
if (duration > 0) {
|
||||
prefix = '+';
|
||||
} else {
|
||||
prefix = '-';
|
||||
duration = -duration;
|
||||
}
|
||||
|
||||
int millis = (int)(duration%1000);
|
||||
int seconds = (int) Math.floor(duration / 1000);
|
||||
int days = 0, hours = 0, minutes = 0;
|
||||
|
||||
if (seconds >= SECONDS_PER_DAY) {
|
||||
days = seconds / SECONDS_PER_DAY;
|
||||
seconds -= days * SECONDS_PER_DAY;
|
||||
}
|
||||
if (seconds >= SECONDS_PER_HOUR) {
|
||||
hours = seconds / SECONDS_PER_HOUR;
|
||||
seconds -= hours * SECONDS_PER_HOUR;
|
||||
}
|
||||
if (seconds >= SECONDS_PER_MINUTE) {
|
||||
minutes = seconds / SECONDS_PER_MINUTE;
|
||||
seconds -= minutes * SECONDS_PER_MINUTE;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
|
||||
if (fieldLen != 0) {
|
||||
int myLen = accumField(days, 1, false, 0);
|
||||
myLen += accumField(hours, 1, myLen > 0, 2);
|
||||
myLen += accumField(minutes, 1, myLen > 0, 2);
|
||||
myLen += accumField(seconds, 1, myLen > 0, 2);
|
||||
myLen += accumField(millis, 2, true, myLen > 0 ? 3 : 0) + 1;
|
||||
while (myLen < fieldLen) {
|
||||
formatStr[pos] = ' ';
|
||||
pos++;
|
||||
myLen++;
|
||||
}
|
||||
}
|
||||
|
||||
formatStr[pos] = prefix;
|
||||
pos++;
|
||||
|
||||
int start = pos;
|
||||
boolean zeropad = fieldLen != 0;
|
||||
pos = printFieldLocked(formatStr, days, 'd', pos, false, 0);
|
||||
pos = printFieldLocked(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
|
||||
pos = printFieldLocked(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
|
||||
pos = printFieldLocked(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
|
||||
pos = printFieldLocked(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
|
||||
formatStr[pos] = 's';
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static void formatDuration(long duration, StringBuilder builder) {
|
||||
synchronized (sFormatSync) {
|
||||
int len = formatDurationLocked(duration, 0);
|
||||
builder.append(sFormatStr, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static void formatDuration(long duration, StringBuilder builder, int fieldLen) {
|
||||
synchronized (sFormatSync) {
|
||||
int len = formatDurationLocked(duration, fieldLen);
|
||||
builder.append(sFormatStr, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
|
||||
synchronized (sFormatSync) {
|
||||
int len = formatDurationLocked(duration, fieldLen);
|
||||
pw.print(new String(sFormatStr, 0, len));
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
@TestApi
|
||||
public static String formatDuration(long duration) {
|
||||
synchronized (sFormatSync) {
|
||||
int len = formatDurationLocked(duration, 0);
|
||||
return new String(sFormatStr, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static void formatDuration(long duration, PrintWriter pw) {
|
||||
formatDuration(duration, pw, 0);
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static void formatDuration(long time, long now, StringBuilder sb) {
|
||||
if (time == 0) {
|
||||
sb.append("--");
|
||||
return;
|
||||
}
|
||||
formatDuration(time-now, sb, 0);
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static void formatDuration(long time, long now, PrintWriter pw) {
|
||||
if (time == 0) {
|
||||
pw.print("--");
|
||||
return;
|
||||
}
|
||||
formatDuration(time-now, pw, 0);
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static String formatUptime(long time) {
|
||||
return formatTime(time, SystemClock.uptimeMillis());
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static String formatRealtime(long time) {
|
||||
return formatTime(time, SystemClock.elapsedRealtime());
|
||||
}
|
||||
|
||||
/** @hide Just for debugging; not internationalized. */
|
||||
public static String formatTime(long time, long referenceTime) {
|
||||
long diff = time - referenceTime;
|
||||
if (diff > 0) {
|
||||
return time + " (in " + diff + " ms)";
|
||||
}
|
||||
if (diff < 0) {
|
||||
return time + " (" + -diff + " ms ago)";
|
||||
}
|
||||
return time + " (now)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a System.currentTimeMillis() value to a time of day value like
|
||||
* that printed in logs. MM-DD HH:MM:SS.MMM
|
||||
*
|
||||
* @param millis since the epoch (1/1/1970)
|
||||
* @return String representation of the time.
|
||||
* @hide
|
||||
*/
|
||||
public static String logTimeOfDay(long millis) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
if (millis >= 0) {
|
||||
c.setTimeInMillis(millis);
|
||||
return String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c);
|
||||
} else {
|
||||
return Long.toString(millis);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public static String formatForLogging(long millis) {
|
||||
if (millis <= 0) {
|
||||
return "unknown";
|
||||
} else {
|
||||
return sLoggingFormat.format(new Date(millis));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump a currentTimeMillis style timestamp for dumpsys.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static void dumpTime(PrintWriter pw, long time) {
|
||||
pw.print(sDumpDateFormat.format(new Date(time)));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to find if a clock time is inclusively between two other clock times
|
||||
* @param reference The time of the day we want check if it is between start and end
|
||||
* @param start The start time reference
|
||||
* @param end The end time
|
||||
* @return true if the reference time is between the two clock times, and false otherwise.
|
||||
*/
|
||||
public static boolean isTimeBetween(@NonNull LocalTime reference,
|
||||
@NonNull LocalTime start,
|
||||
@NonNull LocalTime end) {
|
||||
// ////////E----+-----S////////
|
||||
if ((reference.isBefore(start) && reference.isAfter(end)
|
||||
// -----+----S//////////E------
|
||||
|| (reference.isBefore(end) && reference.isBefore(start) && start.isBefore(end))
|
||||
// ---------S//////////E---+---
|
||||
|| (reference.isAfter(end) && reference.isAfter(start)) && start.isBefore(end))) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump a currentTimeMillis style timestamp for dumpsys, with the delta time from now.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static void dumpTimeWithDelta(PrintWriter pw, long time, long now) {
|
||||
pw.print(sDumpDateFormat.format(new Date(time)));
|
||||
if (time == now) {
|
||||
pw.print(" (now)");
|
||||
} else {
|
||||
pw.print(" (");
|
||||
TimeUtils.formatDuration(time, now, pw);
|
||||
pw.print(")");
|
||||
}
|
||||
}}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 android.os;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Supplier for custom trace messages.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface TraceNameSupplier {
|
||||
|
||||
/**
|
||||
* Gets the name used for trace messages.
|
||||
*/
|
||||
@NonNull String getTraceName();
|
||||
}
|
||||
Reference in New Issue
Block a user