Merge "Add getNetworkSpecifier() and getCarrierConfig()"
diff --git a/api/current.txt b/api/current.txt
index 2dc6430..964712a3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8226,6 +8226,7 @@
field public static final java.lang.String USER_SERVICE = "user";
field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+ field public static final java.lang.String WIFI_AWARE_SERVICE = "wifiaware";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
field public static final java.lang.String WIFI_SERVICE = "wifi";
field public static final java.lang.String WINDOW_SERVICE = "window";
@@ -9886,6 +9887,7 @@
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
+ field public static final java.lang.String FEATURE_WIFI_AWARE = "android.hardware.wifi.aware";
field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
field public static final int GET_ACTIVITIES = 1; // 0x1
field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
@@ -23771,6 +23773,7 @@
field public static final int TRANSPORT_ETHERNET = 3; // 0x3
field public static final int TRANSPORT_VPN = 4; // 0x4
field public static final int TRANSPORT_WIFI = 1; // 0x1
+ field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
}
public class NetworkInfo implements android.os.Parcelable {
@@ -24777,6 +24780,122 @@
}
+package android.net.wifi.aware {
+
+ public class AttachCallback {
+ ctor public AttachCallback();
+ method public void onAttachFailed();
+ method public void onAttached(android.net.wifi.aware.WifiAwareSession);
+ }
+
+ public final class Characteristics implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxMatchFilterLength();
+ method public int getMaxServiceNameLength();
+ method public int getMaxServiceSpecificInfoLength();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
+ }
+
+ public class DiscoverySession {
+ method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void destroy();
+ method public static int getMaxSendRetryCount();
+ method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
+ method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
+ }
+
+ public class DiscoverySessionCallback {
+ ctor public DiscoverySessionCallback();
+ method public void onMessageReceived(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void onMessageSendFailed(int);
+ method public void onMessageSendSucceeded(int);
+ method public void onPublishStarted(android.net.wifi.aware.PublishDiscoverySession);
+ method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
+ method public void onSessionConfigFailed();
+ method public void onSessionConfigUpdated();
+ method public void onSessionTerminated();
+ method public void onSubscribeStarted(android.net.wifi.aware.SubscribeDiscoverySession);
+ }
+
+ public class IdentityChangedListener {
+ ctor public IdentityChangedListener();
+ method public void onIdentityChanged(byte[]);
+ }
+
+ public class PeerHandle {
+ }
+
+ public final class PublishConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.PublishConfig> CREATOR;
+ field public static final int PUBLISH_TYPE_SOLICITED = 1; // 0x1
+ field public static final int PUBLISH_TYPE_UNSOLICITED = 0; // 0x0
+ }
+
+ public static final class PublishConfig.Builder {
+ ctor public PublishConfig.Builder();
+ method public android.net.wifi.aware.PublishConfig build();
+ method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(java.util.List<byte[]>);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishCount(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceName(java.lang.String);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(byte[]);
+ method public android.net.wifi.aware.PublishConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.PublishConfig.Builder setTtlSec(int);
+ }
+
+ public class PublishDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updatePublish(android.net.wifi.aware.PublishConfig);
+ }
+
+ public final class SubscribeConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR;
+ field public static final int MATCH_STYLE_ALL = 1; // 0x1
+ field public static final int MATCH_STYLE_FIRST_ONLY = 0; // 0x0
+ field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1
+ field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0
+ }
+
+ public static final class SubscribeConfig.Builder {
+ ctor public SubscribeConfig.Builder();
+ method public android.net.wifi.aware.SubscribeConfig build();
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(java.util.List<byte[]>);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeCount(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
+ }
+
+ public class SubscribeDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updateSubscribe(android.net.wifi.aware.SubscribeConfig);
+ }
+
+ public class WifiAwareManager {
+ method public void attach(android.net.wifi.aware.AttachCallback, android.os.Handler);
+ method public void attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler);
+ method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method public boolean isAvailable();
+ field public static final java.lang.String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
+ }
+
+ public class WifiAwareSession {
+ method public java.lang.String createNetworkSpecifier(int, byte[], byte[]);
+ method public void destroy();
+ method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
+ method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -54803,8 +54922,10 @@
public final class FileTime implements java.lang.Comparable {
method public int compareTo(java.nio.file.attribute.FileTime);
method public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
+ method public static java.nio.file.attribute.FileTime from(java.time.Instant);
method public static java.nio.file.attribute.FileTime fromMillis(long);
method public long to(java.util.concurrent.TimeUnit);
+ method public java.time.Instant toInstant();
method public long toMillis();
}
@@ -58334,6 +58455,1515 @@
}
+package java.time {
+
+ public abstract class Clock {
+ ctor protected Clock();
+ method public static java.time.Clock fixed(java.time.Instant, java.time.ZoneId);
+ method public abstract java.time.ZoneId getZone();
+ method public abstract java.time.Instant instant();
+ method public long millis();
+ method public static java.time.Clock offset(java.time.Clock, java.time.Duration);
+ method public static java.time.Clock system(java.time.ZoneId);
+ method public static java.time.Clock systemDefaultZone();
+ method public static java.time.Clock systemUTC();
+ method public static java.time.Clock tick(java.time.Clock, java.time.Duration);
+ method public static java.time.Clock tickMinutes(java.time.ZoneId);
+ method public static java.time.Clock tickSeconds(java.time.ZoneId);
+ method public abstract java.time.Clock withZone(java.time.ZoneId);
+ }
+
+ public class DateTimeException extends java.lang.RuntimeException {
+ ctor public DateTimeException(java.lang.String);
+ ctor public DateTimeException(java.lang.String, java.lang.Throwable);
+ }
+
+ public final class DayOfWeek extends java.lang.Enum implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public static java.time.DayOfWeek from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.DayOfWeek minus(long);
+ method public static java.time.DayOfWeek of(int);
+ method public java.time.DayOfWeek plus(long);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.DayOfWeek valueOf(java.lang.String);
+ method public static final java.time.DayOfWeek[] values();
+ enum_constant public static final java.time.DayOfWeek FRIDAY;
+ enum_constant public static final java.time.DayOfWeek MONDAY;
+ enum_constant public static final java.time.DayOfWeek SATURDAY;
+ enum_constant public static final java.time.DayOfWeek SUNDAY;
+ enum_constant public static final java.time.DayOfWeek THURSDAY;
+ enum_constant public static final java.time.DayOfWeek TUESDAY;
+ enum_constant public static final java.time.DayOfWeek WEDNESDAY;
+ }
+
+ public final class Duration implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAmount {
+ method public java.time.Duration abs();
+ method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.Duration between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public int compareTo(java.time.Duration);
+ method public java.time.Duration dividedBy(long);
+ method public static java.time.Duration from(java.time.temporal.TemporalAmount);
+ method public long get(java.time.temporal.TemporalUnit);
+ method public int getNano();
+ method public long getSeconds();
+ method public java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public boolean isNegative();
+ method public boolean isZero();
+ method public java.time.Duration minus(java.time.Duration);
+ method public java.time.Duration minus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Duration minusDays(long);
+ method public java.time.Duration minusHours(long);
+ method public java.time.Duration minusMillis(long);
+ method public java.time.Duration minusMinutes(long);
+ method public java.time.Duration minusNanos(long);
+ method public java.time.Duration minusSeconds(long);
+ method public java.time.Duration multipliedBy(long);
+ method public java.time.Duration negated();
+ method public static java.time.Duration of(long, java.time.temporal.TemporalUnit);
+ method public static java.time.Duration ofDays(long);
+ method public static java.time.Duration ofHours(long);
+ method public static java.time.Duration ofMillis(long);
+ method public static java.time.Duration ofMinutes(long);
+ method public static java.time.Duration ofNanos(long);
+ method public static java.time.Duration ofSeconds(long);
+ method public static java.time.Duration ofSeconds(long, long);
+ method public static java.time.Duration parse(java.lang.CharSequence);
+ method public java.time.Duration plus(java.time.Duration);
+ method public java.time.Duration plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Duration plusDays(long);
+ method public java.time.Duration plusHours(long);
+ method public java.time.Duration plusMillis(long);
+ method public java.time.Duration plusMinutes(long);
+ method public java.time.Duration plusNanos(long);
+ method public java.time.Duration plusSeconds(long);
+ method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public long toDays();
+ method public long toHours();
+ method public long toMillis();
+ method public long toMinutes();
+ method public long toNanos();
+ method public java.time.Duration withNanos(int);
+ method public java.time.Duration withSeconds(long);
+ field public static final java.time.Duration ZERO;
+ }
+
+ public final class Instant implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ method public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ method public int compareTo(java.time.Instant);
+ method public static java.time.Instant from(java.time.temporal.TemporalAccessor);
+ method public long getEpochSecond();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getNano();
+ method public boolean isAfter(java.time.Instant);
+ method public boolean isBefore(java.time.Instant);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.Instant minusMillis(long);
+ method public java.time.Instant minusNanos(long);
+ method public java.time.Instant minusSeconds(long);
+ method public static java.time.Instant now();
+ method public static java.time.Instant now(java.time.Clock);
+ method public static java.time.Instant ofEpochMilli(long);
+ method public static java.time.Instant ofEpochSecond(long);
+ method public static java.time.Instant ofEpochSecond(long, long);
+ method public static java.time.Instant parse(java.lang.CharSequence);
+ method public java.time.Instant plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Instant plusMillis(long);
+ method public java.time.Instant plusNanos(long);
+ method public java.time.Instant plusSeconds(long);
+ method public long toEpochMilli();
+ method public java.time.Instant truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Instant with(java.time.temporal.TemporalField, long);
+ field public static final java.time.Instant EPOCH;
+ field public static final java.time.Instant MAX;
+ field public static final java.time.Instant MIN;
+ }
+
+ public final class LocalDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.LocalDateTime atStartOfDay();
+ method public java.time.ZonedDateTime atStartOfDay(java.time.ZoneId);
+ method public java.time.LocalDateTime atTime(int, int);
+ method public java.time.LocalDateTime atTime(int, int, int);
+ method public java.time.LocalDateTime atTime(int, int, int, int);
+ method public java.time.OffsetDateTime atTime(java.time.OffsetTime);
+ method public static java.time.LocalDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.IsoChronology getChronology();
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getYear();
+ method public int lengthOfMonth();
+ method public java.time.LocalDate minusDays(long);
+ method public java.time.LocalDate minusMonths(long);
+ method public java.time.LocalDate minusWeeks(long);
+ method public java.time.LocalDate minusYears(long);
+ method public static java.time.LocalDate now();
+ method public static java.time.LocalDate now(java.time.ZoneId);
+ method public static java.time.LocalDate now(java.time.Clock);
+ method public static java.time.LocalDate of(int, java.time.Month, int);
+ method public static java.time.LocalDate of(int, int, int);
+ method public static java.time.LocalDate ofEpochDay(long);
+ method public static java.time.LocalDate ofYearDay(int, int);
+ method public static java.time.LocalDate parse(java.lang.CharSequence);
+ method public static java.time.LocalDate parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalDate plusDays(long);
+ method public java.time.LocalDate plusMonths(long);
+ method public java.time.LocalDate plusWeeks(long);
+ method public java.time.LocalDate plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Period until(java.time.chrono.ChronoLocalDate);
+ method public java.time.LocalDate withDayOfMonth(int);
+ method public java.time.LocalDate withDayOfYear(int);
+ method public java.time.LocalDate withMonth(int);
+ method public java.time.LocalDate withYear(int);
+ field public static final java.time.LocalDate MAX;
+ field public static final java.time.LocalDate MIN;
+ }
+
+ public final class LocalDateTime implements java.time.chrono.ChronoLocalDateTime java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ method public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ method public static java.time.LocalDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public int getSecond();
+ method public int getYear();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.LocalDateTime minusDays(long);
+ method public java.time.LocalDateTime minusHours(long);
+ method public java.time.LocalDateTime minusMinutes(long);
+ method public java.time.LocalDateTime minusMonths(long);
+ method public java.time.LocalDateTime minusNanos(long);
+ method public java.time.LocalDateTime minusSeconds(long);
+ method public java.time.LocalDateTime minusWeeks(long);
+ method public java.time.LocalDateTime minusYears(long);
+ method public static java.time.LocalDateTime now();
+ method public static java.time.LocalDateTime now(java.time.ZoneId);
+ method public static java.time.LocalDateTime now(java.time.Clock);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(java.time.LocalDate, java.time.LocalTime);
+ method public static java.time.LocalDateTime ofEpochSecond(long, int, java.time.ZoneOffset);
+ method public static java.time.LocalDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.LocalDateTime parse(java.lang.CharSequence);
+ method public static java.time.LocalDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.LocalDateTime plusDays(long);
+ method public java.time.LocalDateTime plusHours(long);
+ method public java.time.LocalDateTime plusMinutes(long);
+ method public java.time.LocalDateTime plusMonths(long);
+ method public java.time.LocalDateTime plusNanos(long);
+ method public java.time.LocalDateTime plusSeconds(long);
+ method public java.time.LocalDateTime plusWeeks(long);
+ method public java.time.LocalDateTime plusYears(long);
+ method public java.time.LocalDate toLocalDate();
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.LocalDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.LocalDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.LocalDateTime withDayOfMonth(int);
+ method public java.time.LocalDateTime withDayOfYear(int);
+ method public java.time.LocalDateTime withHour(int);
+ method public java.time.LocalDateTime withMinute(int);
+ method public java.time.LocalDateTime withMonth(int);
+ method public java.time.LocalDateTime withNano(int);
+ method public java.time.LocalDateTime withSecond(int);
+ method public java.time.LocalDateTime withYear(int);
+ field public static final java.time.LocalDateTime MAX;
+ field public static final java.time.LocalDateTime MIN;
+ }
+
+ public final class LocalTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDateTime atDate(java.time.LocalDate);
+ method public java.time.OffsetTime atOffset(java.time.ZoneOffset);
+ method public int compareTo(java.time.LocalTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.LocalTime from(java.time.temporal.TemporalAccessor);
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public int getNano();
+ method public int getSecond();
+ method public boolean isAfter(java.time.LocalTime);
+ method public boolean isBefore(java.time.LocalTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime minusHours(long);
+ method public java.time.LocalTime minusMinutes(long);
+ method public java.time.LocalTime minusNanos(long);
+ method public java.time.LocalTime minusSeconds(long);
+ method public static java.time.LocalTime now();
+ method public static java.time.LocalTime now(java.time.ZoneId);
+ method public static java.time.LocalTime now(java.time.Clock);
+ method public static java.time.LocalTime of(int, int);
+ method public static java.time.LocalTime of(int, int, int);
+ method public static java.time.LocalTime of(int, int, int, int);
+ method public static java.time.LocalTime ofNanoOfDay(long);
+ method public static java.time.LocalTime ofSecondOfDay(long);
+ method public static java.time.LocalTime parse(java.lang.CharSequence);
+ method public static java.time.LocalTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime plusHours(long);
+ method public java.time.LocalTime plusMinutes(long);
+ method public java.time.LocalTime plusNanos(long);
+ method public java.time.LocalTime plusSeconds(long);
+ method public long toNanoOfDay();
+ method public int toSecondOfDay();
+ method public java.time.LocalTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime with(java.time.temporal.TemporalField, long);
+ method public java.time.LocalTime withHour(int);
+ method public java.time.LocalTime withMinute(int);
+ method public java.time.LocalTime withNano(int);
+ method public java.time.LocalTime withSecond(int);
+ field public static final java.time.LocalTime MAX;
+ field public static final java.time.LocalTime MIDNIGHT;
+ field public static final java.time.LocalTime MIN;
+ field public static final java.time.LocalTime NOON;
+ }
+
+ public final class Month extends java.lang.Enum implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public int firstDayOfYear(boolean);
+ method public java.time.Month firstMonthOfQuarter();
+ method public static java.time.Month from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public int length(boolean);
+ method public int maxLength();
+ method public int minLength();
+ method public java.time.Month minus(long);
+ method public static java.time.Month of(int);
+ method public java.time.Month plus(long);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.Month valueOf(java.lang.String);
+ method public static final java.time.Month[] values();
+ enum_constant public static final java.time.Month APRIL;
+ enum_constant public static final java.time.Month AUGUST;
+ enum_constant public static final java.time.Month DECEMBER;
+ enum_constant public static final java.time.Month FEBRUARY;
+ enum_constant public static final java.time.Month JANUARY;
+ enum_constant public static final java.time.Month JULY;
+ enum_constant public static final java.time.Month JUNE;
+ enum_constant public static final java.time.Month MARCH;
+ enum_constant public static final java.time.Month MAY;
+ enum_constant public static final java.time.Month NOVEMBER;
+ enum_constant public static final java.time.Month OCTOBER;
+ enum_constant public static final java.time.Month SEPTEMBER;
+ }
+
+ public final class MonthDay implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atYear(int);
+ method public int compareTo(java.time.MonthDay);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.MonthDay from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public boolean isAfter(java.time.MonthDay);
+ method public boolean isBefore(java.time.MonthDay);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isValidYear(int);
+ method public static java.time.MonthDay now();
+ method public static java.time.MonthDay now(java.time.ZoneId);
+ method public static java.time.MonthDay now(java.time.Clock);
+ method public static java.time.MonthDay of(java.time.Month, int);
+ method public static java.time.MonthDay of(int, int);
+ method public static java.time.MonthDay parse(java.lang.CharSequence);
+ method public static java.time.MonthDay parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.MonthDay with(java.time.Month);
+ method public java.time.MonthDay withDayOfMonth(int);
+ method public java.time.MonthDay withMonth(int);
+ }
+
+ public final class OffsetDateTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.ZonedDateTime atZoneSameInstant(java.time.ZoneId);
+ method public java.time.ZonedDateTime atZoneSimilarLocal(java.time.ZoneId);
+ method public int compareTo(java.time.OffsetDateTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.OffsetDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public int getYear();
+ method public boolean isAfter(java.time.OffsetDateTime);
+ method public boolean isBefore(java.time.OffsetDateTime);
+ method public boolean isEqual(java.time.OffsetDateTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime minusDays(long);
+ method public java.time.OffsetDateTime minusHours(long);
+ method public java.time.OffsetDateTime minusMinutes(long);
+ method public java.time.OffsetDateTime minusMonths(long);
+ method public java.time.OffsetDateTime minusNanos(long);
+ method public java.time.OffsetDateTime minusSeconds(long);
+ method public java.time.OffsetDateTime minusWeeks(long);
+ method public java.time.OffsetDateTime minusYears(long);
+ method public static java.time.OffsetDateTime now();
+ method public static java.time.OffsetDateTime now(java.time.ZoneId);
+ method public static java.time.OffsetDateTime now(java.time.Clock);
+ method public static java.time.OffsetDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime of(java.time.LocalDateTime, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime of(int, int, int, int, int, int, int, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.OffsetDateTime parse(java.lang.CharSequence);
+ method public static java.time.OffsetDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.OffsetDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime plusDays(long);
+ method public java.time.OffsetDateTime plusHours(long);
+ method public java.time.OffsetDateTime plusMinutes(long);
+ method public java.time.OffsetDateTime plusMonths(long);
+ method public java.time.OffsetDateTime plusNanos(long);
+ method public java.time.OffsetDateTime plusSeconds(long);
+ method public java.time.OffsetDateTime plusWeeks(long);
+ method public java.time.OffsetDateTime plusYears(long);
+ method public static java.util.Comparator<java.time.OffsetDateTime> timeLineOrder();
+ method public long toEpochSecond();
+ method public java.time.Instant toInstant();
+ method public java.time.LocalDate toLocalDate();
+ method public java.time.LocalDateTime toLocalDateTime();
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.OffsetTime toOffsetTime();
+ method public java.time.ZonedDateTime toZonedDateTime();
+ method public java.time.OffsetDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.OffsetDateTime withDayOfMonth(int);
+ method public java.time.OffsetDateTime withDayOfYear(int);
+ method public java.time.OffsetDateTime withHour(int);
+ method public java.time.OffsetDateTime withMinute(int);
+ method public java.time.OffsetDateTime withMonth(int);
+ method public java.time.OffsetDateTime withNano(int);
+ method public java.time.OffsetDateTime withOffsetSameInstant(java.time.ZoneOffset);
+ method public java.time.OffsetDateTime withOffsetSameLocal(java.time.ZoneOffset);
+ method public java.time.OffsetDateTime withSecond(int);
+ method public java.time.OffsetDateTime withYear(int);
+ field public static final java.time.OffsetDateTime MAX;
+ field public static final java.time.OffsetDateTime MIN;
+ }
+
+ public final class OffsetTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.OffsetDateTime atDate(java.time.LocalDate);
+ method public int compareTo(java.time.OffsetTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.OffsetTime from(java.time.temporal.TemporalAccessor);
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public boolean isAfter(java.time.OffsetTime);
+ method public boolean isBefore(java.time.OffsetTime);
+ method public boolean isEqual(java.time.OffsetTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime minusHours(long);
+ method public java.time.OffsetTime minusMinutes(long);
+ method public java.time.OffsetTime minusNanos(long);
+ method public java.time.OffsetTime minusSeconds(long);
+ method public static java.time.OffsetTime now();
+ method public static java.time.OffsetTime now(java.time.ZoneId);
+ method public static java.time.OffsetTime now(java.time.Clock);
+ method public static java.time.OffsetTime of(java.time.LocalTime, java.time.ZoneOffset);
+ method public static java.time.OffsetTime of(int, int, int, int, java.time.ZoneOffset);
+ method public static java.time.OffsetTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.OffsetTime parse(java.lang.CharSequence);
+ method public static java.time.OffsetTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.OffsetTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime plusHours(long);
+ method public java.time.OffsetTime plusMinutes(long);
+ method public java.time.OffsetTime plusNanos(long);
+ method public java.time.OffsetTime plusSeconds(long);
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.OffsetTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime with(java.time.temporal.TemporalField, long);
+ method public java.time.OffsetTime withHour(int);
+ method public java.time.OffsetTime withMinute(int);
+ method public java.time.OffsetTime withNano(int);
+ method public java.time.OffsetTime withOffsetSameInstant(java.time.ZoneOffset);
+ method public java.time.OffsetTime withOffsetSameLocal(java.time.ZoneOffset);
+ method public java.time.OffsetTime withSecond(int);
+ field public static final java.time.OffsetTime MAX;
+ field public static final java.time.OffsetTime MIN;
+ }
+
+ public final class Period implements java.time.chrono.ChronoPeriod java.io.Serializable {
+ method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.Period between(java.time.LocalDate, java.time.LocalDate);
+ method public static java.time.Period from(java.time.temporal.TemporalAmount);
+ method public long get(java.time.temporal.TemporalUnit);
+ method public java.time.chrono.IsoChronology getChronology();
+ method public int getDays();
+ method public int getMonths();
+ method public java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public int getYears();
+ method public java.time.Period minus(java.time.temporal.TemporalAmount);
+ method public java.time.Period minusDays(long);
+ method public java.time.Period minusMonths(long);
+ method public java.time.Period minusYears(long);
+ method public java.time.Period multipliedBy(int);
+ method public java.time.Period normalized();
+ method public static java.time.Period of(int, int, int);
+ method public static java.time.Period ofDays(int);
+ method public static java.time.Period ofMonths(int);
+ method public static java.time.Period ofWeeks(int);
+ method public static java.time.Period ofYears(int);
+ method public static java.time.Period parse(java.lang.CharSequence);
+ method public java.time.Period plus(java.time.temporal.TemporalAmount);
+ method public java.time.Period plusDays(long);
+ method public java.time.Period plusMonths(long);
+ method public java.time.Period plusYears(long);
+ method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public long toTotalMonths();
+ method public java.time.Period withDays(int);
+ method public java.time.Period withMonths(int);
+ method public java.time.Period withYears(int);
+ field public static final java.time.Period ZERO;
+ }
+
+ public final class Year implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atDay(int);
+ method public java.time.YearMonth atMonth(java.time.Month);
+ method public java.time.YearMonth atMonth(int);
+ method public java.time.LocalDate atMonthDay(java.time.MonthDay);
+ method public int compareTo(java.time.Year);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.Year from(java.time.temporal.TemporalAccessor);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isAfter(java.time.Year);
+ method public boolean isBefore(java.time.Year);
+ method public static boolean isLeap(long);
+ method public boolean isLeap();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public boolean isValidMonthDay(java.time.MonthDay);
+ method public int length();
+ method public java.time.Year minusYears(long);
+ method public static java.time.Year now();
+ method public static java.time.Year now(java.time.ZoneId);
+ method public static java.time.Year now(java.time.Clock);
+ method public static java.time.Year of(int);
+ method public static java.time.Year parse(java.lang.CharSequence);
+ method public static java.time.Year parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.Year plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Year plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Year with(java.time.temporal.TemporalField, long);
+ field public static final int MAX_VALUE = 999999999; // 0x3b9ac9ff
+ field public static final int MIN_VALUE = -999999999; // 0xc4653601
+ }
+
+ public final class YearMonth implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atDay(int);
+ method public java.time.LocalDate atEndOfMonth();
+ method public int compareTo(java.time.YearMonth);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.YearMonth from(java.time.temporal.TemporalAccessor);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getYear();
+ method public boolean isAfter(java.time.YearMonth);
+ method public boolean isBefore(java.time.YearMonth);
+ method public boolean isLeapYear();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public boolean isValidDay(int);
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public java.time.YearMonth minusMonths(long);
+ method public java.time.YearMonth minusYears(long);
+ method public static java.time.YearMonth now();
+ method public static java.time.YearMonth now(java.time.ZoneId);
+ method public static java.time.YearMonth now(java.time.Clock);
+ method public static java.time.YearMonth of(int, java.time.Month);
+ method public static java.time.YearMonth of(int, int);
+ method public static java.time.YearMonth parse(java.lang.CharSequence);
+ method public static java.time.YearMonth parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.YearMonth plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.YearMonth plusMonths(long);
+ method public java.time.YearMonth plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.YearMonth with(java.time.temporal.TemporalField, long);
+ method public java.time.YearMonth withMonth(int);
+ method public java.time.YearMonth withYear(int);
+ }
+
+ public abstract class ZoneId implements java.io.Serializable {
+ method public static java.time.ZoneId from(java.time.temporal.TemporalAccessor);
+ method public static java.util.Set<java.lang.String> getAvailableZoneIds();
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public abstract java.lang.String getId();
+ method public abstract java.time.zone.ZoneRules getRules();
+ method public java.time.ZoneId normalized();
+ method public static java.time.ZoneId of(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+ method public static java.time.ZoneId of(java.lang.String);
+ method public static java.time.ZoneId ofOffset(java.lang.String, java.time.ZoneOffset);
+ method public static java.time.ZoneId systemDefault();
+ field public static final java.util.Map<java.lang.String, java.lang.String> SHORT_IDS;
+ }
+
+ public final class ZoneOffset extends java.time.ZoneId implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public int compareTo(java.time.ZoneOffset);
+ method public static java.time.ZoneOffset from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getId();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.zone.ZoneRules getRules();
+ method public int getTotalSeconds();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public static java.time.ZoneOffset of(java.lang.String);
+ method public static java.time.ZoneOffset ofHours(int);
+ method public static java.time.ZoneOffset ofHoursMinutes(int, int);
+ method public static java.time.ZoneOffset ofHoursMinutesSeconds(int, int, int);
+ method public static java.time.ZoneOffset ofTotalSeconds(int);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ field public static final java.time.ZoneOffset MAX;
+ field public static final java.time.ZoneOffset MIN;
+ field public static final java.time.ZoneOffset UTC;
+ }
+
+ public final class ZonedDateTime implements java.time.chrono.ChronoZonedDateTime java.io.Serializable java.time.temporal.Temporal {
+ method public static java.time.ZonedDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public int getYear();
+ method public java.time.ZoneId getZone();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.ZonedDateTime minusDays(long);
+ method public java.time.ZonedDateTime minusHours(long);
+ method public java.time.ZonedDateTime minusMinutes(long);
+ method public java.time.ZonedDateTime minusMonths(long);
+ method public java.time.ZonedDateTime minusNanos(long);
+ method public java.time.ZonedDateTime minusSeconds(long);
+ method public java.time.ZonedDateTime minusWeeks(long);
+ method public java.time.ZonedDateTime minusYears(long);
+ method public static java.time.ZonedDateTime now();
+ method public static java.time.ZonedDateTime now(java.time.ZoneId);
+ method public static java.time.ZonedDateTime now(java.time.Clock);
+ method public static java.time.ZonedDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneId);
+ method public static java.time.ZonedDateTime of(java.time.LocalDateTime, java.time.ZoneId);
+ method public static java.time.ZonedDateTime of(int, int, int, int, int, int, int, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofInstant(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofLocal(java.time.LocalDateTime, java.time.ZoneId, java.time.ZoneOffset);
+ method public static java.time.ZonedDateTime ofStrict(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ method public static java.time.ZonedDateTime parse(java.lang.CharSequence);
+ method public static java.time.ZonedDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.ZonedDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.ZonedDateTime plusDays(long);
+ method public java.time.ZonedDateTime plusHours(long);
+ method public java.time.ZonedDateTime plusMinutes(long);
+ method public java.time.ZonedDateTime plusMonths(long);
+ method public java.time.ZonedDateTime plusNanos(long);
+ method public java.time.ZonedDateTime plusSeconds(long);
+ method public java.time.ZonedDateTime plusWeeks(long);
+ method public java.time.ZonedDateTime plusYears(long);
+ method public java.time.LocalDateTime toLocalDateTime();
+ method public java.time.OffsetDateTime toOffsetDateTime();
+ method public java.time.ZonedDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.ZonedDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.ZonedDateTime withDayOfMonth(int);
+ method public java.time.ZonedDateTime withDayOfYear(int);
+ method public java.time.ZonedDateTime withEarlierOffsetAtOverlap();
+ method public java.time.ZonedDateTime withFixedOffsetZone();
+ method public java.time.ZonedDateTime withHour(int);
+ method public java.time.ZonedDateTime withLaterOffsetAtOverlap();
+ method public java.time.ZonedDateTime withMinute(int);
+ method public java.time.ZonedDateTime withMonth(int);
+ method public java.time.ZonedDateTime withNano(int);
+ method public java.time.ZonedDateTime withSecond(int);
+ method public java.time.ZonedDateTime withYear(int);
+ method public java.time.ZonedDateTime withZoneSameInstant(java.time.ZoneId);
+ method public java.time.ZonedDateTime withZoneSameLocal(java.time.ZoneId);
+ }
+
+}
+
+package java.time.chrono {
+
+ public abstract class AbstractChronology implements java.time.chrono.Chronology {
+ ctor protected AbstractChronology();
+ method public int compareTo(java.time.chrono.Chronology);
+ method public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.format.ResolverStyle);
+ }
+
+ public abstract interface ChronoLocalDate implements java.lang.Comparable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public default java.time.chrono.ChronoLocalDateTime<?> atTime(java.time.LocalTime);
+ method public default int compareTo(java.time.chrono.ChronoLocalDate);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoLocalDate from(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.chrono.Chronology getChronology();
+ method public default java.time.chrono.Era getEra();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoLocalDate);
+ method public default boolean isBefore(java.time.chrono.ChronoLocalDate);
+ method public default boolean isEqual(java.time.chrono.ChronoLocalDate);
+ method public default boolean isLeapYear();
+ method public default boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract int lengthOfMonth();
+ method public default int lengthOfYear();
+ method public default java.time.chrono.ChronoLocalDate plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoLocalDate> timeLineOrder();
+ method public default long toEpochDay();
+ method public abstract java.lang.String toString();
+ method public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ method public default java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalField, long);
+ }
+
+ abstract class ChronoLocalDateImpl<D extends java.time.chrono.ChronoLocalDate> implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ }
+
+ public abstract interface ChronoLocalDateTime<D extends java.time.chrono.ChronoLocalDate> implements java.lang.Comparable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> atZone(java.time.ZoneId);
+ method public default int compareTo(java.time.chrono.ChronoLocalDateTime<?>);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoLocalDateTime<?> from(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.Chronology getChronology();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoLocalDateTime<?>);
+ method public default boolean isBefore(java.time.chrono.ChronoLocalDateTime<?>);
+ method public default boolean isEqual(java.time.chrono.ChronoLocalDateTime<?>);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoLocalDateTime<?>> timeLineOrder();
+ method public default long toEpochSecond(java.time.ZoneOffset);
+ method public default java.time.Instant toInstant(java.time.ZoneOffset);
+ method public abstract D toLocalDate();
+ method public abstract java.time.LocalTime toLocalTime();
+ method public abstract java.lang.String toString();
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> with(java.time.temporal.TemporalField, long);
+ }
+
+ public abstract interface ChronoPeriod implements java.time.temporal.TemporalAmount {
+ method public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.chrono.ChronoPeriod between(java.time.chrono.ChronoLocalDate, java.time.chrono.ChronoLocalDate);
+ method public abstract boolean equals(java.lang.Object);
+ method public abstract long get(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.Chronology getChronology();
+ method public abstract java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public abstract int hashCode();
+ method public default boolean isNegative();
+ method public default boolean isZero();
+ method public abstract java.time.chrono.ChronoPeriod minus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.chrono.ChronoPeriod multipliedBy(int);
+ method public default java.time.chrono.ChronoPeriod negated();
+ method public abstract java.time.chrono.ChronoPeriod normalized();
+ method public abstract java.time.chrono.ChronoPeriod plus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public abstract java.lang.String toString();
+ }
+
+ public abstract interface ChronoZonedDateTime<D extends java.time.chrono.ChronoLocalDate> implements java.lang.Comparable java.time.temporal.Temporal {
+ method public default int compareTo(java.time.chrono.ChronoZonedDateTime<?>);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoZonedDateTime<?> from(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.Chronology getChronology();
+ method public default long getLong(java.time.temporal.TemporalField);
+ method public abstract java.time.ZoneOffset getOffset();
+ method public abstract java.time.ZoneId getZone();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoZonedDateTime<?>);
+ method public default boolean isBefore(java.time.chrono.ChronoZonedDateTime<?>);
+ method public default boolean isEqual(java.time.chrono.ChronoZonedDateTime<?>);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoZonedDateTime<?>> timeLineOrder();
+ method public default long toEpochSecond();
+ method public default java.time.Instant toInstant();
+ method public default D toLocalDate();
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> toLocalDateTime();
+ method public default java.time.LocalTime toLocalTime();
+ method public abstract java.lang.String toString();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> with(java.time.temporal.TemporalField, long);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withEarlierOffsetAtOverlap();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withLaterOffsetAtOverlap();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withZoneSameInstant(java.time.ZoneId);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withZoneSameLocal(java.time.ZoneId);
+ }
+
+ public abstract interface Chronology implements java.lang.Comparable {
+ method public abstract int compareTo(java.time.chrono.Chronology);
+ method public default java.time.chrono.ChronoLocalDate date(java.time.chrono.Era, int, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate date(int, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate date(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.chrono.ChronoLocalDate dateEpochDay(long);
+ method public default java.time.chrono.ChronoLocalDate dateNow();
+ method public default java.time.chrono.ChronoLocalDate dateNow(java.time.ZoneId);
+ method public default java.time.chrono.ChronoLocalDate dateNow(java.time.Clock);
+ method public default java.time.chrono.ChronoLocalDate dateYearDay(java.time.chrono.Era, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate dateYearDay(int, int);
+ method public abstract boolean equals(java.lang.Object);
+ method public abstract java.time.chrono.Era eraOf(int);
+ method public abstract java.util.List<java.time.chrono.Era> eras();
+ method public static java.time.chrono.Chronology from(java.time.temporal.TemporalAccessor);
+ method public static java.util.Set<java.time.chrono.Chronology> getAvailableChronologies();
+ method public abstract java.lang.String getCalendarType();
+ method public default java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public abstract java.lang.String getId();
+ method public abstract int hashCode();
+ method public abstract boolean isLeapYear(long);
+ method public default java.time.chrono.ChronoLocalDateTime<? extends java.time.chrono.ChronoLocalDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public static java.time.chrono.Chronology of(java.lang.String);
+ method public static java.time.chrono.Chronology ofLocale(java.util.Locale);
+ method public default java.time.chrono.ChronoPeriod period(int, int, int);
+ method public abstract int prolepticYear(java.time.chrono.Era, int);
+ method public abstract java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public abstract java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.format.ResolverStyle);
+ method public abstract java.lang.String toString();
+ method public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ }
+
+ public abstract interface Era implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public default java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public default long getLong(java.time.temporal.TemporalField);
+ method public abstract int getValue();
+ method public default boolean isSupported(java.time.temporal.TemporalField);
+ }
+
+ public final class HijrahChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.HijrahDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.HijrahDate date(int, int, int);
+ method public java.time.chrono.HijrahDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.HijrahDate dateEpochDay(long);
+ method public java.time.chrono.HijrahDate dateNow();
+ method public java.time.chrono.HijrahDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.HijrahDate dateNow(java.time.Clock);
+ method public java.time.chrono.HijrahDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.HijrahDate dateYearDay(int, int);
+ method public java.time.chrono.HijrahEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.HijrahDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.HijrahDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.HijrahChronology INSTANCE;
+ }
+
+ public final class HijrahDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.HijrahDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.HijrahChronology getChronology();
+ method public java.time.chrono.HijrahEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public boolean isLeapYear();
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public static java.time.chrono.HijrahDate now();
+ method public static java.time.chrono.HijrahDate now(java.time.ZoneId);
+ method public static java.time.chrono.HijrahDate now(java.time.Clock);
+ method public static java.time.chrono.HijrahDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ method public java.time.chrono.HijrahDate withVariant(java.time.chrono.HijrahChronology);
+ }
+
+ public final class HijrahEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.HijrahEra of(int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.chrono.HijrahEra valueOf(java.lang.String);
+ method public static final java.time.chrono.HijrahEra[] values();
+ enum_constant public static final java.time.chrono.HijrahEra AH;
+ }
+
+ public final class IsoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.LocalDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.LocalDate date(int, int, int);
+ method public java.time.LocalDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.LocalDate dateEpochDay(long);
+ method public java.time.LocalDate dateNow();
+ method public java.time.LocalDate dateNow(java.time.ZoneId);
+ method public java.time.LocalDate dateNow(java.time.Clock);
+ method public java.time.LocalDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.LocalDate dateYearDay(int, int);
+ method public java.time.chrono.IsoEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.LocalDateTime localDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.Period period(int, int, int);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.ZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.ZonedDateTime zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.IsoChronology INSTANCE;
+ }
+
+ public final class IsoEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.IsoEra of(int);
+ method public static java.time.chrono.IsoEra valueOf(java.lang.String);
+ method public static final java.time.chrono.IsoEra[] values();
+ enum_constant public static final java.time.chrono.IsoEra BCE;
+ enum_constant public static final java.time.chrono.IsoEra CE;
+ }
+
+ public final class JapaneseChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.JapaneseDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.JapaneseDate date(int, int, int);
+ method public java.time.chrono.JapaneseDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.JapaneseDate dateEpochDay(long);
+ method public java.time.chrono.JapaneseDate dateNow();
+ method public java.time.chrono.JapaneseDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.JapaneseDate dateNow(java.time.Clock);
+ method public java.time.chrono.JapaneseDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.JapaneseDate dateYearDay(int, int);
+ method public java.time.chrono.JapaneseEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.JapaneseDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.JapaneseDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.JapaneseChronology INSTANCE;
+ }
+
+ public final class JapaneseDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.JapaneseDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.JapaneseChronology getChronology();
+ method public java.time.chrono.JapaneseEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public static java.time.chrono.JapaneseDate now();
+ method public static java.time.chrono.JapaneseDate now(java.time.ZoneId);
+ method public static java.time.chrono.JapaneseDate now(java.time.Clock);
+ method public static java.time.chrono.JapaneseDate of(java.time.chrono.JapaneseEra, int, int, int);
+ method public static java.time.chrono.JapaneseDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class JapaneseEra implements java.time.chrono.Era java.io.Serializable {
+ method public int getValue();
+ method public static java.time.chrono.JapaneseEra of(int);
+ method public static java.time.chrono.JapaneseEra valueOf(java.lang.String);
+ method public static java.time.chrono.JapaneseEra[] values();
+ field public static final java.time.chrono.JapaneseEra HEISEI;
+ field public static final java.time.chrono.JapaneseEra MEIJI;
+ field public static final java.time.chrono.JapaneseEra SHOWA;
+ field public static final java.time.chrono.JapaneseEra TAISHO;
+ }
+
+ public final class MinguoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.MinguoDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.MinguoDate date(int, int, int);
+ method public java.time.chrono.MinguoDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.MinguoDate dateEpochDay(long);
+ method public java.time.chrono.MinguoDate dateNow();
+ method public java.time.chrono.MinguoDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.MinguoDate dateNow(java.time.Clock);
+ method public java.time.chrono.MinguoDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.MinguoDate dateYearDay(int, int);
+ method public java.time.chrono.MinguoEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.MinguoDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.MinguoDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.MinguoChronology INSTANCE;
+ }
+
+ public final class MinguoDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.MinguoDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.MinguoChronology getChronology();
+ method public java.time.chrono.MinguoEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public static java.time.chrono.MinguoDate now();
+ method public static java.time.chrono.MinguoDate now(java.time.ZoneId);
+ method public static java.time.chrono.MinguoDate now(java.time.Clock);
+ method public static java.time.chrono.MinguoDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class MinguoEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.MinguoEra of(int);
+ method public static java.time.chrono.MinguoEra valueOf(java.lang.String);
+ method public static final java.time.chrono.MinguoEra[] values();
+ enum_constant public static final java.time.chrono.MinguoEra BEFORE_ROC;
+ enum_constant public static final java.time.chrono.MinguoEra ROC;
+ }
+
+ public final class ThaiBuddhistChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.ThaiBuddhistDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.ThaiBuddhistDate date(int, int, int);
+ method public java.time.chrono.ThaiBuddhistDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ThaiBuddhistDate dateEpochDay(long);
+ method public java.time.chrono.ThaiBuddhistDate dateNow();
+ method public java.time.chrono.ThaiBuddhistDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.ThaiBuddhistDate dateNow(java.time.Clock);
+ method public java.time.chrono.ThaiBuddhistDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.ThaiBuddhistDate dateYearDay(int, int);
+ method public java.time.chrono.ThaiBuddhistEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.ThaiBuddhistDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.ThaiBuddhistDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.ThaiBuddhistChronology INSTANCE;
+ }
+
+ public final class ThaiBuddhistDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.ThaiBuddhistDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ThaiBuddhistChronology getChronology();
+ method public java.time.chrono.ThaiBuddhistEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public static java.time.chrono.ThaiBuddhistDate now();
+ method public static java.time.chrono.ThaiBuddhistDate now(java.time.ZoneId);
+ method public static java.time.chrono.ThaiBuddhistDate now(java.time.Clock);
+ method public static java.time.chrono.ThaiBuddhistDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class ThaiBuddhistEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.ThaiBuddhistEra of(int);
+ method public static java.time.chrono.ThaiBuddhistEra valueOf(java.lang.String);
+ method public static final java.time.chrono.ThaiBuddhistEra[] values();
+ enum_constant public static final java.time.chrono.ThaiBuddhistEra BE;
+ enum_constant public static final java.time.chrono.ThaiBuddhistEra BEFORE_BE;
+ }
+
+}
+
+package java.time.format {
+
+ public final class DateTimeFormatter {
+ method public java.lang.String format(java.time.temporal.TemporalAccessor);
+ method public void formatTo(java.time.temporal.TemporalAccessor, java.lang.Appendable);
+ method public java.time.chrono.Chronology getChronology();
+ method public java.time.format.DecimalStyle getDecimalStyle();
+ method public java.util.Locale getLocale();
+ method public java.util.Set<java.time.temporal.TemporalField> getResolverFields();
+ method public java.time.format.ResolverStyle getResolverStyle();
+ method public java.time.ZoneId getZone();
+ method public static java.time.format.DateTimeFormatter ofLocalizedDate(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedTime(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofPattern(java.lang.String);
+ method public static java.time.format.DateTimeFormatter ofPattern(java.lang.String, java.util.Locale);
+ method public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence);
+ method public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence, java.text.ParsePosition);
+ method public <T> T parse(java.lang.CharSequence, java.time.temporal.TemporalQuery<T>);
+ method public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery<?>...);
+ method public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition);
+ method public static final java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
+ method public static final java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
+ method public java.text.Format toFormat();
+ method public java.text.Format toFormat(java.time.temporal.TemporalQuery<?>);
+ method public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology);
+ method public java.time.format.DateTimeFormatter withDecimalStyle(java.time.format.DecimalStyle);
+ method public java.time.format.DateTimeFormatter withLocale(java.util.Locale);
+ method public java.time.format.DateTimeFormatter withResolverFields(java.time.temporal.TemporalField...);
+ method public java.time.format.DateTimeFormatter withResolverFields(java.util.Set<java.time.temporal.TemporalField>);
+ method public java.time.format.DateTimeFormatter withResolverStyle(java.time.format.ResolverStyle);
+ method public java.time.format.DateTimeFormatter withZone(java.time.ZoneId);
+ field public static final java.time.format.DateTimeFormatter BASIC_ISO_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_INSTANT;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_ORDINAL_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_WEEK_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_ZONED_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter RFC_1123_DATE_TIME;
+ }
+
+ public final class DateTimeFormatterBuilder {
+ ctor public DateTimeFormatterBuilder();
+ method public java.time.format.DateTimeFormatterBuilder append(java.time.format.DateTimeFormatter);
+ method public java.time.format.DateTimeFormatterBuilder appendChronologyId();
+ method public java.time.format.DateTimeFormatterBuilder appendChronologyText(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendFraction(java.time.temporal.TemporalField, int, int, boolean);
+ method public java.time.format.DateTimeFormatterBuilder appendInstant();
+ method public java.time.format.DateTimeFormatterBuilder appendInstant(int);
+ method public java.time.format.DateTimeFormatterBuilder appendLiteral(char);
+ method public java.time.format.DateTimeFormatterBuilder appendLiteral(java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendLocalized(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendLocalizedOffset(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendOffset(java.lang.String, java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendOffsetId();
+ method public java.time.format.DateTimeFormatterBuilder appendOptional(java.time.format.DateTimeFormatter);
+ method public java.time.format.DateTimeFormatterBuilder appendPattern(java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField, java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField, java.util.Map<java.lang.Long, java.lang.String>);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField, int);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField, int, int, java.time.format.SignStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField, int, int, int);
+ method public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField, int, int, java.time.chrono.ChronoLocalDate);
+ method public java.time.format.DateTimeFormatterBuilder appendZoneId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneOrOffsetId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneRegionId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle, java.util.Set<java.time.ZoneId>);
+ method public static java.lang.String getLocalizedDateTimePattern(java.time.format.FormatStyle, java.time.format.FormatStyle, java.time.chrono.Chronology, java.util.Locale);
+ method public java.time.format.DateTimeFormatterBuilder optionalEnd();
+ method public java.time.format.DateTimeFormatterBuilder optionalStart();
+ method public java.time.format.DateTimeFormatterBuilder padNext(int);
+ method public java.time.format.DateTimeFormatterBuilder padNext(int, char);
+ method public java.time.format.DateTimeFormatterBuilder parseCaseInsensitive();
+ method public java.time.format.DateTimeFormatterBuilder parseCaseSensitive();
+ method public java.time.format.DateTimeFormatterBuilder parseDefaulting(java.time.temporal.TemporalField, long);
+ method public java.time.format.DateTimeFormatterBuilder parseLenient();
+ method public java.time.format.DateTimeFormatterBuilder parseStrict();
+ method public java.time.format.DateTimeFormatter toFormatter();
+ method public java.time.format.DateTimeFormatter toFormatter(java.util.Locale);
+ }
+
+ public class DateTimeParseException extends java.time.DateTimeException {
+ ctor public DateTimeParseException(java.lang.String, java.lang.CharSequence, int);
+ ctor public DateTimeParseException(java.lang.String, java.lang.CharSequence, int, java.lang.Throwable);
+ method public int getErrorIndex();
+ method public java.lang.String getParsedString();
+ }
+
+ public final class DecimalStyle {
+ method public static java.util.Set<java.util.Locale> getAvailableLocales();
+ method public char getDecimalSeparator();
+ method public char getNegativeSign();
+ method public char getPositiveSign();
+ method public char getZeroDigit();
+ method public static java.time.format.DecimalStyle of(java.util.Locale);
+ method public static java.time.format.DecimalStyle ofDefaultLocale();
+ method public java.time.format.DecimalStyle withDecimalSeparator(char);
+ method public java.time.format.DecimalStyle withNegativeSign(char);
+ method public java.time.format.DecimalStyle withPositiveSign(char);
+ method public java.time.format.DecimalStyle withZeroDigit(char);
+ field public static final java.time.format.DecimalStyle STANDARD;
+ }
+
+ public final class FormatStyle extends java.lang.Enum {
+ method public static java.time.format.FormatStyle valueOf(java.lang.String);
+ method public static final java.time.format.FormatStyle[] values();
+ enum_constant public static final java.time.format.FormatStyle FULL;
+ enum_constant public static final java.time.format.FormatStyle LONG;
+ enum_constant public static final java.time.format.FormatStyle MEDIUM;
+ enum_constant public static final java.time.format.FormatStyle SHORT;
+ }
+
+ public final class ResolverStyle extends java.lang.Enum {
+ method public static java.time.format.ResolverStyle valueOf(java.lang.String);
+ method public static final java.time.format.ResolverStyle[] values();
+ enum_constant public static final java.time.format.ResolverStyle LENIENT;
+ enum_constant public static final java.time.format.ResolverStyle SMART;
+ enum_constant public static final java.time.format.ResolverStyle STRICT;
+ }
+
+ public final class SignStyle extends java.lang.Enum {
+ method public static java.time.format.SignStyle valueOf(java.lang.String);
+ method public static final java.time.format.SignStyle[] values();
+ enum_constant public static final java.time.format.SignStyle ALWAYS;
+ enum_constant public static final java.time.format.SignStyle EXCEEDS_PAD;
+ enum_constant public static final java.time.format.SignStyle NEVER;
+ enum_constant public static final java.time.format.SignStyle NORMAL;
+ enum_constant public static final java.time.format.SignStyle NOT_NEGATIVE;
+ }
+
+ public final class TextStyle extends java.lang.Enum {
+ method public java.time.format.TextStyle asNormal();
+ method public java.time.format.TextStyle asStandalone();
+ method public boolean isStandalone();
+ method public static java.time.format.TextStyle valueOf(java.lang.String);
+ method public static final java.time.format.TextStyle[] values();
+ enum_constant public static final java.time.format.TextStyle FULL;
+ enum_constant public static final java.time.format.TextStyle FULL_STANDALONE;
+ enum_constant public static final java.time.format.TextStyle NARROW;
+ enum_constant public static final java.time.format.TextStyle NARROW_STANDALONE;
+ enum_constant public static final java.time.format.TextStyle SHORT;
+ enum_constant public static final java.time.format.TextStyle SHORT_STANDALONE;
+ }
+
+}
+
+package java.time.temporal {
+
+ public final class ChronoField extends java.lang.Enum implements java.time.temporal.TemporalField {
+ method public <R extends java.time.temporal.Temporal> R adjustInto(R, long);
+ method public int checkValidIntValue(long);
+ method public long checkValidValue(long);
+ method public java.time.temporal.TemporalUnit getBaseUnit();
+ method public java.lang.String getDisplayName(java.util.Locale);
+ method public long getFrom(java.time.temporal.TemporalAccessor);
+ method public java.time.temporal.TemporalUnit getRangeUnit();
+ method public boolean isDateBased();
+ method public boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ method public boolean isTimeBased();
+ method public java.time.temporal.ValueRange range();
+ method public java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ method public static java.time.temporal.ChronoField valueOf(java.lang.String);
+ method public static final java.time.temporal.ChronoField[] values();
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_WEEK_OF_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_WEEK_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField AMPM_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField CLOCK_HOUR_OF_AMPM;
+ enum_constant public static final java.time.temporal.ChronoField CLOCK_HOUR_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_WEEK;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField EPOCH_DAY;
+ enum_constant public static final java.time.temporal.ChronoField ERA;
+ enum_constant public static final java.time.temporal.ChronoField HOUR_OF_AMPM;
+ enum_constant public static final java.time.temporal.ChronoField HOUR_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField INSTANT_SECONDS;
+ enum_constant public static final java.time.temporal.ChronoField MICRO_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MICRO_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField MILLI_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MILLI_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField MINUTE_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MINUTE_OF_HOUR;
+ enum_constant public static final java.time.temporal.ChronoField MONTH_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField NANO_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField NANO_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField OFFSET_SECONDS;
+ enum_constant public static final java.time.temporal.ChronoField PROLEPTIC_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField SECOND_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField SECOND_OF_MINUTE;
+ enum_constant public static final java.time.temporal.ChronoField YEAR;
+ enum_constant public static final java.time.temporal.ChronoField YEAR_OF_ERA;
+ }
+
+ public final class ChronoUnit extends java.lang.Enum implements java.time.temporal.TemporalUnit {
+ method public <R extends java.time.temporal.Temporal> R addTo(R, long);
+ method public long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public java.time.Duration getDuration();
+ method public boolean isDateBased();
+ method public boolean isDurationEstimated();
+ method public boolean isSupportedBy(java.time.temporal.Temporal);
+ method public boolean isTimeBased();
+ method public static java.time.temporal.ChronoUnit valueOf(java.lang.String);
+ method public static final java.time.temporal.ChronoUnit[] values();
+ enum_constant public static final java.time.temporal.ChronoUnit CENTURIES;
+ enum_constant public static final java.time.temporal.ChronoUnit DAYS;
+ enum_constant public static final java.time.temporal.ChronoUnit DECADES;
+ enum_constant public static final java.time.temporal.ChronoUnit ERAS;
+ enum_constant public static final java.time.temporal.ChronoUnit FOREVER;
+ enum_constant public static final java.time.temporal.ChronoUnit HALF_DAYS;
+ enum_constant public static final java.time.temporal.ChronoUnit HOURS;
+ enum_constant public static final java.time.temporal.ChronoUnit MICROS;
+ enum_constant public static final java.time.temporal.ChronoUnit MILLENNIA;
+ enum_constant public static final java.time.temporal.ChronoUnit MILLIS;
+ enum_constant public static final java.time.temporal.ChronoUnit MINUTES;
+ enum_constant public static final java.time.temporal.ChronoUnit MONTHS;
+ enum_constant public static final java.time.temporal.ChronoUnit NANOS;
+ enum_constant public static final java.time.temporal.ChronoUnit SECONDS;
+ enum_constant public static final java.time.temporal.ChronoUnit WEEKS;
+ enum_constant public static final java.time.temporal.ChronoUnit YEARS;
+ }
+
+ public final class IsoFields {
+ field public static final java.time.temporal.TemporalField DAY_OF_QUARTER;
+ field public static final java.time.temporal.TemporalField QUARTER_OF_YEAR;
+ field public static final java.time.temporal.TemporalUnit QUARTER_YEARS;
+ field public static final java.time.temporal.TemporalField WEEK_BASED_YEAR;
+ field public static final java.time.temporal.TemporalUnit WEEK_BASED_YEARS;
+ field public static final java.time.temporal.TemporalField WEEK_OF_WEEK_BASED_YEAR;
+ }
+
+ public final class JulianFields {
+ field public static final java.time.temporal.TemporalField JULIAN_DAY;
+ field public static final java.time.temporal.TemporalField MODIFIED_JULIAN_DAY;
+ field public static final java.time.temporal.TemporalField RATA_DIE;
+ }
+
+ public abstract interface Temporal implements java.time.temporal.TemporalAccessor {
+ method public abstract boolean isSupported(java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ method public default java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ method public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ method public abstract java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ }
+
+ public abstract interface TemporalAccessor {
+ method public default int get(java.time.temporal.TemporalField);
+ method public abstract long getLong(java.time.temporal.TemporalField);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public default java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ }
+
+ public abstract interface TemporalAdjuster {
+ method public abstract java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ }
+
+ public final class TemporalAdjusters {
+ method public static java.time.temporal.TemporalAdjuster dayOfWeekInMonth(int, java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster firstDayOfMonth();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfNextMonth();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfNextYear();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfYear();
+ method public static java.time.temporal.TemporalAdjuster firstInMonth(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster lastDayOfMonth();
+ method public static java.time.temporal.TemporalAdjuster lastDayOfYear();
+ method public static java.time.temporal.TemporalAdjuster lastInMonth(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster next(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster nextOrSame(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster ofDateAdjuster(java.util.function.UnaryOperator<java.time.LocalDate>);
+ method public static java.time.temporal.TemporalAdjuster previous(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster previousOrSame(java.time.DayOfWeek);
+ }
+
+ public abstract interface TemporalAmount {
+ method public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public abstract long get(java.time.temporal.TemporalUnit);
+ method public abstract java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ }
+
+ public abstract interface TemporalField {
+ method public abstract <R extends java.time.temporal.Temporal> R adjustInto(R, long);
+ method public abstract java.time.temporal.TemporalUnit getBaseUnit();
+ method public default java.lang.String getDisplayName(java.util.Locale);
+ method public abstract long getFrom(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.temporal.TemporalUnit getRangeUnit();
+ method public abstract boolean isDateBased();
+ method public abstract boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ method public abstract boolean isTimeBased();
+ method public abstract java.time.temporal.ValueRange range();
+ method public abstract java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ method public default java.time.temporal.TemporalAccessor resolve(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.temporal.TemporalAccessor, java.time.format.ResolverStyle);
+ method public abstract java.lang.String toString();
+ }
+
+ public final class TemporalQueries {
+ method public static java.time.temporal.TemporalQuery<java.time.chrono.Chronology> chronology();
+ method public static java.time.temporal.TemporalQuery<java.time.LocalDate> localDate();
+ method public static java.time.temporal.TemporalQuery<java.time.LocalTime> localTime();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneOffset> offset();
+ method public static java.time.temporal.TemporalQuery<java.time.temporal.TemporalUnit> precision();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneId> zone();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneId> zoneId();
+ }
+
+ public abstract interface TemporalQuery<R> {
+ method public abstract R queryFrom(java.time.temporal.TemporalAccessor);
+ }
+
+ public abstract interface TemporalUnit {
+ method public abstract <R extends java.time.temporal.Temporal> R addTo(R, long);
+ method public abstract long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public abstract java.time.Duration getDuration();
+ method public abstract boolean isDateBased();
+ method public abstract boolean isDurationEstimated();
+ method public default boolean isSupportedBy(java.time.temporal.Temporal);
+ method public abstract boolean isTimeBased();
+ method public abstract java.lang.String toString();
+ }
+
+ public class UnsupportedTemporalTypeException extends java.time.DateTimeException {
+ ctor public UnsupportedTemporalTypeException(java.lang.String);
+ ctor public UnsupportedTemporalTypeException(java.lang.String, java.lang.Throwable);
+ }
+
+ public final class ValueRange implements java.io.Serializable {
+ method public int checkValidIntValue(long, java.time.temporal.TemporalField);
+ method public long checkValidValue(long, java.time.temporal.TemporalField);
+ method public long getLargestMinimum();
+ method public long getMaximum();
+ method public long getMinimum();
+ method public long getSmallestMaximum();
+ method public boolean isFixed();
+ method public boolean isIntValue();
+ method public boolean isValidIntValue(long);
+ method public boolean isValidValue(long);
+ method public static java.time.temporal.ValueRange of(long, long);
+ method public static java.time.temporal.ValueRange of(long, long, long);
+ method public static java.time.temporal.ValueRange of(long, long, long, long);
+ }
+
+ public final class WeekFields implements java.io.Serializable {
+ method public java.time.temporal.TemporalField dayOfWeek();
+ method public java.time.DayOfWeek getFirstDayOfWeek();
+ method public int getMinimalDaysInFirstWeek();
+ method public static java.time.temporal.WeekFields of(java.util.Locale);
+ method public static java.time.temporal.WeekFields of(java.time.DayOfWeek, int);
+ method public java.time.temporal.TemporalField weekBasedYear();
+ method public java.time.temporal.TemporalField weekOfMonth();
+ method public java.time.temporal.TemporalField weekOfWeekBasedYear();
+ method public java.time.temporal.TemporalField weekOfYear();
+ field public static final java.time.temporal.WeekFields ISO;
+ field public static final java.time.temporal.WeekFields SUNDAY_START;
+ field public static final java.time.temporal.TemporalUnit WEEK_BASED_YEARS;
+ }
+
+}
+
+package java.time.zone {
+
+ public final class ZoneOffsetTransition implements java.lang.Comparable java.io.Serializable {
+ method public int compareTo(java.time.zone.ZoneOffsetTransition);
+ method public java.time.LocalDateTime getDateTimeAfter();
+ method public java.time.LocalDateTime getDateTimeBefore();
+ method public java.time.Duration getDuration();
+ method public java.time.Instant getInstant();
+ method public java.time.ZoneOffset getOffsetAfter();
+ method public java.time.ZoneOffset getOffsetBefore();
+ method public boolean isGap();
+ method public boolean isOverlap();
+ method public boolean isValidOffset(java.time.ZoneOffset);
+ method public static java.time.zone.ZoneOffsetTransition of(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ method public long toEpochSecond();
+ }
+
+ public final class ZoneOffsetTransitionRule implements java.io.Serializable {
+ method public java.time.zone.ZoneOffsetTransition createTransition(int);
+ method public int getDayOfMonthIndicator();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public java.time.LocalTime getLocalTime();
+ method public java.time.Month getMonth();
+ method public java.time.ZoneOffset getOffsetAfter();
+ method public java.time.ZoneOffset getOffsetBefore();
+ method public java.time.ZoneOffset getStandardOffset();
+ method public java.time.zone.ZoneOffsetTransitionRule.TimeDefinition getTimeDefinition();
+ method public boolean isMidnightEndOfDay();
+ method public static java.time.zone.ZoneOffsetTransitionRule of(java.time.Month, int, java.time.DayOfWeek, java.time.LocalTime, boolean, java.time.zone.ZoneOffsetTransitionRule.TimeDefinition, java.time.ZoneOffset, java.time.ZoneOffset, java.time.ZoneOffset);
+ }
+
+ public static final class ZoneOffsetTransitionRule.TimeDefinition extends java.lang.Enum {
+ method public java.time.LocalDateTime createDateTime(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ method public static java.time.zone.ZoneOffsetTransitionRule.TimeDefinition valueOf(java.lang.String);
+ method public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition[] values();
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition STANDARD;
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition UTC;
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition WALL;
+ }
+
+ public final class ZoneRules implements java.io.Serializable {
+ method public java.time.Duration getDaylightSavings(java.time.Instant);
+ method public java.time.ZoneOffset getOffset(java.time.Instant);
+ method public java.time.ZoneOffset getOffset(java.time.LocalDateTime);
+ method public java.time.ZoneOffset getStandardOffset(java.time.Instant);
+ method public java.time.zone.ZoneOffsetTransition getTransition(java.time.LocalDateTime);
+ method public java.util.List<java.time.zone.ZoneOffsetTransitionRule> getTransitionRules();
+ method public java.util.List<java.time.zone.ZoneOffsetTransition> getTransitions();
+ method public java.util.List<java.time.ZoneOffset> getValidOffsets(java.time.LocalDateTime);
+ method public boolean isDaylightSavings(java.time.Instant);
+ method public boolean isFixedOffset();
+ method public boolean isValidOffset(java.time.LocalDateTime, java.time.ZoneOffset);
+ method public java.time.zone.ZoneOffsetTransition nextTransition(java.time.Instant);
+ method public static java.time.zone.ZoneRules of(java.time.ZoneOffset, java.time.ZoneOffset, java.util.List<java.time.zone.ZoneOffsetTransition>, java.util.List<java.time.zone.ZoneOffsetTransition>, java.util.List<java.time.zone.ZoneOffsetTransitionRule>);
+ method public static java.time.zone.ZoneRules of(java.time.ZoneOffset);
+ method public java.time.zone.ZoneOffsetTransition previousTransition(java.time.Instant);
+ }
+
+ public class ZoneRulesException extends java.time.DateTimeException {
+ ctor public ZoneRulesException(java.lang.String);
+ ctor public ZoneRulesException(java.lang.String, java.lang.Throwable);
+ }
+
+}
+
package java.util {
public abstract class AbstractCollection<E> implements java.util.Collection {
@@ -58704,7 +60334,9 @@
method public int get(int);
method public int getActualMaximum(int);
method public int getActualMinimum(int);
+ method public static java.util.Set<java.lang.String> getAvailableCalendarTypes();
method public static synchronized java.util.Locale[] getAvailableLocales();
+ method public java.lang.String getCalendarType();
method public java.lang.String getDisplayName(int, int, java.util.Locale);
method public java.util.Map<java.lang.String, java.lang.Integer> getDisplayNames(int, int, java.util.Locale);
method public int getFirstDayOfWeek();
@@ -58739,6 +60371,7 @@
method public void setTimeInMillis(long);
method public void setTimeZone(java.util.TimeZone);
method public void setWeekDate(int, int, int);
+ method public final java.time.Instant toInstant();
field public static final int ALL_STYLES = 0; // 0x0
field public static final int AM = 0; // 0x0
field public static final int AM_PM = 9; // 0x9
@@ -58761,12 +60394,16 @@
field public static final int JULY = 6; // 0x6
field public static final int JUNE = 5; // 0x5
field public static final int LONG = 2; // 0x2
+ field public static final int LONG_FORMAT = 2; // 0x2
+ field public static final int LONG_STANDALONE = 32770; // 0x8002
field public static final int MARCH = 2; // 0x2
field public static final int MAY = 4; // 0x4
field public static final int MILLISECOND = 14; // 0xe
field public static final int MINUTE = 12; // 0xc
field public static final int MONDAY = 2; // 0x2
field public static final int MONTH = 2; // 0x2
+ field public static final int NARROW_FORMAT = 4; // 0x4
+ field public static final int NARROW_STANDALONE = 32772; // 0x8004
field public static final int NOVEMBER = 10; // 0xa
field public static final int OCTOBER = 9; // 0x9
field public static final int PM = 1; // 0x1
@@ -58774,6 +60411,8 @@
field public static final int SECOND = 13; // 0xd
field public static final int SEPTEMBER = 8; // 0x8
field public static final int SHORT = 1; // 0x1
+ field public static final int SHORT_FORMAT = 1; // 0x1
+ field public static final int SHORT_STANDALONE = 32769; // 0x8001
field public static final int SUNDAY = 1; // 0x1
field public static final int THURSDAY = 5; // 0x5
field public static final int TUESDAY = 3; // 0x3
@@ -58790,6 +60429,24 @@
field protected long time;
}
+ public static class Calendar.Builder {
+ ctor public Calendar.Builder();
+ method public java.util.Calendar build();
+ method public java.util.Calendar.Builder set(int, int);
+ method public java.util.Calendar.Builder setCalendarType(java.lang.String);
+ method public java.util.Calendar.Builder setDate(int, int, int);
+ method public java.util.Calendar.Builder setFields(int...);
+ method public java.util.Calendar.Builder setInstant(long);
+ method public java.util.Calendar.Builder setInstant(java.util.Date);
+ method public java.util.Calendar.Builder setLenient(boolean);
+ method public java.util.Calendar.Builder setLocale(java.util.Locale);
+ method public java.util.Calendar.Builder setTimeOfDay(int, int, int);
+ method public java.util.Calendar.Builder setTimeOfDay(int, int, int, int);
+ method public java.util.Calendar.Builder setTimeZone(java.util.TimeZone);
+ method public java.util.Calendar.Builder setWeekDate(int, int, int);
+ method public java.util.Calendar.Builder setWeekDefinition(int, int);
+ }
+
public abstract interface Collection<E> implements java.lang.Iterable {
method public abstract boolean add(E);
method public abstract boolean addAll(java.util.Collection<? extends E>);
@@ -58925,6 +60582,7 @@
method public boolean before(java.util.Date);
method public java.lang.Object clone();
method public int compareTo(java.util.Date);
+ method public static java.util.Date from(java.time.Instant);
method public deprecated int getDate();
method public deprecated int getDay();
method public deprecated int getHours();
@@ -58943,6 +60601,7 @@
method public void setTime(long);
method public deprecated void setYear(int);
method public deprecated java.lang.String toGMTString();
+ method public java.time.Instant toInstant();
method public deprecated java.lang.String toLocaleString();
}
@@ -59112,6 +60771,7 @@
method public void add(int, int);
method protected void computeFields();
method protected void computeTime();
+ method public static java.util.GregorianCalendar from(java.time.ZonedDateTime);
method public int getGreatestMinimum(int);
method public final java.util.Date getGregorianChange();
method public int getLeastMaximum(int);
@@ -59121,6 +60781,7 @@
method public final boolean isWeekDateSupported();
method public void roll(int, boolean);
method public void setGregorianChange(java.util.Date);
+ method public java.time.ZonedDateTime toZonedDateTime();
field public static final int AD = 1; // 0x1
field public static final int BC = 0; // 0x0
}
@@ -60148,12 +61809,14 @@
method public int getOffset(long);
method public abstract int getRawOffset();
method public static synchronized java.util.TimeZone getTimeZone(java.lang.String);
+ method public static java.util.TimeZone getTimeZone(java.time.ZoneId);
method public boolean hasSameRules(java.util.TimeZone);
method public abstract boolean inDaylightTime(java.util.Date);
method public boolean observesDaylightTime();
method public static synchronized void setDefault(java.util.TimeZone);
method public void setID(java.lang.String);
method public abstract void setRawOffset(int);
+ method public java.time.ZoneId toZoneId();
method public abstract boolean useDaylightTime();
field public static final int LONG = 1; // 0x1
field public static final int SHORT = 0; // 0x0
@@ -60760,31 +62423,31 @@
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
ctor public CopyOnWriteArrayList(E[]);
- method public synchronized boolean add(E);
- method public synchronized void add(int, E);
- method public synchronized boolean addAll(java.util.Collection<? extends E>);
- method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
- method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
- method public synchronized boolean addIfAbsent(E);
- method public synchronized void clear();
+ method public boolean add(E);
+ method public void add(int, E);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public boolean addAll(int, java.util.Collection<? extends E>);
+ method public int addAllAbsent(java.util.Collection<? extends E>);
+ method public boolean addIfAbsent(E);
+ method public void clear();
method public java.lang.Object clone();
method public boolean contains(java.lang.Object);
method public boolean containsAll(java.util.Collection<?>);
method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
- method public int indexOf(E, int);
method public int indexOf(java.lang.Object);
+ method public int indexOf(E, int);
method public boolean isEmpty();
method public java.util.Iterator<E> iterator();
- method public int lastIndexOf(E, int);
method public int lastIndexOf(java.lang.Object);
- method public java.util.ListIterator<E> listIterator(int);
+ method public int lastIndexOf(E, int);
method public java.util.ListIterator<E> listIterator();
- method public synchronized E remove(int);
- method public synchronized boolean remove(java.lang.Object);
- method public synchronized boolean removeAll(java.util.Collection<?>);
- method public synchronized boolean retainAll(java.util.Collection<?>);
- method public synchronized E set(int, E);
+ method public java.util.ListIterator<E> listIterator(int);
+ method public E remove(int);
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public E set(int, E);
method public int size();
method public java.util.List<E> subList(int, int);
method public java.lang.Object[] toArray();
@@ -62635,10 +64298,12 @@
method public java.lang.StringBuffer appendTail(java.lang.StringBuffer);
method public int end();
method public int end(int);
+ method public int end(java.lang.String);
method public boolean find();
method public boolean find(int);
method public java.lang.String group();
method public java.lang.String group(int);
+ method public java.lang.String group(java.lang.String);
method public int groupCount();
method public boolean hasAnchoringBounds();
method public boolean hasTransparentBounds();
@@ -62657,6 +64322,7 @@
method public java.util.regex.Matcher reset(java.lang.CharSequence);
method public int start();
method public int start(int) throws java.lang.IllegalStateException;
+ method public int start(java.lang.String);
method public java.util.regex.MatchResult toMatchResult();
method public java.util.regex.Matcher useAnchoringBounds(boolean);
method public java.util.regex.Matcher usePattern(java.util.regex.Pattern);
diff --git a/api/system-current.txt b/api/system-current.txt
index 2e32179..49dc7c5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40,6 +40,7 @@
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
+ field public static final java.lang.String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE";
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
field public static final java.lang.String BIND_PRINT_RECOMMENDATION_SERVICE = "android.permission.BIND_PRINT_RECOMMENDATION_SERVICE";
@@ -62,7 +63,7 @@
field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
field public static final java.lang.String BODY_SENSORS = "android.permission.BODY_SENSORS";
field public static final java.lang.String BRICK = "android.permission.BRICK";
- field public static final java.lang.String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED";
+ field public static final deprecated java.lang.String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED";
field public static final java.lang.String BROADCAST_PACKAGE_REMOVED = "android.permission.BROADCAST_PACKAGE_REMOVED";
field public static final java.lang.String BROADCAST_SMS = "android.permission.BROADCAST_SMS";
field public static final java.lang.String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY";
@@ -196,6 +197,7 @@
field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
+ field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
@@ -8559,6 +8561,7 @@
field public static final java.lang.String USER_SERVICE = "user";
field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+ field public static final java.lang.String WIFI_AWARE_SERVICE = "wifiaware";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
field public static final java.lang.String WIFI_RTT_SERVICE = "rttmanager";
field public static final java.lang.String WIFI_SCANNING_SERVICE = "wifiscanner";
@@ -10266,6 +10269,7 @@
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
+ field public static final java.lang.String FEATURE_WIFI_AWARE = "android.hardware.wifi.aware";
field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
@@ -25604,6 +25608,7 @@
field public static final int TRANSPORT_ETHERNET = 3; // 0x3
field public static final int TRANSPORT_VPN = 4; // 0x4
field public static final int TRANSPORT_WIFI = 1; // 0x1
+ field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
}
public class NetworkInfo implements android.os.Parcelable {
@@ -25760,6 +25765,14 @@
field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
}
+ public static final class RecommendationRequest.Builder {
+ ctor public RecommendationRequest.Builder();
+ method public android.net.RecommendationRequest build();
+ method public android.net.RecommendationRequest.Builder setCurrentRecommendedWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setNetworkCapabilities(android.net.NetworkCapabilities);
+ method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
+ }
+
public final class RecommendationResult implements android.os.Parcelable {
method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
method public static android.net.RecommendationResult createDoNotConnectRecommendation();
@@ -25824,10 +25837,16 @@
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, android.os.Bundle);
+ method public int calculateBadge(int);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
+ field public static final int BADGING_4K = 30; // 0x1e
+ field public static final int BADGING_HD = 20; // 0x14
+ field public static final int BADGING_NONE = 0; // 0x0
+ field public static final int BADGING_SD = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
field public final android.os.Bundle attributes;
field public final boolean meteredHint;
@@ -25835,6 +25854,9 @@
field public final android.net.RssiCurve rssiCurve;
}
+ public static abstract class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
+ }
+
public class TrafficStats {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
@@ -26843,6 +26865,8 @@
public class WifiConfiguration implements android.os.Parcelable {
ctor public WifiConfiguration();
method public int describeContents();
+ method public boolean hasNoInternetAccess();
+ method public boolean isNoInternetAccessExpected();
method public boolean isPasspoint();
method public void writeToParcel(android.os.Parcel, int);
field public java.lang.String BSSID;
@@ -27015,6 +27039,7 @@
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
+ method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
method public android.net.wifi.WifiManager.WifiLock createWifiLock(java.lang.String);
@@ -27114,6 +27139,11 @@
field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
}
+ public static abstract interface WifiManager.ActionListener {
+ method public abstract void onFailure(int);
+ method public abstract void onSuccess();
+ }
+
public class WifiManager.MulticastLock {
method public void acquire();
method public boolean isHeld();
@@ -27294,6 +27324,122 @@
}
+package android.net.wifi.aware {
+
+ public class AttachCallback {
+ ctor public AttachCallback();
+ method public void onAttachFailed();
+ method public void onAttached(android.net.wifi.aware.WifiAwareSession);
+ }
+
+ public final class Characteristics implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxMatchFilterLength();
+ method public int getMaxServiceNameLength();
+ method public int getMaxServiceSpecificInfoLength();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
+ }
+
+ public class DiscoverySession {
+ method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void destroy();
+ method public static int getMaxSendRetryCount();
+ method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
+ method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
+ }
+
+ public class DiscoverySessionCallback {
+ ctor public DiscoverySessionCallback();
+ method public void onMessageReceived(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void onMessageSendFailed(int);
+ method public void onMessageSendSucceeded(int);
+ method public void onPublishStarted(android.net.wifi.aware.PublishDiscoverySession);
+ method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
+ method public void onSessionConfigFailed();
+ method public void onSessionConfigUpdated();
+ method public void onSessionTerminated();
+ method public void onSubscribeStarted(android.net.wifi.aware.SubscribeDiscoverySession);
+ }
+
+ public class IdentityChangedListener {
+ ctor public IdentityChangedListener();
+ method public void onIdentityChanged(byte[]);
+ }
+
+ public class PeerHandle {
+ }
+
+ public final class PublishConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.PublishConfig> CREATOR;
+ field public static final int PUBLISH_TYPE_SOLICITED = 1; // 0x1
+ field public static final int PUBLISH_TYPE_UNSOLICITED = 0; // 0x0
+ }
+
+ public static final class PublishConfig.Builder {
+ ctor public PublishConfig.Builder();
+ method public android.net.wifi.aware.PublishConfig build();
+ method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(java.util.List<byte[]>);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishCount(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceName(java.lang.String);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(byte[]);
+ method public android.net.wifi.aware.PublishConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.PublishConfig.Builder setTtlSec(int);
+ }
+
+ public class PublishDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updatePublish(android.net.wifi.aware.PublishConfig);
+ }
+
+ public final class SubscribeConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR;
+ field public static final int MATCH_STYLE_ALL = 1; // 0x1
+ field public static final int MATCH_STYLE_FIRST_ONLY = 0; // 0x0
+ field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1
+ field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0
+ }
+
+ public static final class SubscribeConfig.Builder {
+ ctor public SubscribeConfig.Builder();
+ method public android.net.wifi.aware.SubscribeConfig build();
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(java.util.List<byte[]>);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeCount(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
+ }
+
+ public class SubscribeDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updateSubscribe(android.net.wifi.aware.SubscribeConfig);
+ }
+
+ public class WifiAwareManager {
+ method public void attach(android.net.wifi.aware.AttachCallback, android.os.Handler);
+ method public void attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler);
+ method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method public boolean isAvailable();
+ field public static final java.lang.String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
+ }
+
+ public class WifiAwareSession {
+ method public java.lang.String createNetworkSpecifier(int, byte[], byte[]);
+ method public void destroy();
+ method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
+ method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -40626,6 +40772,8 @@
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getImei();
+ method public java.lang.String getImei(int);
method public java.lang.String getLine1Number();
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
@@ -58374,8 +58522,10 @@
public final class FileTime implements java.lang.Comparable {
method public int compareTo(java.nio.file.attribute.FileTime);
method public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
+ method public static java.nio.file.attribute.FileTime from(java.time.Instant);
method public static java.nio.file.attribute.FileTime fromMillis(long);
method public long to(java.util.concurrent.TimeUnit);
+ method public java.time.Instant toInstant();
method public long toMillis();
}
@@ -61905,6 +62055,1515 @@
}
+package java.time {
+
+ public abstract class Clock {
+ ctor protected Clock();
+ method public static java.time.Clock fixed(java.time.Instant, java.time.ZoneId);
+ method public abstract java.time.ZoneId getZone();
+ method public abstract java.time.Instant instant();
+ method public long millis();
+ method public static java.time.Clock offset(java.time.Clock, java.time.Duration);
+ method public static java.time.Clock system(java.time.ZoneId);
+ method public static java.time.Clock systemDefaultZone();
+ method public static java.time.Clock systemUTC();
+ method public static java.time.Clock tick(java.time.Clock, java.time.Duration);
+ method public static java.time.Clock tickMinutes(java.time.ZoneId);
+ method public static java.time.Clock tickSeconds(java.time.ZoneId);
+ method public abstract java.time.Clock withZone(java.time.ZoneId);
+ }
+
+ public class DateTimeException extends java.lang.RuntimeException {
+ ctor public DateTimeException(java.lang.String);
+ ctor public DateTimeException(java.lang.String, java.lang.Throwable);
+ }
+
+ public final class DayOfWeek extends java.lang.Enum implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public static java.time.DayOfWeek from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.DayOfWeek minus(long);
+ method public static java.time.DayOfWeek of(int);
+ method public java.time.DayOfWeek plus(long);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.DayOfWeek valueOf(java.lang.String);
+ method public static final java.time.DayOfWeek[] values();
+ enum_constant public static final java.time.DayOfWeek FRIDAY;
+ enum_constant public static final java.time.DayOfWeek MONDAY;
+ enum_constant public static final java.time.DayOfWeek SATURDAY;
+ enum_constant public static final java.time.DayOfWeek SUNDAY;
+ enum_constant public static final java.time.DayOfWeek THURSDAY;
+ enum_constant public static final java.time.DayOfWeek TUESDAY;
+ enum_constant public static final java.time.DayOfWeek WEDNESDAY;
+ }
+
+ public final class Duration implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAmount {
+ method public java.time.Duration abs();
+ method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.Duration between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public int compareTo(java.time.Duration);
+ method public java.time.Duration dividedBy(long);
+ method public static java.time.Duration from(java.time.temporal.TemporalAmount);
+ method public long get(java.time.temporal.TemporalUnit);
+ method public int getNano();
+ method public long getSeconds();
+ method public java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public boolean isNegative();
+ method public boolean isZero();
+ method public java.time.Duration minus(java.time.Duration);
+ method public java.time.Duration minus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Duration minusDays(long);
+ method public java.time.Duration minusHours(long);
+ method public java.time.Duration minusMillis(long);
+ method public java.time.Duration minusMinutes(long);
+ method public java.time.Duration minusNanos(long);
+ method public java.time.Duration minusSeconds(long);
+ method public java.time.Duration multipliedBy(long);
+ method public java.time.Duration negated();
+ method public static java.time.Duration of(long, java.time.temporal.TemporalUnit);
+ method public static java.time.Duration ofDays(long);
+ method public static java.time.Duration ofHours(long);
+ method public static java.time.Duration ofMillis(long);
+ method public static java.time.Duration ofMinutes(long);
+ method public static java.time.Duration ofNanos(long);
+ method public static java.time.Duration ofSeconds(long);
+ method public static java.time.Duration ofSeconds(long, long);
+ method public static java.time.Duration parse(java.lang.CharSequence);
+ method public java.time.Duration plus(java.time.Duration);
+ method public java.time.Duration plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Duration plusDays(long);
+ method public java.time.Duration plusHours(long);
+ method public java.time.Duration plusMillis(long);
+ method public java.time.Duration plusMinutes(long);
+ method public java.time.Duration plusNanos(long);
+ method public java.time.Duration plusSeconds(long);
+ method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public long toDays();
+ method public long toHours();
+ method public long toMillis();
+ method public long toMinutes();
+ method public long toNanos();
+ method public java.time.Duration withNanos(int);
+ method public java.time.Duration withSeconds(long);
+ field public static final java.time.Duration ZERO;
+ }
+
+ public final class Instant implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ method public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ method public int compareTo(java.time.Instant);
+ method public static java.time.Instant from(java.time.temporal.TemporalAccessor);
+ method public long getEpochSecond();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getNano();
+ method public boolean isAfter(java.time.Instant);
+ method public boolean isBefore(java.time.Instant);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.Instant minusMillis(long);
+ method public java.time.Instant minusNanos(long);
+ method public java.time.Instant minusSeconds(long);
+ method public static java.time.Instant now();
+ method public static java.time.Instant now(java.time.Clock);
+ method public static java.time.Instant ofEpochMilli(long);
+ method public static java.time.Instant ofEpochSecond(long);
+ method public static java.time.Instant ofEpochSecond(long, long);
+ method public static java.time.Instant parse(java.lang.CharSequence);
+ method public java.time.Instant plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Instant plusMillis(long);
+ method public java.time.Instant plusNanos(long);
+ method public java.time.Instant plusSeconds(long);
+ method public long toEpochMilli();
+ method public java.time.Instant truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Instant with(java.time.temporal.TemporalField, long);
+ field public static final java.time.Instant EPOCH;
+ field public static final java.time.Instant MAX;
+ field public static final java.time.Instant MIN;
+ }
+
+ public final class LocalDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.LocalDateTime atStartOfDay();
+ method public java.time.ZonedDateTime atStartOfDay(java.time.ZoneId);
+ method public java.time.LocalDateTime atTime(int, int);
+ method public java.time.LocalDateTime atTime(int, int, int);
+ method public java.time.LocalDateTime atTime(int, int, int, int);
+ method public java.time.OffsetDateTime atTime(java.time.OffsetTime);
+ method public static java.time.LocalDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.IsoChronology getChronology();
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getYear();
+ method public int lengthOfMonth();
+ method public java.time.LocalDate minusDays(long);
+ method public java.time.LocalDate minusMonths(long);
+ method public java.time.LocalDate minusWeeks(long);
+ method public java.time.LocalDate minusYears(long);
+ method public static java.time.LocalDate now();
+ method public static java.time.LocalDate now(java.time.ZoneId);
+ method public static java.time.LocalDate now(java.time.Clock);
+ method public static java.time.LocalDate of(int, java.time.Month, int);
+ method public static java.time.LocalDate of(int, int, int);
+ method public static java.time.LocalDate ofEpochDay(long);
+ method public static java.time.LocalDate ofYearDay(int, int);
+ method public static java.time.LocalDate parse(java.lang.CharSequence);
+ method public static java.time.LocalDate parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalDate plusDays(long);
+ method public java.time.LocalDate plusMonths(long);
+ method public java.time.LocalDate plusWeeks(long);
+ method public java.time.LocalDate plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Period until(java.time.chrono.ChronoLocalDate);
+ method public java.time.LocalDate withDayOfMonth(int);
+ method public java.time.LocalDate withDayOfYear(int);
+ method public java.time.LocalDate withMonth(int);
+ method public java.time.LocalDate withYear(int);
+ field public static final java.time.LocalDate MAX;
+ field public static final java.time.LocalDate MIN;
+ }
+
+ public final class LocalDateTime implements java.time.chrono.ChronoLocalDateTime java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ method public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ method public static java.time.LocalDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public int getSecond();
+ method public int getYear();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.LocalDateTime minusDays(long);
+ method public java.time.LocalDateTime minusHours(long);
+ method public java.time.LocalDateTime minusMinutes(long);
+ method public java.time.LocalDateTime minusMonths(long);
+ method public java.time.LocalDateTime minusNanos(long);
+ method public java.time.LocalDateTime minusSeconds(long);
+ method public java.time.LocalDateTime minusWeeks(long);
+ method public java.time.LocalDateTime minusYears(long);
+ method public static java.time.LocalDateTime now();
+ method public static java.time.LocalDateTime now(java.time.ZoneId);
+ method public static java.time.LocalDateTime now(java.time.Clock);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(java.time.LocalDate, java.time.LocalTime);
+ method public static java.time.LocalDateTime ofEpochSecond(long, int, java.time.ZoneOffset);
+ method public static java.time.LocalDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.LocalDateTime parse(java.lang.CharSequence);
+ method public static java.time.LocalDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.LocalDateTime plusDays(long);
+ method public java.time.LocalDateTime plusHours(long);
+ method public java.time.LocalDateTime plusMinutes(long);
+ method public java.time.LocalDateTime plusMonths(long);
+ method public java.time.LocalDateTime plusNanos(long);
+ method public java.time.LocalDateTime plusSeconds(long);
+ method public java.time.LocalDateTime plusWeeks(long);
+ method public java.time.LocalDateTime plusYears(long);
+ method public java.time.LocalDate toLocalDate();
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.LocalDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.LocalDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.LocalDateTime withDayOfMonth(int);
+ method public java.time.LocalDateTime withDayOfYear(int);
+ method public java.time.LocalDateTime withHour(int);
+ method public java.time.LocalDateTime withMinute(int);
+ method public java.time.LocalDateTime withMonth(int);
+ method public java.time.LocalDateTime withNano(int);
+ method public java.time.LocalDateTime withSecond(int);
+ method public java.time.LocalDateTime withYear(int);
+ field public static final java.time.LocalDateTime MAX;
+ field public static final java.time.LocalDateTime MIN;
+ }
+
+ public final class LocalTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDateTime atDate(java.time.LocalDate);
+ method public java.time.OffsetTime atOffset(java.time.ZoneOffset);
+ method public int compareTo(java.time.LocalTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.LocalTime from(java.time.temporal.TemporalAccessor);
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public int getNano();
+ method public int getSecond();
+ method public boolean isAfter(java.time.LocalTime);
+ method public boolean isBefore(java.time.LocalTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime minusHours(long);
+ method public java.time.LocalTime minusMinutes(long);
+ method public java.time.LocalTime minusNanos(long);
+ method public java.time.LocalTime minusSeconds(long);
+ method public static java.time.LocalTime now();
+ method public static java.time.LocalTime now(java.time.ZoneId);
+ method public static java.time.LocalTime now(java.time.Clock);
+ method public static java.time.LocalTime of(int, int);
+ method public static java.time.LocalTime of(int, int, int);
+ method public static java.time.LocalTime of(int, int, int, int);
+ method public static java.time.LocalTime ofNanoOfDay(long);
+ method public static java.time.LocalTime ofSecondOfDay(long);
+ method public static java.time.LocalTime parse(java.lang.CharSequence);
+ method public static java.time.LocalTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime plusHours(long);
+ method public java.time.LocalTime plusMinutes(long);
+ method public java.time.LocalTime plusNanos(long);
+ method public java.time.LocalTime plusSeconds(long);
+ method public long toNanoOfDay();
+ method public int toSecondOfDay();
+ method public java.time.LocalTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime with(java.time.temporal.TemporalField, long);
+ method public java.time.LocalTime withHour(int);
+ method public java.time.LocalTime withMinute(int);
+ method public java.time.LocalTime withNano(int);
+ method public java.time.LocalTime withSecond(int);
+ field public static final java.time.LocalTime MAX;
+ field public static final java.time.LocalTime MIDNIGHT;
+ field public static final java.time.LocalTime MIN;
+ field public static final java.time.LocalTime NOON;
+ }
+
+ public final class Month extends java.lang.Enum implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public int firstDayOfYear(boolean);
+ method public java.time.Month firstMonthOfQuarter();
+ method public static java.time.Month from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public int length(boolean);
+ method public int maxLength();
+ method public int minLength();
+ method public java.time.Month minus(long);
+ method public static java.time.Month of(int);
+ method public java.time.Month plus(long);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.Month valueOf(java.lang.String);
+ method public static final java.time.Month[] values();
+ enum_constant public static final java.time.Month APRIL;
+ enum_constant public static final java.time.Month AUGUST;
+ enum_constant public static final java.time.Month DECEMBER;
+ enum_constant public static final java.time.Month FEBRUARY;
+ enum_constant public static final java.time.Month JANUARY;
+ enum_constant public static final java.time.Month JULY;
+ enum_constant public static final java.time.Month JUNE;
+ enum_constant public static final java.time.Month MARCH;
+ enum_constant public static final java.time.Month MAY;
+ enum_constant public static final java.time.Month NOVEMBER;
+ enum_constant public static final java.time.Month OCTOBER;
+ enum_constant public static final java.time.Month SEPTEMBER;
+ }
+
+ public final class MonthDay implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atYear(int);
+ method public int compareTo(java.time.MonthDay);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.MonthDay from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public boolean isAfter(java.time.MonthDay);
+ method public boolean isBefore(java.time.MonthDay);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isValidYear(int);
+ method public static java.time.MonthDay now();
+ method public static java.time.MonthDay now(java.time.ZoneId);
+ method public static java.time.MonthDay now(java.time.Clock);
+ method public static java.time.MonthDay of(java.time.Month, int);
+ method public static java.time.MonthDay of(int, int);
+ method public static java.time.MonthDay parse(java.lang.CharSequence);
+ method public static java.time.MonthDay parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.MonthDay with(java.time.Month);
+ method public java.time.MonthDay withDayOfMonth(int);
+ method public java.time.MonthDay withMonth(int);
+ }
+
+ public final class OffsetDateTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.ZonedDateTime atZoneSameInstant(java.time.ZoneId);
+ method public java.time.ZonedDateTime atZoneSimilarLocal(java.time.ZoneId);
+ method public int compareTo(java.time.OffsetDateTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.OffsetDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public int getYear();
+ method public boolean isAfter(java.time.OffsetDateTime);
+ method public boolean isBefore(java.time.OffsetDateTime);
+ method public boolean isEqual(java.time.OffsetDateTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime minusDays(long);
+ method public java.time.OffsetDateTime minusHours(long);
+ method public java.time.OffsetDateTime minusMinutes(long);
+ method public java.time.OffsetDateTime minusMonths(long);
+ method public java.time.OffsetDateTime minusNanos(long);
+ method public java.time.OffsetDateTime minusSeconds(long);
+ method public java.time.OffsetDateTime minusWeeks(long);
+ method public java.time.OffsetDateTime minusYears(long);
+ method public static java.time.OffsetDateTime now();
+ method public static java.time.OffsetDateTime now(java.time.ZoneId);
+ method public static java.time.OffsetDateTime now(java.time.Clock);
+ method public static java.time.OffsetDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime of(java.time.LocalDateTime, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime of(int, int, int, int, int, int, int, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.OffsetDateTime parse(java.lang.CharSequence);
+ method public static java.time.OffsetDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.OffsetDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime plusDays(long);
+ method public java.time.OffsetDateTime plusHours(long);
+ method public java.time.OffsetDateTime plusMinutes(long);
+ method public java.time.OffsetDateTime plusMonths(long);
+ method public java.time.OffsetDateTime plusNanos(long);
+ method public java.time.OffsetDateTime plusSeconds(long);
+ method public java.time.OffsetDateTime plusWeeks(long);
+ method public java.time.OffsetDateTime plusYears(long);
+ method public static java.util.Comparator<java.time.OffsetDateTime> timeLineOrder();
+ method public long toEpochSecond();
+ method public java.time.Instant toInstant();
+ method public java.time.LocalDate toLocalDate();
+ method public java.time.LocalDateTime toLocalDateTime();
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.OffsetTime toOffsetTime();
+ method public java.time.ZonedDateTime toZonedDateTime();
+ method public java.time.OffsetDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.OffsetDateTime withDayOfMonth(int);
+ method public java.time.OffsetDateTime withDayOfYear(int);
+ method public java.time.OffsetDateTime withHour(int);
+ method public java.time.OffsetDateTime withMinute(int);
+ method public java.time.OffsetDateTime withMonth(int);
+ method public java.time.OffsetDateTime withNano(int);
+ method public java.time.OffsetDateTime withOffsetSameInstant(java.time.ZoneOffset);
+ method public java.time.OffsetDateTime withOffsetSameLocal(java.time.ZoneOffset);
+ method public java.time.OffsetDateTime withSecond(int);
+ method public java.time.OffsetDateTime withYear(int);
+ field public static final java.time.OffsetDateTime MAX;
+ field public static final java.time.OffsetDateTime MIN;
+ }
+
+ public final class OffsetTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.OffsetDateTime atDate(java.time.LocalDate);
+ method public int compareTo(java.time.OffsetTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.OffsetTime from(java.time.temporal.TemporalAccessor);
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public boolean isAfter(java.time.OffsetTime);
+ method public boolean isBefore(java.time.OffsetTime);
+ method public boolean isEqual(java.time.OffsetTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime minusHours(long);
+ method public java.time.OffsetTime minusMinutes(long);
+ method public java.time.OffsetTime minusNanos(long);
+ method public java.time.OffsetTime minusSeconds(long);
+ method public static java.time.OffsetTime now();
+ method public static java.time.OffsetTime now(java.time.ZoneId);
+ method public static java.time.OffsetTime now(java.time.Clock);
+ method public static java.time.OffsetTime of(java.time.LocalTime, java.time.ZoneOffset);
+ method public static java.time.OffsetTime of(int, int, int, int, java.time.ZoneOffset);
+ method public static java.time.OffsetTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.OffsetTime parse(java.lang.CharSequence);
+ method public static java.time.OffsetTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.OffsetTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime plusHours(long);
+ method public java.time.OffsetTime plusMinutes(long);
+ method public java.time.OffsetTime plusNanos(long);
+ method public java.time.OffsetTime plusSeconds(long);
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.OffsetTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime with(java.time.temporal.TemporalField, long);
+ method public java.time.OffsetTime withHour(int);
+ method public java.time.OffsetTime withMinute(int);
+ method public java.time.OffsetTime withNano(int);
+ method public java.time.OffsetTime withOffsetSameInstant(java.time.ZoneOffset);
+ method public java.time.OffsetTime withOffsetSameLocal(java.time.ZoneOffset);
+ method public java.time.OffsetTime withSecond(int);
+ field public static final java.time.OffsetTime MAX;
+ field public static final java.time.OffsetTime MIN;
+ }
+
+ public final class Period implements java.time.chrono.ChronoPeriod java.io.Serializable {
+ method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.Period between(java.time.LocalDate, java.time.LocalDate);
+ method public static java.time.Period from(java.time.temporal.TemporalAmount);
+ method public long get(java.time.temporal.TemporalUnit);
+ method public java.time.chrono.IsoChronology getChronology();
+ method public int getDays();
+ method public int getMonths();
+ method public java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public int getYears();
+ method public java.time.Period minus(java.time.temporal.TemporalAmount);
+ method public java.time.Period minusDays(long);
+ method public java.time.Period minusMonths(long);
+ method public java.time.Period minusYears(long);
+ method public java.time.Period multipliedBy(int);
+ method public java.time.Period normalized();
+ method public static java.time.Period of(int, int, int);
+ method public static java.time.Period ofDays(int);
+ method public static java.time.Period ofMonths(int);
+ method public static java.time.Period ofWeeks(int);
+ method public static java.time.Period ofYears(int);
+ method public static java.time.Period parse(java.lang.CharSequence);
+ method public java.time.Period plus(java.time.temporal.TemporalAmount);
+ method public java.time.Period plusDays(long);
+ method public java.time.Period plusMonths(long);
+ method public java.time.Period plusYears(long);
+ method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public long toTotalMonths();
+ method public java.time.Period withDays(int);
+ method public java.time.Period withMonths(int);
+ method public java.time.Period withYears(int);
+ field public static final java.time.Period ZERO;
+ }
+
+ public final class Year implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atDay(int);
+ method public java.time.YearMonth atMonth(java.time.Month);
+ method public java.time.YearMonth atMonth(int);
+ method public java.time.LocalDate atMonthDay(java.time.MonthDay);
+ method public int compareTo(java.time.Year);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.Year from(java.time.temporal.TemporalAccessor);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isAfter(java.time.Year);
+ method public boolean isBefore(java.time.Year);
+ method public static boolean isLeap(long);
+ method public boolean isLeap();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public boolean isValidMonthDay(java.time.MonthDay);
+ method public int length();
+ method public java.time.Year minusYears(long);
+ method public static java.time.Year now();
+ method public static java.time.Year now(java.time.ZoneId);
+ method public static java.time.Year now(java.time.Clock);
+ method public static java.time.Year of(int);
+ method public static java.time.Year parse(java.lang.CharSequence);
+ method public static java.time.Year parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.Year plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Year plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Year with(java.time.temporal.TemporalField, long);
+ field public static final int MAX_VALUE = 999999999; // 0x3b9ac9ff
+ field public static final int MIN_VALUE = -999999999; // 0xc4653601
+ }
+
+ public final class YearMonth implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atDay(int);
+ method public java.time.LocalDate atEndOfMonth();
+ method public int compareTo(java.time.YearMonth);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.YearMonth from(java.time.temporal.TemporalAccessor);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getYear();
+ method public boolean isAfter(java.time.YearMonth);
+ method public boolean isBefore(java.time.YearMonth);
+ method public boolean isLeapYear();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public boolean isValidDay(int);
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public java.time.YearMonth minusMonths(long);
+ method public java.time.YearMonth minusYears(long);
+ method public static java.time.YearMonth now();
+ method public static java.time.YearMonth now(java.time.ZoneId);
+ method public static java.time.YearMonth now(java.time.Clock);
+ method public static java.time.YearMonth of(int, java.time.Month);
+ method public static java.time.YearMonth of(int, int);
+ method public static java.time.YearMonth parse(java.lang.CharSequence);
+ method public static java.time.YearMonth parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.YearMonth plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.YearMonth plusMonths(long);
+ method public java.time.YearMonth plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.YearMonth with(java.time.temporal.TemporalField, long);
+ method public java.time.YearMonth withMonth(int);
+ method public java.time.YearMonth withYear(int);
+ }
+
+ public abstract class ZoneId implements java.io.Serializable {
+ method public static java.time.ZoneId from(java.time.temporal.TemporalAccessor);
+ method public static java.util.Set<java.lang.String> getAvailableZoneIds();
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public abstract java.lang.String getId();
+ method public abstract java.time.zone.ZoneRules getRules();
+ method public java.time.ZoneId normalized();
+ method public static java.time.ZoneId of(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+ method public static java.time.ZoneId of(java.lang.String);
+ method public static java.time.ZoneId ofOffset(java.lang.String, java.time.ZoneOffset);
+ method public static java.time.ZoneId systemDefault();
+ field public static final java.util.Map<java.lang.String, java.lang.String> SHORT_IDS;
+ }
+
+ public final class ZoneOffset extends java.time.ZoneId implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public int compareTo(java.time.ZoneOffset);
+ method public static java.time.ZoneOffset from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getId();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.zone.ZoneRules getRules();
+ method public int getTotalSeconds();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public static java.time.ZoneOffset of(java.lang.String);
+ method public static java.time.ZoneOffset ofHours(int);
+ method public static java.time.ZoneOffset ofHoursMinutes(int, int);
+ method public static java.time.ZoneOffset ofHoursMinutesSeconds(int, int, int);
+ method public static java.time.ZoneOffset ofTotalSeconds(int);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ field public static final java.time.ZoneOffset MAX;
+ field public static final java.time.ZoneOffset MIN;
+ field public static final java.time.ZoneOffset UTC;
+ }
+
+ public final class ZonedDateTime implements java.time.chrono.ChronoZonedDateTime java.io.Serializable java.time.temporal.Temporal {
+ method public static java.time.ZonedDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public int getYear();
+ method public java.time.ZoneId getZone();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.ZonedDateTime minusDays(long);
+ method public java.time.ZonedDateTime minusHours(long);
+ method public java.time.ZonedDateTime minusMinutes(long);
+ method public java.time.ZonedDateTime minusMonths(long);
+ method public java.time.ZonedDateTime minusNanos(long);
+ method public java.time.ZonedDateTime minusSeconds(long);
+ method public java.time.ZonedDateTime minusWeeks(long);
+ method public java.time.ZonedDateTime minusYears(long);
+ method public static java.time.ZonedDateTime now();
+ method public static java.time.ZonedDateTime now(java.time.ZoneId);
+ method public static java.time.ZonedDateTime now(java.time.Clock);
+ method public static java.time.ZonedDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneId);
+ method public static java.time.ZonedDateTime of(java.time.LocalDateTime, java.time.ZoneId);
+ method public static java.time.ZonedDateTime of(int, int, int, int, int, int, int, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofInstant(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofLocal(java.time.LocalDateTime, java.time.ZoneId, java.time.ZoneOffset);
+ method public static java.time.ZonedDateTime ofStrict(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ method public static java.time.ZonedDateTime parse(java.lang.CharSequence);
+ method public static java.time.ZonedDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.ZonedDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.ZonedDateTime plusDays(long);
+ method public java.time.ZonedDateTime plusHours(long);
+ method public java.time.ZonedDateTime plusMinutes(long);
+ method public java.time.ZonedDateTime plusMonths(long);
+ method public java.time.ZonedDateTime plusNanos(long);
+ method public java.time.ZonedDateTime plusSeconds(long);
+ method public java.time.ZonedDateTime plusWeeks(long);
+ method public java.time.ZonedDateTime plusYears(long);
+ method public java.time.LocalDateTime toLocalDateTime();
+ method public java.time.OffsetDateTime toOffsetDateTime();
+ method public java.time.ZonedDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.ZonedDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.ZonedDateTime withDayOfMonth(int);
+ method public java.time.ZonedDateTime withDayOfYear(int);
+ method public java.time.ZonedDateTime withEarlierOffsetAtOverlap();
+ method public java.time.ZonedDateTime withFixedOffsetZone();
+ method public java.time.ZonedDateTime withHour(int);
+ method public java.time.ZonedDateTime withLaterOffsetAtOverlap();
+ method public java.time.ZonedDateTime withMinute(int);
+ method public java.time.ZonedDateTime withMonth(int);
+ method public java.time.ZonedDateTime withNano(int);
+ method public java.time.ZonedDateTime withSecond(int);
+ method public java.time.ZonedDateTime withYear(int);
+ method public java.time.ZonedDateTime withZoneSameInstant(java.time.ZoneId);
+ method public java.time.ZonedDateTime withZoneSameLocal(java.time.ZoneId);
+ }
+
+}
+
+package java.time.chrono {
+
+ public abstract class AbstractChronology implements java.time.chrono.Chronology {
+ ctor protected AbstractChronology();
+ method public int compareTo(java.time.chrono.Chronology);
+ method public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.format.ResolverStyle);
+ }
+
+ public abstract interface ChronoLocalDate implements java.lang.Comparable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public default java.time.chrono.ChronoLocalDateTime<?> atTime(java.time.LocalTime);
+ method public default int compareTo(java.time.chrono.ChronoLocalDate);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoLocalDate from(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.chrono.Chronology getChronology();
+ method public default java.time.chrono.Era getEra();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoLocalDate);
+ method public default boolean isBefore(java.time.chrono.ChronoLocalDate);
+ method public default boolean isEqual(java.time.chrono.ChronoLocalDate);
+ method public default boolean isLeapYear();
+ method public default boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract int lengthOfMonth();
+ method public default int lengthOfYear();
+ method public default java.time.chrono.ChronoLocalDate plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoLocalDate> timeLineOrder();
+ method public default long toEpochDay();
+ method public abstract java.lang.String toString();
+ method public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ method public default java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalField, long);
+ }
+
+ abstract class ChronoLocalDateImpl<D extends java.time.chrono.ChronoLocalDate> implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ }
+
+ public abstract interface ChronoLocalDateTime<D extends java.time.chrono.ChronoLocalDate> implements java.lang.Comparable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> atZone(java.time.ZoneId);
+ method public default int compareTo(java.time.chrono.ChronoLocalDateTime<?>);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoLocalDateTime<?> from(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.Chronology getChronology();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoLocalDateTime<?>);
+ method public default boolean isBefore(java.time.chrono.ChronoLocalDateTime<?>);
+ method public default boolean isEqual(java.time.chrono.ChronoLocalDateTime<?>);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoLocalDateTime<?>> timeLineOrder();
+ method public default long toEpochSecond(java.time.ZoneOffset);
+ method public default java.time.Instant toInstant(java.time.ZoneOffset);
+ method public abstract D toLocalDate();
+ method public abstract java.time.LocalTime toLocalTime();
+ method public abstract java.lang.String toString();
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> with(java.time.temporal.TemporalField, long);
+ }
+
+ public abstract interface ChronoPeriod implements java.time.temporal.TemporalAmount {
+ method public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.chrono.ChronoPeriod between(java.time.chrono.ChronoLocalDate, java.time.chrono.ChronoLocalDate);
+ method public abstract boolean equals(java.lang.Object);
+ method public abstract long get(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.Chronology getChronology();
+ method public abstract java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public abstract int hashCode();
+ method public default boolean isNegative();
+ method public default boolean isZero();
+ method public abstract java.time.chrono.ChronoPeriod minus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.chrono.ChronoPeriod multipliedBy(int);
+ method public default java.time.chrono.ChronoPeriod negated();
+ method public abstract java.time.chrono.ChronoPeriod normalized();
+ method public abstract java.time.chrono.ChronoPeriod plus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public abstract java.lang.String toString();
+ }
+
+ public abstract interface ChronoZonedDateTime<D extends java.time.chrono.ChronoLocalDate> implements java.lang.Comparable java.time.temporal.Temporal {
+ method public default int compareTo(java.time.chrono.ChronoZonedDateTime<?>);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoZonedDateTime<?> from(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.Chronology getChronology();
+ method public default long getLong(java.time.temporal.TemporalField);
+ method public abstract java.time.ZoneOffset getOffset();
+ method public abstract java.time.ZoneId getZone();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoZonedDateTime<?>);
+ method public default boolean isBefore(java.time.chrono.ChronoZonedDateTime<?>);
+ method public default boolean isEqual(java.time.chrono.ChronoZonedDateTime<?>);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoZonedDateTime<?>> timeLineOrder();
+ method public default long toEpochSecond();
+ method public default java.time.Instant toInstant();
+ method public default D toLocalDate();
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> toLocalDateTime();
+ method public default java.time.LocalTime toLocalTime();
+ method public abstract java.lang.String toString();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> with(java.time.temporal.TemporalField, long);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withEarlierOffsetAtOverlap();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withLaterOffsetAtOverlap();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withZoneSameInstant(java.time.ZoneId);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withZoneSameLocal(java.time.ZoneId);
+ }
+
+ public abstract interface Chronology implements java.lang.Comparable {
+ method public abstract int compareTo(java.time.chrono.Chronology);
+ method public default java.time.chrono.ChronoLocalDate date(java.time.chrono.Era, int, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate date(int, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate date(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.chrono.ChronoLocalDate dateEpochDay(long);
+ method public default java.time.chrono.ChronoLocalDate dateNow();
+ method public default java.time.chrono.ChronoLocalDate dateNow(java.time.ZoneId);
+ method public default java.time.chrono.ChronoLocalDate dateNow(java.time.Clock);
+ method public default java.time.chrono.ChronoLocalDate dateYearDay(java.time.chrono.Era, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate dateYearDay(int, int);
+ method public abstract boolean equals(java.lang.Object);
+ method public abstract java.time.chrono.Era eraOf(int);
+ method public abstract java.util.List<java.time.chrono.Era> eras();
+ method public static java.time.chrono.Chronology from(java.time.temporal.TemporalAccessor);
+ method public static java.util.Set<java.time.chrono.Chronology> getAvailableChronologies();
+ method public abstract java.lang.String getCalendarType();
+ method public default java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public abstract java.lang.String getId();
+ method public abstract int hashCode();
+ method public abstract boolean isLeapYear(long);
+ method public default java.time.chrono.ChronoLocalDateTime<? extends java.time.chrono.ChronoLocalDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public static java.time.chrono.Chronology of(java.lang.String);
+ method public static java.time.chrono.Chronology ofLocale(java.util.Locale);
+ method public default java.time.chrono.ChronoPeriod period(int, int, int);
+ method public abstract int prolepticYear(java.time.chrono.Era, int);
+ method public abstract java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public abstract java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.format.ResolverStyle);
+ method public abstract java.lang.String toString();
+ method public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ }
+
+ public abstract interface Era implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public default java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public default long getLong(java.time.temporal.TemporalField);
+ method public abstract int getValue();
+ method public default boolean isSupported(java.time.temporal.TemporalField);
+ }
+
+ public final class HijrahChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.HijrahDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.HijrahDate date(int, int, int);
+ method public java.time.chrono.HijrahDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.HijrahDate dateEpochDay(long);
+ method public java.time.chrono.HijrahDate dateNow();
+ method public java.time.chrono.HijrahDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.HijrahDate dateNow(java.time.Clock);
+ method public java.time.chrono.HijrahDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.HijrahDate dateYearDay(int, int);
+ method public java.time.chrono.HijrahEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.HijrahDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.HijrahDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.HijrahChronology INSTANCE;
+ }
+
+ public final class HijrahDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.HijrahDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.HijrahChronology getChronology();
+ method public java.time.chrono.HijrahEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public boolean isLeapYear();
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public static java.time.chrono.HijrahDate now();
+ method public static java.time.chrono.HijrahDate now(java.time.ZoneId);
+ method public static java.time.chrono.HijrahDate now(java.time.Clock);
+ method public static java.time.chrono.HijrahDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ method public java.time.chrono.HijrahDate withVariant(java.time.chrono.HijrahChronology);
+ }
+
+ public final class HijrahEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.HijrahEra of(int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.chrono.HijrahEra valueOf(java.lang.String);
+ method public static final java.time.chrono.HijrahEra[] values();
+ enum_constant public static final java.time.chrono.HijrahEra AH;
+ }
+
+ public final class IsoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.LocalDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.LocalDate date(int, int, int);
+ method public java.time.LocalDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.LocalDate dateEpochDay(long);
+ method public java.time.LocalDate dateNow();
+ method public java.time.LocalDate dateNow(java.time.ZoneId);
+ method public java.time.LocalDate dateNow(java.time.Clock);
+ method public java.time.LocalDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.LocalDate dateYearDay(int, int);
+ method public java.time.chrono.IsoEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.LocalDateTime localDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.Period period(int, int, int);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.ZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.ZonedDateTime zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.IsoChronology INSTANCE;
+ }
+
+ public final class IsoEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.IsoEra of(int);
+ method public static java.time.chrono.IsoEra valueOf(java.lang.String);
+ method public static final java.time.chrono.IsoEra[] values();
+ enum_constant public static final java.time.chrono.IsoEra BCE;
+ enum_constant public static final java.time.chrono.IsoEra CE;
+ }
+
+ public final class JapaneseChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.JapaneseDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.JapaneseDate date(int, int, int);
+ method public java.time.chrono.JapaneseDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.JapaneseDate dateEpochDay(long);
+ method public java.time.chrono.JapaneseDate dateNow();
+ method public java.time.chrono.JapaneseDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.JapaneseDate dateNow(java.time.Clock);
+ method public java.time.chrono.JapaneseDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.JapaneseDate dateYearDay(int, int);
+ method public java.time.chrono.JapaneseEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.JapaneseDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.JapaneseDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.JapaneseChronology INSTANCE;
+ }
+
+ public final class JapaneseDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.JapaneseDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.JapaneseChronology getChronology();
+ method public java.time.chrono.JapaneseEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public static java.time.chrono.JapaneseDate now();
+ method public static java.time.chrono.JapaneseDate now(java.time.ZoneId);
+ method public static java.time.chrono.JapaneseDate now(java.time.Clock);
+ method public static java.time.chrono.JapaneseDate of(java.time.chrono.JapaneseEra, int, int, int);
+ method public static java.time.chrono.JapaneseDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class JapaneseEra implements java.time.chrono.Era java.io.Serializable {
+ method public int getValue();
+ method public static java.time.chrono.JapaneseEra of(int);
+ method public static java.time.chrono.JapaneseEra valueOf(java.lang.String);
+ method public static java.time.chrono.JapaneseEra[] values();
+ field public static final java.time.chrono.JapaneseEra HEISEI;
+ field public static final java.time.chrono.JapaneseEra MEIJI;
+ field public static final java.time.chrono.JapaneseEra SHOWA;
+ field public static final java.time.chrono.JapaneseEra TAISHO;
+ }
+
+ public final class MinguoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.MinguoDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.MinguoDate date(int, int, int);
+ method public java.time.chrono.MinguoDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.MinguoDate dateEpochDay(long);
+ method public java.time.chrono.MinguoDate dateNow();
+ method public java.time.chrono.MinguoDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.MinguoDate dateNow(java.time.Clock);
+ method public java.time.chrono.MinguoDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.MinguoDate dateYearDay(int, int);
+ method public java.time.chrono.MinguoEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.MinguoDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.MinguoDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.MinguoChronology INSTANCE;
+ }
+
+ public final class MinguoDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.MinguoDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.MinguoChronology getChronology();
+ method public java.time.chrono.MinguoEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public static java.time.chrono.MinguoDate now();
+ method public static java.time.chrono.MinguoDate now(java.time.ZoneId);
+ method public static java.time.chrono.MinguoDate now(java.time.Clock);
+ method public static java.time.chrono.MinguoDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class MinguoEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.MinguoEra of(int);
+ method public static java.time.chrono.MinguoEra valueOf(java.lang.String);
+ method public static final java.time.chrono.MinguoEra[] values();
+ enum_constant public static final java.time.chrono.MinguoEra BEFORE_ROC;
+ enum_constant public static final java.time.chrono.MinguoEra ROC;
+ }
+
+ public final class ThaiBuddhistChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.ThaiBuddhistDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.ThaiBuddhistDate date(int, int, int);
+ method public java.time.chrono.ThaiBuddhistDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ThaiBuddhistDate dateEpochDay(long);
+ method public java.time.chrono.ThaiBuddhistDate dateNow();
+ method public java.time.chrono.ThaiBuddhistDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.ThaiBuddhistDate dateNow(java.time.Clock);
+ method public java.time.chrono.ThaiBuddhistDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.ThaiBuddhistDate dateYearDay(int, int);
+ method public java.time.chrono.ThaiBuddhistEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.ThaiBuddhistDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.ThaiBuddhistDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.ThaiBuddhistChronology INSTANCE;
+ }
+
+ public final class ThaiBuddhistDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.ThaiBuddhistDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ThaiBuddhistChronology getChronology();
+ method public java.time.chrono.ThaiBuddhistEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public static java.time.chrono.ThaiBuddhistDate now();
+ method public static java.time.chrono.ThaiBuddhistDate now(java.time.ZoneId);
+ method public static java.time.chrono.ThaiBuddhistDate now(java.time.Clock);
+ method public static java.time.chrono.ThaiBuddhistDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class ThaiBuddhistEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.ThaiBuddhistEra of(int);
+ method public static java.time.chrono.ThaiBuddhistEra valueOf(java.lang.String);
+ method public static final java.time.chrono.ThaiBuddhistEra[] values();
+ enum_constant public static final java.time.chrono.ThaiBuddhistEra BE;
+ enum_constant public static final java.time.chrono.ThaiBuddhistEra BEFORE_BE;
+ }
+
+}
+
+package java.time.format {
+
+ public final class DateTimeFormatter {
+ method public java.lang.String format(java.time.temporal.TemporalAccessor);
+ method public void formatTo(java.time.temporal.TemporalAccessor, java.lang.Appendable);
+ method public java.time.chrono.Chronology getChronology();
+ method public java.time.format.DecimalStyle getDecimalStyle();
+ method public java.util.Locale getLocale();
+ method public java.util.Set<java.time.temporal.TemporalField> getResolverFields();
+ method public java.time.format.ResolverStyle getResolverStyle();
+ method public java.time.ZoneId getZone();
+ method public static java.time.format.DateTimeFormatter ofLocalizedDate(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedTime(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofPattern(java.lang.String);
+ method public static java.time.format.DateTimeFormatter ofPattern(java.lang.String, java.util.Locale);
+ method public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence);
+ method public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence, java.text.ParsePosition);
+ method public <T> T parse(java.lang.CharSequence, java.time.temporal.TemporalQuery<T>);
+ method public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery<?>...);
+ method public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition);
+ method public static final java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
+ method public static final java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
+ method public java.text.Format toFormat();
+ method public java.text.Format toFormat(java.time.temporal.TemporalQuery<?>);
+ method public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology);
+ method public java.time.format.DateTimeFormatter withDecimalStyle(java.time.format.DecimalStyle);
+ method public java.time.format.DateTimeFormatter withLocale(java.util.Locale);
+ method public java.time.format.DateTimeFormatter withResolverFields(java.time.temporal.TemporalField...);
+ method public java.time.format.DateTimeFormatter withResolverFields(java.util.Set<java.time.temporal.TemporalField>);
+ method public java.time.format.DateTimeFormatter withResolverStyle(java.time.format.ResolverStyle);
+ method public java.time.format.DateTimeFormatter withZone(java.time.ZoneId);
+ field public static final java.time.format.DateTimeFormatter BASIC_ISO_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_INSTANT;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_ORDINAL_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_WEEK_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_ZONED_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter RFC_1123_DATE_TIME;
+ }
+
+ public final class DateTimeFormatterBuilder {
+ ctor public DateTimeFormatterBuilder();
+ method public java.time.format.DateTimeFormatterBuilder append(java.time.format.DateTimeFormatter);
+ method public java.time.format.DateTimeFormatterBuilder appendChronologyId();
+ method public java.time.format.DateTimeFormatterBuilder appendChronologyText(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendFraction(java.time.temporal.TemporalField, int, int, boolean);
+ method public java.time.format.DateTimeFormatterBuilder appendInstant();
+ method public java.time.format.DateTimeFormatterBuilder appendInstant(int);
+ method public java.time.format.DateTimeFormatterBuilder appendLiteral(char);
+ method public java.time.format.DateTimeFormatterBuilder appendLiteral(java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendLocalized(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendLocalizedOffset(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendOffset(java.lang.String, java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendOffsetId();
+ method public java.time.format.DateTimeFormatterBuilder appendOptional(java.time.format.DateTimeFormatter);
+ method public java.time.format.DateTimeFormatterBuilder appendPattern(java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField, java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField, java.util.Map<java.lang.Long, java.lang.String>);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField, int);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField, int, int, java.time.format.SignStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField, int, int, int);
+ method public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField, int, int, java.time.chrono.ChronoLocalDate);
+ method public java.time.format.DateTimeFormatterBuilder appendZoneId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneOrOffsetId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneRegionId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle, java.util.Set<java.time.ZoneId>);
+ method public static java.lang.String getLocalizedDateTimePattern(java.time.format.FormatStyle, java.time.format.FormatStyle, java.time.chrono.Chronology, java.util.Locale);
+ method public java.time.format.DateTimeFormatterBuilder optionalEnd();
+ method public java.time.format.DateTimeFormatterBuilder optionalStart();
+ method public java.time.format.DateTimeFormatterBuilder padNext(int);
+ method public java.time.format.DateTimeFormatterBuilder padNext(int, char);
+ method public java.time.format.DateTimeFormatterBuilder parseCaseInsensitive();
+ method public java.time.format.DateTimeFormatterBuilder parseCaseSensitive();
+ method public java.time.format.DateTimeFormatterBuilder parseDefaulting(java.time.temporal.TemporalField, long);
+ method public java.time.format.DateTimeFormatterBuilder parseLenient();
+ method public java.time.format.DateTimeFormatterBuilder parseStrict();
+ method public java.time.format.DateTimeFormatter toFormatter();
+ method public java.time.format.DateTimeFormatter toFormatter(java.util.Locale);
+ }
+
+ public class DateTimeParseException extends java.time.DateTimeException {
+ ctor public DateTimeParseException(java.lang.String, java.lang.CharSequence, int);
+ ctor public DateTimeParseException(java.lang.String, java.lang.CharSequence, int, java.lang.Throwable);
+ method public int getErrorIndex();
+ method public java.lang.String getParsedString();
+ }
+
+ public final class DecimalStyle {
+ method public static java.util.Set<java.util.Locale> getAvailableLocales();
+ method public char getDecimalSeparator();
+ method public char getNegativeSign();
+ method public char getPositiveSign();
+ method public char getZeroDigit();
+ method public static java.time.format.DecimalStyle of(java.util.Locale);
+ method public static java.time.format.DecimalStyle ofDefaultLocale();
+ method public java.time.format.DecimalStyle withDecimalSeparator(char);
+ method public java.time.format.DecimalStyle withNegativeSign(char);
+ method public java.time.format.DecimalStyle withPositiveSign(char);
+ method public java.time.format.DecimalStyle withZeroDigit(char);
+ field public static final java.time.format.DecimalStyle STANDARD;
+ }
+
+ public final class FormatStyle extends java.lang.Enum {
+ method public static java.time.format.FormatStyle valueOf(java.lang.String);
+ method public static final java.time.format.FormatStyle[] values();
+ enum_constant public static final java.time.format.FormatStyle FULL;
+ enum_constant public static final java.time.format.FormatStyle LONG;
+ enum_constant public static final java.time.format.FormatStyle MEDIUM;
+ enum_constant public static final java.time.format.FormatStyle SHORT;
+ }
+
+ public final class ResolverStyle extends java.lang.Enum {
+ method public static java.time.format.ResolverStyle valueOf(java.lang.String);
+ method public static final java.time.format.ResolverStyle[] values();
+ enum_constant public static final java.time.format.ResolverStyle LENIENT;
+ enum_constant public static final java.time.format.ResolverStyle SMART;
+ enum_constant public static final java.time.format.ResolverStyle STRICT;
+ }
+
+ public final class SignStyle extends java.lang.Enum {
+ method public static java.time.format.SignStyle valueOf(java.lang.String);
+ method public static final java.time.format.SignStyle[] values();
+ enum_constant public static final java.time.format.SignStyle ALWAYS;
+ enum_constant public static final java.time.format.SignStyle EXCEEDS_PAD;
+ enum_constant public static final java.time.format.SignStyle NEVER;
+ enum_constant public static final java.time.format.SignStyle NORMAL;
+ enum_constant public static final java.time.format.SignStyle NOT_NEGATIVE;
+ }
+
+ public final class TextStyle extends java.lang.Enum {
+ method public java.time.format.TextStyle asNormal();
+ method public java.time.format.TextStyle asStandalone();
+ method public boolean isStandalone();
+ method public static java.time.format.TextStyle valueOf(java.lang.String);
+ method public static final java.time.format.TextStyle[] values();
+ enum_constant public static final java.time.format.TextStyle FULL;
+ enum_constant public static final java.time.format.TextStyle FULL_STANDALONE;
+ enum_constant public static final java.time.format.TextStyle NARROW;
+ enum_constant public static final java.time.format.TextStyle NARROW_STANDALONE;
+ enum_constant public static final java.time.format.TextStyle SHORT;
+ enum_constant public static final java.time.format.TextStyle SHORT_STANDALONE;
+ }
+
+}
+
+package java.time.temporal {
+
+ public final class ChronoField extends java.lang.Enum implements java.time.temporal.TemporalField {
+ method public <R extends java.time.temporal.Temporal> R adjustInto(R, long);
+ method public int checkValidIntValue(long);
+ method public long checkValidValue(long);
+ method public java.time.temporal.TemporalUnit getBaseUnit();
+ method public java.lang.String getDisplayName(java.util.Locale);
+ method public long getFrom(java.time.temporal.TemporalAccessor);
+ method public java.time.temporal.TemporalUnit getRangeUnit();
+ method public boolean isDateBased();
+ method public boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ method public boolean isTimeBased();
+ method public java.time.temporal.ValueRange range();
+ method public java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ method public static java.time.temporal.ChronoField valueOf(java.lang.String);
+ method public static final java.time.temporal.ChronoField[] values();
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_WEEK_OF_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_WEEK_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField AMPM_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField CLOCK_HOUR_OF_AMPM;
+ enum_constant public static final java.time.temporal.ChronoField CLOCK_HOUR_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_WEEK;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField EPOCH_DAY;
+ enum_constant public static final java.time.temporal.ChronoField ERA;
+ enum_constant public static final java.time.temporal.ChronoField HOUR_OF_AMPM;
+ enum_constant public static final java.time.temporal.ChronoField HOUR_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField INSTANT_SECONDS;
+ enum_constant public static final java.time.temporal.ChronoField MICRO_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MICRO_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField MILLI_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MILLI_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField MINUTE_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MINUTE_OF_HOUR;
+ enum_constant public static final java.time.temporal.ChronoField MONTH_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField NANO_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField NANO_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField OFFSET_SECONDS;
+ enum_constant public static final java.time.temporal.ChronoField PROLEPTIC_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField SECOND_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField SECOND_OF_MINUTE;
+ enum_constant public static final java.time.temporal.ChronoField YEAR;
+ enum_constant public static final java.time.temporal.ChronoField YEAR_OF_ERA;
+ }
+
+ public final class ChronoUnit extends java.lang.Enum implements java.time.temporal.TemporalUnit {
+ method public <R extends java.time.temporal.Temporal> R addTo(R, long);
+ method public long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public java.time.Duration getDuration();
+ method public boolean isDateBased();
+ method public boolean isDurationEstimated();
+ method public boolean isSupportedBy(java.time.temporal.Temporal);
+ method public boolean isTimeBased();
+ method public static java.time.temporal.ChronoUnit valueOf(java.lang.String);
+ method public static final java.time.temporal.ChronoUnit[] values();
+ enum_constant public static final java.time.temporal.ChronoUnit CENTURIES;
+ enum_constant public static final java.time.temporal.ChronoUnit DAYS;
+ enum_constant public static final java.time.temporal.ChronoUnit DECADES;
+ enum_constant public static final java.time.temporal.ChronoUnit ERAS;
+ enum_constant public static final java.time.temporal.ChronoUnit FOREVER;
+ enum_constant public static final java.time.temporal.ChronoUnit HALF_DAYS;
+ enum_constant public static final java.time.temporal.ChronoUnit HOURS;
+ enum_constant public static final java.time.temporal.ChronoUnit MICROS;
+ enum_constant public static final java.time.temporal.ChronoUnit MILLENNIA;
+ enum_constant public static final java.time.temporal.ChronoUnit MILLIS;
+ enum_constant public static final java.time.temporal.ChronoUnit MINUTES;
+ enum_constant public static final java.time.temporal.ChronoUnit MONTHS;
+ enum_constant public static final java.time.temporal.ChronoUnit NANOS;
+ enum_constant public static final java.time.temporal.ChronoUnit SECONDS;
+ enum_constant public static final java.time.temporal.ChronoUnit WEEKS;
+ enum_constant public static final java.time.temporal.ChronoUnit YEARS;
+ }
+
+ public final class IsoFields {
+ field public static final java.time.temporal.TemporalField DAY_OF_QUARTER;
+ field public static final java.time.temporal.TemporalField QUARTER_OF_YEAR;
+ field public static final java.time.temporal.TemporalUnit QUARTER_YEARS;
+ field public static final java.time.temporal.TemporalField WEEK_BASED_YEAR;
+ field public static final java.time.temporal.TemporalUnit WEEK_BASED_YEARS;
+ field public static final java.time.temporal.TemporalField WEEK_OF_WEEK_BASED_YEAR;
+ }
+
+ public final class JulianFields {
+ field public static final java.time.temporal.TemporalField JULIAN_DAY;
+ field public static final java.time.temporal.TemporalField MODIFIED_JULIAN_DAY;
+ field public static final java.time.temporal.TemporalField RATA_DIE;
+ }
+
+ public abstract interface Temporal implements java.time.temporal.TemporalAccessor {
+ method public abstract boolean isSupported(java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ method public default java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ method public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ method public abstract java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ }
+
+ public abstract interface TemporalAccessor {
+ method public default int get(java.time.temporal.TemporalField);
+ method public abstract long getLong(java.time.temporal.TemporalField);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public default java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ }
+
+ public abstract interface TemporalAdjuster {
+ method public abstract java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ }
+
+ public final class TemporalAdjusters {
+ method public static java.time.temporal.TemporalAdjuster dayOfWeekInMonth(int, java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster firstDayOfMonth();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfNextMonth();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfNextYear();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfYear();
+ method public static java.time.temporal.TemporalAdjuster firstInMonth(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster lastDayOfMonth();
+ method public static java.time.temporal.TemporalAdjuster lastDayOfYear();
+ method public static java.time.temporal.TemporalAdjuster lastInMonth(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster next(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster nextOrSame(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster ofDateAdjuster(java.util.function.UnaryOperator<java.time.LocalDate>);
+ method public static java.time.temporal.TemporalAdjuster previous(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster previousOrSame(java.time.DayOfWeek);
+ }
+
+ public abstract interface TemporalAmount {
+ method public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public abstract long get(java.time.temporal.TemporalUnit);
+ method public abstract java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ }
+
+ public abstract interface TemporalField {
+ method public abstract <R extends java.time.temporal.Temporal> R adjustInto(R, long);
+ method public abstract java.time.temporal.TemporalUnit getBaseUnit();
+ method public default java.lang.String getDisplayName(java.util.Locale);
+ method public abstract long getFrom(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.temporal.TemporalUnit getRangeUnit();
+ method public abstract boolean isDateBased();
+ method public abstract boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ method public abstract boolean isTimeBased();
+ method public abstract java.time.temporal.ValueRange range();
+ method public abstract java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ method public default java.time.temporal.TemporalAccessor resolve(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.temporal.TemporalAccessor, java.time.format.ResolverStyle);
+ method public abstract java.lang.String toString();
+ }
+
+ public final class TemporalQueries {
+ method public static java.time.temporal.TemporalQuery<java.time.chrono.Chronology> chronology();
+ method public static java.time.temporal.TemporalQuery<java.time.LocalDate> localDate();
+ method public static java.time.temporal.TemporalQuery<java.time.LocalTime> localTime();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneOffset> offset();
+ method public static java.time.temporal.TemporalQuery<java.time.temporal.TemporalUnit> precision();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneId> zone();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneId> zoneId();
+ }
+
+ public abstract interface TemporalQuery<R> {
+ method public abstract R queryFrom(java.time.temporal.TemporalAccessor);
+ }
+
+ public abstract interface TemporalUnit {
+ method public abstract <R extends java.time.temporal.Temporal> R addTo(R, long);
+ method public abstract long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public abstract java.time.Duration getDuration();
+ method public abstract boolean isDateBased();
+ method public abstract boolean isDurationEstimated();
+ method public default boolean isSupportedBy(java.time.temporal.Temporal);
+ method public abstract boolean isTimeBased();
+ method public abstract java.lang.String toString();
+ }
+
+ public class UnsupportedTemporalTypeException extends java.time.DateTimeException {
+ ctor public UnsupportedTemporalTypeException(java.lang.String);
+ ctor public UnsupportedTemporalTypeException(java.lang.String, java.lang.Throwable);
+ }
+
+ public final class ValueRange implements java.io.Serializable {
+ method public int checkValidIntValue(long, java.time.temporal.TemporalField);
+ method public long checkValidValue(long, java.time.temporal.TemporalField);
+ method public long getLargestMinimum();
+ method public long getMaximum();
+ method public long getMinimum();
+ method public long getSmallestMaximum();
+ method public boolean isFixed();
+ method public boolean isIntValue();
+ method public boolean isValidIntValue(long);
+ method public boolean isValidValue(long);
+ method public static java.time.temporal.ValueRange of(long, long);
+ method public static java.time.temporal.ValueRange of(long, long, long);
+ method public static java.time.temporal.ValueRange of(long, long, long, long);
+ }
+
+ public final class WeekFields implements java.io.Serializable {
+ method public java.time.temporal.TemporalField dayOfWeek();
+ method public java.time.DayOfWeek getFirstDayOfWeek();
+ method public int getMinimalDaysInFirstWeek();
+ method public static java.time.temporal.WeekFields of(java.util.Locale);
+ method public static java.time.temporal.WeekFields of(java.time.DayOfWeek, int);
+ method public java.time.temporal.TemporalField weekBasedYear();
+ method public java.time.temporal.TemporalField weekOfMonth();
+ method public java.time.temporal.TemporalField weekOfWeekBasedYear();
+ method public java.time.temporal.TemporalField weekOfYear();
+ field public static final java.time.temporal.WeekFields ISO;
+ field public static final java.time.temporal.WeekFields SUNDAY_START;
+ field public static final java.time.temporal.TemporalUnit WEEK_BASED_YEARS;
+ }
+
+}
+
+package java.time.zone {
+
+ public final class ZoneOffsetTransition implements java.lang.Comparable java.io.Serializable {
+ method public int compareTo(java.time.zone.ZoneOffsetTransition);
+ method public java.time.LocalDateTime getDateTimeAfter();
+ method public java.time.LocalDateTime getDateTimeBefore();
+ method public java.time.Duration getDuration();
+ method public java.time.Instant getInstant();
+ method public java.time.ZoneOffset getOffsetAfter();
+ method public java.time.ZoneOffset getOffsetBefore();
+ method public boolean isGap();
+ method public boolean isOverlap();
+ method public boolean isValidOffset(java.time.ZoneOffset);
+ method public static java.time.zone.ZoneOffsetTransition of(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ method public long toEpochSecond();
+ }
+
+ public final class ZoneOffsetTransitionRule implements java.io.Serializable {
+ method public java.time.zone.ZoneOffsetTransition createTransition(int);
+ method public int getDayOfMonthIndicator();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public java.time.LocalTime getLocalTime();
+ method public java.time.Month getMonth();
+ method public java.time.ZoneOffset getOffsetAfter();
+ method public java.time.ZoneOffset getOffsetBefore();
+ method public java.time.ZoneOffset getStandardOffset();
+ method public java.time.zone.ZoneOffsetTransitionRule.TimeDefinition getTimeDefinition();
+ method public boolean isMidnightEndOfDay();
+ method public static java.time.zone.ZoneOffsetTransitionRule of(java.time.Month, int, java.time.DayOfWeek, java.time.LocalTime, boolean, java.time.zone.ZoneOffsetTransitionRule.TimeDefinition, java.time.ZoneOffset, java.time.ZoneOffset, java.time.ZoneOffset);
+ }
+
+ public static final class ZoneOffsetTransitionRule.TimeDefinition extends java.lang.Enum {
+ method public java.time.LocalDateTime createDateTime(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ method public static java.time.zone.ZoneOffsetTransitionRule.TimeDefinition valueOf(java.lang.String);
+ method public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition[] values();
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition STANDARD;
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition UTC;
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition WALL;
+ }
+
+ public final class ZoneRules implements java.io.Serializable {
+ method public java.time.Duration getDaylightSavings(java.time.Instant);
+ method public java.time.ZoneOffset getOffset(java.time.Instant);
+ method public java.time.ZoneOffset getOffset(java.time.LocalDateTime);
+ method public java.time.ZoneOffset getStandardOffset(java.time.Instant);
+ method public java.time.zone.ZoneOffsetTransition getTransition(java.time.LocalDateTime);
+ method public java.util.List<java.time.zone.ZoneOffsetTransitionRule> getTransitionRules();
+ method public java.util.List<java.time.zone.ZoneOffsetTransition> getTransitions();
+ method public java.util.List<java.time.ZoneOffset> getValidOffsets(java.time.LocalDateTime);
+ method public boolean isDaylightSavings(java.time.Instant);
+ method public boolean isFixedOffset();
+ method public boolean isValidOffset(java.time.LocalDateTime, java.time.ZoneOffset);
+ method public java.time.zone.ZoneOffsetTransition nextTransition(java.time.Instant);
+ method public static java.time.zone.ZoneRules of(java.time.ZoneOffset, java.time.ZoneOffset, java.util.List<java.time.zone.ZoneOffsetTransition>, java.util.List<java.time.zone.ZoneOffsetTransition>, java.util.List<java.time.zone.ZoneOffsetTransitionRule>);
+ method public static java.time.zone.ZoneRules of(java.time.ZoneOffset);
+ method public java.time.zone.ZoneOffsetTransition previousTransition(java.time.Instant);
+ }
+
+ public class ZoneRulesException extends java.time.DateTimeException {
+ ctor public ZoneRulesException(java.lang.String);
+ ctor public ZoneRulesException(java.lang.String, java.lang.Throwable);
+ }
+
+}
+
package java.util {
public abstract class AbstractCollection<E> implements java.util.Collection {
@@ -62275,7 +63934,9 @@
method public int get(int);
method public int getActualMaximum(int);
method public int getActualMinimum(int);
+ method public static java.util.Set<java.lang.String> getAvailableCalendarTypes();
method public static synchronized java.util.Locale[] getAvailableLocales();
+ method public java.lang.String getCalendarType();
method public java.lang.String getDisplayName(int, int, java.util.Locale);
method public java.util.Map<java.lang.String, java.lang.Integer> getDisplayNames(int, int, java.util.Locale);
method public int getFirstDayOfWeek();
@@ -62310,6 +63971,7 @@
method public void setTimeInMillis(long);
method public void setTimeZone(java.util.TimeZone);
method public void setWeekDate(int, int, int);
+ method public final java.time.Instant toInstant();
field public static final int ALL_STYLES = 0; // 0x0
field public static final int AM = 0; // 0x0
field public static final int AM_PM = 9; // 0x9
@@ -62332,12 +63994,16 @@
field public static final int JULY = 6; // 0x6
field public static final int JUNE = 5; // 0x5
field public static final int LONG = 2; // 0x2
+ field public static final int LONG_FORMAT = 2; // 0x2
+ field public static final int LONG_STANDALONE = 32770; // 0x8002
field public static final int MARCH = 2; // 0x2
field public static final int MAY = 4; // 0x4
field public static final int MILLISECOND = 14; // 0xe
field public static final int MINUTE = 12; // 0xc
field public static final int MONDAY = 2; // 0x2
field public static final int MONTH = 2; // 0x2
+ field public static final int NARROW_FORMAT = 4; // 0x4
+ field public static final int NARROW_STANDALONE = 32772; // 0x8004
field public static final int NOVEMBER = 10; // 0xa
field public static final int OCTOBER = 9; // 0x9
field public static final int PM = 1; // 0x1
@@ -62345,6 +64011,8 @@
field public static final int SECOND = 13; // 0xd
field public static final int SEPTEMBER = 8; // 0x8
field public static final int SHORT = 1; // 0x1
+ field public static final int SHORT_FORMAT = 1; // 0x1
+ field public static final int SHORT_STANDALONE = 32769; // 0x8001
field public static final int SUNDAY = 1; // 0x1
field public static final int THURSDAY = 5; // 0x5
field public static final int TUESDAY = 3; // 0x3
@@ -62361,6 +64029,24 @@
field protected long time;
}
+ public static class Calendar.Builder {
+ ctor public Calendar.Builder();
+ method public java.util.Calendar build();
+ method public java.util.Calendar.Builder set(int, int);
+ method public java.util.Calendar.Builder setCalendarType(java.lang.String);
+ method public java.util.Calendar.Builder setDate(int, int, int);
+ method public java.util.Calendar.Builder setFields(int...);
+ method public java.util.Calendar.Builder setInstant(long);
+ method public java.util.Calendar.Builder setInstant(java.util.Date);
+ method public java.util.Calendar.Builder setLenient(boolean);
+ method public java.util.Calendar.Builder setLocale(java.util.Locale);
+ method public java.util.Calendar.Builder setTimeOfDay(int, int, int);
+ method public java.util.Calendar.Builder setTimeOfDay(int, int, int, int);
+ method public java.util.Calendar.Builder setTimeZone(java.util.TimeZone);
+ method public java.util.Calendar.Builder setWeekDate(int, int, int);
+ method public java.util.Calendar.Builder setWeekDefinition(int, int);
+ }
+
public abstract interface Collection<E> implements java.lang.Iterable {
method public abstract boolean add(E);
method public abstract boolean addAll(java.util.Collection<? extends E>);
@@ -62496,6 +64182,7 @@
method public boolean before(java.util.Date);
method public java.lang.Object clone();
method public int compareTo(java.util.Date);
+ method public static java.util.Date from(java.time.Instant);
method public deprecated int getDate();
method public deprecated int getDay();
method public deprecated int getHours();
@@ -62514,6 +64201,7 @@
method public void setTime(long);
method public deprecated void setYear(int);
method public deprecated java.lang.String toGMTString();
+ method public java.time.Instant toInstant();
method public deprecated java.lang.String toLocaleString();
}
@@ -62683,6 +64371,7 @@
method public void add(int, int);
method protected void computeFields();
method protected void computeTime();
+ method public static java.util.GregorianCalendar from(java.time.ZonedDateTime);
method public int getGreatestMinimum(int);
method public final java.util.Date getGregorianChange();
method public int getLeastMaximum(int);
@@ -62692,6 +64381,7 @@
method public final boolean isWeekDateSupported();
method public void roll(int, boolean);
method public void setGregorianChange(java.util.Date);
+ method public java.time.ZonedDateTime toZonedDateTime();
field public static final int AD = 1; // 0x1
field public static final int BC = 0; // 0x0
}
@@ -63719,12 +65409,14 @@
method public int getOffset(long);
method public abstract int getRawOffset();
method public static synchronized java.util.TimeZone getTimeZone(java.lang.String);
+ method public static java.util.TimeZone getTimeZone(java.time.ZoneId);
method public boolean hasSameRules(java.util.TimeZone);
method public abstract boolean inDaylightTime(java.util.Date);
method public boolean observesDaylightTime();
method public static synchronized void setDefault(java.util.TimeZone);
method public void setID(java.lang.String);
method public abstract void setRawOffset(int);
+ method public java.time.ZoneId toZoneId();
method public abstract boolean useDaylightTime();
field public static final int LONG = 1; // 0x1
field public static final int SHORT = 0; // 0x0
@@ -64331,31 +66023,31 @@
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
ctor public CopyOnWriteArrayList(E[]);
- method public synchronized boolean add(E);
- method public synchronized void add(int, E);
- method public synchronized boolean addAll(java.util.Collection<? extends E>);
- method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
- method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
- method public synchronized boolean addIfAbsent(E);
- method public synchronized void clear();
+ method public boolean add(E);
+ method public void add(int, E);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public boolean addAll(int, java.util.Collection<? extends E>);
+ method public int addAllAbsent(java.util.Collection<? extends E>);
+ method public boolean addIfAbsent(E);
+ method public void clear();
method public java.lang.Object clone();
method public boolean contains(java.lang.Object);
method public boolean containsAll(java.util.Collection<?>);
method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
- method public int indexOf(E, int);
method public int indexOf(java.lang.Object);
+ method public int indexOf(E, int);
method public boolean isEmpty();
method public java.util.Iterator<E> iterator();
- method public int lastIndexOf(E, int);
method public int lastIndexOf(java.lang.Object);
- method public java.util.ListIterator<E> listIterator(int);
+ method public int lastIndexOf(E, int);
method public java.util.ListIterator<E> listIterator();
- method public synchronized E remove(int);
- method public synchronized boolean remove(java.lang.Object);
- method public synchronized boolean removeAll(java.util.Collection<?>);
- method public synchronized boolean retainAll(java.util.Collection<?>);
- method public synchronized E set(int, E);
+ method public java.util.ListIterator<E> listIterator(int);
+ method public E remove(int);
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public E set(int, E);
method public int size();
method public java.util.List<E> subList(int, int);
method public java.lang.Object[] toArray();
@@ -66206,10 +67898,12 @@
method public java.lang.StringBuffer appendTail(java.lang.StringBuffer);
method public int end();
method public int end(int);
+ method public int end(java.lang.String);
method public boolean find();
method public boolean find(int);
method public java.lang.String group();
method public java.lang.String group(int);
+ method public java.lang.String group(java.lang.String);
method public int groupCount();
method public boolean hasAnchoringBounds();
method public boolean hasTransparentBounds();
@@ -66228,6 +67922,7 @@
method public java.util.regex.Matcher reset(java.lang.CharSequence);
method public int start();
method public int start(int) throws java.lang.IllegalStateException;
+ method public int start(java.lang.String);
method public java.util.regex.MatchResult toMatchResult();
method public java.util.regex.Matcher useAnchoringBounds(boolean);
method public java.util.regex.Matcher usePattern(java.util.regex.Pattern);
diff --git a/api/test-current.txt b/api/test-current.txt
index 5a2f607..2b0ca00 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -8237,6 +8237,7 @@
field public static final java.lang.String USER_SERVICE = "user";
field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+ field public static final java.lang.String WIFI_AWARE_SERVICE = "wifiaware";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
field public static final java.lang.String WIFI_SERVICE = "wifi";
field public static final java.lang.String WINDOW_SERVICE = "window";
@@ -9902,6 +9903,7 @@
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
+ field public static final java.lang.String FEATURE_WIFI_AWARE = "android.hardware.wifi.aware";
field public static final java.lang.String FEATURE_WIFI_DIRECT = "android.hardware.wifi.direct";
field public static final int GET_ACTIVITIES = 1; // 0x1
field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
@@ -23844,6 +23846,7 @@
field public static final int TRANSPORT_ETHERNET = 3; // 0x3
field public static final int TRANSPORT_VPN = 4; // 0x4
field public static final int TRANSPORT_WIFI = 1; // 0x1
+ field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
}
public class NetworkInfo implements android.os.Parcelable {
@@ -24850,6 +24853,122 @@
}
+package android.net.wifi.aware {
+
+ public class AttachCallback {
+ ctor public AttachCallback();
+ method public void onAttachFailed();
+ method public void onAttached(android.net.wifi.aware.WifiAwareSession);
+ }
+
+ public final class Characteristics implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxMatchFilterLength();
+ method public int getMaxServiceNameLength();
+ method public int getMaxServiceSpecificInfoLength();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
+ }
+
+ public class DiscoverySession {
+ method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void destroy();
+ method public static int getMaxSendRetryCount();
+ method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
+ method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
+ }
+
+ public class DiscoverySessionCallback {
+ ctor public DiscoverySessionCallback();
+ method public void onMessageReceived(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void onMessageSendFailed(int);
+ method public void onMessageSendSucceeded(int);
+ method public void onPublishStarted(android.net.wifi.aware.PublishDiscoverySession);
+ method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
+ method public void onSessionConfigFailed();
+ method public void onSessionConfigUpdated();
+ method public void onSessionTerminated();
+ method public void onSubscribeStarted(android.net.wifi.aware.SubscribeDiscoverySession);
+ }
+
+ public class IdentityChangedListener {
+ ctor public IdentityChangedListener();
+ method public void onIdentityChanged(byte[]);
+ }
+
+ public class PeerHandle {
+ }
+
+ public final class PublishConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.PublishConfig> CREATOR;
+ field public static final int PUBLISH_TYPE_SOLICITED = 1; // 0x1
+ field public static final int PUBLISH_TYPE_UNSOLICITED = 0; // 0x0
+ }
+
+ public static final class PublishConfig.Builder {
+ ctor public PublishConfig.Builder();
+ method public android.net.wifi.aware.PublishConfig build();
+ method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(java.util.List<byte[]>);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishCount(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceName(java.lang.String);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(byte[]);
+ method public android.net.wifi.aware.PublishConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.PublishConfig.Builder setTtlSec(int);
+ }
+
+ public class PublishDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updatePublish(android.net.wifi.aware.PublishConfig);
+ }
+
+ public final class SubscribeConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR;
+ field public static final int MATCH_STYLE_ALL = 1; // 0x1
+ field public static final int MATCH_STYLE_FIRST_ONLY = 0; // 0x0
+ field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1
+ field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0
+ }
+
+ public static final class SubscribeConfig.Builder {
+ ctor public SubscribeConfig.Builder();
+ method public android.net.wifi.aware.SubscribeConfig build();
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(java.util.List<byte[]>);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchStyle(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(java.lang.String);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(byte[]);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeCount(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
+ }
+
+ public class SubscribeDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updateSubscribe(android.net.wifi.aware.SubscribeConfig);
+ }
+
+ public class WifiAwareManager {
+ method public void attach(android.net.wifi.aware.AttachCallback, android.os.Handler);
+ method public void attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler);
+ method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method public boolean isAvailable();
+ field public static final java.lang.String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
+ }
+
+ public class WifiAwareSession {
+ method public java.lang.String createNetworkSpecifier(int, byte[], byte[]);
+ method public void destroy();
+ method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
+ method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -54894,8 +55013,10 @@
public final class FileTime implements java.lang.Comparable {
method public int compareTo(java.nio.file.attribute.FileTime);
method public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
+ method public static java.nio.file.attribute.FileTime from(java.time.Instant);
method public static java.nio.file.attribute.FileTime fromMillis(long);
method public long to(java.util.concurrent.TimeUnit);
+ method public java.time.Instant toInstant();
method public long toMillis();
}
@@ -58425,6 +58546,1515 @@
}
+package java.time {
+
+ public abstract class Clock {
+ ctor protected Clock();
+ method public static java.time.Clock fixed(java.time.Instant, java.time.ZoneId);
+ method public abstract java.time.ZoneId getZone();
+ method public abstract java.time.Instant instant();
+ method public long millis();
+ method public static java.time.Clock offset(java.time.Clock, java.time.Duration);
+ method public static java.time.Clock system(java.time.ZoneId);
+ method public static java.time.Clock systemDefaultZone();
+ method public static java.time.Clock systemUTC();
+ method public static java.time.Clock tick(java.time.Clock, java.time.Duration);
+ method public static java.time.Clock tickMinutes(java.time.ZoneId);
+ method public static java.time.Clock tickSeconds(java.time.ZoneId);
+ method public abstract java.time.Clock withZone(java.time.ZoneId);
+ }
+
+ public class DateTimeException extends java.lang.RuntimeException {
+ ctor public DateTimeException(java.lang.String);
+ ctor public DateTimeException(java.lang.String, java.lang.Throwable);
+ }
+
+ public final class DayOfWeek extends java.lang.Enum implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public static java.time.DayOfWeek from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.DayOfWeek minus(long);
+ method public static java.time.DayOfWeek of(int);
+ method public java.time.DayOfWeek plus(long);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.DayOfWeek valueOf(java.lang.String);
+ method public static final java.time.DayOfWeek[] values();
+ enum_constant public static final java.time.DayOfWeek FRIDAY;
+ enum_constant public static final java.time.DayOfWeek MONDAY;
+ enum_constant public static final java.time.DayOfWeek SATURDAY;
+ enum_constant public static final java.time.DayOfWeek SUNDAY;
+ enum_constant public static final java.time.DayOfWeek THURSDAY;
+ enum_constant public static final java.time.DayOfWeek TUESDAY;
+ enum_constant public static final java.time.DayOfWeek WEDNESDAY;
+ }
+
+ public final class Duration implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAmount {
+ method public java.time.Duration abs();
+ method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.Duration between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public int compareTo(java.time.Duration);
+ method public java.time.Duration dividedBy(long);
+ method public static java.time.Duration from(java.time.temporal.TemporalAmount);
+ method public long get(java.time.temporal.TemporalUnit);
+ method public int getNano();
+ method public long getSeconds();
+ method public java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public boolean isNegative();
+ method public boolean isZero();
+ method public java.time.Duration minus(java.time.Duration);
+ method public java.time.Duration minus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Duration minusDays(long);
+ method public java.time.Duration minusHours(long);
+ method public java.time.Duration minusMillis(long);
+ method public java.time.Duration minusMinutes(long);
+ method public java.time.Duration minusNanos(long);
+ method public java.time.Duration minusSeconds(long);
+ method public java.time.Duration multipliedBy(long);
+ method public java.time.Duration negated();
+ method public static java.time.Duration of(long, java.time.temporal.TemporalUnit);
+ method public static java.time.Duration ofDays(long);
+ method public static java.time.Duration ofHours(long);
+ method public static java.time.Duration ofMillis(long);
+ method public static java.time.Duration ofMinutes(long);
+ method public static java.time.Duration ofNanos(long);
+ method public static java.time.Duration ofSeconds(long);
+ method public static java.time.Duration ofSeconds(long, long);
+ method public static java.time.Duration parse(java.lang.CharSequence);
+ method public java.time.Duration plus(java.time.Duration);
+ method public java.time.Duration plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Duration plusDays(long);
+ method public java.time.Duration plusHours(long);
+ method public java.time.Duration plusMillis(long);
+ method public java.time.Duration plusMinutes(long);
+ method public java.time.Duration plusNanos(long);
+ method public java.time.Duration plusSeconds(long);
+ method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public long toDays();
+ method public long toHours();
+ method public long toMillis();
+ method public long toMinutes();
+ method public long toNanos();
+ method public java.time.Duration withNanos(int);
+ method public java.time.Duration withSeconds(long);
+ field public static final java.time.Duration ZERO;
+ }
+
+ public final class Instant implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ method public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ method public int compareTo(java.time.Instant);
+ method public static java.time.Instant from(java.time.temporal.TemporalAccessor);
+ method public long getEpochSecond();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getNano();
+ method public boolean isAfter(java.time.Instant);
+ method public boolean isBefore(java.time.Instant);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.Instant minusMillis(long);
+ method public java.time.Instant minusNanos(long);
+ method public java.time.Instant minusSeconds(long);
+ method public static java.time.Instant now();
+ method public static java.time.Instant now(java.time.Clock);
+ method public static java.time.Instant ofEpochMilli(long);
+ method public static java.time.Instant ofEpochSecond(long);
+ method public static java.time.Instant ofEpochSecond(long, long);
+ method public static java.time.Instant parse(java.lang.CharSequence);
+ method public java.time.Instant plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Instant plusMillis(long);
+ method public java.time.Instant plusNanos(long);
+ method public java.time.Instant plusSeconds(long);
+ method public long toEpochMilli();
+ method public java.time.Instant truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Instant with(java.time.temporal.TemporalField, long);
+ field public static final java.time.Instant EPOCH;
+ field public static final java.time.Instant MAX;
+ field public static final java.time.Instant MIN;
+ }
+
+ public final class LocalDate implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.LocalDateTime atStartOfDay();
+ method public java.time.ZonedDateTime atStartOfDay(java.time.ZoneId);
+ method public java.time.LocalDateTime atTime(int, int);
+ method public java.time.LocalDateTime atTime(int, int, int);
+ method public java.time.LocalDateTime atTime(int, int, int, int);
+ method public java.time.OffsetDateTime atTime(java.time.OffsetTime);
+ method public static java.time.LocalDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.IsoChronology getChronology();
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getYear();
+ method public int lengthOfMonth();
+ method public java.time.LocalDate minusDays(long);
+ method public java.time.LocalDate minusMonths(long);
+ method public java.time.LocalDate minusWeeks(long);
+ method public java.time.LocalDate minusYears(long);
+ method public static java.time.LocalDate now();
+ method public static java.time.LocalDate now(java.time.ZoneId);
+ method public static java.time.LocalDate now(java.time.Clock);
+ method public static java.time.LocalDate of(int, java.time.Month, int);
+ method public static java.time.LocalDate of(int, int, int);
+ method public static java.time.LocalDate ofEpochDay(long);
+ method public static java.time.LocalDate ofYearDay(int, int);
+ method public static java.time.LocalDate parse(java.lang.CharSequence);
+ method public static java.time.LocalDate parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalDate plusDays(long);
+ method public java.time.LocalDate plusMonths(long);
+ method public java.time.LocalDate plusWeeks(long);
+ method public java.time.LocalDate plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Period until(java.time.chrono.ChronoLocalDate);
+ method public java.time.LocalDate withDayOfMonth(int);
+ method public java.time.LocalDate withDayOfYear(int);
+ method public java.time.LocalDate withMonth(int);
+ method public java.time.LocalDate withYear(int);
+ field public static final java.time.LocalDate MAX;
+ field public static final java.time.LocalDate MIN;
+ }
+
+ public final class LocalDateTime implements java.time.chrono.ChronoLocalDateTime java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.OffsetDateTime atOffset(java.time.ZoneOffset);
+ method public java.time.ZonedDateTime atZone(java.time.ZoneId);
+ method public static java.time.LocalDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public int getSecond();
+ method public int getYear();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.LocalDateTime minusDays(long);
+ method public java.time.LocalDateTime minusHours(long);
+ method public java.time.LocalDateTime minusMinutes(long);
+ method public java.time.LocalDateTime minusMonths(long);
+ method public java.time.LocalDateTime minusNanos(long);
+ method public java.time.LocalDateTime minusSeconds(long);
+ method public java.time.LocalDateTime minusWeeks(long);
+ method public java.time.LocalDateTime minusYears(long);
+ method public static java.time.LocalDateTime now();
+ method public static java.time.LocalDateTime now(java.time.ZoneId);
+ method public static java.time.LocalDateTime now(java.time.Clock);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, java.time.Month, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(int, int, int, int, int, int, int);
+ method public static java.time.LocalDateTime of(java.time.LocalDate, java.time.LocalTime);
+ method public static java.time.LocalDateTime ofEpochSecond(long, int, java.time.ZoneOffset);
+ method public static java.time.LocalDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.LocalDateTime parse(java.lang.CharSequence);
+ method public static java.time.LocalDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.LocalDateTime plusDays(long);
+ method public java.time.LocalDateTime plusHours(long);
+ method public java.time.LocalDateTime plusMinutes(long);
+ method public java.time.LocalDateTime plusMonths(long);
+ method public java.time.LocalDateTime plusNanos(long);
+ method public java.time.LocalDateTime plusSeconds(long);
+ method public java.time.LocalDateTime plusWeeks(long);
+ method public java.time.LocalDateTime plusYears(long);
+ method public java.time.LocalDate toLocalDate();
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.LocalDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.LocalDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.LocalDateTime withDayOfMonth(int);
+ method public java.time.LocalDateTime withDayOfYear(int);
+ method public java.time.LocalDateTime withHour(int);
+ method public java.time.LocalDateTime withMinute(int);
+ method public java.time.LocalDateTime withMonth(int);
+ method public java.time.LocalDateTime withNano(int);
+ method public java.time.LocalDateTime withSecond(int);
+ method public java.time.LocalDateTime withYear(int);
+ field public static final java.time.LocalDateTime MAX;
+ field public static final java.time.LocalDateTime MIN;
+ }
+
+ public final class LocalTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDateTime atDate(java.time.LocalDate);
+ method public java.time.OffsetTime atOffset(java.time.ZoneOffset);
+ method public int compareTo(java.time.LocalTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.LocalTime from(java.time.temporal.TemporalAccessor);
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public int getNano();
+ method public int getSecond();
+ method public boolean isAfter(java.time.LocalTime);
+ method public boolean isBefore(java.time.LocalTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime minusHours(long);
+ method public java.time.LocalTime minusMinutes(long);
+ method public java.time.LocalTime minusNanos(long);
+ method public java.time.LocalTime minusSeconds(long);
+ method public static java.time.LocalTime now();
+ method public static java.time.LocalTime now(java.time.ZoneId);
+ method public static java.time.LocalTime now(java.time.Clock);
+ method public static java.time.LocalTime of(int, int);
+ method public static java.time.LocalTime of(int, int, int);
+ method public static java.time.LocalTime of(int, int, int, int);
+ method public static java.time.LocalTime ofNanoOfDay(long);
+ method public static java.time.LocalTime ofSecondOfDay(long);
+ method public static java.time.LocalTime parse(java.lang.CharSequence);
+ method public static java.time.LocalTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.LocalTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime plusHours(long);
+ method public java.time.LocalTime plusMinutes(long);
+ method public java.time.LocalTime plusNanos(long);
+ method public java.time.LocalTime plusSeconds(long);
+ method public long toNanoOfDay();
+ method public int toSecondOfDay();
+ method public java.time.LocalTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.LocalTime with(java.time.temporal.TemporalField, long);
+ method public java.time.LocalTime withHour(int);
+ method public java.time.LocalTime withMinute(int);
+ method public java.time.LocalTime withNano(int);
+ method public java.time.LocalTime withSecond(int);
+ field public static final java.time.LocalTime MAX;
+ field public static final java.time.LocalTime MIDNIGHT;
+ field public static final java.time.LocalTime MIN;
+ field public static final java.time.LocalTime NOON;
+ }
+
+ public final class Month extends java.lang.Enum implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public int firstDayOfYear(boolean);
+ method public java.time.Month firstMonthOfQuarter();
+ method public static java.time.Month from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public int length(boolean);
+ method public int maxLength();
+ method public int minLength();
+ method public java.time.Month minus(long);
+ method public static java.time.Month of(int);
+ method public java.time.Month plus(long);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.Month valueOf(java.lang.String);
+ method public static final java.time.Month[] values();
+ enum_constant public static final java.time.Month APRIL;
+ enum_constant public static final java.time.Month AUGUST;
+ enum_constant public static final java.time.Month DECEMBER;
+ enum_constant public static final java.time.Month FEBRUARY;
+ enum_constant public static final java.time.Month JANUARY;
+ enum_constant public static final java.time.Month JULY;
+ enum_constant public static final java.time.Month JUNE;
+ enum_constant public static final java.time.Month MARCH;
+ enum_constant public static final java.time.Month MAY;
+ enum_constant public static final java.time.Month NOVEMBER;
+ enum_constant public static final java.time.Month OCTOBER;
+ enum_constant public static final java.time.Month SEPTEMBER;
+ }
+
+ public final class MonthDay implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atYear(int);
+ method public int compareTo(java.time.MonthDay);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.MonthDay from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public boolean isAfter(java.time.MonthDay);
+ method public boolean isBefore(java.time.MonthDay);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isValidYear(int);
+ method public static java.time.MonthDay now();
+ method public static java.time.MonthDay now(java.time.ZoneId);
+ method public static java.time.MonthDay now(java.time.Clock);
+ method public static java.time.MonthDay of(java.time.Month, int);
+ method public static java.time.MonthDay of(int, int);
+ method public static java.time.MonthDay parse(java.lang.CharSequence);
+ method public static java.time.MonthDay parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.MonthDay with(java.time.Month);
+ method public java.time.MonthDay withDayOfMonth(int);
+ method public java.time.MonthDay withMonth(int);
+ }
+
+ public final class OffsetDateTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.ZonedDateTime atZoneSameInstant(java.time.ZoneId);
+ method public java.time.ZonedDateTime atZoneSimilarLocal(java.time.ZoneId);
+ method public int compareTo(java.time.OffsetDateTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.OffsetDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public int getYear();
+ method public boolean isAfter(java.time.OffsetDateTime);
+ method public boolean isBefore(java.time.OffsetDateTime);
+ method public boolean isEqual(java.time.OffsetDateTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime minusDays(long);
+ method public java.time.OffsetDateTime minusHours(long);
+ method public java.time.OffsetDateTime minusMinutes(long);
+ method public java.time.OffsetDateTime minusMonths(long);
+ method public java.time.OffsetDateTime minusNanos(long);
+ method public java.time.OffsetDateTime minusSeconds(long);
+ method public java.time.OffsetDateTime minusWeeks(long);
+ method public java.time.OffsetDateTime minusYears(long);
+ method public static java.time.OffsetDateTime now();
+ method public static java.time.OffsetDateTime now(java.time.ZoneId);
+ method public static java.time.OffsetDateTime now(java.time.Clock);
+ method public static java.time.OffsetDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime of(java.time.LocalDateTime, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime of(int, int, int, int, int, int, int, java.time.ZoneOffset);
+ method public static java.time.OffsetDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.OffsetDateTime parse(java.lang.CharSequence);
+ method public static java.time.OffsetDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.OffsetDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime plusDays(long);
+ method public java.time.OffsetDateTime plusHours(long);
+ method public java.time.OffsetDateTime plusMinutes(long);
+ method public java.time.OffsetDateTime plusMonths(long);
+ method public java.time.OffsetDateTime plusNanos(long);
+ method public java.time.OffsetDateTime plusSeconds(long);
+ method public java.time.OffsetDateTime plusWeeks(long);
+ method public java.time.OffsetDateTime plusYears(long);
+ method public static java.util.Comparator<java.time.OffsetDateTime> timeLineOrder();
+ method public long toEpochSecond();
+ method public java.time.Instant toInstant();
+ method public java.time.LocalDate toLocalDate();
+ method public java.time.LocalDateTime toLocalDateTime();
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.OffsetTime toOffsetTime();
+ method public java.time.ZonedDateTime toZonedDateTime();
+ method public java.time.OffsetDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.OffsetDateTime withDayOfMonth(int);
+ method public java.time.OffsetDateTime withDayOfYear(int);
+ method public java.time.OffsetDateTime withHour(int);
+ method public java.time.OffsetDateTime withMinute(int);
+ method public java.time.OffsetDateTime withMonth(int);
+ method public java.time.OffsetDateTime withNano(int);
+ method public java.time.OffsetDateTime withOffsetSameInstant(java.time.ZoneOffset);
+ method public java.time.OffsetDateTime withOffsetSameLocal(java.time.ZoneOffset);
+ method public java.time.OffsetDateTime withSecond(int);
+ method public java.time.OffsetDateTime withYear(int);
+ field public static final java.time.OffsetDateTime MAX;
+ field public static final java.time.OffsetDateTime MIN;
+ }
+
+ public final class OffsetTime implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.OffsetDateTime atDate(java.time.LocalDate);
+ method public int compareTo(java.time.OffsetTime);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.OffsetTime from(java.time.temporal.TemporalAccessor);
+ method public int getHour();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getMinute();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public boolean isAfter(java.time.OffsetTime);
+ method public boolean isBefore(java.time.OffsetTime);
+ method public boolean isEqual(java.time.OffsetTime);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime minusHours(long);
+ method public java.time.OffsetTime minusMinutes(long);
+ method public java.time.OffsetTime minusNanos(long);
+ method public java.time.OffsetTime minusSeconds(long);
+ method public static java.time.OffsetTime now();
+ method public static java.time.OffsetTime now(java.time.ZoneId);
+ method public static java.time.OffsetTime now(java.time.Clock);
+ method public static java.time.OffsetTime of(java.time.LocalTime, java.time.ZoneOffset);
+ method public static java.time.OffsetTime of(int, int, int, int, java.time.ZoneOffset);
+ method public static java.time.OffsetTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.OffsetTime parse(java.lang.CharSequence);
+ method public static java.time.OffsetTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.OffsetTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime plusHours(long);
+ method public java.time.OffsetTime plusMinutes(long);
+ method public java.time.OffsetTime plusNanos(long);
+ method public java.time.OffsetTime plusSeconds(long);
+ method public java.time.LocalTime toLocalTime();
+ method public java.time.OffsetTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.OffsetTime with(java.time.temporal.TemporalField, long);
+ method public java.time.OffsetTime withHour(int);
+ method public java.time.OffsetTime withMinute(int);
+ method public java.time.OffsetTime withNano(int);
+ method public java.time.OffsetTime withOffsetSameInstant(java.time.ZoneOffset);
+ method public java.time.OffsetTime withOffsetSameLocal(java.time.ZoneOffset);
+ method public java.time.OffsetTime withSecond(int);
+ field public static final java.time.OffsetTime MAX;
+ field public static final java.time.OffsetTime MIN;
+ }
+
+ public final class Period implements java.time.chrono.ChronoPeriod java.io.Serializable {
+ method public java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.Period between(java.time.LocalDate, java.time.LocalDate);
+ method public static java.time.Period from(java.time.temporal.TemporalAmount);
+ method public long get(java.time.temporal.TemporalUnit);
+ method public java.time.chrono.IsoChronology getChronology();
+ method public int getDays();
+ method public int getMonths();
+ method public java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public int getYears();
+ method public java.time.Period minus(java.time.temporal.TemporalAmount);
+ method public java.time.Period minusDays(long);
+ method public java.time.Period minusMonths(long);
+ method public java.time.Period minusYears(long);
+ method public java.time.Period multipliedBy(int);
+ method public java.time.Period normalized();
+ method public static java.time.Period of(int, int, int);
+ method public static java.time.Period ofDays(int);
+ method public static java.time.Period ofMonths(int);
+ method public static java.time.Period ofWeeks(int);
+ method public static java.time.Period ofYears(int);
+ method public static java.time.Period parse(java.lang.CharSequence);
+ method public java.time.Period plus(java.time.temporal.TemporalAmount);
+ method public java.time.Period plusDays(long);
+ method public java.time.Period plusMonths(long);
+ method public java.time.Period plusYears(long);
+ method public java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public long toTotalMonths();
+ method public java.time.Period withDays(int);
+ method public java.time.Period withMonths(int);
+ method public java.time.Period withYears(int);
+ field public static final java.time.Period ZERO;
+ }
+
+ public final class Year implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atDay(int);
+ method public java.time.YearMonth atMonth(java.time.Month);
+ method public java.time.YearMonth atMonth(int);
+ method public java.time.LocalDate atMonthDay(java.time.MonthDay);
+ method public int compareTo(java.time.Year);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.Year from(java.time.temporal.TemporalAccessor);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int getValue();
+ method public boolean isAfter(java.time.Year);
+ method public boolean isBefore(java.time.Year);
+ method public static boolean isLeap(long);
+ method public boolean isLeap();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public boolean isValidMonthDay(java.time.MonthDay);
+ method public int length();
+ method public java.time.Year minusYears(long);
+ method public static java.time.Year now();
+ method public static java.time.Year now(java.time.ZoneId);
+ method public static java.time.Year now(java.time.Clock);
+ method public static java.time.Year of(int);
+ method public static java.time.Year parse(java.lang.CharSequence);
+ method public static java.time.Year parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.Year plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.Year plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.Year with(java.time.temporal.TemporalField, long);
+ field public static final int MAX_VALUE = 999999999; // 0x3b9ac9ff
+ field public static final int MIN_VALUE = -999999999; // 0xc4653601
+ }
+
+ public final class YearMonth implements java.lang.Comparable java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public java.time.LocalDate atDay(int);
+ method public java.time.LocalDate atEndOfMonth();
+ method public int compareTo(java.time.YearMonth);
+ method public java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.YearMonth from(java.time.temporal.TemporalAccessor);
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getYear();
+ method public boolean isAfter(java.time.YearMonth);
+ method public boolean isBefore(java.time.YearMonth);
+ method public boolean isLeapYear();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalUnit);
+ method public boolean isValidDay(int);
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public java.time.YearMonth minusMonths(long);
+ method public java.time.YearMonth minusYears(long);
+ method public static java.time.YearMonth now();
+ method public static java.time.YearMonth now(java.time.ZoneId);
+ method public static java.time.YearMonth now(java.time.Clock);
+ method public static java.time.YearMonth of(int, java.time.Month);
+ method public static java.time.YearMonth of(int, int);
+ method public static java.time.YearMonth parse(java.lang.CharSequence);
+ method public static java.time.YearMonth parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.YearMonth plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.YearMonth plusMonths(long);
+ method public java.time.YearMonth plusYears(long);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.YearMonth with(java.time.temporal.TemporalField, long);
+ method public java.time.YearMonth withMonth(int);
+ method public java.time.YearMonth withYear(int);
+ }
+
+ public abstract class ZoneId implements java.io.Serializable {
+ method public static java.time.ZoneId from(java.time.temporal.TemporalAccessor);
+ method public static java.util.Set<java.lang.String> getAvailableZoneIds();
+ method public java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public abstract java.lang.String getId();
+ method public abstract java.time.zone.ZoneRules getRules();
+ method public java.time.ZoneId normalized();
+ method public static java.time.ZoneId of(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
+ method public static java.time.ZoneId of(java.lang.String);
+ method public static java.time.ZoneId ofOffset(java.lang.String, java.time.ZoneOffset);
+ method public static java.time.ZoneId systemDefault();
+ field public static final java.util.Map<java.lang.String, java.lang.String> SHORT_IDS;
+ }
+
+ public final class ZoneOffset extends java.time.ZoneId implements java.lang.Comparable java.io.Serializable java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public int compareTo(java.time.ZoneOffset);
+ method public static java.time.ZoneOffset from(java.time.temporal.TemporalAccessor);
+ method public int get(java.time.temporal.TemporalField);
+ method public java.lang.String getId();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public java.time.zone.ZoneRules getRules();
+ method public int getTotalSeconds();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public static java.time.ZoneOffset of(java.lang.String);
+ method public static java.time.ZoneOffset ofHours(int);
+ method public static java.time.ZoneOffset ofHoursMinutes(int, int);
+ method public static java.time.ZoneOffset ofHoursMinutesSeconds(int, int, int);
+ method public static java.time.ZoneOffset ofTotalSeconds(int);
+ method public <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ field public static final java.time.ZoneOffset MAX;
+ field public static final java.time.ZoneOffset MIN;
+ field public static final java.time.ZoneOffset UTC;
+ }
+
+ public final class ZonedDateTime implements java.time.chrono.ChronoZonedDateTime java.io.Serializable java.time.temporal.Temporal {
+ method public static java.time.ZonedDateTime from(java.time.temporal.TemporalAccessor);
+ method public int getDayOfMonth();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public int getDayOfYear();
+ method public int getHour();
+ method public int getMinute();
+ method public java.time.Month getMonth();
+ method public int getMonthValue();
+ method public int getNano();
+ method public java.time.ZoneOffset getOffset();
+ method public int getSecond();
+ method public int getYear();
+ method public java.time.ZoneId getZone();
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public java.time.ZonedDateTime minusDays(long);
+ method public java.time.ZonedDateTime minusHours(long);
+ method public java.time.ZonedDateTime minusMinutes(long);
+ method public java.time.ZonedDateTime minusMonths(long);
+ method public java.time.ZonedDateTime minusNanos(long);
+ method public java.time.ZonedDateTime minusSeconds(long);
+ method public java.time.ZonedDateTime minusWeeks(long);
+ method public java.time.ZonedDateTime minusYears(long);
+ method public static java.time.ZonedDateTime now();
+ method public static java.time.ZonedDateTime now(java.time.ZoneId);
+ method public static java.time.ZonedDateTime now(java.time.Clock);
+ method public static java.time.ZonedDateTime of(java.time.LocalDate, java.time.LocalTime, java.time.ZoneId);
+ method public static java.time.ZonedDateTime of(java.time.LocalDateTime, java.time.ZoneId);
+ method public static java.time.ZonedDateTime of(int, int, int, int, int, int, int, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofInstant(java.time.Instant, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofInstant(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ method public static java.time.ZonedDateTime ofLocal(java.time.LocalDateTime, java.time.ZoneId, java.time.ZoneOffset);
+ method public static java.time.ZonedDateTime ofStrict(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneId);
+ method public static java.time.ZonedDateTime parse(java.lang.CharSequence);
+ method public static java.time.ZonedDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter);
+ method public java.time.ZonedDateTime plus(long, java.time.temporal.TemporalUnit);
+ method public java.time.ZonedDateTime plusDays(long);
+ method public java.time.ZonedDateTime plusHours(long);
+ method public java.time.ZonedDateTime plusMinutes(long);
+ method public java.time.ZonedDateTime plusMonths(long);
+ method public java.time.ZonedDateTime plusNanos(long);
+ method public java.time.ZonedDateTime plusSeconds(long);
+ method public java.time.ZonedDateTime plusWeeks(long);
+ method public java.time.ZonedDateTime plusYears(long);
+ method public java.time.LocalDateTime toLocalDateTime();
+ method public java.time.OffsetDateTime toOffsetDateTime();
+ method public java.time.ZonedDateTime truncatedTo(java.time.temporal.TemporalUnit);
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public java.time.ZonedDateTime with(java.time.temporal.TemporalField, long);
+ method public java.time.ZonedDateTime withDayOfMonth(int);
+ method public java.time.ZonedDateTime withDayOfYear(int);
+ method public java.time.ZonedDateTime withEarlierOffsetAtOverlap();
+ method public java.time.ZonedDateTime withFixedOffsetZone();
+ method public java.time.ZonedDateTime withHour(int);
+ method public java.time.ZonedDateTime withLaterOffsetAtOverlap();
+ method public java.time.ZonedDateTime withMinute(int);
+ method public java.time.ZonedDateTime withMonth(int);
+ method public java.time.ZonedDateTime withNano(int);
+ method public java.time.ZonedDateTime withSecond(int);
+ method public java.time.ZonedDateTime withYear(int);
+ method public java.time.ZonedDateTime withZoneSameInstant(java.time.ZoneId);
+ method public java.time.ZonedDateTime withZoneSameLocal(java.time.ZoneId);
+ }
+
+}
+
+package java.time.chrono {
+
+ public abstract class AbstractChronology implements java.time.chrono.Chronology {
+ ctor protected AbstractChronology();
+ method public int compareTo(java.time.chrono.Chronology);
+ method public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.format.ResolverStyle);
+ }
+
+ public abstract interface ChronoLocalDate implements java.lang.Comparable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public default java.time.chrono.ChronoLocalDateTime<?> atTime(java.time.LocalTime);
+ method public default int compareTo(java.time.chrono.ChronoLocalDate);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoLocalDate from(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.chrono.Chronology getChronology();
+ method public default java.time.chrono.Era getEra();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoLocalDate);
+ method public default boolean isBefore(java.time.chrono.ChronoLocalDate);
+ method public default boolean isEqual(java.time.chrono.ChronoLocalDate);
+ method public default boolean isLeapYear();
+ method public default boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract int lengthOfMonth();
+ method public default int lengthOfYear();
+ method public default java.time.chrono.ChronoLocalDate plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoLocalDate> timeLineOrder();
+ method public default long toEpochDay();
+ method public abstract java.lang.String toString();
+ method public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ method public default java.time.chrono.ChronoLocalDate with(java.time.temporal.TemporalField, long);
+ }
+
+ abstract class ChronoLocalDateImpl<D extends java.time.chrono.ChronoLocalDate> implements java.time.chrono.ChronoLocalDate java.io.Serializable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ }
+
+ public abstract interface ChronoLocalDateTime<D extends java.time.chrono.ChronoLocalDate> implements java.lang.Comparable java.time.temporal.Temporal java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> atZone(java.time.ZoneId);
+ method public default int compareTo(java.time.chrono.ChronoLocalDateTime<?>);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoLocalDateTime<?> from(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.Chronology getChronology();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoLocalDateTime<?>);
+ method public default boolean isBefore(java.time.chrono.ChronoLocalDateTime<?>);
+ method public default boolean isEqual(java.time.chrono.ChronoLocalDateTime<?>);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoLocalDateTime<?>> timeLineOrder();
+ method public default long toEpochSecond(java.time.ZoneOffset);
+ method public default java.time.Instant toInstant(java.time.ZoneOffset);
+ method public abstract D toLocalDate();
+ method public abstract java.time.LocalTime toLocalTime();
+ method public abstract java.lang.String toString();
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> with(java.time.temporal.TemporalField, long);
+ }
+
+ public abstract interface ChronoPeriod implements java.time.temporal.TemporalAmount {
+ method public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public static java.time.chrono.ChronoPeriod between(java.time.chrono.ChronoLocalDate, java.time.chrono.ChronoLocalDate);
+ method public abstract boolean equals(java.lang.Object);
+ method public abstract long get(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.Chronology getChronology();
+ method public abstract java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public abstract int hashCode();
+ method public default boolean isNegative();
+ method public default boolean isZero();
+ method public abstract java.time.chrono.ChronoPeriod minus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.chrono.ChronoPeriod multipliedBy(int);
+ method public default java.time.chrono.ChronoPeriod negated();
+ method public abstract java.time.chrono.ChronoPeriod normalized();
+ method public abstract java.time.chrono.ChronoPeriod plus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ method public abstract java.lang.String toString();
+ }
+
+ public abstract interface ChronoZonedDateTime<D extends java.time.chrono.ChronoLocalDate> implements java.lang.Comparable java.time.temporal.Temporal {
+ method public default int compareTo(java.time.chrono.ChronoZonedDateTime<?>);
+ method public abstract boolean equals(java.lang.Object);
+ method public default java.lang.String format(java.time.format.DateTimeFormatter);
+ method public static java.time.chrono.ChronoZonedDateTime<?> from(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.Chronology getChronology();
+ method public default long getLong(java.time.temporal.TemporalField);
+ method public abstract java.time.ZoneOffset getOffset();
+ method public abstract java.time.ZoneId getZone();
+ method public abstract int hashCode();
+ method public default boolean isAfter(java.time.chrono.ChronoZonedDateTime<?>);
+ method public default boolean isBefore(java.time.chrono.ChronoZonedDateTime<?>);
+ method public default boolean isEqual(java.time.chrono.ChronoZonedDateTime<?>);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default boolean isSupported(java.time.temporal.TemporalUnit);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> plus(long, java.time.temporal.TemporalUnit);
+ method public static java.util.Comparator<java.time.chrono.ChronoZonedDateTime<?>> timeLineOrder();
+ method public default long toEpochSecond();
+ method public default java.time.Instant toInstant();
+ method public default D toLocalDate();
+ method public abstract java.time.chrono.ChronoLocalDateTime<D> toLocalDateTime();
+ method public default java.time.LocalTime toLocalTime();
+ method public abstract java.lang.String toString();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> with(java.time.temporal.TemporalField, long);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withEarlierOffsetAtOverlap();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withLaterOffsetAtOverlap();
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withZoneSameInstant(java.time.ZoneId);
+ method public abstract java.time.chrono.ChronoZonedDateTime<D> withZoneSameLocal(java.time.ZoneId);
+ }
+
+ public abstract interface Chronology implements java.lang.Comparable {
+ method public abstract int compareTo(java.time.chrono.Chronology);
+ method public default java.time.chrono.ChronoLocalDate date(java.time.chrono.Era, int, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate date(int, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate date(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.chrono.ChronoLocalDate dateEpochDay(long);
+ method public default java.time.chrono.ChronoLocalDate dateNow();
+ method public default java.time.chrono.ChronoLocalDate dateNow(java.time.ZoneId);
+ method public default java.time.chrono.ChronoLocalDate dateNow(java.time.Clock);
+ method public default java.time.chrono.ChronoLocalDate dateYearDay(java.time.chrono.Era, int, int);
+ method public abstract java.time.chrono.ChronoLocalDate dateYearDay(int, int);
+ method public abstract boolean equals(java.lang.Object);
+ method public abstract java.time.chrono.Era eraOf(int);
+ method public abstract java.util.List<java.time.chrono.Era> eras();
+ method public static java.time.chrono.Chronology from(java.time.temporal.TemporalAccessor);
+ method public static java.util.Set<java.time.chrono.Chronology> getAvailableChronologies();
+ method public abstract java.lang.String getCalendarType();
+ method public default java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public abstract java.lang.String getId();
+ method public abstract int hashCode();
+ method public abstract boolean isLeapYear(long);
+ method public default java.time.chrono.ChronoLocalDateTime<? extends java.time.chrono.ChronoLocalDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public static java.time.chrono.Chronology of(java.lang.String);
+ method public static java.time.chrono.Chronology ofLocale(java.util.Locale);
+ method public default java.time.chrono.ChronoPeriod period(int, int, int);
+ method public abstract int prolepticYear(java.time.chrono.Era, int);
+ method public abstract java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public abstract java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.format.ResolverStyle);
+ method public abstract java.lang.String toString();
+ method public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ }
+
+ public abstract interface Era implements java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster {
+ method public default java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ method public default java.lang.String getDisplayName(java.time.format.TextStyle, java.util.Locale);
+ method public default long getLong(java.time.temporal.TemporalField);
+ method public abstract int getValue();
+ method public default boolean isSupported(java.time.temporal.TemporalField);
+ }
+
+ public final class HijrahChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.HijrahDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.HijrahDate date(int, int, int);
+ method public java.time.chrono.HijrahDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.HijrahDate dateEpochDay(long);
+ method public java.time.chrono.HijrahDate dateNow();
+ method public java.time.chrono.HijrahDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.HijrahDate dateNow(java.time.Clock);
+ method public java.time.chrono.HijrahDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.HijrahDate dateYearDay(int, int);
+ method public java.time.chrono.HijrahEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.HijrahDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.HijrahDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.HijrahChronology INSTANCE;
+ }
+
+ public final class HijrahDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.HijrahDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.HijrahDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.HijrahChronology getChronology();
+ method public java.time.chrono.HijrahEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public boolean isLeapYear();
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public static java.time.chrono.HijrahDate now();
+ method public static java.time.chrono.HijrahDate now(java.time.ZoneId);
+ method public static java.time.chrono.HijrahDate now(java.time.Clock);
+ method public static java.time.chrono.HijrahDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ method public java.time.chrono.HijrahDate withVariant(java.time.chrono.HijrahChronology);
+ }
+
+ public final class HijrahEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.HijrahEra of(int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public static java.time.chrono.HijrahEra valueOf(java.lang.String);
+ method public static final java.time.chrono.HijrahEra[] values();
+ enum_constant public static final java.time.chrono.HijrahEra AH;
+ }
+
+ public final class IsoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.LocalDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.LocalDate date(int, int, int);
+ method public java.time.LocalDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.LocalDate dateEpochDay(long);
+ method public java.time.LocalDate dateNow();
+ method public java.time.LocalDate dateNow(java.time.ZoneId);
+ method public java.time.LocalDate dateNow(java.time.Clock);
+ method public java.time.LocalDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.LocalDate dateYearDay(int, int);
+ method public java.time.chrono.IsoEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.LocalDateTime localDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.Period period(int, int, int);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.ZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.ZonedDateTime zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.IsoChronology INSTANCE;
+ }
+
+ public final class IsoEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.IsoEra of(int);
+ method public static java.time.chrono.IsoEra valueOf(java.lang.String);
+ method public static final java.time.chrono.IsoEra[] values();
+ enum_constant public static final java.time.chrono.IsoEra BCE;
+ enum_constant public static final java.time.chrono.IsoEra CE;
+ }
+
+ public final class JapaneseChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.JapaneseDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.JapaneseDate date(int, int, int);
+ method public java.time.chrono.JapaneseDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.JapaneseDate dateEpochDay(long);
+ method public java.time.chrono.JapaneseDate dateNow();
+ method public java.time.chrono.JapaneseDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.JapaneseDate dateNow(java.time.Clock);
+ method public java.time.chrono.JapaneseDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.JapaneseDate dateYearDay(int, int);
+ method public java.time.chrono.JapaneseEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.JapaneseDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.JapaneseDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.JapaneseChronology INSTANCE;
+ }
+
+ public final class JapaneseDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.JapaneseDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.JapaneseDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.JapaneseChronology getChronology();
+ method public java.time.chrono.JapaneseEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public boolean isSupported(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public int lengthOfYear();
+ method public static java.time.chrono.JapaneseDate now();
+ method public static java.time.chrono.JapaneseDate now(java.time.ZoneId);
+ method public static java.time.chrono.JapaneseDate now(java.time.Clock);
+ method public static java.time.chrono.JapaneseDate of(java.time.chrono.JapaneseEra, int, int, int);
+ method public static java.time.chrono.JapaneseDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class JapaneseEra implements java.time.chrono.Era java.io.Serializable {
+ method public int getValue();
+ method public static java.time.chrono.JapaneseEra of(int);
+ method public static java.time.chrono.JapaneseEra valueOf(java.lang.String);
+ method public static java.time.chrono.JapaneseEra[] values();
+ field public static final java.time.chrono.JapaneseEra HEISEI;
+ field public static final java.time.chrono.JapaneseEra MEIJI;
+ field public static final java.time.chrono.JapaneseEra SHOWA;
+ field public static final java.time.chrono.JapaneseEra TAISHO;
+ }
+
+ public final class MinguoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.MinguoDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.MinguoDate date(int, int, int);
+ method public java.time.chrono.MinguoDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.MinguoDate dateEpochDay(long);
+ method public java.time.chrono.MinguoDate dateNow();
+ method public java.time.chrono.MinguoDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.MinguoDate dateNow(java.time.Clock);
+ method public java.time.chrono.MinguoDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.MinguoDate dateYearDay(int, int);
+ method public java.time.chrono.MinguoEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.MinguoDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.MinguoDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.MinguoChronology INSTANCE;
+ }
+
+ public final class MinguoDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.MinguoDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.MinguoDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.MinguoChronology getChronology();
+ method public java.time.chrono.MinguoEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public static java.time.chrono.MinguoDate now();
+ method public static java.time.chrono.MinguoDate now(java.time.ZoneId);
+ method public static java.time.chrono.MinguoDate now(java.time.Clock);
+ method public static java.time.chrono.MinguoDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class MinguoEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.MinguoEra of(int);
+ method public static java.time.chrono.MinguoEra valueOf(java.lang.String);
+ method public static final java.time.chrono.MinguoEra[] values();
+ enum_constant public static final java.time.chrono.MinguoEra BEFORE_ROC;
+ enum_constant public static final java.time.chrono.MinguoEra ROC;
+ }
+
+ public final class ThaiBuddhistChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+ method public java.time.chrono.ThaiBuddhistDate date(java.time.chrono.Era, int, int, int);
+ method public java.time.chrono.ThaiBuddhistDate date(int, int, int);
+ method public java.time.chrono.ThaiBuddhistDate date(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ThaiBuddhistDate dateEpochDay(long);
+ method public java.time.chrono.ThaiBuddhistDate dateNow();
+ method public java.time.chrono.ThaiBuddhistDate dateNow(java.time.ZoneId);
+ method public java.time.chrono.ThaiBuddhistDate dateNow(java.time.Clock);
+ method public java.time.chrono.ThaiBuddhistDate dateYearDay(java.time.chrono.Era, int, int);
+ method public java.time.chrono.ThaiBuddhistDate dateYearDay(int, int);
+ method public java.time.chrono.ThaiBuddhistEra eraOf(int);
+ method public java.util.List<java.time.chrono.Era> eras();
+ method public java.lang.String getCalendarType();
+ method public java.lang.String getId();
+ method public boolean isLeapYear(long);
+ method public java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> localDateTime(java.time.temporal.TemporalAccessor);
+ method public int prolepticYear(java.time.chrono.Era, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.ChronoField);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.ThaiBuddhistDate> zonedDateTime(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ChronoZonedDateTime<java.time.chrono.ThaiBuddhistDate> zonedDateTime(java.time.Instant, java.time.ZoneId);
+ field public static final java.time.chrono.ThaiBuddhistChronology INSTANCE;
+ }
+
+ public final class ThaiBuddhistDate extends java.time.chrono.ChronoLocalDateImpl implements java.time.chrono.ChronoLocalDate java.io.Serializable {
+ method public final java.time.chrono.ChronoLocalDateTime<java.time.chrono.ThaiBuddhistDate> atTime(java.time.LocalTime);
+ method public static java.time.chrono.ThaiBuddhistDate from(java.time.temporal.TemporalAccessor);
+ method public java.time.chrono.ThaiBuddhistChronology getChronology();
+ method public java.time.chrono.ThaiBuddhistEra getEra();
+ method public long getLong(java.time.temporal.TemporalField);
+ method public int lengthOfMonth();
+ method public static java.time.chrono.ThaiBuddhistDate now();
+ method public static java.time.chrono.ThaiBuddhistDate now(java.time.ZoneId);
+ method public static java.time.chrono.ThaiBuddhistDate now(java.time.Clock);
+ method public static java.time.chrono.ThaiBuddhistDate of(int, int, int);
+ method public java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ method public long toEpochDay();
+ method public java.time.chrono.ChronoPeriod until(java.time.chrono.ChronoLocalDate);
+ }
+
+ public final class ThaiBuddhistEra extends java.lang.Enum implements java.time.chrono.Era {
+ method public int getValue();
+ method public static java.time.chrono.ThaiBuddhistEra of(int);
+ method public static java.time.chrono.ThaiBuddhistEra valueOf(java.lang.String);
+ method public static final java.time.chrono.ThaiBuddhistEra[] values();
+ enum_constant public static final java.time.chrono.ThaiBuddhistEra BE;
+ enum_constant public static final java.time.chrono.ThaiBuddhistEra BEFORE_BE;
+ }
+
+}
+
+package java.time.format {
+
+ public final class DateTimeFormatter {
+ method public java.lang.String format(java.time.temporal.TemporalAccessor);
+ method public void formatTo(java.time.temporal.TemporalAccessor, java.lang.Appendable);
+ method public java.time.chrono.Chronology getChronology();
+ method public java.time.format.DecimalStyle getDecimalStyle();
+ method public java.util.Locale getLocale();
+ method public java.util.Set<java.time.temporal.TemporalField> getResolverFields();
+ method public java.time.format.ResolverStyle getResolverStyle();
+ method public java.time.ZoneId getZone();
+ method public static java.time.format.DateTimeFormatter ofLocalizedDate(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofLocalizedTime(java.time.format.FormatStyle);
+ method public static java.time.format.DateTimeFormatter ofPattern(java.lang.String);
+ method public static java.time.format.DateTimeFormatter ofPattern(java.lang.String, java.util.Locale);
+ method public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence);
+ method public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence, java.text.ParsePosition);
+ method public <T> T parse(java.lang.CharSequence, java.time.temporal.TemporalQuery<T>);
+ method public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence, java.time.temporal.TemporalQuery<?>...);
+ method public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence, java.text.ParsePosition);
+ method public static final java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays();
+ method public static final java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond();
+ method public java.text.Format toFormat();
+ method public java.text.Format toFormat(java.time.temporal.TemporalQuery<?>);
+ method public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology);
+ method public java.time.format.DateTimeFormatter withDecimalStyle(java.time.format.DecimalStyle);
+ method public java.time.format.DateTimeFormatter withLocale(java.util.Locale);
+ method public java.time.format.DateTimeFormatter withResolverFields(java.time.temporal.TemporalField...);
+ method public java.time.format.DateTimeFormatter withResolverFields(java.util.Set<java.time.temporal.TemporalField>);
+ method public java.time.format.DateTimeFormatter withResolverStyle(java.time.format.ResolverStyle);
+ method public java.time.format.DateTimeFormatter withZone(java.time.ZoneId);
+ field public static final java.time.format.DateTimeFormatter BASIC_ISO_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_INSTANT;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_LOCAL_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_OFFSET_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_ORDINAL_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_TIME;
+ field public static final java.time.format.DateTimeFormatter ISO_WEEK_DATE;
+ field public static final java.time.format.DateTimeFormatter ISO_ZONED_DATE_TIME;
+ field public static final java.time.format.DateTimeFormatter RFC_1123_DATE_TIME;
+ }
+
+ public final class DateTimeFormatterBuilder {
+ ctor public DateTimeFormatterBuilder();
+ method public java.time.format.DateTimeFormatterBuilder append(java.time.format.DateTimeFormatter);
+ method public java.time.format.DateTimeFormatterBuilder appendChronologyId();
+ method public java.time.format.DateTimeFormatterBuilder appendChronologyText(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendFraction(java.time.temporal.TemporalField, int, int, boolean);
+ method public java.time.format.DateTimeFormatterBuilder appendInstant();
+ method public java.time.format.DateTimeFormatterBuilder appendInstant(int);
+ method public java.time.format.DateTimeFormatterBuilder appendLiteral(char);
+ method public java.time.format.DateTimeFormatterBuilder appendLiteral(java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendLocalized(java.time.format.FormatStyle, java.time.format.FormatStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendLocalizedOffset(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendOffset(java.lang.String, java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendOffsetId();
+ method public java.time.format.DateTimeFormatterBuilder appendOptional(java.time.format.DateTimeFormatter);
+ method public java.time.format.DateTimeFormatterBuilder appendPattern(java.lang.String);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField, java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField, java.util.Map<java.lang.Long, java.lang.String>);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField, int);
+ method public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField, int, int, java.time.format.SignStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField, int, int, int);
+ method public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField, int, int, java.time.chrono.ChronoLocalDate);
+ method public java.time.format.DateTimeFormatterBuilder appendZoneId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneOrOffsetId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneRegionId();
+ method public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle);
+ method public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle, java.util.Set<java.time.ZoneId>);
+ method public static java.lang.String getLocalizedDateTimePattern(java.time.format.FormatStyle, java.time.format.FormatStyle, java.time.chrono.Chronology, java.util.Locale);
+ method public java.time.format.DateTimeFormatterBuilder optionalEnd();
+ method public java.time.format.DateTimeFormatterBuilder optionalStart();
+ method public java.time.format.DateTimeFormatterBuilder padNext(int);
+ method public java.time.format.DateTimeFormatterBuilder padNext(int, char);
+ method public java.time.format.DateTimeFormatterBuilder parseCaseInsensitive();
+ method public java.time.format.DateTimeFormatterBuilder parseCaseSensitive();
+ method public java.time.format.DateTimeFormatterBuilder parseDefaulting(java.time.temporal.TemporalField, long);
+ method public java.time.format.DateTimeFormatterBuilder parseLenient();
+ method public java.time.format.DateTimeFormatterBuilder parseStrict();
+ method public java.time.format.DateTimeFormatter toFormatter();
+ method public java.time.format.DateTimeFormatter toFormatter(java.util.Locale);
+ }
+
+ public class DateTimeParseException extends java.time.DateTimeException {
+ ctor public DateTimeParseException(java.lang.String, java.lang.CharSequence, int);
+ ctor public DateTimeParseException(java.lang.String, java.lang.CharSequence, int, java.lang.Throwable);
+ method public int getErrorIndex();
+ method public java.lang.String getParsedString();
+ }
+
+ public final class DecimalStyle {
+ method public static java.util.Set<java.util.Locale> getAvailableLocales();
+ method public char getDecimalSeparator();
+ method public char getNegativeSign();
+ method public char getPositiveSign();
+ method public char getZeroDigit();
+ method public static java.time.format.DecimalStyle of(java.util.Locale);
+ method public static java.time.format.DecimalStyle ofDefaultLocale();
+ method public java.time.format.DecimalStyle withDecimalSeparator(char);
+ method public java.time.format.DecimalStyle withNegativeSign(char);
+ method public java.time.format.DecimalStyle withPositiveSign(char);
+ method public java.time.format.DecimalStyle withZeroDigit(char);
+ field public static final java.time.format.DecimalStyle STANDARD;
+ }
+
+ public final class FormatStyle extends java.lang.Enum {
+ method public static java.time.format.FormatStyle valueOf(java.lang.String);
+ method public static final java.time.format.FormatStyle[] values();
+ enum_constant public static final java.time.format.FormatStyle FULL;
+ enum_constant public static final java.time.format.FormatStyle LONG;
+ enum_constant public static final java.time.format.FormatStyle MEDIUM;
+ enum_constant public static final java.time.format.FormatStyle SHORT;
+ }
+
+ public final class ResolverStyle extends java.lang.Enum {
+ method public static java.time.format.ResolverStyle valueOf(java.lang.String);
+ method public static final java.time.format.ResolverStyle[] values();
+ enum_constant public static final java.time.format.ResolverStyle LENIENT;
+ enum_constant public static final java.time.format.ResolverStyle SMART;
+ enum_constant public static final java.time.format.ResolverStyle STRICT;
+ }
+
+ public final class SignStyle extends java.lang.Enum {
+ method public static java.time.format.SignStyle valueOf(java.lang.String);
+ method public static final java.time.format.SignStyle[] values();
+ enum_constant public static final java.time.format.SignStyle ALWAYS;
+ enum_constant public static final java.time.format.SignStyle EXCEEDS_PAD;
+ enum_constant public static final java.time.format.SignStyle NEVER;
+ enum_constant public static final java.time.format.SignStyle NORMAL;
+ enum_constant public static final java.time.format.SignStyle NOT_NEGATIVE;
+ }
+
+ public final class TextStyle extends java.lang.Enum {
+ method public java.time.format.TextStyle asNormal();
+ method public java.time.format.TextStyle asStandalone();
+ method public boolean isStandalone();
+ method public static java.time.format.TextStyle valueOf(java.lang.String);
+ method public static final java.time.format.TextStyle[] values();
+ enum_constant public static final java.time.format.TextStyle FULL;
+ enum_constant public static final java.time.format.TextStyle FULL_STANDALONE;
+ enum_constant public static final java.time.format.TextStyle NARROW;
+ enum_constant public static final java.time.format.TextStyle NARROW_STANDALONE;
+ enum_constant public static final java.time.format.TextStyle SHORT;
+ enum_constant public static final java.time.format.TextStyle SHORT_STANDALONE;
+ }
+
+}
+
+package java.time.temporal {
+
+ public final class ChronoField extends java.lang.Enum implements java.time.temporal.TemporalField {
+ method public <R extends java.time.temporal.Temporal> R adjustInto(R, long);
+ method public int checkValidIntValue(long);
+ method public long checkValidValue(long);
+ method public java.time.temporal.TemporalUnit getBaseUnit();
+ method public java.lang.String getDisplayName(java.util.Locale);
+ method public long getFrom(java.time.temporal.TemporalAccessor);
+ method public java.time.temporal.TemporalUnit getRangeUnit();
+ method public boolean isDateBased();
+ method public boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ method public boolean isTimeBased();
+ method public java.time.temporal.ValueRange range();
+ method public java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ method public static java.time.temporal.ChronoField valueOf(java.lang.String);
+ method public static final java.time.temporal.ChronoField[] values();
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_DAY_OF_WEEK_IN_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_WEEK_OF_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField ALIGNED_WEEK_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField AMPM_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField CLOCK_HOUR_OF_AMPM;
+ enum_constant public static final java.time.temporal.ChronoField CLOCK_HOUR_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_WEEK;
+ enum_constant public static final java.time.temporal.ChronoField DAY_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField EPOCH_DAY;
+ enum_constant public static final java.time.temporal.ChronoField ERA;
+ enum_constant public static final java.time.temporal.ChronoField HOUR_OF_AMPM;
+ enum_constant public static final java.time.temporal.ChronoField HOUR_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField INSTANT_SECONDS;
+ enum_constant public static final java.time.temporal.ChronoField MICRO_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MICRO_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField MILLI_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MILLI_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField MINUTE_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField MINUTE_OF_HOUR;
+ enum_constant public static final java.time.temporal.ChronoField MONTH_OF_YEAR;
+ enum_constant public static final java.time.temporal.ChronoField NANO_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField NANO_OF_SECOND;
+ enum_constant public static final java.time.temporal.ChronoField OFFSET_SECONDS;
+ enum_constant public static final java.time.temporal.ChronoField PROLEPTIC_MONTH;
+ enum_constant public static final java.time.temporal.ChronoField SECOND_OF_DAY;
+ enum_constant public static final java.time.temporal.ChronoField SECOND_OF_MINUTE;
+ enum_constant public static final java.time.temporal.ChronoField YEAR;
+ enum_constant public static final java.time.temporal.ChronoField YEAR_OF_ERA;
+ }
+
+ public final class ChronoUnit extends java.lang.Enum implements java.time.temporal.TemporalUnit {
+ method public <R extends java.time.temporal.Temporal> R addTo(R, long);
+ method public long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public java.time.Duration getDuration();
+ method public boolean isDateBased();
+ method public boolean isDurationEstimated();
+ method public boolean isSupportedBy(java.time.temporal.Temporal);
+ method public boolean isTimeBased();
+ method public static java.time.temporal.ChronoUnit valueOf(java.lang.String);
+ method public static final java.time.temporal.ChronoUnit[] values();
+ enum_constant public static final java.time.temporal.ChronoUnit CENTURIES;
+ enum_constant public static final java.time.temporal.ChronoUnit DAYS;
+ enum_constant public static final java.time.temporal.ChronoUnit DECADES;
+ enum_constant public static final java.time.temporal.ChronoUnit ERAS;
+ enum_constant public static final java.time.temporal.ChronoUnit FOREVER;
+ enum_constant public static final java.time.temporal.ChronoUnit HALF_DAYS;
+ enum_constant public static final java.time.temporal.ChronoUnit HOURS;
+ enum_constant public static final java.time.temporal.ChronoUnit MICROS;
+ enum_constant public static final java.time.temporal.ChronoUnit MILLENNIA;
+ enum_constant public static final java.time.temporal.ChronoUnit MILLIS;
+ enum_constant public static final java.time.temporal.ChronoUnit MINUTES;
+ enum_constant public static final java.time.temporal.ChronoUnit MONTHS;
+ enum_constant public static final java.time.temporal.ChronoUnit NANOS;
+ enum_constant public static final java.time.temporal.ChronoUnit SECONDS;
+ enum_constant public static final java.time.temporal.ChronoUnit WEEKS;
+ enum_constant public static final java.time.temporal.ChronoUnit YEARS;
+ }
+
+ public final class IsoFields {
+ field public static final java.time.temporal.TemporalField DAY_OF_QUARTER;
+ field public static final java.time.temporal.TemporalField QUARTER_OF_YEAR;
+ field public static final java.time.temporal.TemporalUnit QUARTER_YEARS;
+ field public static final java.time.temporal.TemporalField WEEK_BASED_YEAR;
+ field public static final java.time.temporal.TemporalUnit WEEK_BASED_YEARS;
+ field public static final java.time.temporal.TemporalField WEEK_OF_WEEK_BASED_YEAR;
+ }
+
+ public final class JulianFields {
+ field public static final java.time.temporal.TemporalField JULIAN_DAY;
+ field public static final java.time.temporal.TemporalField MODIFIED_JULIAN_DAY;
+ field public static final java.time.temporal.TemporalField RATA_DIE;
+ }
+
+ public abstract interface Temporal implements java.time.temporal.TemporalAccessor {
+ method public abstract boolean isSupported(java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal minus(java.time.temporal.TemporalAmount);
+ method public default java.time.temporal.Temporal minus(long, java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal plus(java.time.temporal.TemporalAmount);
+ method public abstract java.time.temporal.Temporal plus(long, java.time.temporal.TemporalUnit);
+ method public abstract long until(java.time.temporal.Temporal, java.time.temporal.TemporalUnit);
+ method public default java.time.temporal.Temporal with(java.time.temporal.TemporalAdjuster);
+ method public abstract java.time.temporal.Temporal with(java.time.temporal.TemporalField, long);
+ }
+
+ public abstract interface TemporalAccessor {
+ method public default int get(java.time.temporal.TemporalField);
+ method public abstract long getLong(java.time.temporal.TemporalField);
+ method public abstract boolean isSupported(java.time.temporal.TemporalField);
+ method public default <R> R query(java.time.temporal.TemporalQuery<R>);
+ method public default java.time.temporal.ValueRange range(java.time.temporal.TemporalField);
+ }
+
+ public abstract interface TemporalAdjuster {
+ method public abstract java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal);
+ }
+
+ public final class TemporalAdjusters {
+ method public static java.time.temporal.TemporalAdjuster dayOfWeekInMonth(int, java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster firstDayOfMonth();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfNextMonth();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfNextYear();
+ method public static java.time.temporal.TemporalAdjuster firstDayOfYear();
+ method public static java.time.temporal.TemporalAdjuster firstInMonth(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster lastDayOfMonth();
+ method public static java.time.temporal.TemporalAdjuster lastDayOfYear();
+ method public static java.time.temporal.TemporalAdjuster lastInMonth(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster next(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster nextOrSame(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster ofDateAdjuster(java.util.function.UnaryOperator<java.time.LocalDate>);
+ method public static java.time.temporal.TemporalAdjuster previous(java.time.DayOfWeek);
+ method public static java.time.temporal.TemporalAdjuster previousOrSame(java.time.DayOfWeek);
+ }
+
+ public abstract interface TemporalAmount {
+ method public abstract java.time.temporal.Temporal addTo(java.time.temporal.Temporal);
+ method public abstract long get(java.time.temporal.TemporalUnit);
+ method public abstract java.util.List<java.time.temporal.TemporalUnit> getUnits();
+ method public abstract java.time.temporal.Temporal subtractFrom(java.time.temporal.Temporal);
+ }
+
+ public abstract interface TemporalField {
+ method public abstract <R extends java.time.temporal.Temporal> R adjustInto(R, long);
+ method public abstract java.time.temporal.TemporalUnit getBaseUnit();
+ method public default java.lang.String getDisplayName(java.util.Locale);
+ method public abstract long getFrom(java.time.temporal.TemporalAccessor);
+ method public abstract java.time.temporal.TemporalUnit getRangeUnit();
+ method public abstract boolean isDateBased();
+ method public abstract boolean isSupportedBy(java.time.temporal.TemporalAccessor);
+ method public abstract boolean isTimeBased();
+ method public abstract java.time.temporal.ValueRange range();
+ method public abstract java.time.temporal.ValueRange rangeRefinedBy(java.time.temporal.TemporalAccessor);
+ method public default java.time.temporal.TemporalAccessor resolve(java.util.Map<java.time.temporal.TemporalField, java.lang.Long>, java.time.temporal.TemporalAccessor, java.time.format.ResolverStyle);
+ method public abstract java.lang.String toString();
+ }
+
+ public final class TemporalQueries {
+ method public static java.time.temporal.TemporalQuery<java.time.chrono.Chronology> chronology();
+ method public static java.time.temporal.TemporalQuery<java.time.LocalDate> localDate();
+ method public static java.time.temporal.TemporalQuery<java.time.LocalTime> localTime();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneOffset> offset();
+ method public static java.time.temporal.TemporalQuery<java.time.temporal.TemporalUnit> precision();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneId> zone();
+ method public static java.time.temporal.TemporalQuery<java.time.ZoneId> zoneId();
+ }
+
+ public abstract interface TemporalQuery<R> {
+ method public abstract R queryFrom(java.time.temporal.TemporalAccessor);
+ }
+
+ public abstract interface TemporalUnit {
+ method public abstract <R extends java.time.temporal.Temporal> R addTo(R, long);
+ method public abstract long between(java.time.temporal.Temporal, java.time.temporal.Temporal);
+ method public abstract java.time.Duration getDuration();
+ method public abstract boolean isDateBased();
+ method public abstract boolean isDurationEstimated();
+ method public default boolean isSupportedBy(java.time.temporal.Temporal);
+ method public abstract boolean isTimeBased();
+ method public abstract java.lang.String toString();
+ }
+
+ public class UnsupportedTemporalTypeException extends java.time.DateTimeException {
+ ctor public UnsupportedTemporalTypeException(java.lang.String);
+ ctor public UnsupportedTemporalTypeException(java.lang.String, java.lang.Throwable);
+ }
+
+ public final class ValueRange implements java.io.Serializable {
+ method public int checkValidIntValue(long, java.time.temporal.TemporalField);
+ method public long checkValidValue(long, java.time.temporal.TemporalField);
+ method public long getLargestMinimum();
+ method public long getMaximum();
+ method public long getMinimum();
+ method public long getSmallestMaximum();
+ method public boolean isFixed();
+ method public boolean isIntValue();
+ method public boolean isValidIntValue(long);
+ method public boolean isValidValue(long);
+ method public static java.time.temporal.ValueRange of(long, long);
+ method public static java.time.temporal.ValueRange of(long, long, long);
+ method public static java.time.temporal.ValueRange of(long, long, long, long);
+ }
+
+ public final class WeekFields implements java.io.Serializable {
+ method public java.time.temporal.TemporalField dayOfWeek();
+ method public java.time.DayOfWeek getFirstDayOfWeek();
+ method public int getMinimalDaysInFirstWeek();
+ method public static java.time.temporal.WeekFields of(java.util.Locale);
+ method public static java.time.temporal.WeekFields of(java.time.DayOfWeek, int);
+ method public java.time.temporal.TemporalField weekBasedYear();
+ method public java.time.temporal.TemporalField weekOfMonth();
+ method public java.time.temporal.TemporalField weekOfWeekBasedYear();
+ method public java.time.temporal.TemporalField weekOfYear();
+ field public static final java.time.temporal.WeekFields ISO;
+ field public static final java.time.temporal.WeekFields SUNDAY_START;
+ field public static final java.time.temporal.TemporalUnit WEEK_BASED_YEARS;
+ }
+
+}
+
+package java.time.zone {
+
+ public final class ZoneOffsetTransition implements java.lang.Comparable java.io.Serializable {
+ method public int compareTo(java.time.zone.ZoneOffsetTransition);
+ method public java.time.LocalDateTime getDateTimeAfter();
+ method public java.time.LocalDateTime getDateTimeBefore();
+ method public java.time.Duration getDuration();
+ method public java.time.Instant getInstant();
+ method public java.time.ZoneOffset getOffsetAfter();
+ method public java.time.ZoneOffset getOffsetBefore();
+ method public boolean isGap();
+ method public boolean isOverlap();
+ method public boolean isValidOffset(java.time.ZoneOffset);
+ method public static java.time.zone.ZoneOffsetTransition of(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ method public long toEpochSecond();
+ }
+
+ public final class ZoneOffsetTransitionRule implements java.io.Serializable {
+ method public java.time.zone.ZoneOffsetTransition createTransition(int);
+ method public int getDayOfMonthIndicator();
+ method public java.time.DayOfWeek getDayOfWeek();
+ method public java.time.LocalTime getLocalTime();
+ method public java.time.Month getMonth();
+ method public java.time.ZoneOffset getOffsetAfter();
+ method public java.time.ZoneOffset getOffsetBefore();
+ method public java.time.ZoneOffset getStandardOffset();
+ method public java.time.zone.ZoneOffsetTransitionRule.TimeDefinition getTimeDefinition();
+ method public boolean isMidnightEndOfDay();
+ method public static java.time.zone.ZoneOffsetTransitionRule of(java.time.Month, int, java.time.DayOfWeek, java.time.LocalTime, boolean, java.time.zone.ZoneOffsetTransitionRule.TimeDefinition, java.time.ZoneOffset, java.time.ZoneOffset, java.time.ZoneOffset);
+ }
+
+ public static final class ZoneOffsetTransitionRule.TimeDefinition extends java.lang.Enum {
+ method public java.time.LocalDateTime createDateTime(java.time.LocalDateTime, java.time.ZoneOffset, java.time.ZoneOffset);
+ method public static java.time.zone.ZoneOffsetTransitionRule.TimeDefinition valueOf(java.lang.String);
+ method public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition[] values();
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition STANDARD;
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition UTC;
+ enum_constant public static final java.time.zone.ZoneOffsetTransitionRule.TimeDefinition WALL;
+ }
+
+ public final class ZoneRules implements java.io.Serializable {
+ method public java.time.Duration getDaylightSavings(java.time.Instant);
+ method public java.time.ZoneOffset getOffset(java.time.Instant);
+ method public java.time.ZoneOffset getOffset(java.time.LocalDateTime);
+ method public java.time.ZoneOffset getStandardOffset(java.time.Instant);
+ method public java.time.zone.ZoneOffsetTransition getTransition(java.time.LocalDateTime);
+ method public java.util.List<java.time.zone.ZoneOffsetTransitionRule> getTransitionRules();
+ method public java.util.List<java.time.zone.ZoneOffsetTransition> getTransitions();
+ method public java.util.List<java.time.ZoneOffset> getValidOffsets(java.time.LocalDateTime);
+ method public boolean isDaylightSavings(java.time.Instant);
+ method public boolean isFixedOffset();
+ method public boolean isValidOffset(java.time.LocalDateTime, java.time.ZoneOffset);
+ method public java.time.zone.ZoneOffsetTransition nextTransition(java.time.Instant);
+ method public static java.time.zone.ZoneRules of(java.time.ZoneOffset, java.time.ZoneOffset, java.util.List<java.time.zone.ZoneOffsetTransition>, java.util.List<java.time.zone.ZoneOffsetTransition>, java.util.List<java.time.zone.ZoneOffsetTransitionRule>);
+ method public static java.time.zone.ZoneRules of(java.time.ZoneOffset);
+ method public java.time.zone.ZoneOffsetTransition previousTransition(java.time.Instant);
+ }
+
+ public class ZoneRulesException extends java.time.DateTimeException {
+ ctor public ZoneRulesException(java.lang.String);
+ ctor public ZoneRulesException(java.lang.String, java.lang.Throwable);
+ }
+
+}
+
package java.util {
public abstract class AbstractCollection<E> implements java.util.Collection {
@@ -58795,7 +60425,9 @@
method public int get(int);
method public int getActualMaximum(int);
method public int getActualMinimum(int);
+ method public static java.util.Set<java.lang.String> getAvailableCalendarTypes();
method public static synchronized java.util.Locale[] getAvailableLocales();
+ method public java.lang.String getCalendarType();
method public java.lang.String getDisplayName(int, int, java.util.Locale);
method public java.util.Map<java.lang.String, java.lang.Integer> getDisplayNames(int, int, java.util.Locale);
method public int getFirstDayOfWeek();
@@ -58830,6 +60462,7 @@
method public void setTimeInMillis(long);
method public void setTimeZone(java.util.TimeZone);
method public void setWeekDate(int, int, int);
+ method public final java.time.Instant toInstant();
field public static final int ALL_STYLES = 0; // 0x0
field public static final int AM = 0; // 0x0
field public static final int AM_PM = 9; // 0x9
@@ -58852,12 +60485,16 @@
field public static final int JULY = 6; // 0x6
field public static final int JUNE = 5; // 0x5
field public static final int LONG = 2; // 0x2
+ field public static final int LONG_FORMAT = 2; // 0x2
+ field public static final int LONG_STANDALONE = 32770; // 0x8002
field public static final int MARCH = 2; // 0x2
field public static final int MAY = 4; // 0x4
field public static final int MILLISECOND = 14; // 0xe
field public static final int MINUTE = 12; // 0xc
field public static final int MONDAY = 2; // 0x2
field public static final int MONTH = 2; // 0x2
+ field public static final int NARROW_FORMAT = 4; // 0x4
+ field public static final int NARROW_STANDALONE = 32772; // 0x8004
field public static final int NOVEMBER = 10; // 0xa
field public static final int OCTOBER = 9; // 0x9
field public static final int PM = 1; // 0x1
@@ -58865,6 +60502,8 @@
field public static final int SECOND = 13; // 0xd
field public static final int SEPTEMBER = 8; // 0x8
field public static final int SHORT = 1; // 0x1
+ field public static final int SHORT_FORMAT = 1; // 0x1
+ field public static final int SHORT_STANDALONE = 32769; // 0x8001
field public static final int SUNDAY = 1; // 0x1
field public static final int THURSDAY = 5; // 0x5
field public static final int TUESDAY = 3; // 0x3
@@ -58881,6 +60520,24 @@
field protected long time;
}
+ public static class Calendar.Builder {
+ ctor public Calendar.Builder();
+ method public java.util.Calendar build();
+ method public java.util.Calendar.Builder set(int, int);
+ method public java.util.Calendar.Builder setCalendarType(java.lang.String);
+ method public java.util.Calendar.Builder setDate(int, int, int);
+ method public java.util.Calendar.Builder setFields(int...);
+ method public java.util.Calendar.Builder setInstant(long);
+ method public java.util.Calendar.Builder setInstant(java.util.Date);
+ method public java.util.Calendar.Builder setLenient(boolean);
+ method public java.util.Calendar.Builder setLocale(java.util.Locale);
+ method public java.util.Calendar.Builder setTimeOfDay(int, int, int);
+ method public java.util.Calendar.Builder setTimeOfDay(int, int, int, int);
+ method public java.util.Calendar.Builder setTimeZone(java.util.TimeZone);
+ method public java.util.Calendar.Builder setWeekDate(int, int, int);
+ method public java.util.Calendar.Builder setWeekDefinition(int, int);
+ }
+
public abstract interface Collection<E> implements java.lang.Iterable {
method public abstract boolean add(E);
method public abstract boolean addAll(java.util.Collection<? extends E>);
@@ -59016,6 +60673,7 @@
method public boolean before(java.util.Date);
method public java.lang.Object clone();
method public int compareTo(java.util.Date);
+ method public static java.util.Date from(java.time.Instant);
method public deprecated int getDate();
method public deprecated int getDay();
method public deprecated int getHours();
@@ -59034,6 +60692,7 @@
method public void setTime(long);
method public deprecated void setYear(int);
method public deprecated java.lang.String toGMTString();
+ method public java.time.Instant toInstant();
method public deprecated java.lang.String toLocaleString();
}
@@ -59203,6 +60862,7 @@
method public void add(int, int);
method protected void computeFields();
method protected void computeTime();
+ method public static java.util.GregorianCalendar from(java.time.ZonedDateTime);
method public int getGreatestMinimum(int);
method public final java.util.Date getGregorianChange();
method public int getLeastMaximum(int);
@@ -59212,6 +60872,7 @@
method public final boolean isWeekDateSupported();
method public void roll(int, boolean);
method public void setGregorianChange(java.util.Date);
+ method public java.time.ZonedDateTime toZonedDateTime();
field public static final int AD = 1; // 0x1
field public static final int BC = 0; // 0x0
}
@@ -60239,12 +61900,14 @@
method public int getOffset(long);
method public abstract int getRawOffset();
method public static synchronized java.util.TimeZone getTimeZone(java.lang.String);
+ method public static java.util.TimeZone getTimeZone(java.time.ZoneId);
method public boolean hasSameRules(java.util.TimeZone);
method public abstract boolean inDaylightTime(java.util.Date);
method public boolean observesDaylightTime();
method public static synchronized void setDefault(java.util.TimeZone);
method public void setID(java.lang.String);
method public abstract void setRawOffset(int);
+ method public java.time.ZoneId toZoneId();
method public abstract boolean useDaylightTime();
field public static final int LONG = 1; // 0x1
field public static final int SHORT = 0; // 0x0
@@ -60851,31 +62514,31 @@
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
ctor public CopyOnWriteArrayList(E[]);
- method public synchronized boolean add(E);
- method public synchronized void add(int, E);
- method public synchronized boolean addAll(java.util.Collection<? extends E>);
- method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
- method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
- method public synchronized boolean addIfAbsent(E);
- method public synchronized void clear();
+ method public boolean add(E);
+ method public void add(int, E);
+ method public boolean addAll(java.util.Collection<? extends E>);
+ method public boolean addAll(int, java.util.Collection<? extends E>);
+ method public int addAllAbsent(java.util.Collection<? extends E>);
+ method public boolean addIfAbsent(E);
+ method public void clear();
method public java.lang.Object clone();
method public boolean contains(java.lang.Object);
method public boolean containsAll(java.util.Collection<?>);
method public void forEach(java.util.function.Consumer<? super E>);
method public E get(int);
- method public int indexOf(E, int);
method public int indexOf(java.lang.Object);
+ method public int indexOf(E, int);
method public boolean isEmpty();
method public java.util.Iterator<E> iterator();
- method public int lastIndexOf(E, int);
method public int lastIndexOf(java.lang.Object);
- method public java.util.ListIterator<E> listIterator(int);
+ method public int lastIndexOf(E, int);
method public java.util.ListIterator<E> listIterator();
- method public synchronized E remove(int);
- method public synchronized boolean remove(java.lang.Object);
- method public synchronized boolean removeAll(java.util.Collection<?>);
- method public synchronized boolean retainAll(java.util.Collection<?>);
- method public synchronized E set(int, E);
+ method public java.util.ListIterator<E> listIterator(int);
+ method public E remove(int);
+ method public boolean remove(java.lang.Object);
+ method public boolean removeAll(java.util.Collection<?>);
+ method public boolean retainAll(java.util.Collection<?>);
+ method public E set(int, E);
method public int size();
method public java.util.List<E> subList(int, int);
method public java.lang.Object[] toArray();
@@ -62726,10 +64389,12 @@
method public java.lang.StringBuffer appendTail(java.lang.StringBuffer);
method public int end();
method public int end(int);
+ method public int end(java.lang.String);
method public boolean find();
method public boolean find(int);
method public java.lang.String group();
method public java.lang.String group(int);
+ method public java.lang.String group(java.lang.String);
method public int groupCount();
method public boolean hasAnchoringBounds();
method public boolean hasTransparentBounds();
@@ -62748,6 +64413,7 @@
method public java.util.regex.Matcher reset(java.lang.CharSequence);
method public int start();
method public int start(int) throws java.lang.IllegalStateException;
+ method public int start(java.lang.String);
method public java.util.regex.MatchResult toMatchResult();
method public java.util.regex.Matcher useAnchoringBounds(boolean);
method public java.util.regex.Matcher usePattern(java.util.regex.Pattern);
diff --git a/compiled-classes-phone b/compiled-classes-phone
index 221d687..ec3371e 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -632,6 +632,7 @@
android.bluetooth.BluetoothAudioConfig
android.bluetooth.BluetoothClass
android.bluetooth.BluetoothClass$1
+android.bluetooth.BluetoothCodecConfig
android.bluetooth.BluetoothDevice
android.bluetooth.BluetoothDevice$1
android.bluetooth.BluetoothDevice$2
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8f42467..857a361 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -509,10 +509,23 @@
* Common-path handling of app data dir creation
*/
private static File ensurePrivateDirExists(File file) {
+ return ensurePrivateDirExists(file, 0771, -1);
+ }
+
+ private static File ensurePrivateCacheDirExists(File file) {
+ final int gid = UserHandle.getCacheAppGid(Process.myUid());
+ return ensurePrivateDirExists(file, 02771, gid);
+ }
+
+ private static File ensurePrivateDirExists(File file, int mode, int gid) {
if (!file.exists()) {
+ final String path = file.getAbsolutePath();
try {
- Os.mkdir(file.getAbsolutePath(), 0771);
- Os.chmod(file.getAbsolutePath(), 0771);
+ Os.mkdir(path, mode);
+ Os.chmod(path, mode);
+ if (gid != -1) {
+ Os.chown(path, -1, gid);
+ }
} catch (ErrnoException e) {
if (e.errno == OsConstants.EEXIST) {
// We must have raced with someone; that's okay
@@ -581,7 +594,7 @@
if (mCacheDir == null) {
mCacheDir = new File(getDataDir(), "cache");
}
- return ensurePrivateDirExists(mCacheDir);
+ return ensurePrivateCacheDirExists(mCacheDir);
}
}
@@ -591,7 +604,7 @@
if (mCodeCacheDir == null) {
mCodeCacheDir = new File(getDataDir(), "code_cache");
}
- return ensurePrivateDirExists(mCodeCacheDir);
+ return ensurePrivateCacheDirExists(mCodeCacheDir);
}
}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 353c640..1165fce 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -102,6 +102,27 @@
"android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
/**
+ * Intent used to broadcast the change in the Audio Codec state of the
+ * A2DP Source profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_CODEC_CONFIG} - The current codec configuration. </li>
+ * <li> {@link #EXTRA_PREVIOUS_CODEC_CONFIG} - The previous codec configuration. </li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
+ * connected, otherwise it is not included.</li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CODEC_CONFIG_CHANGED =
+ "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
+
+ /**
* A2DP sink device is streaming music. This state can be one of
* {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
* {@link #ACTION_PLAYING_STATE_CHANGED} intent.
@@ -543,6 +564,54 @@
}
/**
+ * Gets the current codec configuration.
+ *
+ * @return the current codec configuration
+ * @hide
+ */
+ public BluetoothCodecConfig getCodecConfig() {
+ if (DBG) Log.d(TAG, "getCodecConfig");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ return mService.getCodecConfig();
+ }
+ if (mService == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getCodecConfig()", e);
+ return null;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Sets the codec configuration preference.
+ *
+ * @param codecConfig the codec configuration preference
+ * @hide
+ */
+ public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) {
+ if (DBG) Log.d(TAG, "setCodecConfigPreference");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ mService.setCodecConfigPreference(codecConfig);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
+ return;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Helper for converting a state to a string.
*
* For debug use only - strings are not internationalized.
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/core/java/android/bluetooth/BluetoothCodecConfig.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
copy to core/java/android/bluetooth/BluetoothCodecConfig.aidl
index a35e71d..553e66e 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi.aware;
+package android.bluetooth;
-parcelable WifiAwareCharacteristics;
+parcelable BluetoothCodecConfig;
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
new file mode 100644
index 0000000..52cd2de
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2016 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.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Represents the codec configuration for a Bluetooth A2DP source device.
+ *
+ * {@see BluetoothA2dp}
+ *
+ * {@hide}
+ */
+public final class BluetoothCodecConfig implements Parcelable {
+
+ /**
+ * Extra for the codec configuration intents of the individual profiles.
+ *
+ * This extra represents the current codec configuration of the A2DP
+ * profile.
+ */
+ public static final String EXTRA_CODEC_CONFIG = "android.bluetooth.codec.extra.CODEC_CONFIG";
+
+ /**
+ * Extra for the codec configuration intents of the individual profiles.
+ *
+ * This extra represents the previous codec configuration of the A2DP
+ * profile.
+ */
+ public static final String EXTRA_PREVIOUS_CODEC_CONFIG =
+ "android.bluetooth.codec.extra.PREVIOUS_CODEC_CONFIG";
+
+ // Add an entry for each source codec here.
+ // NOTE: The values should be same as those listed in the following file:
+ // hardware/libhardware/include/hardware/bt_av.h
+ public static final int SOURCE_CODEC_TYPE_SBC = 0;
+ public static final int SOURCE_CODEC_TYPE_APTX = 1;
+ public static final int SOURCE_CODEC_TYPE_APTX_HD = 2;
+ public static final int SOURCE_CODEC_TYPE_LDAC = 3;
+
+ public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+
+ public static final int CODEC_PRIORITY_DEFAULT = 0;
+ public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
+
+ public static final int SAMPLE_RATE_NONE = 0;
+ public static final int SAMPLE_RATE_44100 = 0x1 << 0;
+ public static final int SAMPLE_RATE_48000 = 0x1 << 1;
+ public static final int SAMPLE_RATE_88200 = 0x1 << 2;
+ public static final int SAMPLE_RATE_96000 = 0x1 << 3;
+ public static final int SAMPLE_RATE_176400 = 0x1 << 4;
+ public static final int SAMPLE_RATE_192000 = 0x1 << 5;
+
+ public static final int BITS_PER_SAMPLE_NONE = 0;
+ public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
+ public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
+ public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
+
+ public static final int CHANNEL_MODE_NONE = 0;
+ public static final int CHANNEL_MODE_MONO = 0x1 << 0;
+ public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
+
+ private final int mCodecType;
+ private final int mCodecPriority;
+ private final int mSampleRate;
+ private final int mBitsPerSample;
+ private final int mChannelMode;
+ private final long mCodecSpecific1;
+ private final long mCodecSpecific2;
+ private final long mCodecSpecific3;
+ private final long mCodecSpecific4;
+
+ public BluetoothCodecConfig(int codecType, int codecPriority,
+ int sampleRate, int bitsPerSample,
+ int channelMode,long codecSpecific1,
+ long codecSpecific2, long codecSpecific3,
+ long codecSpecific4) {
+ mCodecType = codecType;
+ mCodecPriority = codecPriority;
+ mSampleRate = sampleRate;
+ mBitsPerSample = bitsPerSample;
+ mChannelMode = channelMode;
+ mCodecSpecific1 = codecSpecific1;
+ mCodecSpecific2 = codecSpecific2;
+ mCodecSpecific3 = codecSpecific3;
+ mCodecSpecific4 = codecSpecific4;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothCodecConfig) {
+ BluetoothCodecConfig other = (BluetoothCodecConfig)o;
+ return (other.mCodecType == mCodecType &&
+ other.mCodecPriority == mCodecPriority &&
+ other.mSampleRate == mSampleRate &&
+ other.mBitsPerSample == mBitsPerSample &&
+ other.mChannelMode == mChannelMode &&
+ other.mCodecSpecific1 == mCodecSpecific1 &&
+ other.mCodecSpecific2 == mCodecSpecific2 &&
+ other.mCodecSpecific3 == mCodecSpecific3 &&
+ other.mCodecSpecific4 == mCodecSpecific4);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
+ mBitsPerSample, mChannelMode, mCodecSpecific1,
+ mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
+ }
+
+ @Override
+ public String toString() {
+ return "{mCodecType:" + mCodecType +
+ ",mCodecPriority:" + mCodecPriority +
+ ",mSampleRate:" + String.format("0x%x", mSampleRate) +
+ ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) +
+ ",mChannelMode:" + String.format("0x%x", mChannelMode) +
+ ",mCodecSpecific1:" + mCodecSpecific1 +
+ ",mCodecSpecific2:" + mCodecSpecific2 +
+ ",mCodecSpecific3:" + mCodecSpecific3 +
+ ",mCodecSpecific4:" + mCodecSpecific4 + "}";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothCodecConfig> CREATOR =
+ new Parcelable.Creator<BluetoothCodecConfig>() {
+ public BluetoothCodecConfig createFromParcel(Parcel in) {
+ final int codecType = in.readInt();
+ final int codecPriority = in.readInt();
+ final int sampleRate = in.readInt();
+ final int bitsPerSample = in.readInt();
+ final int channelMode = in.readInt();
+ final long codecSpecific1 = in.readLong();
+ final long codecSpecific2 = in.readLong();
+ final long codecSpecific3 = in.readLong();
+ final long codecSpecific4 = in.readLong();
+ return new BluetoothCodecConfig(codecType, codecPriority,
+ sampleRate, bitsPerSample,
+ channelMode, codecSpecific1,
+ codecSpecific2, codecSpecific3,
+ codecSpecific4);
+ }
+ public BluetoothCodecConfig[] newArray(int size) {
+ return new BluetoothCodecConfig[size];
+ }
+ };
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mCodecType);
+ out.writeInt(mCodecPriority);
+ out.writeInt(mSampleRate);
+ out.writeInt(mBitsPerSample);
+ out.writeInt(mChannelMode);
+ out.writeLong(mCodecSpecific1);
+ out.writeLong(mCodecSpecific2);
+ out.writeLong(mCodecSpecific3);
+ out.writeLong(mCodecSpecific4);
+ }
+
+ /**
+ * Returns the codec type.
+ * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
+ *
+ * @return the codec type
+ */
+ public int getCodecType() {
+ return mCodecType;
+ }
+
+ /**
+ * Returns the codec selection priority.
+ * The codec selection priority is relative to other codecs: larger value
+ * means higher priority. If 0, reset to default.
+ *
+ * @return the codec priority
+ */
+ public int getCodecPriority() {
+ return mCodecPriority;
+ }
+
+ /**
+ * Returns the codec sample rate. The value can be a bitmask with all
+ * supported sample rates:
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
+ *
+ * @return the codec sample rate
+ */
+ public int getSampleRate() {
+ return mSampleRate;
+ }
+
+ /**
+ * Returns the codec bits per sample. The value can be a bitmask with all
+ * bits per sample supported:
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
+ *
+ * @return the codec bits per sample
+ */
+ public int getBitsPerSample() {
+ return mBitsPerSample;
+ }
+
+ /**
+ * Returns the codec channel mode. The value can be a bitmask with all
+ * supported channel modes:
+ * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
+ * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
+ * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
+ *
+ * @return the codec channel mode
+ */
+ public int getChannelMode() {
+ return mChannelMode;
+ }
+
+ /**
+ * Returns a codec specific value1.
+ *
+ * @return a codec specific value1.
+ */
+ public long getCodecSpecific1() {
+ return mCodecSpecific1;
+ }
+
+ /**
+ * Returns a codec specific value2.
+ *
+ * @return a codec specific value2
+ */
+ public long getCodecSpecific2() {
+ return mCodecSpecific2;
+ }
+
+ /**
+ * Returns a codec specific value3.
+ *
+ * @return a codec specific value3
+ */
+ public long getCodecSpecific3() {
+ return mCodecSpecific3;
+ }
+
+ /**
+ * Returns a codec specific value4.
+ *
+ * @return a codec specific value4
+ */
+ public long getCodecSpecific4() {
+ return mCodecSpecific4;
+ }
+
+ /**
+ * Checks whether the audio feeding parameters are same.
+ *
+ * @param other the codec config to compare against
+ * @return true if the audio feeding parameters are same, otherwise false
+ */
+ public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
+ return (other != null && other.mSampleRate == mSampleRate &&
+ other.mBitsPerSample == mBitsPerSample &&
+ other.mChannelMode == mChannelMode);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
index 0f0e050..f519776 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
@@ -45,9 +45,9 @@
* <code>false</code> otherwise.
*/
public void onAppStatusChanged(BluetoothDevice pluggedDevice,
- BluetoothHidDeviceAppConfiguration config, boolean registered) {
- Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + (pluggedDevice == null ?
- null : pluggedDevice.toString()) + " registered=" + registered);
+ BluetoothHidDeviceAppConfiguration config, boolean registered) {
+ Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered="
+ + registered);
}
/**
@@ -60,13 +60,13 @@
* @param state Connection state as defined in {@link BluetoothProfile}.
*/
public void onConnectionStateChanged(BluetoothDevice device, int state) {
- Log.d(TAG, "onConnectionStateChanged: device=" + device.toString() + " state=" + state);
+ Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state);
}
/**
* Callback called when GET_REPORT is received from remote host. Should be
* replied by application using
- * {@link BluetoothHidDevice#replyReport(byte, byte, byte[])}.
+ * {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param type Requested Report Type.
* @param id Requested Report Id, can be 0 if no Report Id are defined in
@@ -74,21 +74,22 @@
* @param bufferSize Requested buffer size, application shall respond with
* at least given number of bytes.
*/
- public void onGetReport(byte type, byte id, int bufferSize) {
- Log.d(TAG, "onGetReport: type=" + type + " id=" + id + " bufferSize=" + bufferSize);
+ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
+ Log.d(TAG, "onGetReport: device=" + device + " type=" + type + " id=" + id + " bufferSize="
+ + bufferSize);
}
/**
* Callback called when SET_REPORT is received from remote host. In case
* received data are invalid, application shall respond with
- * {@link BluetoothHidDevice#reportError()}.
+ * {@link BluetoothHidDevice#reportError(BluetoothDevice)}.
*
* @param type Report Type.
* @param id Report Id.
* @param data Report data.
*/
- public void onSetReport(byte type, byte id, byte[] data) {
- Log.d(TAG, "onSetReport: type=" + type + " id=" + id);
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
}
/**
@@ -99,8 +100,8 @@
*
* @param protocol Protocol Mode.
*/
- public void onSetProtocol(byte protocol) {
- Log.d(TAG, "onSetProtocol: protocol=" + protocol);
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
}
/**
@@ -111,16 +112,17 @@
* @param reportId Report Id.
* @param data Report data.
*/
- public void onIntrData(byte reportId, byte[] data) {
- Log.d(TAG, "onIntrData: reportId=" + reportId);
+ public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
+ Log.d(TAG, "onIntrData: device=" + device + " reportId=" + reportId);
}
/**
* Callback called when Virtual Cable is removed. This can be either due to
- * {@link BluetoothHidDevice#unplug()} or request from remote side. After
- * this callback is received connection will be disconnected automatically.
+ * {@link BluetoothHidDevice#unplug(BluetoothDevice)} or request from remote
+ * side. After this callback is received connection will be disconnected
+ * automatically.
*/
- public void onVirtualCableUnplug() {
- Log.d(TAG, "onVirtualCableUnplug");
+ public void onVirtualCableUnplug(BluetoothDevice device) {
+ Log.d(TAG, "onVirtualCableUnplug: device=" + device);
}
}
diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index 129fe7e..68d105f 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -27,6 +27,7 @@
import android.util.Log;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -137,28 +138,28 @@
}
@Override
- public void onGetReport(byte type, byte id, int bufferSize) {
- mCallback.onGetReport(type, id, bufferSize);
+ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
+ mCallback.onGetReport(device, type, id, bufferSize);
}
@Override
- public void onSetReport(byte type, byte id, byte[] data) {
- mCallback.onSetReport(type, id, data);
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ mCallback.onSetReport(device, type, id, data);
}
@Override
- public void onSetProtocol(byte protocol) {
- mCallback.onSetProtocol(protocol);
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ mCallback.onSetProtocol(device, protocol);
}
@Override
- public void onIntrData(byte reportId, byte[] data) {
- mCallback.onIntrData(reportId, data);
+ public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
+ mCallback.onIntrData(device, reportId, data);
}
@Override
- public void onVirtualCableUnplug() {
- mCallback.onVirtualCableUnplug();
+ public void onVirtualCableUnplug(BluetoothDevice device) {
+ mCallback.onVirtualCableUnplug(device);
}
}
@@ -276,21 +277,59 @@
mServiceListener = null;
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public List<BluetoothDevice> getConnectedDevices() {
Log.v(TAG, "getConnectedDevices()");
- return null;
+
+ if (mService != null) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return new ArrayList<BluetoothDevice>();
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
- return null;
+
+ if (mService != null) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return new ArrayList<BluetoothDevice>();
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public int getConnectionState(BluetoothDevice device) {
- Log.v(TAG, "getConnectionState(): device=" + device.getAddress());
+ Log.v(TAG, "getConnectionState(): device=" + device);
+
+ if (mService != null) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
return STATE_DISCONNECTED;
}
@@ -379,14 +418,12 @@
* @param data Report data, not including Report Id.
* @return
*/
- public boolean sendReport(int id, byte[] data) {
- Log.v(TAG, "sendReport(): id=" + id);
-
+ public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
if (mService != null) {
try {
- result = mService.sendReport(id, data);
+ result = mService.sendReport(device, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -399,21 +436,21 @@
/**
* Sends report to remote host as reply for GET_REPORT request from
- * {@link BluetoothHidDeviceCallback#onGetReport(byte, byte, int)}.
+ * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
*
* @param type Report Type, as in request.
* @param id Report Id, as in request.
* @param data Report data, not including Report Id.
* @return
*/
- public boolean replyReport(byte type, byte id, byte[] data) {
- Log.v(TAG, "replyReport(): type=" + type + " id=" + id);
+ public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
boolean result = false;
if (mService != null) {
try {
- result = mService.replyReport(type, id, data);
+ result = mService.replyReport(device, type, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -426,19 +463,19 @@
/**
* Sends error handshake message as reply for invalid SET_REPORT request
- * from {@link BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])}.
+ * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param error Error to be sent for SET_REPORT via HANDSHAKE.
* @return
*/
- public boolean reportError(byte error) {
- Log.v(TAG, "reportError(): error = " + error);
+ public boolean reportError(BluetoothDevice device, byte error) {
+ Log.v(TAG, "reportError(): device=" + device + " error=" + error);
boolean result = false;
if (mService != null) {
try {
- result = mService.reportError(error);
+ result = mService.reportError(device, error);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -454,14 +491,14 @@
*
* @return
*/
- public boolean unplug() {
- Log.v(TAG, "unplug()");
+ public boolean unplug(BluetoothDevice device) {
+ Log.v(TAG, "unplug(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.unplug();
+ result = mService.unplug(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -478,14 +515,14 @@
*
* @return
*/
- public boolean connect() {
- Log.v(TAG, "connect()");
+ public boolean connect(BluetoothDevice device) {
+ Log.v(TAG, "connect(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.connect();
+ result = mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -501,14 +538,14 @@
*
* @return
*/
- public boolean disconnect() {
- Log.v(TAG, "disconnect()");
+ public boolean disconnect(BluetoothDevice device) {
+ Log.v(TAG, "disconnect(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.disconnect();
+ result = mService.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index b686938..98a5341 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -243,7 +243,7 @@
}
as.mPfd = new ParcelFileDescriptor(fds[0]);
- as.mSocket = new LocalSocket(fds[0]);
+ as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
as.mSocketIS = as.mSocket.getInputStream();
as.mSocketOS = as.mSocket.getOutputStream();
as.mAddress = RemoteAddr;
@@ -367,7 +367,7 @@
if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
if (mPfd == null) throw new IOException("bt socket connect failed");
FileDescriptor fd = mPfd.getFileDescriptor();
- mSocket = new LocalSocket(fd);
+ mSocket = LocalSocket.createConnectedLocalSocket(fd);
mSocketIS = mSocket.getInputStream();
mSocketOS = mSocket.getOutputStream();
}
@@ -416,9 +416,9 @@
if(mSocketState != SocketState.INIT) return EBADFD;
if(mPfd == null) return -1;
FileDescriptor fd = mPfd.getFileDescriptor();
- if (DBG) Log.d(TAG, "bindListen(), new LocalSocket ");
- mSocket = new LocalSocket(fd);
- if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() ");
+ if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
+ mSocket = LocalSocket.createConnectedLocalSocket(fd);
+ if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
mSocketIS = mSocket.getInputStream();
mSocketOS = mSocket.getOutputStream();
}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 26ff9e27..5b524eb 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -16,6 +16,7 @@
package android.bluetooth;
+import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
/**
@@ -36,4 +37,6 @@
oneway void adjustAvrcpAbsoluteVolume(int direction);
oneway void setAvrcpAbsoluteVolume(int volume);
boolean isA2dpPlaying(in BluetoothDevice device);
+ BluetoothCodecConfig getCodecConfig();
+ oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
}
diff --git a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
index 1252876..a737198 100644
--- a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
@@ -23,9 +23,9 @@
interface IBluetoothHidDeviceCallback {
void onAppStatusChanged(in BluetoothDevice device, in BluetoothHidDeviceAppConfiguration config, boolean registered);
void onConnectionStateChanged(in BluetoothDevice device, in int state);
- void onGetReport(in byte type, in byte id, in int bufferSize);
- void onSetReport(in byte type, in byte id, in byte[] data);
- void onSetProtocol(in byte protocol);
- void onIntrData(in byte reportId, in byte[] data);
- void onVirtualCableUnplug();
+ void onGetReport(in BluetoothDevice device, in byte type, in byte id, in int bufferSize);
+ void onSetReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data);
+ void onSetProtocol(in BluetoothDevice device, in byte protocol);
+ void onIntrData(in BluetoothDevice device, in byte reportId, in byte[] data);
+ void onVirtualCableUnplug(in BluetoothDevice device);
}
diff --git a/core/java/android/bluetooth/IBluetoothInputHost.aidl b/core/java/android/bluetooth/IBluetoothInputHost.aidl
index b2c421c..6c4993f 100644
--- a/core/java/android/bluetooth/IBluetoothInputHost.aidl
+++ b/core/java/android/bluetooth/IBluetoothInputHost.aidl
@@ -28,10 +28,13 @@
in BluetoothHidDeviceAppSdpSettings sdp, in BluetoothHidDeviceAppQosSettings inQos,
in BluetoothHidDeviceAppQosSettings outQos, in IBluetoothHidDeviceCallback callback);
boolean unregisterApp(in BluetoothHidDeviceAppConfiguration config);
- boolean sendReport(in int id, in byte[] data);
- boolean replyReport(in byte type, in byte id, in byte[] data);
- boolean reportError(byte error);
- boolean unplug();
- boolean connect();
- boolean disconnect();
+ boolean sendReport(in BluetoothDevice device, in int id, in byte[] data);
+ boolean replyReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data);
+ boolean reportError(in BluetoothDevice device, byte error);
+ boolean unplug(in BluetoothDevice device);
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fd11031..02b86fe 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2768,6 +2768,9 @@
* connectivity. On releases before NYC, it should only be obtained from an application
* context, and not from any other derived context to avoid memory leaks within the calling
* process.
+ * <dt> {@link #WIFI_AWARE_SERVICE} ("wifiaware")
+ * <dd> A {@link android.net.wifi.aware.WifiAwareManager WifiAwareManager} for management of
+ * Wi-Fi Aware discovery and connectivity.
* <dt> {@link #WIFI_P2P_SERVICE} ("wifip2p")
* <dd> A {@link android.net.wifi.p2p.WifiP2pManager WifiP2pManager} for management of
* Wi-Fi Direct connectivity.
@@ -3144,7 +3147,6 @@
*
* @see #getSystemService
* @see android.net.wifi.aware.WifiAwareManager
- * @hide PROPOSED_AWARE_API
*/
public static final String WIFI_AWARE_SERVICE = "wifiaware";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b0efd89..11e19f3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2041,8 +2041,6 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports Wi-Fi Aware.
- *
- * @hide PROPOSED_AWARE_API
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_WIFI_AWARE = "android.hardware.wifi.aware";
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 51431eb..042481f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -223,6 +223,13 @@
public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
/**
+ * Key for passing a user agent string to the captive portal login activity.
+ * {@hide}
+ */
+ public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT =
+ "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
+
+ /**
* Broadcast action to indicate the change of data activity status
* (idle or active) on a network in a recent period.
* The network becomes active when data transmission is started, or
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 932f031..9573953 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -100,4 +100,21 @@
* @hide
*/
boolean requestScores(in NetworkKey[] networks);
+
+ /**
+ * Determine whether the application with the given UID is the enabled scorer.
+ *
+ * @param callingUid the UID to check
+ * @return true if the provided UID is the active scorer, false otherwise.
+ * @hide
+ */
+ boolean isCallerActiveScorer(int callingUid);
+
+ /**
+ * Obtain the package name of the current active network scorer.
+ *
+ * @return the full package name of the current active scorer, or null if there is no active
+ * scorer.
+ */
+ String getActiveScorerPackage();
}
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index 9464222..3fcde330 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -87,9 +87,9 @@
{
LocalSocketImpl acceptedImpl = new LocalSocketImpl();
- impl.accept (acceptedImpl);
+ impl.accept(acceptedImpl);
- return new LocalSocket(acceptedImpl, LocalSocket.SOCKET_UNKNOWN);
+ return LocalSocket.createLocalSocketForAccept(acceptedImpl);
}
/**
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index e14facb1..8afa1ed 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -31,6 +31,7 @@
public class LocalSocket implements Closeable {
private final LocalSocketImpl impl;
+ /** false if impl.create() needs to be called */
private volatile boolean implCreated;
private LocalSocketAddress localAddress;
private boolean isBound;
@@ -61,31 +62,44 @@
*/
public LocalSocket(int sockType) {
this(new LocalSocketImpl(), sockType);
- isBound = false;
- isConnected = false;
}
- /**
- * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
- * @hide
- */
- public LocalSocket(FileDescriptor fd) throws IOException {
- this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
- isBound = true;
- isConnected = true;
- }
-
- /**
- * for use with AndroidServerSocket
- * @param impl a SocketImpl
- */
- /*package*/ LocalSocket(LocalSocketImpl impl, int sockType) {
+ private LocalSocket(LocalSocketImpl impl, int sockType) {
this.impl = impl;
this.sockType = sockType;
this.isConnected = false;
this.isBound = false;
}
+ /**
+ * Creates a LocalSocket instances using the FileDescriptor for an already-connected
+ * AF_LOCAL/UNIX domain stream socket. Note: the FileDescriptor must be closed by the caller:
+ * closing the LocalSocket will not close it.
+ *
+ * @hide - used by BluetoothSocket.
+ */
+ public static LocalSocket createConnectedLocalSocket(FileDescriptor fd) {
+ return createConnectedLocalSocket(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
+ }
+
+ /**
+ * for use with LocalServerSocket.accept()
+ */
+ static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl) {
+ return createConnectedLocalSocket(impl, SOCKET_UNKNOWN);
+ }
+
+ /**
+ * Creates a LocalSocket from an existing LocalSocketImpl that is already connected.
+ */
+ private static LocalSocket createConnectedLocalSocket(LocalSocketImpl impl, int sockType) {
+ LocalSocket socket = new LocalSocket(impl, sockType);
+ socket.isConnected = true;
+ socket.isBound = true;
+ socket.implCreated = true;
+ return socket;
+ }
+
/** {@inheritDoc} */
@Override
public String toString() {
@@ -216,11 +230,11 @@
implCreateIfNeeded();
impl.shutdownOutput();
}
-
+
public void setReceiveBufferSize(int size) throws IOException {
impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
}
-
+
public int getReceiveBufferSize() throws IOException {
return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
}
@@ -228,7 +242,7 @@
public void setSoTimeout(int n) throws IOException {
impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
}
-
+
public int getSoTimeout() throws IOException {
return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
}
@@ -236,7 +250,7 @@
public void setSendBufferSize(int n) throws IOException {
impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
}
-
+
public int getSendBufferSize() throws IOException {
return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
}
@@ -321,5 +335,5 @@
*/
public FileDescriptor getFileDescriptor() {
return impl.getFileDescriptor();
- }
+ }
}
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index 0f0e9c4..05c8afb 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -218,7 +218,7 @@
*
* @param fd non-null; bound file descriptor
*/
- /*package*/ LocalSocketImpl(FileDescriptor fd) throws IOException
+ /*package*/ LocalSocketImpl(FileDescriptor fd)
{
this.fd = fd;
}
@@ -235,29 +235,29 @@
* @throws IOException
*/
public void create(int sockType) throws IOException {
- // no error if socket already created
- // need this for LocalServerSocket.accept()
- if (fd == null) {
- int osType;
- switch (sockType) {
- case LocalSocket.SOCKET_DGRAM:
- osType = OsConstants.SOCK_DGRAM;
- break;
- case LocalSocket.SOCKET_STREAM:
- osType = OsConstants.SOCK_STREAM;
- break;
- case LocalSocket.SOCKET_SEQPACKET:
- osType = OsConstants.SOCK_SEQPACKET;
- break;
- default:
- throw new IllegalStateException("unknown sockType");
- }
- try {
- fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
- mFdCreatedInternally = true;
- } catch (ErrnoException e) {
- e.rethrowAsIOException();
- }
+ if (fd != null) {
+ throw new IOException("LocalSocketImpl already has an fd");
+ }
+
+ int osType;
+ switch (sockType) {
+ case LocalSocket.SOCKET_DGRAM:
+ osType = OsConstants.SOCK_DGRAM;
+ break;
+ case LocalSocket.SOCKET_STREAM:
+ osType = OsConstants.SOCK_STREAM;
+ break;
+ case LocalSocket.SOCKET_SEQPACKET:
+ osType = OsConstants.SOCK_SEQPACKET;
+ break;
+ default:
+ throw new IllegalStateException("unknown sockType");
+ }
+ try {
+ fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
+ mFdCreatedInternally = true;
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
}
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index dacea55..4dd8ce9 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -420,8 +420,6 @@
/**
* Indicates this network uses a Wi-Fi Aware transport.
- *
- * @hide PROPOSED_AWARE_API
*/
public static final int TRANSPORT_WIFI_AWARE = 5;
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 1825956..a6854dc 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -27,7 +27,6 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,19 +43,11 @@
* <p>A network scorer is any application which:
* <ul>
* <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
- * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission which scores
- * networks and (eventually) calls {@link #updateScores} with the results. If this receiver
- * specifies an android:label attribute, this label will be used when referring to the
- * application throughout system settings; otherwise, the application label will be used.
+ * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
+ * protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
+ * permission.
* </ul>
*
- * <p>The system keeps track of an active scorer application; at any time, only this application
- * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
- * {@link #updateScores}. Applications may determine the current active scorer with
- * {@link #getActiveScorerPackage()} and request to change the active scorer by sending an
- * {@link #ACTION_CHANGE_ACTIVE} broadcast with another scorer.
- *
* @hide
*/
@SystemApi
@@ -179,11 +170,11 @@
* scorer.
*/
public String getActiveScorerPackage() {
- NetworkScorerAppData app = new NetworkScorerAppManager(mContext).getActiveScorer();
- if (app == null) {
- return null;
+ try {
+ return mService.getActiveScorerPackage();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return app.packageName;
}
/**
@@ -263,12 +254,9 @@
/**
* Request scoring for networks.
*
- * <p>Note that this is just a helper method to assemble the broadcast, and will run in the
- * calling process.
- *
* @return true if the broadcast was sent, or false if there is no active scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @hide
*/
public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -285,7 +273,7 @@
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
* @hide
@@ -302,7 +290,7 @@
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
* @param filterType the {@link CacheUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -321,7 +309,7 @@
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -342,7 +330,8 @@
* request details
* @return a {@link RecommendationResult} instance containing the recommended network
* to connect to
- * @throws SecurityException
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
*/
public RecommendationResult requestRecommendation(RecommendationRequest request)
throws SecurityException {
@@ -352,4 +341,19 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Determine whether the application with the given UID is the enabled scorer.
+ *
+ * @param callingUid the UID to check
+ * @return true if the provided UID is the active scorer, false otherwise.
+ * @hide
+ */
+ public boolean isCallerActiveScorer(int callingUid) {
+ try {
+ return mService.isCallerActiveScorer(callingUid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 4282ca7..23d5af5 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -16,7 +16,6 @@
package android.net;
-import android.Manifest;
import android.Manifest.permission;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -28,7 +27,9 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+
import com.android.internal.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -226,18 +227,13 @@
}
/** Determine whether the application with the given UID is the enabled scorer. */
+ @Deprecated // Use NetworkScoreManager.isCallerActiveScorer()
public boolean isCallerActiveScorer(int callingUid) {
NetworkScorerAppData defaultApp = getActiveScorer();
if (defaultApp == null) {
return false;
}
- if (callingUid != defaultApp.packageUid) {
- return false;
- }
- // To be extra safe, ensure the caller holds the SCORE_NETWORKS permission. It always
- // should, since it couldn't become the active scorer otherwise, but this can't hurt.
- return mContext.checkCallingPermission(Manifest.permission.SCORE_NETWORKS) ==
- PackageManager.PERMISSION_GRANTED;
+ return callingUid == defaultApp.packageUid;
}
private boolean isNetworkRecommendationsDisabled() {
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
index a96f90d..d013f64 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -41,6 +41,7 @@
* Builder class for constructing {@link RecommendationRequest} instances.
* @hide
*/
+ @SystemApi
public static final class Builder {
private ScanResult[] mScanResults;
private WifiConfiguration mCurrentConfig;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 94e5187..7e3dd77 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
@@ -24,6 +25,8 @@
import java.lang.Math;
import java.lang.UnsupportedOperationException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -33,6 +36,15 @@
*/
@SystemApi
public class ScoredNetwork implements Parcelable {
+
+ /**
+ * Key used with the {@link #attributes} bundle to define the badging curve.
+ *
+ * <p>The badging curve is a {@link RssiCurve} used to map different RSSI values to {@link
+ * Badging} enums.
+ */
+ public static final String ATTRIBUTES_KEY_BADGING_CURVE =
+ "android.net.attributes.key.BADGING_CURVE";
/**
* Extra used with {@link #attributes} to specify whether the
* network is believed to have a captive portal.
@@ -58,6 +70,15 @@
public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET =
"android.net.attributes.key.RANKING_SCORE_OFFSET";
+ @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Badging {}
+
+ public static final int BADGING_NONE = 0;
+ public static final int BADGING_SD = 10;
+ public static final int BADGING_HD = 20;
+ public static final int BADGING_4K = 30;
+
/** A {@link NetworkKey} uniquely identifying this network. */
public final NetworkKey networkKey;
@@ -249,6 +270,25 @@
}
}
+ /**
+ * Return the {@link Badging} enum for this network for the given RSSI, derived from the
+ * badging curve.
+ *
+ * <p>If no badging curve is present, {@link #BADGE_NONE} will be returned.
+ *
+ * @param rssi The rssi level for which the badge should be calculated
+ */
+ @Badging
+ public int calculateBadge(int rssi) {
+ if (attributes != null && attributes.containsKey(ATTRIBUTES_KEY_BADGING_CURVE)) {
+ RssiCurve badgingCurve =
+ attributes.getParcelable(ATTRIBUTES_KEY_BADGING_CURVE);
+ return badgingCurve.lookupScore(rssi);
+ }
+
+ return BADGING_NONE;
+ }
+
public static final Parcelable.Creator<ScoredNetwork> CREATOR =
new Parcelable.Creator<ScoredNetwork>() {
@Override
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 151239b..f6edee0 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -783,7 +783,7 @@
*/
public static boolean isBuildConsistent() {
// Don't care on eng builds. Incremental build may trigger false negative.
- if ("eng".equals(TYPE)) return true;
+ if (IS_ENG) return true;
final String system = SystemProperties.get("ro.build.fingerprint");
final String vendor = SystemProperties.get("ro.vendor.build.fingerprint");
@@ -847,6 +847,10 @@
public static final boolean IS_DEBUGGABLE =
SystemProperties.getInt("ro.debuggable", 0) == 1;
+ /** {@hide} */
+ public static final boolean IS_ENG =
+ "eng".equals(getString("ro.build.type"));
+
/**
* Specifies whether the permissions needed by a legacy app should be
* reviewed before any of its components can run. A legacy app is one
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 481b2dc..e025494 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -17,6 +17,7 @@
package android.os;
import java.util.ArrayList;
+import java.util.NoSuchElementException;
import libcore.util.NativeAllocationRegistry;
/** @hide */
@@ -33,19 +34,24 @@
mNativeContext);
}
+ @Override
public final native void transact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public abstract void onTransact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public native final void registerService(
ArrayList<String> interfaceChain,
- String serviceName);
+ String serviceName)
+ throws RemoteException;
public static native final IHwBinder getService(
String iface,
- String serviceName);
+ String serviceName)
+ throws RemoteException, NoSuchElementException;
// Returns address of the "freeFunction".
private static native final long native_init();
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index c7612d1..a265dd0 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -212,7 +212,7 @@
public native final HwBlob readBuffer();
public native final HwBlob readEmbeddedBuffer(
- long parentHandle, long offset);
+ long parentHandle, long offset, boolean nullable);
public native final void writeBuffer(HwBlob blob);
diff --git a/core/java/android/os/HwRemoteBinder.java b/core/java/android/os/HwRemoteBinder.java
index e617e0a..2f89ce6 100644
--- a/core/java/android/os/HwRemoteBinder.java
+++ b/core/java/android/os/HwRemoteBinder.java
@@ -32,12 +32,15 @@
mNativeContext);
}
+ @Override
public IHwInterface queryLocalInterface(String descriptor) {
return null;
}
+ @Override
public native final void transact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public native boolean linkToDeath(DeathRecipient recipient, long cookie);
public native boolean unlinkToDeath(DeathRecipient recipient);
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index f93bfd7..619f4dc 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -23,7 +23,8 @@
public static final int FLAG_ONEWAY = 1;
public void transact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public IHwInterface queryLocalInterface(String descriptor);
@@ -36,6 +37,5 @@
}
public boolean linkToDeath(DeathRecipient recipient, long cookie);
-
public boolean unlinkToDeath(DeathRecipient recipient);
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 1c3d6bd..dbe2f6d 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -312,11 +312,6 @@
*/
void setDnsConfigurationForNetwork(int netId, in String[] servers, String domains);
- /**
- * Bind name servers to a network in the DNS resolver.
- */
- void setDnsServersForNetwork(int netId, in String[] servers, String domains);
-
void setFirewallEnabled(boolean enabled);
boolean isFirewallEnabled();
void setFirewallInterfaceRule(String iface, boolean allow);
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index c5ceecd..1ee83ae 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -25,5 +25,5 @@
boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
boolean setupBcb(in String command);
boolean clearBcb();
- void rebootRecoveryWithCommand(in String command);
+ void rebootRecoveryWithCommand(in String command, in boolean update);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9cd1a42..d6688e3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -184,6 +184,11 @@
*/
public static final int LAST_SHARED_APPLICATION_GID = 59999;
+ /** {@hide} */
+ public static final int FIRST_APPLICATION_CACHE_GID = 20000;
+ /** {@hide} */
+ public static final int LAST_APPLICATION_CACHE_GID = 29999;
+
/**
* Standard priority of application threads.
* Use with {@link #setThreadPriority(int)} and
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index d48431a..7f9ea438 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -491,15 +491,10 @@
command += securityArg;
}
+ // RECOVERY_SERVICE writes to BCB (bootloader control block) and triggers the reboot.
RecoverySystem rs = (RecoverySystem) context.getSystemService(
Context.RECOVERY_SERVICE);
- if (!rs.setupBcb(command)) {
- throw new IOException("Setup BCB failed");
- }
-
- // Having set up the BCB (bootloader control block), go ahead and reboot
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY_UPDATE);
+ rs.rebootRecoveryWithCommand(command, true /* update */);
throw new IOException("Reboot failed (no permissions?)");
}
@@ -713,7 +708,7 @@
// Write the command into BCB (bootloader control block) and boot from
// there. Will not return unless failed.
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
- rs.rebootRecoveryWithCommand(command.toString());
+ rs.rebootRecoveryWithCommand(command.toString(), false);
throw new IOException("Reboot failed (no permissions?)");
}
@@ -913,9 +908,9 @@
* Talks to RecoverySystemService via Binder to set up the BCB command and
* reboot into recovery accordingly.
*/
- private void rebootRecoveryWithCommand(String command) {
+ private void rebootRecoveryWithCommand(String command, boolean update) {
try {
- mService.rebootRecoveryWithCommand(command);
+ mService.rebootRecoveryWithCommand(command, update);
} catch (RemoteException ignored) {
}
}
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index b3f4453..535a05a 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -213,6 +213,15 @@
}
/**
+ * Returns the cache GID for a given UID or appId.
+ * @hide
+ */
+ public static int getCacheAppGid(int id) {
+ return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE)
+ - Process.FIRST_APPLICATION_UID;
+ }
+
+ /**
* Generate a text representation of the uid, breaking out its individual
* components -- user, app, isolated, etc.
* @hide
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c5507b9..9252887 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -40,6 +40,7 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -49,6 +50,7 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
@@ -930,24 +932,38 @@
}
/** {@hide} */
- public long getPrimaryStorageSize() {
+ public static Pair<String, Long> getPrimaryStoragePathAndSize() {
for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
final long numberBlocks = readLong(path);
if (numberBlocks > 0) {
- return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE;
+ return new Pair<>(path, Long.valueOf(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
}
}
- return 0;
+ return null;
}
- private long readLong(String path) {
+
+ /** {@hide} */
+ public long getPrimaryStorageSize() {
+ final Pair<String, Long> pair = getPrimaryStoragePathAndSize();
+ return pair == null ? 0 : pair.second.longValue();
+ }
+
+ private static long readLong(String path) {
try (final FileInputStream fis = new FileInputStream(path);
final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
return Long.parseLong(reader.readLine());
- } catch (Exception e) {
- Slog.w(TAG, "Could not read " + path, e);
+ } catch (FileNotFoundException e) {
+ // This is expected since we are trying to parse multiple paths.
+ Slog.i(TAG, "readLong(): Path doesn't exist: " + path + ": " + e);
return 0;
- }
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "readLong(): Could not parse " + path + ": " + e);
+ return 0;
+ } catch (Exception e) {
+ Slog.e(TAG, "readLong(): Unknown exception while opening " + path + ": " + e);
+ return 0;
+ }
}
/** @removed */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e52983e..3ea5dcb 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6498,7 +6498,8 @@
QS_TILES,
DOZE_ENABLED,
DOZE_PULSE_ON_PICK_UP,
- DOZE_PULSE_ON_DOUBLE_TAP
+ DOZE_PULSE_ON_DOUBLE_TAP,
+ NFC_PAYMENT_DEFAULT_COMPONENT
};
/**
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 6196a97..dd45cd0 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -58,7 +58,7 @@
private final ByteBuffer mBuffer;
// Layout of event log entry received from Android logger.
- // see system/core/include/log/logger.h
+ // see system/core/include/log/log.h
private static final int LENGTH_OFFSET = 0;
private static final int HEADER_SIZE_OFFSET = 2;
private static final int PROCESS_OFFSET = 4;
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2e0729b..67196ca 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -75,17 +75,6 @@
private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
/**
- * System property used to enable or disable dirty regions invalidation.
- * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
- * The default value of this property is assumed to be true.
- *
- * Possible values:
- * "true", to enable partial invalidates
- * "false", to disable partial invalidates
- */
- static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
-
- /**
* System property used to enable or disable hardware rendering profiling.
* The default value of this property is assumed to be false.
*
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index e0d589a..2d6f443 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -24,6 +24,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -38,70 +40,104 @@
private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32";
private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64";
+ /**
+ * Lock object that protects all other static members.
+ */
+ private static final Object sLock = new Object();
+
+ /**
+ * Instance that maintains the socket connection to the zygote. This is null if the zygote
+ * is not running or is not connected.
+ */
+ @GuardedBy("sLock")
private static ZygoteProcess sZygote;
+ /**
+ * Information about the selected WebView package. This is set from #onWebViewProviderChanged().
+ */
+ @GuardedBy("sLock")
private static PackageInfo sPackage;
+ /**
+ * Flag for whether multi-process WebView is enabled. If this is false, the zygote
+ * will not be started.
+ */
+ @GuardedBy("sLock")
private static boolean sMultiprocessEnabled = false;
public static ZygoteProcess getProcess() {
- connectToZygoteIfNeeded();
- return sZygote;
+ synchronized (sLock) {
+ connectToZygoteIfNeededLocked();
+ return sZygote;
+ }
}
public static String getPackageName() {
- return sPackage.packageName;
+ synchronized (sLock) {
+ return sPackage.packageName;
+ }
}
public static boolean isMultiprocessEnabled() {
- return sMultiprocessEnabled && sPackage != null;
+ synchronized (sLock) {
+ return sMultiprocessEnabled && sPackage != null;
+ }
}
public static void setMultiprocessEnabled(boolean enabled) {
- sMultiprocessEnabled = enabled;
+ synchronized (sLock) {
+ sMultiprocessEnabled = enabled;
- // When toggling between multi-process being on/off, start or stop the
- // service. If it is enabled and the zygote is not yet started, bring up the service.
- // Otherwise, bring down the service. The name may be null if the package
- // information has not yet been resolved.
- final String serviceName = getServiceName();
- if (serviceName == null) return;
+ // When toggling between multi-process being on/off, start or stop the
+ // service. If it is enabled and the zygote is not yet started, bring up the service.
+ // Otherwise, bring down the service. The name may be null if the package
+ // information has not yet been resolved.
+ final String serviceName = getServiceNameLocked();
+ if (serviceName == null) return;
- if (enabled && sZygote == null) {
- SystemService.start(serviceName);
- } else {
- SystemService.stop(serviceName);
- sZygote = null;
+ if (enabled && sZygote == null) {
+ SystemService.start(serviceName);
+ } else {
+ SystemService.stop(serviceName);
+ sZygote = null;
+ }
}
}
public static void onWebViewProviderChanged(PackageInfo packageInfo) {
- sPackage = packageInfo;
+ String serviceName;
+ synchronized (sLock) {
+ sPackage = packageInfo;
- // If multi-process is not enabled, then do not start the zygote service.
- if (!sMultiprocessEnabled) {
- return;
+ // If multi-process is not enabled, then do not start the zygote service.
+ if (!sMultiprocessEnabled) {
+ return;
+ }
+
+ serviceName = getServiceNameLocked();
+ sZygote = null;
+
+ // The service may enter the RUNNING state before it opens the socket,
+ // so connectToZygoteIfNeededLocked() may still fail.
+ if (SystemService.isStopped(serviceName)) {
+ SystemService.start(serviceName);
+ } else {
+ SystemService.restart(serviceName);
+ }
+
+ try {
+ SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
+ } catch (TimeoutException e) {
+ Log.e(LOGTAG, "Timed out waiting for " + serviceName);
+ return;
+ }
+
+ connectToZygoteIfNeededLocked();
}
-
- final String serviceName = getServiceName();
-
- if (SystemService.isStopped(serviceName)) {
- SystemService.start(serviceName);
- } else if (sZygote != null) {
- SystemService.restart(serviceName);
- }
-
- try {
- SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
- } catch (TimeoutException e) {
- Log.e(LOGTAG, "Timed out waiting for " + serviceName);
- return;
- }
-
- connectToZygoteIfNeeded();
}
- private static String getServiceName() {
+ @GuardedBy("sLock")
+ private static String getServiceNameLocked() {
if (sPackage == null)
return null;
@@ -113,7 +149,8 @@
return WEBVIEW_ZYGOTE_SERVICE_32;
}
- private static void connectToZygoteIfNeeded() {
+ @GuardedBy("sLock")
+ private static void connectToZygoteIfNeededLocked() {
if (sZygote != null)
return;
@@ -122,7 +159,7 @@
return;
}
- final String serviceName = getServiceName();
+ final String serviceName = getServiceNameLocked();
if (!SystemService.isRunning(serviceName)) {
Log.e(LOGTAG, serviceName + " is not running");
return;
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index d968e3c..a8a5549 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -62,6 +62,9 @@
ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader(
packagePath, libsPath);
+ // Add the APK to the Zygote's list of allowed files for children.
+ Zygote.nativeAllowFileAcrossFork(packagePath);
+
// Once we have the classloader, look up the WebViewFactoryProvider implementation and
// call preloadInZygote() on it to give it the opportunity to preload the native library
// and perform any other initialisation work that should be shared among the children.
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index fc0ccb7..e1e0a21 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -85,6 +85,9 @@
* file descriptor numbers that are to be closed by the child
* (and replaced by /dev/null) after forking. An integer value
* of -1 in any entry in the array means "ignore this one".
+ * @param fdsToIgnore null-ok an array of ints, either null or holding
+ * one or more POSIX file descriptor numbers that are to be ignored
+ * in the file descriptor table check.
* @param instructionSet null-ok the instruction set to use.
* @param appDataDir null-ok the data directory of the app.
*
@@ -93,11 +96,11 @@
*/
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
- String instructionSet, String appDataDir) {
+ int[] fdsToIgnore, String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
- instructionSet, appDataDir);
+ fdsToIgnore, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Trace.setTracingEnabled(true);
@@ -111,7 +114,7 @@
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
- String instructionSet, String appDataDir);
+ int[] fdsToIgnore, String instructionSet, String appDataDir);
/**
* Special method to start the system server process. In addition to the
@@ -153,6 +156,11 @@
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
/**
+ * Lets children of the zygote inherit open file descriptors to this path.
+ */
+ native protected static void nativeAllowFileAcrossFork(String path);
+
+ /**
* Zygote unmount storage space on initializing.
* This method is called once.
*/
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 44c6e85..ec80303 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -193,11 +193,14 @@
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
+ int[] fdsToIgnore = null;
+
if (parsedArgs.invokeWith != null) {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
+ fdsToIgnore = new int[] { childPipeFd.getInt$(), serverPipeFd.getInt$() };
}
/**
@@ -230,7 +233,7 @@
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
+ parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (ErrnoException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 70e9004..d9d06c5 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -179,6 +179,7 @@
com_android_internal_util_VirtualRefBasePtr.cpp \
com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \
hwbinder/EphemeralStorage.cpp \
+ fd_utils.cpp \
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
index aa6348e..dcb7874 100644
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
+++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
@@ -33,7 +33,9 @@
#include "HarfBuzzNGFaceSkia.h"
#include <stdlib.h>
-#include <cutils/log.h>
+
+#include <log/log.h>
+
#include <SkPaint.h>
#include <SkPath.h>
#include <SkPoint.h>
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index ac82457..59c5be6 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -20,7 +20,7 @@
#include <vector>
-#include <android/log.h>
+#include <log/log.h>
#include <utils/Log.h>
#include "jni.h"
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index ade718b..5e173ca 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -15,10 +15,11 @@
*/
#define LOG_TAG "OpenGLRenderer"
+#include "android/log.h"
+
#include "jni.h"
#include "GraphicsJNI.h"
#include "core_jni_helpers.h"
-#include "log/log.h"
#include "Animator.h"
#include "Interpolator.h"
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 8eb39e1..fbccfd5 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -33,6 +33,7 @@
#include <unordered_map>
#include <queue>
+#include <android-base/macros.h>
#include <cutils/log.h>
#include "JNIHelp.h"
@@ -704,10 +705,10 @@
}
jbyteArray jmsg = env->NewByteArray(msgLen);
- jintArray jheader = env->NewIntArray(sizeof(header));
+ jintArray jheader = env->NewIntArray(arraysize(header));
env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
- env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header);
+ env->SetIntArrayRegion(jheader, 0, arraysize(header), (jint *)header);
ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE],
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 4976002..d30e6eb 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -457,6 +457,18 @@
}
static jint
+android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name)
+{
+ const char *c_address = env->GetStringUTFChars(device_address, NULL);
+ const char *c_name = env->GetStringUTFChars(device_name, NULL);
+ int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
+ c_address, c_name));
+ env->ReleaseStringUTFChars(device_address, c_address);
+ env->ReleaseStringUTFChars(device_name, c_name);
+ return (jint) status;
+}
+
+static jint
android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
{
return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
@@ -1757,6 +1769,7 @@
{"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
{"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
{"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
+ {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
{"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
{"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
{"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index d6d4310..37b6df1 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -202,9 +202,7 @@
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
- do {
- ret = recvmsg(fd, &msg, MSG_NOSIGNAL);
- } while (ret < 0 && errno == EINTR);
+ ret = TEMP_FAILURE_RETRY(recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
if (ret < 0 && errno == EPIPE) {
// Treat this as an end of stream
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index dd5f755..d8fbca8 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -16,32 +16,32 @@
#define LOG_TAG "android.os.Debug"
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <time.h>
#include <sys/time.h>
-#include <errno.h>
-#include <assert.h>
-#include <ctype.h>
-#include <malloc.h>
+#include <time.h>
+#include <unistd.h>
#include <iomanip>
#include <string>
-#include "jni.h"
+#include <android-base/stringprintf.h>
+#include <cutils/debugger.h>
+#include <log/log.h>
+#include <utils/misc.h>
+#include <utils/String8.h>
-#include "android-base/stringprintf.h"
-#include "cutils/debugger.h"
-#include "cutils/log.h"
#include "JNIHelp.h"
-#include "memtrack/memtrack.h"
-#include "memunreachable/memunreachable.h"
-#include "utils/misc.h"
-#include "utils/String8.h"
+#include "jni.h"
+#include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
namespace android
{
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 95e031b..e653900 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -26,7 +26,7 @@
#include <JNIHelp.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <android/hidl/base/1.0/IBase.h>
-#include <android/hidl/base/1.0/BpBase.h>
+#include <android/hidl/base/1.0/BpHwBase.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
@@ -39,6 +39,8 @@
using android::AndroidRuntime;
using android::hardware::hidl_vec;
using android::hardware::hidl_string;
+template<typename T>
+using Return = android::hardware::Return<T>;
#define PACKAGE_PATH "android/os"
#define CLASS_NAME "HwBinder"
@@ -52,6 +54,8 @@
jmethodID get;
} gArrayListMethods;
+static jclass gErrorClass;
+
static struct fields_t {
jfieldID contextID;
jmethodID onTransactID;
@@ -144,6 +148,22 @@
replyObj.get(),
flags);
+ if (env->ExceptionCheck()) {
+ jthrowable excep = env->ExceptionOccurred();
+ env->ExceptionDescribe();
+
+ if (env->IsInstanceOf(excep, gErrorClass)) {
+ /* It's an error */
+ LOG(ERROR) << "Forcefully exiting";
+ exit(1);
+ } else {
+ env->ExceptionClear();
+ LOG(ERROR) << "Uncaught exception!";
+ }
+
+ env->DeleteLocalRef(excep);
+ }
+
status_t err = OK;
if (!replyContext->wasSent()) {
@@ -239,35 +259,32 @@
hidl_vec<hidl_string> interfaceChain;
interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */);
- using android::hidl::manager::V1_0::IServiceManager;
-
sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
/* TODO(b/33440494) this is not right */
- sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpBase(binder);
+ sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpHwBase(binder);
auto manager = hardware::defaultServiceManager();
if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
- signalExceptionForError(env, UNKNOWN_ERROR);
+ signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return;
}
- bool ok = manager->add(
- interfaceChain,
- serviceName,
- base);
+ Return<bool> ret = manager->add(interfaceChain, serviceName, base);
env->ReleaseStringUTFChars(serviceNameObj, serviceName);
serviceName = NULL;
+ bool ok = ret.isOk() && ret;
+
if (ok) {
LOG(INFO) << "Starting thread pool.";
::android::hardware::ProcessState::self()->startThreadPool();
}
- signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR));
+ signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /* canThrowRemoteException */);
}
static jobject JHwBinder_native_getService(
@@ -303,19 +320,18 @@
if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
- signalExceptionForError(env, UNKNOWN_ERROR);
+ signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}
- sp<hardware::IBinder> service;
- manager->get(
- ifaceName,
- serviceName,
- [&service](sp<hidl::base::V1_0::IBase> out) {
- service = hardware::toBinder<
- hidl::base::V1_0::IBase, hidl::base::V1_0::BpBase
- >(out);
- });
+ Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceName, serviceName);
+
+ if (!ret.isOk()) {
+ signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
+ }
+
+ sp<hardware::IBinder> service = hardware::toBinder<
+ hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase>(ret);
env->ReleaseStringUTFChars(ifaceNameObj, ifaceName);
ifaceName = NULL;
@@ -356,6 +372,9 @@
gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I");
gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;");
+ jclass errorClass = FindClassOrDie(env, "java/lang/Error");
+ gErrorClass = MakeGlobalRefOrDie(env, errorClass);
+
return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_os_HwBinder.h b/core/jni/android_os_HwBinder.h
index 2ebc381..fa8fe01 100644
--- a/core/jni/android_os_HwBinder.h
+++ b/core/jni/android_os_HwBinder.h
@@ -24,7 +24,7 @@
namespace android {
-struct JHwBinder : public hardware::BBinder {
+struct JHwBinder : public hardware::BHwBinder {
static void InitClass(JNIEnv *env);
static sp<JHwBinder> SetNativeContext(
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index a10d807..1bd2333 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -49,7 +49,7 @@
} gFields;
-void signalExceptionForError(JNIEnv *env, status_t err) {
+void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) {
switch (err) {
case OK:
break;
@@ -114,8 +114,13 @@
default:
{
+ std::stringstream ss;
+ ss << "HwBinder Error: (" << err << ")";
+
jniThrowException(
- env, "java/lang/RuntimeException", "Unknown error");
+ env,
+ canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException",
+ ss.str().c_str());
break;
}
@@ -563,15 +568,16 @@
size_t parentHandle;
- const hidl_string *s = static_cast<const hidl_string *>(
- parcel->readBuffer(&parentHandle));
+ const hidl_string *s;
+ status_t err = parcel->readBuffer(&parentHandle,
+ reinterpret_cast<const void**>(&s));
- if (s == NULL) {
- signalExceptionForError(env, UNKNOWN_ERROR);
+ if (err != OK) {
+ signalExceptionForError(env, err);
return NULL;
}
- status_t err = ::android::hardware::readEmbeddedFromParcel(
+ err = ::android::hardware::readEmbeddedFromParcel(
const_cast<hidl_string *>(s),
*parcel, parentHandle, 0 /* parentOffset */);
@@ -588,20 +594,20 @@
JNIEnv *env, jobject thiz) { \
hardware::Parcel *parcel = \
JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
- \
size_t parentHandle; \
\
- const hidl_vec<Type> *vec = \
- (const hidl_vec<Type> *)parcel->readBuffer(&parentHandle); \
+ const hidl_vec<Type> *vec; \
+ status_t err = parcel->readBuffer(&parentHandle, \
+ reinterpret_cast<const void**>(&vec)); \
\
- if (vec == NULL) { \
- signalExceptionForError(env, UNKNOWN_ERROR); \
+ if (err != OK) { \
+ signalExceptionForError(env, err); \
return NULL; \
} \
\
size_t childHandle; \
\
- status_t err = ::android::hardware::readEmbeddedFromParcel( \
+ err = ::android::hardware::readEmbeddedFromParcel( \
const_cast<hidl_vec<Type> *>(vec), \
*parcel, \
parentHandle, \
@@ -633,17 +639,18 @@
size_t parentHandle;
- const hidl_vec<bool> *vec =
- (const hidl_vec<bool> *)parcel->readBuffer(&parentHandle);
+ const hidl_vec<bool> *vec;
+ status_t err = parcel->readBuffer(&parentHandle,
+ reinterpret_cast<const void**>(&vec));
- if (vec == NULL) {
- signalExceptionForError(env, UNKNOWN_ERROR);
+ if (err != OK) {
+ signalExceptionForError(env, err);
return NULL;
}
size_t childHandle;
- status_t err = ::android::hardware::readEmbeddedFromParcel(
+ err = ::android::hardware::readEmbeddedFromParcel(
const_cast<hidl_vec<bool> *>(vec),
*parcel,
parentHandle,
@@ -696,16 +703,17 @@
size_t parentHandle;
- const string_vec *vec=
- (const string_vec *)parcel->readBuffer(&parentHandle);
+ const string_vec *vec;
+ status_t err = parcel->readBuffer(&parentHandle,
+ reinterpret_cast<const void **>(&vec));
- if (vec == NULL) {
- signalExceptionForError(env, UNKNOWN_ERROR);
+ if (err != OK) {
+ signalExceptionForError(env, err);
return NULL;
}
size_t childHandle;
- status_t err = ::android::hardware::readEmbeddedFromParcel(
+ err = ::android::hardware::readEmbeddedFromParcel(
const_cast<string_vec *>(vec),
*parcel, parentHandle, 0 /* parentOffset */, &childHandle);
@@ -802,9 +810,10 @@
JHwParcel::GetNativeContext(env, thiz)->getParcel();
size_t handle;
- const void *ptr = parcel->readBuffer(&handle);
+ const void *ptr;
+ status_t status = parcel->readBuffer(&handle, &ptr);
- if (ptr == nullptr) {
+ if (status != OK) {
jniThrowException(env, "java/util/NoSuchElementException", NULL);
return nullptr;
}
@@ -813,18 +822,24 @@
}
static jobject JHwParcel_native_readEmbeddedBuffer(
- JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
+ JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset,
+ jboolean nullable) {
hardware::Parcel *parcel =
JHwParcel::GetNativeContext(env, thiz)->getParcel();
size_t childHandle;
- const void *ptr =
- parcel->readEmbeddedBuffer(&childHandle, parentHandle, offset);
+ const void *ptr;
+ status_t status =
+ parcel->readNullableEmbeddedBuffer(&childHandle, parentHandle, offset,
+ &ptr);
- if (ptr == nullptr) {
+ if (status != OK) {
jniThrowException(env, "java/util/NoSuchElementException", NULL);
return 0;
+ } else if (status == OK && !nullable && ptr == nullptr) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return 0;
}
return JHwBlob::NewObject(env, ptr, childHandle);
@@ -935,7 +950,7 @@
{ "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
(void *)JHwParcel_native_readBuffer },
- { "readEmbeddedBuffer", "(JJ)L" PACKAGE_PATH "/HwBlob;",
+ { "readEmbeddedBuffer", "(JJZ)L" PACKAGE_PATH "/HwBlob;",
(void *)JHwParcel_native_readEmbeddedBuffer },
{ "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h
index 708bbba..f81de9b 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -67,7 +67,7 @@
DISALLOW_COPY_AND_ASSIGN(JHwParcel);
};
-void signalExceptionForError(JNIEnv *env, status_t err);
+void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException = false);
int register_android_os_HwParcel(JNIEnv *env);
} // namespace android
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 0a7d84d..f2f8e52 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -347,7 +347,7 @@
JHwParcel::GetNativeContext(env, replyObj)->getParcel();
status_t err = binder->transact(code, *request, reply, flags);
- signalExceptionForError(env, err);
+ signalExceptionForError(env, err, true /* canThrowRemoteException */);
}
static jboolean JHwRemoteBinder_linkToDeath(JNIEnv* env, jobject thiz,
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 30fc47b..dc5ce39 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -19,15 +19,14 @@
#include <inttypes.h>
+#include <cutils/trace.h>
+#include <utils/String8.h>
+#include <log/log.h>
+
#include <JNIHelp.h>
#include <ScopedUtfChars.h>
#include <ScopedStringChars.h>
-#include <utils/String8.h>
-
-#include <cutils/trace.h>
-#include <cutils/log.h>
-
namespace android {
static void sanitizeString(String8& utf8Chars) {
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 5559d48..abcd1e7 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -29,19 +29,19 @@
#include <sys/types.h>
#include <unistd.h>
-#include <utils/Atomic.h>
#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-#include <utils/List.h>
-#include <utils/KeyedVector.h>
-#include <log/logger.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/threads.h>
+#include <log/log.h>
+#include <utils/Atomic.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/Log.h>
#include <utils/String8.h>
+#include <utils/SystemClock.h>
+#include <utils/threads.h>
#include <ScopedUtfChars.h>
#include <ScopedLocalRef.h>
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 3219d59..0b4fbcc 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -18,6 +18,8 @@
#include <log/log_event_list.h>
+#include <log/log.h>
+
#include "JNIHelp.h"
#include "core_jni_helpers.h"
#include "jni.h"
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 7719e31..20dfe78 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -21,7 +21,7 @@
#include <android-base/macros.h>
#include <assert.h>
#include <cutils/properties.h>
-#include <log/logger.h> // For LOGGER_ENTRY_MAX_PAYLOAD.
+#include <log/log.h> // For LOGGER_ENTRY_MAX_PAYLOAD.
#include <utils/Log.h>
#include <utils/String8.h>
diff --git a/core/jni/android_util_jar_StrictJarFile.cpp b/core/jni/android_util_jar_StrictJarFile.cpp
index 2e31c8b..4f1f926 100644
--- a/core/jni/android_util_jar_StrictJarFile.cpp
+++ b/core/jni/android_util_jar_StrictJarFile.cpp
@@ -20,13 +20,14 @@
#include <memory>
#include <string>
+#include <log/log.h>
+
#include "JNIHelp.h"
#include "JniConstants.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "jni.h"
#include "ziparchive/zip_archive.h"
-#include "cutils/log.h"
namespace android {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index fec8f4e..a32dbad 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -43,6 +43,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "android-base/logging.h"
#include <cutils/fs.h>
#include <cutils/multiuser.h>
#include <cutils/sched_policy.h>
@@ -56,7 +57,7 @@
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
-#include "fd_utils-inl.h"
+#include "fd_utils.h"
#include "nativebridge/native_bridge.h"
@@ -440,6 +441,22 @@
// The list of open zygote file descriptors.
static FileDescriptorTable* gOpenFdTable = NULL;
+static void FillFileDescriptorVector(JNIEnv* env,
+ jintArray java_fds,
+ std::vector<int>* fds) {
+ CHECK(fds != nullptr);
+ if (java_fds != nullptr) {
+ ScopedIntArrayRO ar(env, java_fds);
+ if (ar.get() == nullptr) {
+ RuntimeAbort(env, __LINE__, "Bad fd array");
+ }
+ fds->reserve(ar.size());
+ for (size_t i = 0; i < ar.size(); ++i) {
+ fds->push_back(ar[i]);
+ }
+ }
+}
+
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
@@ -447,6 +464,7 @@
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
+ jintArray fdsToIgnore,
jstring instructionSet, jstring dataDir) {
SetSigChldHandler();
@@ -457,12 +475,14 @@
// If this is the first fork for this zygote, create the open FD table.
// If it isn't, we just need to check whether the list of open files has
// changed (and it shouldn't in the normal case).
+ std::vector<int> fds_to_ignore;
+ FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
if (gOpenFdTable == NULL) {
- gOpenFdTable = FileDescriptorTable::Create();
+ gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
if (gOpenFdTable == NULL) {
RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
}
- } else if (!gOpenFdTable->Restat()) {
+ } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
}
@@ -621,7 +641,9 @@
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
- jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
+ jintArray fdsToClose,
+ jintArray fdsToIgnore,
+ jstring instructionSet, jstring appDataDir) {
jlong capabilities = 0;
// Grant CAP_WAKE_ALARM to the Bluetooth process.
@@ -656,7 +678,7 @@
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
- se_name, false, fdsToClose, instructionSet, appDataDir);
+ se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
}
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -667,7 +689,7 @@
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
- NULL, NULL);
+ NULL, NULL, NULL);
if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -684,6 +706,16 @@
return pid;
}
+static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork(
+ JNIEnv* env, jclass, jstring path) {
+ ScopedUtfChars path_native(env, path);
+ const char* path_cstr = path_native.c_str();
+ if (!path_cstr) {
+ RuntimeAbort(env, __LINE__, "path_cstr == NULL");
+ }
+ FileDescriptorWhitelist::Get()->Allow(path_cstr);
+}
+
static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) {
// Zygote process unmount root storage space initially before every child processes are forked.
// Every forked child processes (include SystemServer) only mount their own root storage space
@@ -724,10 +756,12 @@
static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
- "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
(void *) com_android_internal_os_Zygote_nativeForkSystemServer },
+ { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V",
+ (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork },
{ "nativeUnmountStorageOnInit", "()V",
(void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit }
};
diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h
deleted file mode 100644
index b78b8ff..0000000
--- a/core/jni/fd_utils-inl.h
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#include <string>
-#include <unordered_map>
-#include <set>
-#include <vector>
-#include <algorithm>
-
-#include <android-base/strings.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <cutils/log.h>
-#include "JNIHelp.h"
-#include "ScopedPrimitiveArray.h"
-
-// Whitelist of open paths that the zygote is allowed to keep open.
-//
-// In addition to the paths listed here, all files ending with
-// ".jar" under /system/framework" are whitelisted. See
-// FileDescriptorInfo::IsWhitelisted for the canonical definition.
-//
-// If the whitelisted path is associated with a regular file or a
-// character device, the file is reopened after a fork with the same
-// offset and mode. If the whilelisted path is associated with a
-// AF_UNIX socket, the socket will refer to /dev/null after each
-// fork, and all operations on it will fail.
-static const char* kPathWhitelist[] = {
- "/dev/null",
- "/dev/socket/zygote",
- "/dev/socket/zygote_secondary",
- "/dev/socket/webview_zygote",
- "/sys/kernel/debug/tracing/trace_marker",
- "/system/framework/framework-res.apk",
- "/dev/urandom",
- "/dev/ion",
- "/dev/dri/renderD129", // Fixes b/31172436
-};
-
-static const char* kFdPath = "/proc/self/fd";
-
-// Keeps track of all relevant information (flags, offset etc.) of an
-// open zygote file descriptor.
-class FileDescriptorInfo {
- public:
- // Create a FileDescriptorInfo for a given file descriptor. Returns
- // |NULL| if an error occurred.
- static FileDescriptorInfo* createFromFd(int fd) {
- struct stat f_stat;
- // This should never happen; the zygote should always have the right set
- // of permissions required to stat all its open files.
- if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
- ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
- return NULL;
- }
-
- if (S_ISSOCK(f_stat.st_mode)) {
- std::string socket_name;
- if (!GetSocketName(fd, &socket_name)) {
- return NULL;
- }
-
- if (!IsWhitelisted(socket_name)) {
- ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
- return NULL;
- }
-
- return new FileDescriptorInfo(fd);
- }
-
- // We only handle whitelisted regular files and character devices. Whitelisted
- // character devices must provide a guarantee of sensible behaviour when
- // reopened.
- //
- // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
- // S_ISLINK : Not supported.
- // S_ISBLK : Not supported.
- // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate
- // with the child process across forks but those should have been closed
- // before we got to this point.
- if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
- ALOGE("Unsupported st_mode %d", f_stat.st_mode);
- return NULL;
- }
-
- std::string file_path;
- if (!Readlink(fd, &file_path)) {
- return NULL;
- }
-
- if (!IsWhitelisted(file_path)) {
- ALOGE("Not whitelisted : %s", file_path.c_str());
- return NULL;
- }
-
- // File descriptor flags : currently on FD_CLOEXEC. We can set these
- // using F_SETFD - we're single threaded at this point of execution so
- // there won't be any races.
- const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
- if (fd_flags == -1) {
- ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
- return NULL;
- }
-
- // File status flags :
- // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
- // to the open() call.
- //
- // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
- // do about these, since the file has already been created. We shall ignore
- // them here.
- //
- // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
- // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
- // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
- // their presence and pass them in to open().
- int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
- if (fs_flags == -1) {
- ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
- return NULL;
- }
-
- // File offset : Ignore the offset for non seekable files.
- const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
-
- // We pass the flags that open accepts to open, and use F_SETFL for
- // the rest of them.
- static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
- int open_flags = fs_flags & (kOpenFlags);
- fs_flags = fs_flags & (~(kOpenFlags));
-
- return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
- }
-
- // Checks whether the file descriptor associated with this object
- // refers to the same description.
- bool Restat() const {
- struct stat f_stat;
- if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
- return false;
- }
-
- return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
- }
-
- bool ReopenOrDetach() const {
- if (is_sock) {
- return DetachSocket();
- }
-
- // NOTE: This might happen if the file was unlinked after being opened.
- // It's a common pattern in the case of temporary files and the like but
- // we should not allow such usage from the zygote.
- const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
-
- if (new_fd == -1) {
- ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
- return false;
- }
-
- if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
- close(new_fd);
- ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
- return false;
- }
-
- if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
- close(new_fd);
- ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
- return false;
- }
-
- if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
- close(new_fd);
- ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
- return false;
- }
-
- if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
- close(new_fd);
- ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
- return false;
- }
-
- close(new_fd);
-
- return true;
- }
-
- const int fd;
- const struct stat stat;
- const std::string file_path;
- const int open_flags;
- const int fd_flags;
- const int fs_flags;
- const off_t offset;
- const bool is_sock;
-
- private:
- FileDescriptorInfo(int fd) :
- fd(fd),
- stat(),
- open_flags(0),
- fd_flags(0),
- fs_flags(0),
- offset(0),
- is_sock(true) {
- }
-
- FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
- int fd_flags, int fs_flags, off_t offset) :
- fd(fd),
- stat(stat),
- file_path(file_path),
- open_flags(open_flags),
- fd_flags(fd_flags),
- fs_flags(fs_flags),
- offset(offset),
- is_sock(false) {
- }
-
- // Returns true iff. a given path is whitelisted. A path is whitelisted
- // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
- // under /system/framework that ends with ".jar" or if it is a system
- // framework overlay.
- static bool IsWhitelisted(const std::string& path) {
- for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) {
- if (kPathWhitelist[i] == path) {
- return true;
- }
- }
-
- static const char* kFrameworksPrefix = "/system/framework/";
- static const char* kJarSuffix = ".jar";
- if (android::base::StartsWith(path, kFrameworksPrefix)
- && android::base::EndsWith(path, kJarSuffix)) {
- return true;
- }
-
- // Whitelist files needed for Runtime Resource Overlay, like these:
- // /system/vendor/overlay/framework-res.apk
- // /system/vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
- // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
- // /data/resource-cache/system@vendor@overlay@PG@framework-res.apk@idmap
- static const char* kOverlayDir = "/system/vendor/overlay/";
- static const char* kApkSuffix = ".apk";
-
- if (android::base::StartsWith(path, kOverlayDir)
- && android::base::EndsWith(path, kApkSuffix)
- && path.find("/../") == std::string::npos) {
- return true;
- }
-
- static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
- static const char* kOverlayIdmapSuffix = ".apk@idmap";
- if (android::base::StartsWith(path, kOverlayIdmapPrefix)
- && android::base::EndsWith(path, kOverlayIdmapSuffix)) {
- return true;
- }
-
- return false;
- }
-
- // TODO: Call android::base::Readlink instead of copying the code here.
- static bool Readlink(const int fd, std::string* result) {
- char path[64];
- snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
- // Code copied from android::base::Readlink starts here :
-
- // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
- // and truncates to whatever size you do supply, so it can't be used to query.
- // We could call lstat first, but that would introduce a race condition that
- // we couldn't detect.
- // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
- char buf[4096];
- ssize_t len = readlink(path, buf, sizeof(buf));
- if (len == -1) return false;
-
- result->assign(buf, len);
- return true;
- }
-
- // Returns the locally-bound name of the socket |fd|. Returns true
- // iff. all of the following hold :
- //
- // - the socket's sa_family is AF_UNIX.
- // - the length of the path is greater than zero (i.e, not an unnamed socket).
- // - the first byte of the path isn't zero (i.e, not a socket with an abstract
- // address).
- static bool GetSocketName(const int fd, std::string* result) {
- sockaddr_storage ss;
- sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
- socklen_t addr_len = sizeof(ss);
-
- if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
- ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
- return false;
- }
-
- if (addr->sa_family != AF_UNIX) {
- ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
- return false;
- }
-
- const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
-
- size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
- // This is an unnamed local socket, we do not accept it.
- if (path_len == 0) {
- ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
- return false;
- }
-
- // This is a local socket with an abstract address, we do not accept it.
- if (unix_addr->sun_path[0] == '\0') {
- ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
- return false;
- }
-
- // If we're here, sun_path must refer to a null terminated filesystem
- // pathname (man 7 unix). Remove the terminator before assigning it to an
- // std::string.
- if (unix_addr->sun_path[path_len - 1] == '\0') {
- --path_len;
- }
-
- result->assign(unix_addr->sun_path, path_len);
- return true;
- }
-
- bool DetachSocket() const {
- const int dev_null_fd = open("/dev/null", O_RDWR);
- if (dev_null_fd < 0) {
- ALOGE("Failed to open /dev/null : %s", strerror(errno));
- return false;
- }
-
- if (dup2(dev_null_fd, fd) == -1) {
- ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
- return false;
- }
-
- if (close(dev_null_fd) == -1) {
- ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
- return false;
- }
-
- return true;
- }
-
- DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
-};
-
-// A FileDescriptorTable is a collection of FileDescriptorInfo objects
-// keyed by their FDs.
-class FileDescriptorTable {
- public:
- // Creates a new FileDescriptorTable. This function scans
- // /proc/self/fd for the list of open file descriptors and collects
- // information about them. Returns NULL if an error occurs.
- static FileDescriptorTable* Create() {
- DIR* d = opendir(kFdPath);
- if (d == NULL) {
- ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
- return NULL;
- }
- int dir_fd = dirfd(d);
- dirent* e;
-
- std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
- while ((e = readdir(d)) != NULL) {
- const int fd = ParseFd(e, dir_fd);
- if (fd == -1) {
- continue;
- }
-
- FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
- if (info == NULL) {
- if (closedir(d) == -1) {
- ALOGE("Unable to close directory : %s", strerror(errno));
- }
- return NULL;
- }
- open_fd_map[fd] = info;
- }
-
- if (closedir(d) == -1) {
- ALOGE("Unable to close directory : %s", strerror(errno));
- return NULL;
- }
- return new FileDescriptorTable(open_fd_map);
- }
-
- bool Restat() {
- std::set<int> open_fds;
-
- // First get the list of open descriptors.
- DIR* d = opendir(kFdPath);
- if (d == NULL) {
- ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
- return false;
- }
-
- int dir_fd = dirfd(d);
- dirent* e;
- while ((e = readdir(d)) != NULL) {
- const int fd = ParseFd(e, dir_fd);
- if (fd == -1) {
- continue;
- }
-
- open_fds.insert(fd);
- }
-
- if (closedir(d) == -1) {
- ALOGE("Unable to close directory : %s", strerror(errno));
- return false;
- }
-
- return RestatInternal(open_fds);
- }
-
- // Reopens all file descriptors that are contained in the table. Returns true
- // if all descriptors were successfully re-opened or detached, and false if an
- // error occurred.
- bool ReopenOrDetach() {
- std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
- for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
- const FileDescriptorInfo* info = it->second;
- if (info == NULL || !info->ReopenOrDetach()) {
- return false;
- }
- }
-
- return true;
- }
-
- private:
- FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map)
- : open_fd_map_(map) {
- }
-
- bool RestatInternal(std::set<int>& open_fds) {
- bool error = false;
-
- // Iterate through the list of file descriptors we've already recorded
- // and check whether :
- //
- // (a) they continue to be open.
- // (b) they refer to the same file.
- std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
- while (it != open_fd_map_.end()) {
- std::set<int>::const_iterator element = open_fds.find(it->first);
- if (element == open_fds.end()) {
- // The entry from the file descriptor table is no longer in the list
- // of open files. We warn about this condition and remove it from
- // the list of FDs under consideration.
- //
- // TODO(narayan): This will be an error in a future android release.
- // error = true;
- // ALOGW("Zygote closed file descriptor %d.", it->first);
- it = open_fd_map_.erase(it);
- } else {
- // The entry from the file descriptor table is still open. Restat
- // it and check whether it refers to the same file.
- const bool same_file = it->second->Restat();
- if (!same_file) {
- // The file descriptor refers to a different description. We must
- // update our entry in the table.
- delete it->second;
- it->second = FileDescriptorInfo::createFromFd(*element);
- if (it->second == NULL) {
- // The descriptor no longer no longer refers to a whitelisted file.
- // We flag an error and remove it from the list of files we're
- // tracking.
- error = true;
- it = open_fd_map_.erase(it);
- } else {
- // Successfully restatted the file, move on to the next open FD.
- ++it;
- }
- } else {
- // It's the same file. Nothing to do here. Move on to the next open
- // FD.
- ++it;
- }
-
- // Finally, remove the FD from the set of open_fds. We do this last because
- // |element| will not remain valid after a call to erase.
- open_fds.erase(element);
- }
- }
-
- if (open_fds.size() > 0) {
- // The zygote has opened new file descriptors since our last inspection.
- // We warn about this condition and add them to our table.
- //
- // TODO(narayan): This will be an error in a future android release.
- // error = true;
- // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
-
- // TODO(narayan): This code will be removed in a future android release.
- std::set<int>::const_iterator it;
- for (it = open_fds.begin(); it != open_fds.end(); ++it) {
- const int fd = (*it);
- FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
- if (info == NULL) {
- // A newly opened file is not on the whitelist. Flag an error and
- // continue.
- error = true;
- } else {
- // Track the newly opened file.
- open_fd_map_[fd] = info;
- }
- }
- }
-
- return !error;
- }
-
- static int ParseFd(dirent* e, int dir_fd) {
- char* end;
- const int fd = strtol(e->d_name, &end, 10);
- if ((*end) != '\0') {
- return -1;
- }
-
- // Don't bother with the standard input/output/error, they're handled
- // specially post-fork anyway.
- if (fd <= STDERR_FILENO || fd == dir_fd) {
- return -1;
- }
-
- return fd;
- }
-
- // Invariant: All values in this unordered_map are non-NULL.
- std::unordered_map<int, FileDescriptorInfo*> open_fd_map_;
-
- DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable);
-};
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
new file mode 100644
index 0000000..59a536b
--- /dev/null
+++ b/core/jni/fd_utils.cpp
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "fd_utils.h"
+
+#include <algorithm>
+
+#include <fcntl.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <android-base/strings.h>
+#include <cutils/log.h>
+
+// Static whitelist of open paths that the zygote is allowed to keep open.
+static const char* kPathWhitelist[] = {
+ "/dev/null",
+ "/dev/socket/zygote",
+ "/dev/socket/zygote_secondary",
+ "/dev/socket/webview_zygote",
+ "/sys/kernel/debug/tracing/trace_marker",
+ "/system/framework/framework-res.apk",
+ "/dev/urandom",
+ "/dev/ion",
+ "/dev/dri/renderD129", // Fixes b/31172436
+};
+
+static const char kFdPath[] = "/proc/self/fd";
+
+// static
+FileDescriptorWhitelist* FileDescriptorWhitelist::Get() {
+ if (instance_ == nullptr) {
+ instance_ = new FileDescriptorWhitelist();
+ }
+ return instance_;
+}
+
+bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
+ // Check the static whitelist path.
+ for (const auto& whitelist_path : kPathWhitelist) {
+ if (path == whitelist_path)
+ return true;
+ }
+
+ // Check any paths added to the dynamic whitelist.
+ for (const auto& whitelist_path : whitelist_) {
+ if (path == whitelist_path)
+ return true;
+ }
+
+ static const std::string kFrameworksPrefix = "/system/framework/";
+ static const std::string kJarSuffix = ".jar";
+ if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) {
+ return true;
+ }
+
+ // Whitelist files needed for Runtime Resource Overlay, like these:
+ // /system/vendor/overlay/framework-res.apk
+ // /system/vendor/overlay-subdir/pg/framework-res.apk
+ // /vendor/overlay/framework-res.apk
+ // /vendor/overlay/PG/android-framework-runtime-resource-overlay.apk
+ // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
+ // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
+ // See AssetManager.cpp for more details on overlay-subdir.
+ static const std::string kOverlayDir = "/system/vendor/overlay/";
+ static const std::string kVendorOverlayDir = "/vendor/overlay";
+ static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const std::string kApkSuffix = ".apk";
+
+ if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir)
+ || StartsWith(path, kVendorOverlayDir))
+ && EndsWith(path, kApkSuffix)
+ && path.find("/../") == std::string::npos) {
+ return true;
+ }
+
+ static const std::string kOverlayIdmapPrefix = "/data/resource-cache/";
+ static const std::string kOverlayIdmapSuffix = ".apk@idmap";
+ if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix)
+ && path.find("/../") == std::string::npos) {
+ return true;
+ }
+
+ // All regular files that are placed under this path are whitelisted automatically.
+ static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
+ if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) {
+ return true;
+ }
+
+ return false;
+}
+
+FileDescriptorWhitelist::FileDescriptorWhitelist()
+ : whitelist_() {
+}
+
+// TODO: Call android::base::StartsWith instead of copying the code here.
+// static
+bool FileDescriptorWhitelist::StartsWith(const std::string& str,
+ const std::string& prefix) {
+ return str.compare(0, prefix.size(), prefix) == 0;
+}
+
+// TODO: Call android::base::EndsWith instead of copying the code here.
+// static
+bool FileDescriptorWhitelist::EndsWith(const std::string& str,
+ const std::string& suffix) {
+ if (suffix.size() > str.size()) {
+ return false;
+ }
+
+ return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
+
+// static
+FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
+ struct stat f_stat;
+ // This should never happen; the zygote should always have the right set
+ // of permissions required to stat all its open files.
+ if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+ ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
+ return NULL;
+ }
+
+ const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
+
+ if (S_ISSOCK(f_stat.st_mode)) {
+ std::string socket_name;
+ if (!GetSocketName(fd, &socket_name)) {
+ return NULL;
+ }
+
+ if (!whitelist->IsAllowed(socket_name)) {
+ ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
+ return NULL;
+ }
+
+ return new FileDescriptorInfo(fd);
+ }
+
+ // We only handle whitelisted regular files and character devices. Whitelisted
+ // character devices must provide a guarantee of sensible behaviour when
+ // reopened.
+ //
+ // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
+ // S_ISLINK : Not supported.
+ // S_ISBLK : Not supported.
+ // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate
+ // with the child process across forks but those should have been closed
+ // before we got to this point.
+ if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
+ ALOGE("Unsupported st_mode %d", f_stat.st_mode);
+ return NULL;
+ }
+
+ std::string file_path;
+ if (!Readlink(fd, &file_path)) {
+ return NULL;
+ }
+
+ if (!whitelist->IsAllowed(file_path)) {
+ ALOGE("Not whitelisted : %s", file_path.c_str());
+ return NULL;
+ }
+
+ // File descriptor flags : currently on FD_CLOEXEC. We can set these
+ // using F_SETFD - we're single threaded at this point of execution so
+ // there won't be any races.
+ const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
+ if (fd_flags == -1) {
+ ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
+ return NULL;
+ }
+
+ // File status flags :
+ // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
+ // to the open() call.
+ //
+ // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
+ // do about these, since the file has already been created. We shall ignore
+ // them here.
+ //
+ // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
+ // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
+ // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
+ // their presence and pass them in to open().
+ int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
+ if (fs_flags == -1) {
+ ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
+ return NULL;
+ }
+
+ // File offset : Ignore the offset for non seekable files.
+ const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
+
+ // We pass the flags that open accepts to open, and use F_SETFL for
+ // the rest of them.
+ static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
+ int open_flags = fs_flags & (kOpenFlags);
+ fs_flags = fs_flags & (~(kOpenFlags));
+
+ return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
+}
+
+bool FileDescriptorInfo::Restat() const {
+ struct stat f_stat;
+ if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+ return false;
+ }
+
+ return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
+}
+
+bool FileDescriptorInfo::ReopenOrDetach() const {
+ if (is_sock) {
+ return DetachSocket();
+ }
+
+ // NOTE: This might happen if the file was unlinked after being opened.
+ // It's a common pattern in the case of temporary files and the like but
+ // we should not allow such usage from the zygote.
+ const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
+
+ if (new_fd == -1) {
+ ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
+ return false;
+ }
+
+ if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
+ close(new_fd);
+ ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
+ return false;
+ }
+
+ if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
+ close(new_fd);
+ ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
+ return false;
+ }
+
+ if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
+ close(new_fd);
+ ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
+ return false;
+ }
+
+ if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
+ close(new_fd);
+ ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
+ return false;
+ }
+
+ close(new_fd);
+
+ return true;
+}
+
+FileDescriptorInfo::FileDescriptorInfo(int fd) :
+ fd(fd),
+ stat(),
+ open_flags(0),
+ fd_flags(0),
+ fs_flags(0),
+ offset(0),
+ is_sock(true) {
+}
+
+FileDescriptorInfo::FileDescriptorInfo(struct stat stat, const std::string& file_path,
+ int fd, int open_flags, int fd_flags, int fs_flags,
+ off_t offset) :
+ fd(fd),
+ stat(stat),
+ file_path(file_path),
+ open_flags(open_flags),
+ fd_flags(fd_flags),
+ fs_flags(fs_flags),
+ offset(offset),
+ is_sock(false) {
+}
+
+// TODO: Call android::base::Readlink instead of copying the code here.
+// static
+bool FileDescriptorInfo::Readlink(const int fd, std::string* result) {
+ char path[64];
+ snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+ // Code copied from android::base::Readlink starts here :
+
+ // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
+ // and truncates to whatever size you do supply, so it can't be used to query.
+ // We could call lstat first, but that would introduce a race condition that
+ // we couldn't detect.
+ // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
+ char buf[4096];
+ ssize_t len = readlink(path, buf, sizeof(buf));
+ if (len == -1) return false;
+
+ result->assign(buf, len);
+ return true;
+}
+
+// static
+bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
+ sockaddr_storage ss;
+ sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
+ socklen_t addr_len = sizeof(ss);
+
+ if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
+ ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
+ return false;
+ }
+
+ if (addr->sa_family != AF_UNIX) {
+ ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
+ return false;
+ }
+
+ const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
+
+ size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
+ // This is an unnamed local socket, we do not accept it.
+ if (path_len == 0) {
+ ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
+ return false;
+ }
+
+ // This is a local socket with an abstract address, we do not accept it.
+ if (unix_addr->sun_path[0] == '\0') {
+ ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
+ return false;
+ }
+
+ // If we're here, sun_path must refer to a null terminated filesystem
+ // pathname (man 7 unix). Remove the terminator before assigning it to an
+ // std::string.
+ if (unix_addr->sun_path[path_len - 1] == '\0') {
+ --path_len;
+ }
+
+ result->assign(unix_addr->sun_path, path_len);
+ return true;
+}
+
+bool FileDescriptorInfo::DetachSocket() const {
+ const int dev_null_fd = open("/dev/null", O_RDWR);
+ if (dev_null_fd < 0) {
+ ALOGE("Failed to open /dev/null : %s", strerror(errno));
+ return false;
+ }
+
+ if (dup2(dev_null_fd, fd) == -1) {
+ ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
+ return false;
+ }
+
+ if (close(dev_null_fd) == -1) {
+ ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+// static
+FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
+ DIR* d = opendir(kFdPath);
+ if (d == NULL) {
+ ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+ return NULL;
+ }
+ int dir_fd = dirfd(d);
+ dirent* e;
+
+ std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
+ while ((e = readdir(d)) != NULL) {
+ const int fd = ParseFd(e, dir_fd);
+ if (fd == -1) {
+ continue;
+ }
+ if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
+ ALOGI("Ignoring open file descriptor %d", fd);
+ continue;
+ }
+
+ FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+ if (info == NULL) {
+ if (closedir(d) == -1) {
+ ALOGE("Unable to close directory : %s", strerror(errno));
+ }
+ return NULL;
+ }
+ open_fd_map[fd] = info;
+ }
+
+ if (closedir(d) == -1) {
+ ALOGE("Unable to close directory : %s", strerror(errno));
+ return NULL;
+ }
+ return new FileDescriptorTable(open_fd_map);
+}
+
+bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
+ std::set<int> open_fds;
+
+ // First get the list of open descriptors.
+ DIR* d = opendir(kFdPath);
+ if (d == NULL) {
+ ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+ return false;
+ }
+
+ int dir_fd = dirfd(d);
+ dirent* e;
+ while ((e = readdir(d)) != NULL) {
+ const int fd = ParseFd(e, dir_fd);
+ if (fd == -1) {
+ continue;
+ }
+ if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
+ ALOGI("Ignoring open file descriptor %d", fd);
+ continue;
+ }
+
+ open_fds.insert(fd);
+ }
+
+ if (closedir(d) == -1) {
+ ALOGE("Unable to close directory : %s", strerror(errno));
+ return false;
+ }
+
+ return RestatInternal(open_fds);
+}
+
+// Reopens all file descriptors that are contained in the table. Returns true
+// if all descriptors were successfully re-opened or detached, and false if an
+// error occurred.
+bool FileDescriptorTable::ReopenOrDetach() {
+ std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
+ for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
+ const FileDescriptorInfo* info = it->second;
+ if (info == NULL || !info->ReopenOrDetach()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+FileDescriptorTable::FileDescriptorTable(
+ const std::unordered_map<int, FileDescriptorInfo*>& map)
+ : open_fd_map_(map) {
+}
+
+bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) {
+ bool error = false;
+
+ // Iterate through the list of file descriptors we've already recorded
+ // and check whether :
+ //
+ // (a) they continue to be open.
+ // (b) they refer to the same file.
+ std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
+ while (it != open_fd_map_.end()) {
+ std::set<int>::const_iterator element = open_fds.find(it->first);
+ if (element == open_fds.end()) {
+ // The entry from the file descriptor table is no longer in the list
+ // of open files. We warn about this condition and remove it from
+ // the list of FDs under consideration.
+ //
+ // TODO(narayan): This will be an error in a future android release.
+ // error = true;
+ // ALOGW("Zygote closed file descriptor %d.", it->first);
+ it = open_fd_map_.erase(it);
+ } else {
+ // The entry from the file descriptor table is still open. Restat
+ // it and check whether it refers to the same file.
+ const bool same_file = it->second->Restat();
+ if (!same_file) {
+ // The file descriptor refers to a different description. We must
+ // update our entry in the table.
+ delete it->second;
+ it->second = FileDescriptorInfo::CreateFromFd(*element);
+ if (it->second == NULL) {
+ // The descriptor no longer no longer refers to a whitelisted file.
+ // We flag an error and remove it from the list of files we're
+ // tracking.
+ error = true;
+ it = open_fd_map_.erase(it);
+ } else {
+ // Successfully restatted the file, move on to the next open FD.
+ ++it;
+ }
+ } else {
+ // It's the same file. Nothing to do here. Move on to the next open
+ // FD.
+ ++it;
+ }
+
+ // Finally, remove the FD from the set of open_fds. We do this last because
+ // |element| will not remain valid after a call to erase.
+ open_fds.erase(element);
+ }
+ }
+
+ if (open_fds.size() > 0) {
+ // The zygote has opened new file descriptors since our last inspection.
+ // We warn about this condition and add them to our table.
+ //
+ // TODO(narayan): This will be an error in a future android release.
+ // error = true;
+ // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
+
+ // TODO(narayan): This code will be removed in a future android release.
+ std::set<int>::const_iterator it;
+ for (it = open_fds.begin(); it != open_fds.end(); ++it) {
+ const int fd = (*it);
+ FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+ if (info == NULL) {
+ // A newly opened file is not on the whitelist. Flag an error and
+ // continue.
+ error = true;
+ } else {
+ // Track the newly opened file.
+ open_fd_map_[fd] = info;
+ }
+ }
+ }
+
+ return !error;
+}
+
+// static
+int FileDescriptorTable::ParseFd(dirent* e, int dir_fd) {
+ char* end;
+ const int fd = strtol(e->d_name, &end, 10);
+ if ((*end) != '\0') {
+ return -1;
+ }
+
+ // Don't bother with the standard input/output/error, they're handled
+ // specially post-fork anyway.
+ if (fd <= STDERR_FILENO || fd == dir_fd) {
+ return -1;
+ }
+
+ return fd;
+}
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
new file mode 100644
index 0000000..03298c3
--- /dev/null
+++ b/core/jni/fd_utils.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef FRAMEWORKS_BASE_CORE_JNI_FD_UTILS_H_
+#define FRAMEWORKS_BASE_CORE_JNI_FD_UTILS_H_
+
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <android-base/macros.h>
+
+// Whitelist of open paths that the zygote is allowed to keep open.
+//
+// In addition to the paths listed in kPathWhitelist in file_utils.cpp, and
+// paths dynamically added with Allow(), all files ending with ".jar"
+// under /system/framework" are whitelisted. See IsAllowed() for the canonical
+// definition.
+//
+// If the whitelisted path is associated with a regular file or a
+// character device, the file is reopened after a fork with the same
+// offset and mode. If the whilelisted path is associated with a
+// AF_UNIX socket, the socket will refer to /dev/null after each
+// fork, and all operations on it will fail.
+class FileDescriptorWhitelist {
+ public:
+ // Lazily creates the global whitelist.
+ static FileDescriptorWhitelist* Get();
+
+ // Adds a path to the whitelist.
+ void Allow(const std::string& path) {
+ whitelist_.push_back(path);
+ }
+
+ // Returns true iff. a given path is whitelisted. A path is whitelisted
+ // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
+ // under /system/framework that ends with ".jar" or if it is a system
+ // framework overlay.
+ bool IsAllowed(const std::string& path) const;
+
+ private:
+ FileDescriptorWhitelist();
+
+ static bool StartsWith(const std::string& str, const std::string& prefix);
+
+ static bool EndsWith(const std::string& str, const std::string& suffix);
+
+ static FileDescriptorWhitelist* instance_;
+
+ std::vector<std::string> whitelist_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist);
+};
+
+// Keeps track of all relevant information (flags, offset etc.) of an
+// open zygote file descriptor.
+class FileDescriptorInfo {
+ public:
+ // Create a FileDescriptorInfo for a given file descriptor. Returns
+ // |NULL| if an error occurred.
+ static FileDescriptorInfo* CreateFromFd(int fd);
+
+ // Checks whether the file descriptor associated with this object
+ // refers to the same description.
+ bool Restat() const;
+
+ bool ReopenOrDetach() const;
+
+ const int fd;
+ const struct stat stat;
+ const std::string file_path;
+ const int open_flags;
+ const int fd_flags;
+ const int fs_flags;
+ const off_t offset;
+ const bool is_sock;
+
+ private:
+ FileDescriptorInfo(int fd);
+
+ FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
+ int fd_flags, int fs_flags, off_t offset);
+
+ static bool Readlink(const int fd, std::string* result);
+
+ // Returns the locally-bound name of the socket |fd|. Returns true
+ // iff. all of the following hold :
+ //
+ // - the socket's sa_family is AF_UNIX.
+ // - the length of the path is greater than zero (i.e, not an unnamed socket).
+ // - the first byte of the path isn't zero (i.e, not a socket with an abstract
+ // address).
+ static bool GetSocketName(const int fd, std::string* result);
+
+ bool DetachSocket() const;
+
+ DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
+};
+
+// A FileDescriptorTable is a collection of FileDescriptorInfo objects
+// keyed by their FDs.
+class FileDescriptorTable {
+ public:
+ // Creates a new FileDescriptorTable. This function scans
+ // /proc/self/fd for the list of open file descriptors and collects
+ // information about them. Returns NULL if an error occurs.
+ static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore);
+
+ bool Restat(const std::vector<int>& fds_to_ignore);
+
+ // Reopens all file descriptors that are contained in the table. Returns true
+ // if all descriptors were successfully re-opened or detached, and false if an
+ // error occurred.
+ bool ReopenOrDetach();
+
+ private:
+ FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
+
+ bool RestatInternal(std::set<int>& open_fds);
+
+ static int ParseFd(dirent* e, int dir_fd);
+
+ // Invariant: All values in this unordered_map are non-NULL.
+ std::unordered_map<int, FileDescriptorInfo*> open_fd_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable);
+};
+
+#endif // FRAMEWORKS_BASE_CORE_JNI_FD_UTILS_H_
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 60cf810..048214a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -167,6 +167,8 @@
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
@@ -1230,6 +1232,12 @@
<permission android:name="android.permission.SCORE_NETWORKS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows applications to request network
+ recommendations and scores from the NetworkScoreService.
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
+ android:protectionLevel="signature" />
+
<!-- ======================================= -->
<!-- Permissions for short range, peripheral networks -->
<!-- ======================================= -->
@@ -2046,6 +2054,12 @@
<permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
android:protectionLevel="signature" />
+ <!-- Allows the system to bind to the discovered Network Recommendation Service.
+ @SystemApi @hide -->
+ <permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/>
+
<!-- ========================================= -->
<!-- Permissions for special development tools -->
<!-- ========================================= -->
@@ -2634,7 +2648,10 @@
android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to broadcast privileged networking requests.
- <p>Not for use by third-party applications. @hide -->
+ <p>Not for use by third-party applications.
+ @hide
+ @deprecated Use {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} instead
+ -->
<permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4cf1226..dbc4324 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1280,9 +1280,8 @@
<!-- A list of potential packages, in priority order, that may contain a
network recommendation provider. A network recommendation provider must:
* Be granted the SCORE_NETWORKS permission.
- * Include a Receiver for the android.net.scoring.SCORE_NETWORKS action guarded by the
- BROADCAST_NETWORK_PRIVILEGED permission.
- * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action.
+ * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
+ protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
This may be empty if network scoring and recommending isn't supported.
-->
@@ -2676,4 +2675,7 @@
<!-- An array of packages for which notifications cannot be blocked. -->
<string-array translatable="false" name="config_nonBlockableNotificationPackages" />
+
+ <!-- Component name of the default cell broadcast receiver -->
+ <string name="config_defaultCellBroadcastReceiverComponent" translatable="false">com.android.cellbroadcastreceiver/.PrivilegedCellBroadcastReceiver</string>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5d399c1..38137f8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2912,17 +2912,6 @@
<!-- If there is ever a ringtone set for some setting, but that ringtone can no longer be resolved, t his is shown instead. For example, if the ringtone was on a SD card and it had been removed, this woudl be shown for ringtones on that SD card. -->
<string name="ringtone_unknown">Unknown ringtone</string>
- <!-- A notification is shown when there are open wireless networks nearby. This is the notification's title. -->
- <plurals name="wifi_available">
- <item quantity="one">Wi-Fi network available</item>
- <item quantity="other">Wi-Fi networks available</item>
- </plurals>
- <!-- A notification is shown when there are open wireless networks nearby. This is the notification's message. -->
- <plurals name="wifi_available_detailed">
- <item quantity="one">Open Wi-Fi network available</item>
- <item quantity="other">Open Wi-Fi networks available</item>
- </plurals>
-
<!-- A notification is shown when a wifi captive portal network is detected. This is the notification's title. -->
<string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fe88cd1..9db131b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1787,8 +1787,6 @@
<java-symbol type="layout" name="safe_mode" />
<java-symbol type="layout" name="simple_list_item_2_single_choice" />
<java-symbol type="layout" name="app_error_dialog" />
- <java-symbol type="plurals" name="wifi_available" />
- <java-symbol type="plurals" name="wifi_available_detailed" />
<java-symbol type="string" name="accessibility_binding_label" />
<java-symbol type="string" name="adb_active_notification_message" />
<java-symbol type="string" name="adb_active_notification_title" />
@@ -2739,4 +2737,6 @@
<!-- Network Recommendation -->
<java-symbol type="array" name="config_networkRecommendationPackageNames" />
+
+ <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" />
</resources>
diff --git a/core/tests/coretests/src/android/net/IpPrefixTest.java b/core/tests/coretests/src/android/net/IpPrefixTest.java
index fcc6389..4f2387d 100644
--- a/core/tests/coretests/src/android/net/IpPrefixTest.java
+++ b/core/tests/coretests/src/android/net/IpPrefixTest.java
@@ -18,14 +18,14 @@
import android.net.IpPrefix;
import android.os.Parcel;
-import static android.test.MoreAsserts.assertNotEqual;
import android.test.suitebuilder.annotation.SmallTest;
-
-import static org.junit.Assert.assertArrayEquals;
import java.net.InetAddress;
import java.util.Random;
import junit.framework.TestCase;
+import static android.test.MoreAsserts.assertNotEqual;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
public class IpPrefixTest extends TestCase {
@@ -242,25 +242,42 @@
@SmallTest
public void testHashCode() {
- IpPrefix p;
- int oldCode = -1;
+ IpPrefix p = new IpPrefix(new byte[4], 0);
Random random = new Random();
for (int i = 0; i < 100; i++) {
+ final IpPrefix oldP = p;
if (random.nextBoolean()) {
// IPv4.
byte[] b = new byte[4];
random.nextBytes(b);
p = new IpPrefix(b, random.nextInt(33));
- assertNotEqual(oldCode, p.hashCode());
- oldCode = p.hashCode();
} else {
// IPv6.
byte[] b = new byte[16];
random.nextBytes(b);
p = new IpPrefix(b, random.nextInt(129));
- assertNotEqual(oldCode, p.hashCode());
- oldCode = p.hashCode();
}
+ if (p.equals(oldP)) {
+ assertEquals(p.hashCode(), oldP.hashCode());
+ }
+ if (p.hashCode() != oldP.hashCode()) {
+ assertNotEqual(p, oldP);
+ }
+ }
+ }
+
+ @SmallTest
+ public void testHashCodeIsNotConstant() {
+ IpPrefix[] prefixes = {
+ new IpPrefix("2001:db8:f00::ace:d00d/127"),
+ new IpPrefix("192.0.2.0/23"),
+ new IpPrefix("::/0"),
+ new IpPrefix("0.0.0.0/0"),
+ };
+ for (int i = 0; i < prefixes.length; i++) {
+ for (int j = i + 1; j < prefixes.length; j++) {
+ assertNotEqual(prefixes[i].hashCode(), prefixes[j].hashCode());
+ }
}
}
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 5bfff26..29020ba 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -169,6 +169,25 @@
assertNull(activeScorer);
}
+ public void testIsCallerActiveScorer_providerNotAvailable() throws Exception {
+ ContentResolver cr = mTargetContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
+
+ assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(924));
+ }
+
+ public void testIsCallerActiveScorer_providerAvailable() throws Exception {
+ setNetworkRecommendationPackageNames("package1");
+ mockScoreNetworksGranted("package1");
+ mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
+
+ ContentResolver cr = mTargetContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
+
+ assertTrue(mNetworkScorerAppManager.isCallerActiveScorer(924));
+ assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(925));
+ }
+
private void setNetworkRecommendationPackageNames(String... names) {
if (names == null) {
names = new String[0];
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
index 9c3346e..e818c56 100644
--- a/core/tests/coretests/src/android/net/ScoredNetworkTest.java
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -166,4 +166,52 @@
assertTrue(newNetwork.meteredHint);
assertNull(newNetwork.attributes);
}
+
+ @Test
+ public void calculateBadgeShouldReturnNoBadgeWhenNoAttributesBundle() {
+ ScoredNetwork network = new ScoredNetwork(KEY, CURVE);
+ assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnNoBadgeWhenNoBadgingCurveInBundle() {
+ ScoredNetwork network = new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES);
+ assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturn4kBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_4K);
+ assertEquals(ScoredNetwork.BADGING_4K, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnHdBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_HD);
+ assertEquals(ScoredNetwork.BADGING_HD, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnSdBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_SD);
+ assertEquals(ScoredNetwork.BADGING_SD, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnNoBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_NONE);
+ assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+ }
+
+ private ScoredNetwork buildScoredNetworkWithGivenBadgeForTestRssi(int badge) {
+ RssiCurve badgingCurve =
+ new RssiCurve(RSSI_START, 10, new byte[] {0, 0, 0, 0, 0, 0, (byte) badge});
+ Bundle attr = new Bundle();
+ attr.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, badgingCurve);
+ return new ScoredNetwork(KEY, CURVE, false /* meteredHint */, attr);
+ }
}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 9b2b9f1..836ede6 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -23,7 +23,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 8
LOCAL_PACKAGE_NAME := MultiDexLegacyAndException
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index 874263f..2915914 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -23,7 +23,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 8
LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp
@@ -45,7 +45,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 8
LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 5d6b3a8..1f1939c 100755
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -294,7 +294,7 @@
skuList.add("premiumUpgrade");
skuList.add("gas");
Bundle querySkus = new Bundle();
-querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
+querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
</pre>
<p>
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index ba4a4ff..76a430e 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -16,14 +16,13 @@
#define LOG_TAG "backup_data"
-#include <androidfw/BackupHelpers.h>
-#include <utils/ByteOrder.h>
-
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <cutils/log.h>
+#include <androidfw/BackupHelpers.h>
+#include <log/log.h>
+#include <utils/ByteOrder.h>
namespace android {
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index 78e9d91..8bfe2b6 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -18,23 +18,22 @@
#include <androidfw/BackupHelpers.h>
-#include <utils/KeyedVector.h>
-#include <utils/ByteOrder.h>
-#include <utils/String8.h>
-
#include <errno.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/stat.h>
-#include <sys/time.h> // for utimes
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h> // for utimes
+#include <sys/uio.h>
#include <unistd.h>
#include <utime.h>
-#include <fcntl.h>
#include <zlib.h>
-#include <cutils/log.h>
+#include <log/log.h>
+#include <utils/ByteOrder.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
namespace android {
diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
index 8a2979a..f543565 100644
--- a/libs/androidfw/include/androidfw/CursorWindow.h
+++ b/libs/androidfw/include/androidfw/CursorWindow.h
@@ -17,11 +17,11 @@
#ifndef _ANDROID__DATABASE_WINDOW_H
#define _ANDROID__DATABASE_WINDOW_H
-#include <cutils/log.h>
#include <stddef.h>
#include <stdint.h>
#include <binder/Parcel.h>
+#include <log/log.h>
#include <utils/String8.h>
#if LOG_NDEBUG
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 9d5860c..f5bb821 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -142,7 +142,7 @@
}
uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
- uint32_t dirtyMask;
+ uint32_t dirtyMask = 0;
AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 6d5833b..2b4fe17 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -16,7 +16,7 @@
#include "DamageAccumulator.h"
-#include <cutils/log.h>
+#include <log/log.h>
#include "RenderNode.h"
#include "utils/MathUtils.h"
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 4cfbb2a..ff3ee22 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -13,16 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include <DeviceInfo.h>
#include "Extensions.h"
-#include <GLES2/gl2.h>
-#include <log/log.h>
-
#include <thread>
#include <mutex>
+#include <log/log.h>
+
+#include <GLES2/gl2.h>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h
index bfb1bf1..352f3d7 100644
--- a/libs/hwui/GpuMemoryTracker.h
+++ b/libs/hwui/GpuMemoryTracker.h
@@ -15,10 +15,11 @@
*/
#pragma once
-#include <cutils/log.h>
#include <pthread.h>
#include <ostream>
+#include <log/log.h>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index cc47f00..9af8eeb 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -16,10 +16,11 @@
#include "Interpolator.h"
-#include "utils/MathUtils.h"
-
#include <algorithm>
-#include <cutils/log.h>
+
+#include <log/log.h>
+
+#include "utils/MathUtils.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index ed6b211..2132c2b 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -13,21 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "JankTracker.h"
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <limits>
+
+#include <cutils/ashmem.h>
+#include <log/log.h>
+
#include "Properties.h"
#include "utils/TimeUtils.h"
-#include <algorithm>
-#include <cutils/ashmem.h>
-#include <cutils/log.h>
-#include <cstdio>
-#include <errno.h>
-#include <inttypes.h>
-#include <limits>
-#include <cmath>
-#include <sys/mman.h>
-
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
index bbef36b..280af87 100644
--- a/libs/hwui/PixelBuffer.h
+++ b/libs/hwui/PixelBuffer.h
@@ -18,7 +18,8 @@
#define ANDROID_HWUI_PIXEL_BUFFER_H
#include <GLES3/gl3.h>
-#include <cutils/log.h>
+
+#include <log/log.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 6f68c2b..c1e2e5e 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "Properties.h"
-
#include "Debug.h"
-#include <cutils/compiler.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
#include <algorithm>
#include <cstdlib>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <log/log.h>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 9df32b28..5db5efb 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -16,7 +16,10 @@
#include "SkiaCanvasProxy.h"
-#include <cutils/log.h>
+#include <memory>
+
+#include <log/log.h>
+
#include <SkPatchUtils.h>
#include <SkPaint.h>
#include <SkPath.h>
@@ -24,8 +27,6 @@
#include <SkRect.h>
#include <SkRRect.h>
-#include <memory>
-
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index a455f57..159a144 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -16,9 +16,10 @@
#include "MinikinSkia.h"
+#include <log/log.h>
+
#include <SkPaint.h>
#include <SkTypeface.h>
-#include <cutils/log.h>
namespace android {
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 67b775d..eda94bf 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -13,15 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "MinikinUtils.h"
+#include <string>
+
+#include <log/log.h>
+
#include "Paint.h"
#include "SkPathMeasure.h"
#include "Typeface.h"
-#include <cutils/log.h>
-#include <string>
-
namespace android {
FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index ac6a28f..99bc9a7 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -16,16 +16,18 @@
#include "EglManager.h"
+#include <string>
+
+#include "utils/StringUtils.h"
+#include <cutils/properties.h>
+#include <log/log.h>
+
#include "Caches.h"
#include "DeviceInfo.h"
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
-#include "utils/StringUtils.h"
-#include <cutils/log.h>
-#include <cutils/properties.h>
#include <EGL/eglext.h>
-#include <string>
#define GLES_VERSION 2
@@ -134,7 +136,12 @@
void EglManager::initExtensions() {
auto extensions = StringUtils::split(
eglQueryString(mEglDisplay, EGL_EXTENSIONS));
- EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age");
+ // For our purposes we don't care if EGL_BUFFER_AGE is a result of
+ // EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
+ // under EGL_KHR_partial_update and we don't need the expanded scope
+ // that EGL_EXT_buffer_age provides.
+ EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age")
+ || extensions.has("EGL_KHR_partial_update");
EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update");
LOG_ALWAYS_FATAL_IF(!extensions.has("EGL_KHR_swap_buffers_with_damage"),
"Missing required extension EGL_KHR_swap_buffers_with_damage");
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index c5af061..6533c2e 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -22,8 +22,8 @@
#include "renderthread/RenderProxy.h"
#include "renderthread/RenderTask.h"
-#include <cutils/log.h>
#include <gui/Surface.h>
+#include <log/log.h>
#include <ui/PixelFormat.h>
using namespace android;
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
index b49c1eb..f8dfe10 100644
--- a/libs/hwui/utils/GLUtils.h
+++ b/libs/hwui/utils/GLUtils.h
@@ -18,7 +18,7 @@
#include "Debug.h"
-#include <cutils/log.h>
+#include <log/log.h>
namespace android {
namespace uirenderer {
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index abef66f..07bcbd3 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -15,7 +15,6 @@
*/
#define LOG_TAG "PointerController"
-
//#define LOG_NDEBUG 0
// Log debug messages about pointer updates
@@ -23,8 +22,9 @@
#include "PointerController.h"
-#include <cutils/log.h>
+#include <log/log.h>
+// ToDo: Fix code to be warning free
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <SkBitmap.h>
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 0bc832a..049b76e 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -15,15 +15,15 @@
*/
#define LOG_TAG "Sprites"
-
//#define LOG_NDEBUG 0
#include "SpriteController.h"
-#include <cutils/log.h>
+#include <log/log.h>
#include <utils/String8.h>
#include <gui/Surface.h>
+// ToDo: Fix code to be warning free
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <SkBitmap.h>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 33c1c3f..ce75bb49 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3278,6 +3278,20 @@
return delay;
}
+ /**
+ * Indicate A2DP device configuration has changed.
+ * @param device Bluetooth device whose configuration has changed.
+ * {@hide}
+ */
+ public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) {
+ IAudioService service = getService();
+ try {
+ service.handleBluetoothA2dpDeviceConfigChange(device);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** {@hide} */
public IRingtonePlayer getRingtonePlayer() {
try {
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index f597440..8a28255 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -678,6 +678,9 @@
public static native int setDeviceConnectionState(int device, int state,
String device_address, String device_name);
public static native int getDeviceConnectionState(int device, String device_address);
+ public static native int handleDeviceConfigChange(int device,
+ String device_address,
+ String device_name);
public static native int setPhoneState(int state);
public static native int setForceUse(int usage, int config);
public static native int getForceUse(int usage);
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index c7931fc..9e5ac72 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -133,6 +133,8 @@
int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile);
+ void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
+
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
boolean isCameraSoundForced();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 949acc0..d0f8b73b 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2336,10 +2336,7 @@
}
private void scanInternalSubtitleTracks() {
- if (mSubtitleController == null) {
- Log.d(TAG, "setSubtitleAnchor in MediaPlayer");
- setSubtitleAnchor();
- }
+ setSubtitleAnchor();
populateInbandTracks();
diff --git a/media/mca/filterpacks/native/base/geometry.cpp b/media/mca/filterpacks/native/base/geometry.cpp
index 7812d502..44b13e4 100644
--- a/media/mca/filterpacks/native/base/geometry.cpp
+++ b/media/mca/filterpacks/native/base/geometry.cpp
@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "geometry"
-#include <cutils/log.h>
#include <cmath>
+#include <log/log.h>
+
#include "geometry.h"
namespace android {
diff --git a/media/mca/filterpacks/native/base/time_util.cpp b/media/mca/filterpacks/native/base/time_util.cpp
index 1a78a95..7d383df 100644
--- a/media/mca/filterpacks/native/base/time_util.cpp
+++ b/media/mca/filterpacks/native/base/time_util.cpp
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "time_util"
#include "time_util.h"
#include "utilities.h"
-#include <cutils/log.h>
#include <sys/time.h>
#include <map>
+#include <log/log.h>
+
namespace android {
namespace filterfw {
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 33c9655..5843637 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -17,4 +17,5 @@
name: "libandroid.ndk",
symbol_file: "libandroid.map.txt",
first_version: "9",
+ unversioned_until: "current",
}
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index e09b0b4..17feb53 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -17,4 +17,5 @@
name: "libjnigraphics.ndk",
symbol_file: "libjnigraphics.map.txt",
first_version: "9",
+ unversioned_until: "current",
}
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index bb8eb2c..23a8655 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -55,12 +55,15 @@
import java.util.Random;
public class CaptivePortalLoginActivity extends Activity {
- private static final String TAG = "CaptivePortalLogin";
+ private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
+ private static final boolean DBG = true;
+
private static final int SOCKET_TIMEOUT_MS = 10000;
private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
- private URL mURL;
+ private URL mUrl;
+ private String mUserAgent;
private Network mNetwork;
private CaptivePortal mCaptivePortal;
private NetworkCallback mNetworkCallback;
@@ -72,17 +75,20 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCm = ConnectivityManager.from(this);
- String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
- if (url == null) url = mCm.getCaptivePortalServerUrl();
- try {
- mURL = new URL(url);
- } catch (MalformedURLException e) {
- // System misconfigured, bail out in a way that at least provides network access.
- Log.e(TAG, "Invalid captive portal URL, url=" + url);
- done(Result.WANTED_AS_IS);
- }
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
+ mUserAgent = getIntent().getParcelableExtra(
+ ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
+ mUrl = getUrl();
+ if (mUrl == null) {
+ // getUrl() failed to parse the url provided in the intent: bail out in a way that
+ // at least provides network access.
+ done(Result.WANTED_AS_IS);
+ return;
+ }
+ if (DBG) {
+ Log.d(TAG, String.format("onCreate for %s", mUrl.toString()));
+ }
// Also initializes proxy system properties.
mCm.bindProcessToNetwork(mNetwork);
@@ -149,6 +155,9 @@
}
private void done(Result result) {
+ if (DBG) {
+ Log.d(TAG, String.format("Result %s for %s", result.name(), mUrl.toString()));
+ }
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
mNetworkCallback = null;
@@ -185,22 +194,31 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
- if (id == R.id.action_use_network) {
- done(Result.WANTED_AS_IS);
- return true;
+ final Result result;
+ final String action;
+ final int id = item.getItemId();
+ switch (id) {
+ case R.id.action_use_network:
+ result = Result.WANTED_AS_IS;
+ action = "USE_NETWORK";
+ break;
+ case R.id.action_do_not_use_network:
+ result = Result.UNWANTED;
+ action = "DO_NOT_USE_NETWORK";
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
}
- if (id == R.id.action_do_not_use_network) {
- done(Result.UNWANTED);
- return true;
+ if (DBG) {
+ Log.d(TAG, String.format("onOptionsItemSelect %s for %s", action, mUrl.toString()));
}
- return super.onOptionsItemSelected(item);
+ done(result);
+ return true;
}
@Override
public void onDestroy() {
super.onDestroy();
-
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
mNetworkCallback = null;
@@ -215,11 +233,29 @@
} catch (InterruptedException e) {
}
}
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mURL.toString())));
+ final String url = mUrl.toString();
+ if (DBG) {
+ Log.d(TAG, "starting activity with intent ACTION_VIEW for " + url);
+ }
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
}
+ private URL getUrl() {
+ String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
+ if (url == null) {
+ url = mCm.getCaptivePortalServerUrl();
+ }
+ try {
+ return new URL(url);
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "Invalid captive portal URL " + url);
+ }
+ return null;
+ }
+
private void testForCaptivePortal() {
+ // TODO: reuse NetworkMonitor facilities for consistent captive portal detection.
new Thread(new Runnable() {
public void run() {
// Give time for captive portal to open.
@@ -230,11 +266,14 @@
HttpURLConnection urlConnection = null;
int httpResponseCode = 500;
try {
- urlConnection = (HttpURLConnection) mURL.openConnection();
+ urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setUseCaches(false);
+ if (mUserAgent != null) {
+ urlConnection.setRequestProperty("User-Agent", mUserAgent);
+ }
urlConnection.getInputStream();
httpResponseCode = urlConnection.getResponseCode();
} catch (IOException e) {
@@ -292,7 +331,7 @@
// settings. Now prompt the WebView read the Network-specific proxy settings.
setWebViewProxy();
// Load the real page.
- view.loadUrl(mURL.toString());
+ view.loadUrl(mUrl.toString());
return;
} else if (mPagesLoaded == 2) {
// Prevent going back to empty first page.
diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk
new file mode 100644
index 0000000..82be132
--- /dev/null
+++ b/packages/CarrierDefaultApp/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CarrierDefaultApp
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+# This finds and builds the test apk as well, so a single make does both.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
new file mode 100644
index 0000000..28d9e5c
--- /dev/null
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.carrierdefaultapp"
+ android:sharedUserId="android.uid.phone" >
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application android:label="@string/app_name" >
+ <receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.CARRIER_SIGNAL_REDIRECTED" />
+ </intent-filter>
+ </receiver>
+ <activity android:name="com.android.carrierdefaultapp.CaptivePortalLaunchActivity"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
+ android:excludeFromRecents="true"/>
+ </application>
+</manifest>
diff --git a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
new file mode 100644
index 0000000..5896757
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2016 Google Inc.
+
+ 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/glif_icon_size"
+ android:height="@dimen/glif_icon_size"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:fillColor="?android:attr/colorPrimary"
+ android:pathData="M39.98,8c0,-2.21 -1.77,-4 -3.98,-4L20,4L8,16v24c0,2.21 1.79,4 4,4h24.02c2.21,0 3.98,-1.79 3.98,-4l-0.02,-32zM18,38h-4v-4h4v4zM34,38h-4v-4h4v4zM18,30h-4v-8h4v8zM26,38h-4v-8h4v8zM26,26h-4v-4h4v4zM34,30h-4v-8h4v8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/CarrierDefaultApp/res/values/dimens.xml b/packages/CarrierDefaultApp/res/values/dimens.xml
new file mode 100644
index 0000000..a3c5049
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values/dimens.xml
@@ -0,0 +1,3 @@
+<resources>
+ <dimen name="glif_icon_size">32dp</dimen>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
new file mode 100644
index 0000000..838ff39
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">CarrierDefaultApp</string>
+ <string name="portal_notification_id">Activate your service</string>
+ <string name="no_data_notification_id">No data service</string>
+ <string name="portal_notification_detail">Tap to activate your service</string>
+ <string name="no_data_notification_detail">No Service, please contact your service provider</string>
+ <string name="progress_dialogue_network_connection">Connecting to captive portal...</string>
+ <string name="alert_dialogue_network_timeout">Network timeout, would you like to retry?</string>
+ <string name="alert_dialogue_network_timeout_title">Network unavailable</string>
+ <string name="quit">Quit</string>
+ <string name="wait">Wait</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values/styles.xml b/packages/CarrierDefaultApp/res/values/styles.xml
new file mode 100644
index 0000000..3d26915
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values/styles.xml
@@ -0,0 +1,3 @@
+<resources>
+ <style name="AlertDialog" parent="android:Theme.Material.Light.Dialog.Alert"/>
+</resources>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
new file mode 100644
index 0000000..b7fde12
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 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.carrierdefaultapp;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.CaptivePortal;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+import android.os.Bundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
+import android.net.ICaptivePortal;
+import android.view.ContextThemeWrapper;
+import android.view.WindowManager;
+import com.android.carrierdefaultapp.R;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.ArrayUtils;
+
+import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
+
+/**
+ * Activity that launches in response to the captive portal notification
+ * @see com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
+ * This activity requests network connection if there is no available one, launches the
+ * {@link com.android.captiveportallogin portalApp} and keeps track of the portal activation result.
+ */
+public class CaptivePortalLaunchActivity extends Activity {
+ private static final String TAG = CaptivePortalLaunchActivity.class.getSimpleName();
+ private static final boolean DBG = true;
+ public static final int NETWORK_REQUEST_TIMEOUT_IN_MS = 5 * 1000;
+
+ private ConnectivityManager mCm = null;
+ private ConnectivityManager.NetworkCallback mCb = null;
+ /* Progress dialogue when request network connection for captive portal */
+ private AlertDialog mProgressDialog = null;
+ /* Alert dialogue when network request is timeout */
+ private AlertDialog mAlertDialog = null;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCm = ConnectivityManager.from(this);
+ // Check network connection before loading portal
+ Network network = getNetworkForCaptivePortal();
+ NetworkInfo nwInfo = mCm.getNetworkInfo(network);
+ if (nwInfo == null || !nwInfo.isConnected()) {
+ if (DBG) logd("Network unavailable, request restricted connection");
+ requestNetwork(getIntent());
+ } else {
+ launchCaptivePortal(getIntent(), network);
+ }
+ }
+
+ // show progress dialog during network connecting
+ private void showConnectingProgressDialog() {
+ mProgressDialog = new ProgressDialog(getApplicationContext());
+ mProgressDialog.setMessage(getString(R.string.progress_dialogue_network_connection));
+ mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mProgressDialog.show();
+ }
+
+ // if network request is timeout, show alert dialog with two option: cancel & wait
+ private void showConnectionTimeoutAlertDialog() {
+ mAlertDialog = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AlertDialog))
+ .setMessage(getString(R.string.alert_dialogue_network_timeout))
+ .setTitle(getString(R.string.alert_dialogue_network_timeout_title))
+ .setNegativeButton(getString(R.string.quit),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // cancel
+ dismissDialog(mAlertDialog);
+ finish();
+ }
+ })
+ .setPositiveButton(getString(R.string.wait),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // wait, request network again
+ dismissDialog(mAlertDialog);
+ requestNetwork(getIntent());
+ }
+ })
+ .create();
+ mAlertDialog.show();
+ }
+
+ private void requestNetwork(final Intent intent) {
+ NetworkRequest request = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .build();
+
+ mCb = new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ if (DBG) logd("Network available: " + network);
+ dismissDialog(mProgressDialog);
+ mCm.bindProcessToNetwork(network);
+ launchCaptivePortal(intent, network);
+ }
+
+ @Override
+ public void onUnavailable() {
+ if (DBG) logd("Network unavailable");
+ dismissDialog(mProgressDialog);
+ showConnectionTimeoutAlertDialog();
+ }
+ };
+ showConnectingProgressDialog();
+ mCm.requestNetwork(request, mCb, NETWORK_REQUEST_TIMEOUT_IN_MS);
+ }
+
+ private void releaseNetworkRequest() {
+ logd("release Network Request");
+ if (mCb != null) {
+ mCm.unregisterNetworkCallback(mCb);
+ mCb = null;
+ }
+ }
+
+ private void dismissDialog(AlertDialog dialog) {
+ if (dialog != null) {
+ dialog.dismiss();
+ }
+ }
+
+ private Network getNetworkForCaptivePortal() {
+ Network[] info = mCm.getAllNetworks();
+ if (!ArrayUtils.isEmpty(info)) {
+ for (Network nw : info) {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(nw);
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ return nw;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void launchCaptivePortal(final Intent intent, Network network) {
+ String redirectUrl = intent.getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ if (TextUtils.isEmpty(redirectUrl) || !matchUrl(redirectUrl, subId)) {
+ loge("Launch portal fails due to incorrect redirection URL: " +
+ Rlog.pii(TAG, redirectUrl));
+ return;
+ }
+ final Intent portalIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
+ portalIntent.putExtra(ConnectivityManager.EXTRA_NETWORK, network);
+ portalIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
+ new CaptivePortal(new ICaptivePortal.Stub() {
+ @Override
+ public void appResponse(int response) {
+ logd("portal response code: " + response);
+ releaseNetworkRequest();
+ if (response == APP_RETURN_DISMISSED) {
+ // Upon success http response code, trigger re-evaluation
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_ENABLE_RADIO, intent,
+ getApplicationContext());
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_ENABLE_METERED_APNS, intent,
+ getApplicationContext());
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS,
+ intent, getApplicationContext());
+ }
+ }
+ }));
+ portalIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, redirectUrl);
+ portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ if (DBG) logd("launching portal");
+ startActivity(portalIntent);
+ finish();
+ }
+
+ // match configured redirection url
+ private boolean matchUrl(String url, int subId) {
+ CarrierConfigManager configManager = getApplicationContext()
+ .getSystemService(CarrierConfigManager.class);
+ String[] redirectURLs = configManager.getConfigForSubId(subId).getStringArray(
+ CarrierConfigManager.KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY);
+ if (ArrayUtils.isEmpty(redirectURLs)) {
+ if (DBG) logd("match is unnecessary without any configured redirection url");
+ return true;
+ }
+ for (String redirectURL : redirectURLs) {
+ if (url.startsWith(redirectURL)) {
+ return true;
+ }
+ }
+ if (DBG) loge("no match found for configured redirection url");
+ return false;
+ }
+
+ private static void logd(String s) {
+ Rlog.d(TAG, s);
+ }
+
+ private static void loge(String s) {
+ Rlog.d(TAG, s);
+ }
+}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
new file mode 100644
index 0000000..db4890f
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 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.carrierdefaultapp;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.carrierdefaultapp.R;
+/**
+ * This util class provides common logic for carrier actions
+ */
+public class CarrierActionUtils {
+ private static final String TAG = CarrierActionUtils.class.getSimpleName();
+
+ private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
+ private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
+ private static final int PORTAL_NOTIFICATION_ID = 0;
+ private static final int NO_DATA_NOTIFICATION_ID = 1;
+ private static boolean ENABLE = true;
+
+ // A list of supported carrier action idx
+ public static final int CARRIER_ACTION_ENABLE_METERED_APNS = 0;
+ public static final int CARRIER_ACTION_DISABLE_METERED_APNS = 1;
+ public static final int CARRIER_ACTION_DISABLE_RADIO = 2;
+ public static final int CARRIER_ACTION_ENABLE_RADIO = 3;
+ public static final int CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION = 4;
+ public static final int CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION = 5;
+ public static final int CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS = 6;
+
+ public static void applyCarrierAction(int actionIdx, Intent intent, Context context) {
+ switch (actionIdx) {
+ case CARRIER_ACTION_ENABLE_METERED_APNS:
+ onEnableAllMeteredApns(intent, context);
+ break;
+ case CARRIER_ACTION_DISABLE_METERED_APNS:
+ onDisableAllMeteredApns(intent, context);
+ break;
+ case CARRIER_ACTION_DISABLE_RADIO:
+ onDisableRadio(intent, context);
+ break;
+ case CARRIER_ACTION_ENABLE_RADIO:
+ onEnableRadio(intent, context);
+ break;
+ case CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION:
+ onShowCaptivePortalNotification(intent, context);
+ break;
+ case CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION:
+ onShowNoDataServiceNotification(context);
+ break;
+ case CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS:
+ onCancelAllNotifications(context);
+ break;
+ default:
+ loge("unsupported carrier action index: " + actionIdx);
+ }
+ }
+
+ private static void onDisableAllMeteredApns(Intent intent, Context context) {
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ logd("onDisableAllMeteredApns subId: " + subId);
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ telephonyMgr.carrierActionSetMeteredApnsEnabled(subId, !ENABLE);
+ }
+
+ private static void onEnableAllMeteredApns(Intent intent, Context context) {
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ logd("onEnableAllMeteredApns subId: " + subId);
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ telephonyMgr.carrierActionSetMeteredApnsEnabled(subId, ENABLE);
+ }
+
+ private static void onDisableRadio(Intent intent, Context context) {
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ logd("onDisableRadio subId: " + subId);
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ telephonyMgr.carrierActionSetRadioEnabled(subId, !ENABLE);
+ }
+
+ private static void onEnableRadio(Intent intent, Context context) {
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ logd("onEnableRadio subId: " + subId);
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ telephonyMgr.carrierActionSetRadioEnabled(subId, ENABLE);
+ }
+
+ private static void onShowCaptivePortalNotification(Intent intent, Context context) {
+ logd("onShowCaptivePortalNotification");
+ final NotificationManager notificationMgr = context.getSystemService(
+ NotificationManager.class);
+ Intent portalIntent = new Intent(context, CaptivePortalLaunchActivity.class);
+ portalIntent.putExtras(intent);
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ Notification notification = getNotification(context, R.string.portal_notification_id,
+ R.string.portal_notification_detail, pendingIntent);
+ try {
+ notificationMgr.notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
+ } catch (NullPointerException npe) {
+ loge("setNotificationVisible: " + npe);
+ }
+ }
+
+ private static void onShowNoDataServiceNotification(Context context) {
+ logd("onShowNoDataServiceNotification");
+ final NotificationManager notificationMgr = context.getSystemService(
+ NotificationManager.class);
+ Notification notification = getNotification(context, R.string.no_data_notification_id,
+ R.string.no_data_notification_detail, null);
+ try {
+ notificationMgr.notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
+ } catch (NullPointerException npe) {
+ loge("setNotificationVisible: " + npe);
+ }
+ }
+
+ private static void onCancelAllNotifications(Context context) {
+ logd("onCancelAllNotifications");
+ final NotificationManager notificationMgr = context.getSystemService(
+ NotificationManager.class);
+ notificationMgr.cancelAll();
+ }
+
+ private static Notification getNotification(Context context, int titleId, int textId,
+ PendingIntent pendingIntent) {
+ Resources resources = context.getResources();
+ Notification.Builder builder = new Notification.Builder(context)
+ .setContentTitle(resources.getString(titleId))
+ .setContentText(resources.getString(textId))
+ .setSmallIcon(R.drawable.ic_sim_card)
+ .setOngoing(true)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setLocalOnly(true)
+ .setWhen(System.currentTimeMillis())
+ .setShowWhen(false);
+
+ if (pendingIntent != null) {
+ builder.setContentIntent(pendingIntent);
+ }
+ return builder.build();
+ }
+
+ private static void logd(String s) {
+ Log.d(TAG, s);
+ }
+
+ private static void loge(String s) {
+ Log.e(TAG, s);
+ }
+}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
new file mode 100644
index 0000000..bc0fa02
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierDefaultBroadcastReceiver.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.carrierdefaultapp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import java.util.List;
+
+public class CarrierDefaultBroadcastReceiver extends BroadcastReceiver{
+ private static final String TAG = CarrierDefaultBroadcastReceiver.class.getSimpleName();
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "onReceive intent: " + intent.getAction());
+ List<Integer> actionList = CustomConfigLoader.loadCarrierActionList(context, intent);
+ for (int actionIdx : actionList) {
+ Log.d(TAG, "apply carrier action idx: " + actionIdx);
+ CarrierActionUtils.applyCarrierAction(actionIdx, intent, context);
+ }
+ }
+}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
new file mode 100644
index 0000000..e1125d9
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016 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.carrierdefaultapp;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.ArrayUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Default carrier app allows carrier customization. OEMs could configure a list
+ * of carrier actions defined in {@link com.android.carrierdefaultapp.CarrierActionUtils
+ * CarrierActionUtils} to act upon certain signal or even different args of the same signal.
+ * This allows different interpretations of the signal between carriers and could easily alter the
+ * app's behavior in a configurable way. This helper class loads and parses the carrier configs
+ * and return a list of predefined carrier actions for the given input signal.
+ */
+public class CustomConfigLoader {
+ // delimiters for parsing carrier configs of the form "arg1, arg2 : action1, action2"
+ private static final String INTRA_GROUP_DELIMITER = "\\s*,\\s*";
+ private static final String INTER_GROUP_DELIMITER = "\\s*:\\s*";
+
+ private static final String TAG = CustomConfigLoader.class.getSimpleName();
+ private static final boolean VDBG = Rlog.isLoggable(TAG, Log.VERBOSE);
+
+ /**
+ * loads and parses the carrier config, return a list of carrier action for the given signal
+ * @param context
+ * @param intent passing signal for config match
+ * @return a list of carrier action for the given signal based on the carrier config.
+ *
+ * Example: input intent TelephonyIntent.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+ * This intent allows fined-grained matching based on both intent type & extra values:
+ * apnType and errorCode.
+ * apnType read from passing intent is "default" and errorCode is 0x26 for example and
+ * returned carrier config from carrier_default_actions_on_redirection_string_array is
+ * {
+ * "default, 0x26:1,4", // 0x26(NETWORK_FAILURE)
+ * "default, 0x70:2,3" // 0x70(APN_TYPE_CONFLICT)
+ * }
+ * [1, 4] // 1(CARRIER_ACTION_DISABLE_METERED_APNS), 4(CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION)
+ * returns as the action index list based on the matching rule.
+ */
+ public static List<Integer> loadCarrierActionList(Context context, Intent intent) {
+ CarrierConfigManager carrierConfigManager = (CarrierConfigManager) context.getSystemService(
+ Context.CARRIER_CONFIG_SERVICE);
+ // return an empty list if no match found
+ List<Integer> actionList = new ArrayList<>();
+ if (carrierConfigManager == null) {
+ Rlog.e(TAG, "load carrier config failure with carrier config manager uninitialized");
+ return actionList;
+ }
+ PersistableBundle b = carrierConfigManager.getConfig();
+ if (b != null) {
+ String[] configs = null;
+ // used for intents which allow fine-grained interpretation based on intent extras
+ String arg1 = null;
+ String arg2 = null;
+ switch (intent.getAction()) {
+ case TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED:
+ configs = b.getStringArray(CarrierConfigManager
+ .KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY);
+ break;
+ case TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED:
+ configs = b.getStringArray(CarrierConfigManager
+ .KEY_CARRIER_DEFAULT_ACTIONS_ON_DCFAILURE_STRING_ARRAY);
+ arg1 = intent.getStringExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY);
+ arg2 = intent.getStringExtra(TelephonyIntents.EXTRA_ERROR_CODE_KEY);
+ break;
+ default:
+ Rlog.e(TAG, "load carrier config failure with un-configured key: " +
+ intent.getAction());
+ break;
+ }
+ if (!ArrayUtils.isEmpty(configs)) {
+ for (String config : configs) {
+ // parse each config until find the matching one
+ matchConfig(config, arg1, arg2, actionList);
+ if (!actionList.isEmpty()) {
+ // return the first match
+ if (VDBG) Rlog.d(TAG, "found match action list: " + actionList.toString());
+ return actionList;
+ }
+ }
+ }
+ Rlog.d(TAG, "no matching entry for signal: " + intent.getAction() + "arg1: " + arg1
+ + "arg2: " + arg2);
+ }
+ return actionList;
+ }
+
+ /**
+ * Match based on the config's format and input args
+ * passing arg1, arg2 should match the format of the config
+ * case 1: config {actionIdx1, actionIdx2...} arg1 and arg2 must be null
+ * case 2: config {arg1, arg2 : actionIdx1, actionIdx2...} requires full match of non-null args
+ * case 3: config {arg1 : actionIdx1, actionIdx2...} only need to match arg1
+ *
+ * @param config action list config obtained from CarrierConfigManager
+ * @param arg1 first intent argument, set if required for config match
+ * @param arg2 second intent argument, set if required for config match
+ * @param actionList append each parsed action to the passing list
+ */
+ private static void matchConfig(String config, String arg1, String arg2,
+ List<Integer> actionList) {
+ String[] splitStr = config.trim().split(INTER_GROUP_DELIMITER, 2);
+ String actionStr = null;
+
+ if (splitStr.length == 1 && arg1 == null && arg2 == null) {
+ // case 1
+ actionStr = splitStr[0];
+ } else if (splitStr.length == 2 && arg1 != null && arg2 != null) {
+ // case 2
+ String[] args = splitStr[0].split(INTRA_GROUP_DELIMITER);
+ if (args.length == 2 && TextUtils.equals(arg1, args[0]) &&
+ TextUtils.equals(arg2, args[1])) {
+ actionStr = splitStr[1];
+ }
+ } else if ((splitStr.length == 2) && (arg1 != null) && (arg2 == null)) {
+ // case 3
+ String[] args = splitStr[0].split(INTRA_GROUP_DELIMITER);
+ if (args.length == 1 && TextUtils.equals(arg1, args[0])) {
+ actionStr = splitStr[1];
+ }
+ }
+ // convert from string -> action idx list if found a matching entry
+ String[] actions = null;
+ if (!TextUtils.isEmpty(actionStr)) {
+ actions = actionStr.split(INTRA_GROUP_DELIMITER);
+ }
+ if (!ArrayUtils.isEmpty(actions)) {
+ for (String idx : actions) {
+ try {
+ actionList.add(Integer.parseInt(idx));
+ } catch (NumberFormatException e) {
+ Rlog.e(TAG, "NumberFormatException(string: " + idx + " config:" + config + "): "
+ + e);
+ }
+ }
+ }
+ }
+}
diff --git a/packages/CarrierDefaultApp/tests/Android.mk b/packages/CarrierDefaultApp/tests/Android.mk
new file mode 100644
index 0000000..6ebb575
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/Android.mk
@@ -0,0 +1,25 @@
+# Copyright 2016, 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CERTIFICATE := platform
+
+# Include all makefiles in subdirectories
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+
+
+
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
new file mode 100644
index 0000000..092df50
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/Android.mk
@@ -0,0 +1,34 @@
+# Copyright 2016, 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target-minus-junit4
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CarrierDefaultAppUnitTests
+
+LOCAL_INSTRUMENTATION_FOR := CarrierDefaultApp
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/CarrierDefaultApp/tests/unit/AndroidManifest.xml b/packages/CarrierDefaultApp/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..3a06a09
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.carrierdefaultapp.tests.unit">
+ <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.carrierdefaultapp"
+ android:label="CarrierDefaultApp Unit Test Cases">
+ </instrumentation>
+</manifest>
+
+
+
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultActivityTestCase.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultActivityTestCase.java
new file mode 100644
index 0000000..c5a1243
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultActivityTestCase.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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.carrierdefaultapp;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.test.ActivityUnitTestCase;
+import android.util.Log;
+
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+
+public class CarrierDefaultActivityTestCase<T extends Activity> extends ActivityUnitTestCase<T> {
+
+ protected TestContext mContext;
+
+ private T mActivity;
+
+ CarrierDefaultActivityTestCase(Class<T> activityClass) {
+ super(activityClass);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext(getInstrumentation().getTargetContext());
+ setActivityContext(mContext);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ protected T startActivity() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity = startActivity(createActivityIntent(), null, null);
+ }
+ });
+ return mActivity;
+ }
+
+ protected void stopActivity() throws Exception {
+ getInstrumentation().callActivityOnStop(mActivity);
+ }
+
+ protected Intent createActivityIntent() {
+ Intent intent = new Intent();
+ return intent;
+ }
+
+ protected <S> void injectSystemService(Class<S> cls, S service) {
+ mContext.injectSystemService(cls, service);
+ }
+}
\ No newline at end of file
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
new file mode 100644
index 0000000..f9dbcd4
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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.carrierdefaultapp;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+import android.telephony.TelephonyManager;
+import android.test.InstrumentationTestCase;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class CarrierDefaultReceiverTest extends InstrumentationTestCase {
+ @Mock
+ private NotificationManager mNotificationMgr;
+ @Mock
+ private TelephonyManager mTelephonyMgr;
+ @Mock
+ private CarrierConfigManager mCarrierConfigMgr;
+ @Captor
+ private ArgumentCaptor<Integer> mInt;
+ @Captor
+ private ArgumentCaptor<Notification> mNotification;
+ @Captor
+ private ArgumentCaptor<String> mString;
+ private TestContext mContext;
+ private CarrierDefaultBroadcastReceiver mReceiver;
+ private static String TAG;
+
+ private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
+ private static final int PORTAL_NOTIFICATION_ID = 0;
+ private static int subId = 0;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ TAG = this.getClass().getSimpleName();
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext(getInstrumentation().getTargetContext());
+ mContext.injectSystemService(NotificationManager.class, mNotificationMgr);
+ mContext.injectSystemService(TelephonyManager.class, mTelephonyMgr);
+ mContext.injectSystemService(CarrierConfigManager.class, mCarrierConfigMgr);
+
+ mReceiver = new CarrierDefaultBroadcastReceiver();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void testOnReceiveRedirection() {
+ // carrier action idx list includes 4(portal notification) & 1(disable metered APNs)
+ // upon redirection signal
+ PersistableBundle b = new PersistableBundle();
+ b.putStringArray(CarrierConfigManager
+ .KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY, new String[]{"4,1"});
+ doReturn(b).when(mCarrierConfigMgr).getConfig();
+
+ Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
+ intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ Rlog.d(TAG, "OnReceive redirection intent");
+ mReceiver.onReceive(mContext, intent);
+
+ mContext.waitForMs(100);
+
+ Rlog.d(TAG, "verify carrier action: showPortalNotification");
+ verify(mNotificationMgr, times(1)).notify(mString.capture(), mInt.capture(),
+ mNotification.capture());
+ assertEquals(PORTAL_NOTIFICATION_ID, (int) mInt.getValue());
+ assertEquals(PORTAL_NOTIFICATION_TAG, mString.getValue());
+ PendingIntent pendingIntent = mNotification.getValue().contentIntent;
+ assertNotNull(pendingIntent);
+
+ Rlog.d(TAG, "verify carrier action: disable all metered apns");
+ verify(mTelephonyMgr).carrierActionSetMeteredApnsEnabled(eq(subId), eq(false));
+ }
+}
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java
new file mode 100644
index 0000000..8a18d72
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java
@@ -0,0 +1,108 @@
+package com.android.carrierdefaultapp;
+
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+
+import com.android.internal.telephony.TelephonyIntents;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class LaunchCaptivePortalActivityTest extends
+ CarrierDefaultActivityTestCase<CaptivePortalLaunchActivity> {
+
+ @Mock
+ private ConnectivityManager mCm;
+ @Mock
+ private NetworkInfo mNetworkInfo;
+ @Mock
+ private Network mNetwork;
+
+ @Captor
+ private ArgumentCaptor<Integer> mInt;
+ @Captor
+ private ArgumentCaptor<NetworkRequest> mNetworkReq;
+
+ private NetworkCapabilities mNetworkCapabilities;
+
+ public LaunchCaptivePortalActivityTest() {
+ super(CaptivePortalLaunchActivity.class);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ injectSystemService(ConnectivityManager.class, mCm);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override
+ protected Intent createActivityIntent() {
+ Intent intent = new Intent(getInstrumentation().getTargetContext(),
+ CaptivePortalLaunchActivity.class);
+ intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, "url");
+ return intent;
+ }
+
+ @Test
+ public void testWithoutInternetConnection() throws Throwable {
+ startActivity();
+ TestContext.waitForMs(100);
+ verify(mCm, atLeast(1)).requestNetwork(mNetworkReq.capture(), any(), mInt.capture());
+ // verify network request
+ assert(mNetworkReq.getValue().networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ assert(mNetworkReq.getValue().networkCapabilities.hasTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR));
+ assertFalse(mNetworkReq.getValue().networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED));
+ assertEquals(CaptivePortalLaunchActivity.NETWORK_REQUEST_TIMEOUT_IN_MS,
+ (int) mInt.getValue());
+ // verify captive portal app is not launched due to unavailable network
+ assertNull(getStartedActivityIntent());
+ stopActivity();
+ }
+
+ @Test
+ public void testWithInternetConnection() throws Throwable {
+ // Mock internet connection
+ mNetworkCapabilities = new NetworkCapabilities()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ doReturn(new Network[]{mNetwork}).when(mCm).getAllNetworks();
+ doReturn(mNetworkCapabilities).when(mCm).getNetworkCapabilities(eq(mNetwork));
+ doReturn(mNetworkInfo).when(mCm).getNetworkInfo(eq(mNetwork));
+ doReturn(true).when(mNetworkInfo).isConnected();
+
+ startActivity();
+ TestContext.waitForMs(100);
+ // verify there is no network request with internet connection
+ verify(mCm, times(0)).requestNetwork(any(), any(), anyInt());
+ // verify captive portal app is launched
+ assertNotNull(getStartedActivityIntent());
+ assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN,
+ getStartedActivityIntent().getAction());
+ stopActivity();
+ }
+}
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/TestContext.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/TestContext.java
new file mode 100644
index 0000000..e50666b
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/TestContext.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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.carrierdefaultapp;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.util.Log;
+
+import java.util.HashMap;
+
+public class TestContext extends ContextWrapper {
+
+ private final String TAG = this.getClass().getSimpleName();
+
+ private HashMap<String, Object> mInjectedSystemServices = new HashMap<>();
+
+ public TestContext(Context base) {
+ super(base);
+ }
+
+ public <S> void injectSystemService(Class<S> cls, S service) {
+ final String name = getSystemServiceName(cls);
+ mInjectedSystemServices.put(name, service);
+ }
+
+ @Override
+ public Context getApplicationContext() {
+ return this;
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (mInjectedSystemServices.containsKey(name)) {
+ Log.d(TAG, "return mocked system service for " + name);
+ return mInjectedSystemServices.get(name);
+ }
+ Log.d(TAG, "return real system service for " + name);
+ return super.getSystemService(name);
+ }
+
+ public static void waitForMs(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ }
+ }
+}
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 5b11303..f79cf04 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -100,6 +100,129 @@
<item>Always use HDCP checking</item>
</string-array>
+
+ <!-- Bluetooth settings -->
+
+ <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item>Default</item>
+ <item>SBC</item>
+ <item>aptX</item>
+ <item>aptX-HD</item>
+ <item>LDAC</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_values" translatable="false" >
+ <item>1000000</item>
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_summaries" >
+ <item>Default</item>
+ <item>SBC</item>
+ <item>aptX</item>
+ <item>aptX-HD</item>
+ <item>LDAC</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+ <item>Default</item>
+ <item>44.1 kHz</item>
+ <item>48.0 kHz</item>
+ <item>88.2 kHz</item>
+ <item>96.0 kHz</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec Sample Rate selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_sample_rate_values" translatable="false" >
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>4</item>
+ <item>8</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_sample_rate_summaries" >
+ <item>Default</item>
+ <item>44.1 kHz</item>
+ <item>48.0 kHz</item>
+ <item>88.2 kHz</item>
+ <item>96.0 kHz</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+ <item>Default</item>
+ <item>16 bits/sample</item>
+ <item>24 bits/sample</item>
+ <item>32 bits/sample</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec Bits Per Sample selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_bits_per_sample_values" translatable="false" >
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>4</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries" >
+ <item>Default</item>
+ <item>16 bits/sample</item>
+ <item>24 bits/sample</item>
+ <item>32 bits/sample</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+ <item>Default</item>
+ <item>Mono</item>
+ <item>Stereo</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec Channel Mode selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_channel_mode_values" translatable="false" >
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_channel_mode_summaries" >
+ <item>Default</item>
+ <item>Mono</item>
+ <item>Stereo</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item>Sound quality preferred (990kbps/909kbps)</item>
+ <item>Standard (660kbps/606kbps)</item>
+ <item>Connection preferred (330kbps/303kbps)</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec LDAC Playback Quaility selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_values" translatable="false" >
+ <item>1000</item>
+ <item>1001</item>
+ <item>1002</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries" >
+ <item>Sound quality preferred (990kbps/909kbps)</item>
+ <item>Standard (660kbps/606kbps)</item>
+ <item>Connection preferred (330kbps/303kbps)</item>
+ </string-array>
+
<!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
<string-array name="select_logd_size_titles">
<item>Off</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 29839e7..f389000 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -428,6 +428,31 @@
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
+ <!-- UI debug setting: Select Bluetooth Audio Codec -->
+ <string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec -->
+ <string name="bluetooth_select_a2dp_codec_type_dialog_title">Select Preferred Bluetooth A2DP Codec</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio Sample Rate -->
+ <string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Sample Rate -->
+ <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Select Preferred Bluetooth A2DP Codec Sample Rate</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio Bits Per Sample -->
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Bits Per Sample -->
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title">Select Preferred Bluetooth A2DP Codec Bits Per Sample</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio Channel Mode -->
+ <string name="bluetooth_select_a2dp_codec_channel_mode">Bluetooth Audio Channel Mode</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Channel Mode -->
+ <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title">Select Preferred Bluetooth A2DP Codec Channel Mode</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio LDAC Playback Quality -->
+ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Playback Quality</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec LDAC Playback Quality -->
+ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Select Preferred Bluetooth A2DP Codec LDAC Playback Quality</string>
+
<!-- setting Checkbox summary whether to show options for wireless display certification -->
<string name="wifi_display_certification_summary">Show options for wireless display certification</string>
<!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index ca0248e..04d0e65 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -27,7 +27,7 @@
<android.support.v7.widget.RecyclerView
android:id="@android:id/list"
- android:layout_width="@dimen/notification_panel_width"
+ android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollIndicators="top"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 5c8a6e2..a172e19 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -358,6 +358,11 @@
private final TouchAnimator.Listener mNonFirstPageListener =
new TouchAnimator.ListenerAdapter() {
@Override
+ public void onAnimationAtEnd() {
+ mQuickQsPanel.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
public void onAnimationStarted() {
mQuickQsPanel.setVisibility(View.VISIBLE);
}
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 9f01c18..a61743d 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -19,7 +19,7 @@
system/netd/server/binder
LOCAL_JAVA_LIBRARIES := services.net telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
+LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
ifneq ($(INCREMENTAL_BUILDS),)
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index adc59de..4f43eac 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -2029,6 +2029,11 @@
}
writer.flush();
+ if (args.length == 0) {
+ // Add arg to produce output
+ args = new String[1];
+ args[0] = "--print";
+ }
}
if (mBluetoothBinder == null) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 66f5c4d..b3627ad 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -883,7 +883,7 @@
private void handleMobileDataAlwaysOn() {
final boolean enable = (Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1);
+ mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1) == 1);
final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
if (enable == isEnabled) {
return; // Nothing to do.
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 74ff41c..6296375 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -154,7 +154,8 @@
3110 unknown_sources_enabled (value|1)
# Package Manager critical info
3120 pm_critical_info (msg|3)
-
+# Disk usage stats for verifying quota correctness
+3121 pm_package_stats (manual_time|2|3),(quota_time|2|3),(manual_data|2|2),(quota_data|2|2),(manual_cache|2|2),(quota_cache|2|2)
# ---------------------------
# WindowManagerService.java
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b9a4831..4cc2931 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -46,6 +46,7 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.ObbInfo;
+import android.net.TrafficStats;
import android.net.Uri;
import android.os.Binder;
import android.os.DropBoxManager;
@@ -86,6 +87,7 @@
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.Xml;
@@ -3738,6 +3740,18 @@
pw.println();
pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
+ final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
+ if (pair == null) {
+ pw.println("Internal storage total size: N/A");
+ } else {
+ pw.print("Internal storage (");
+ pw.print(pair.first);
+ pw.print(") total size: ");
+ pw.print(pair.second);
+ pw.print(" (");
+ pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
+ pw.println(" GB)");
+ }
pw.println("Force adoptable: " + mForceAdoptable);
pw.println();
pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8f16504..158527d 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1905,31 +1905,6 @@
}
@Override
- public void setDnsServersForNetwork(int netId, String[] servers, String domains) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- Command cmd;
- if (servers.length > 0) {
- cmd = new Command("resolver", "setnetdns", netId,
- (domains == null ? "" : domains));
- for (String s : servers) {
- InetAddress a = NetworkUtils.numericToInetAddress(s);
- if (a.isAnyLocalAddress() == false) {
- cmd.appendArg(a.getHostAddress());
- }
- }
- } else {
- cmd = new Command("resolver", "clearnetdns", netId);
- }
-
- try {
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
- }
-
- @Override
public void addVpnUidRanges(int netId, UidRange[] ranges) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 983d039..e23844c 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -34,9 +34,9 @@
import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.net.NetworkScoreManager;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -301,7 +301,8 @@
// If we're not connected at all then create a new connection.
if (mServiceConnection == null) {
- mServiceConnection = new ScoringServiceConnection(componentName);
+ mServiceConnection = new ScoringServiceConnection(componentName,
+ scorerData.packageUid);
}
// Make sure the connection is connected (idempotent)
@@ -325,7 +326,7 @@
@Override
public boolean updateScores(ScoredNetwork[] networks) {
- if (!mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid())) {
+ if (!isCallerActiveScorer(getCallingUid())) {
throw new SecurityException("Caller with UID " + getCallingUid() +
" is not the active scorer.");
}
@@ -380,13 +381,16 @@
}
}
+ private boolean isCallerSystemUid() {
+ // REQUEST_NETWORK_SCORES is a signature only permission.
+ return mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) ==
+ PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public boolean clearScores() {
- // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
- // should be allowed to flush all scores.
- if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
- mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
- PackageManager.PERMISSION_GRANTED) {
+ // Only the active scorer or the system should be allowed to flush all scores.
+ if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
final long token = Binder.clearCallingIdentity();
try {
clearInternal();
@@ -409,20 +413,45 @@
// In the future, should this API be opened to 3p apps, we will need to lock this down and
// figure out another way to streamline the UX.
- // mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
// Scorers (recommendation providers) are selected and no longer set.
return false;
}
+ /**
+ * Determine whether the application with the given UID is the enabled scorer.
+ *
+ * @param callingUid the UID to check
+ * @return true if the provided UID is the active scorer, false otherwise.
+ */
+ @Override
+ public boolean isCallerActiveScorer(int callingUid) {
+ synchronized (mServiceConnectionLock) {
+ return mServiceConnection != null && mServiceConnection.mScoringAppUid == callingUid;
+ }
+ }
+
+ /**
+ * Obtain the package name of the current active network scorer.
+ *
+ * @return the full package name of the current active scorer, or null if there is no active
+ * scorer.
+ */
+ @Override
+ public String getActiveScorerPackage() {
+ synchronized (mServiceConnectionLock) {
+ if (mServiceConnection != null) {
+ return mServiceConnection.mComponentName.getPackageName();
+ }
+ }
+ return null;
+ }
+
@Override
public void disableScoring() {
- // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
- // should be allowed to disable scoring.
- if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
- mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
- PackageManager.PERMISSION_GRANTED) {
+ // Only the active scorer or the system should be allowed to disable scoring.
+ if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
// no-op for now but we could write to the setting if needed.
} else {
throw new SecurityException(
@@ -450,7 +479,7 @@
public void registerNetworkScoreCache(int networkType,
INetworkScoreCache scoreCache,
int filterType) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
final long token = Binder.clearCallingIdentity();
try {
synchronized (mScoreCaches) {
@@ -475,7 +504,7 @@
@Override
public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
final long token = Binder.clearCallingIdentity();
try {
synchronized (mScoreCaches) {
@@ -496,7 +525,7 @@
@Override
public RecommendationResult requestRecommendation(RecommendationRequest request) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
throwIfCalledOnMainThread();
final long token = Binder.clearCallingIdentity();
try {
@@ -526,7 +555,7 @@
@Override
public boolean requestScores(NetworkKey[] networks) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
final long token = Binder.clearCallingIdentity();
try {
final INetworkRecommendationProvider provider = getRecommendationProvider();
@@ -624,12 +653,14 @@
private static class ScoringServiceConnection implements ServiceConnection {
private final ComponentName mComponentName;
+ private final int mScoringAppUid;
private volatile boolean mBound = false;
private volatile boolean mConnected = false;
private volatile INetworkRecommendationProvider mRecommendationProvider;
- ScoringServiceConnection(ComponentName componentName) {
+ ScoringServiceConnection(ComponentName componentName, int scoringAppUid) {
mComponentName = componentName;
+ mScoringAppUid = scoringAppUid;
}
void connect(Context context) {
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index 3c8c699..2010e64 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -181,7 +181,7 @@
}
@Override // Binder call
- public void rebootRecoveryWithCommand(String command) {
+ public void rebootRecoveryWithCommand(String command, boolean update) {
if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
synchronized (sRequestLock) {
if (!setupOrClearBcb(true, command)) {
@@ -190,7 +190,10 @@
// Having set up the BCB, go ahead and reboot.
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY);
+ // PowerManagerService may additionally request uncrypting the package when it's
+ // to install an update (REBOOT_RECOVERY_UPDATE).
+ pm.reboot(update ? PowerManager.REBOOT_RECOVERY_UPDATE :
+ PowerManager.REBOOT_RECOVERY);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5b02c79..bc03901 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3729,13 +3729,14 @@
* resources like shared libraries and access user-wide resources
*/
if (ArrayUtils.isEmpty(permGids)) {
- gids = new int[2];
+ gids = new int[3];
} else {
- gids = new int[permGids.length + 2];
- System.arraycopy(permGids, 0, gids, 2, permGids.length);
+ gids = new int[permGids.length + 3];
+ System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
- gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
+ gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
+ gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
checkTime(startTime, "startProcess: building args");
if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 7fe6c3e..5d619c1 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -225,6 +225,7 @@
private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100;
private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101;
private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
+ private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
// end of messages handled under wakelock
private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
@@ -3146,7 +3147,7 @@
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SINK_CONNECTION_STATE,
state,
- 0,
+ 0 /* arg2 unused */,
btDevice,
delay);
}
@@ -3163,7 +3164,7 @@
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SRC_CONNECTION_STATE,
state,
- 0,
+ 0 /* arg2 unused */,
btDevice,
0 /* delay */);
}
@@ -3809,8 +3810,8 @@
int delay = checkSendBecomingNoisyIntent(type, state);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
- 0,
- 0,
+ 0 /* arg1 unused */,
+ 0 /* arg2 unused */,
new WiredDeviceConnectionState(type, state, address, name, caller),
delay);
}
@@ -3833,13 +3834,25 @@
(profile == BluetoothProfile.A2DP ?
MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
state,
- 0,
+ 0 /* arg2 unused */,
device,
delay);
}
return delay;
}
+ public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
+ {
+ synchronized (mConnectedDevices) {
+ queueMsgUnderWakeLock(mAudioHandler,
+ MSG_A2DP_DEVICE_CONFIG_CHANGE,
+ 0 /* arg1 unused */,
+ 0 /* arg1 unused */,
+ device,
+ 0 /* delay */);
+ }
+ }
+
///////////////////////////////////////////////////////////////////////////
// Inner classes
///////////////////////////////////////////////////////////////////////////
@@ -4644,6 +4657,11 @@
mAudioEventWakeLock.release();
break;
+ case MSG_A2DP_DEVICE_CONFIG_CHANGE:
+ onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj);
+ mAudioEventWakeLock.release();
+ break;
+
case MSG_REPORT_NEW_ROUTES: {
int N = mRoutesObservers.beginBroadcast();
if (N > 0) {
@@ -4866,7 +4884,7 @@
private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
{
if (DEBUG_VOL) {
- Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state);
+ Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
}
if (btDevice == null) {
return;
@@ -4877,9 +4895,9 @@
}
synchronized (mConnectedDevices) {
- String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- btDevice.getAddress());
- DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ btDevice.getAddress());
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
boolean isConnected = deviceSpec != null;
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
@@ -4930,7 +4948,7 @@
private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
{
if (DEBUG_VOL) {
- Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state);
+ Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state);
}
if (btDevice == null) {
return;
@@ -4941,8 +4959,8 @@
}
synchronized (mConnectedDevices) {
- String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
- DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ final String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
boolean isConnected = deviceSpec != null;
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
@@ -4953,6 +4971,31 @@
}
}
+ private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
+ {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
+ }
+ if (btDevice == null) {
+ return;
+ }
+ String address = btDevice.getAddress();
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ address = "";
+ }
+
+ int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
+ synchronized (mConnectedDevices) {
+ final String key = makeDeviceListKey(device, address);
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ if (deviceSpec != null) {
+ // Device is connected
+ AudioSystem.handleDeviceConfigChange(device, address,
+ btDevice.getName());
+ }
+ }
+ }
+
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
// address is not used for now, but may be used when multiple a2dp devices are supported
synchronized (mA2dpAvrcpLock) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ea2cf5f..9ffe2b7 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -80,7 +80,8 @@
*/
public class NetworkMonitor extends StateMachine {
private static final String TAG = NetworkMonitor.class.getSimpleName();
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
// Default configuration values for captive portal detection probes.
// TODO: append a random length parameter to the default HTTPS url.
@@ -432,6 +433,8 @@
}));
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL,
mLastPortalProbeResult.detectUrl);
+ intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT,
+ getCaptivePortalUserAgent(mContext));
intent.setFlags(
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
@@ -954,7 +957,7 @@
latencyBroadcast.putExtra(EXTRA_SSID, currentWifiInfo.getSSID());
latencyBroadcast.putExtra(EXTRA_BSSID, currentWifiInfo.getBSSID());
} else {
- if (DBG) logw("network info is TYPE_WIFI but no ConnectionInfo found");
+ if (VDBG) logw("network info is TYPE_WIFI but no ConnectionInfo found");
return;
}
break;
@@ -967,8 +970,8 @@
if (cellInfo.isRegistered()) {
numRegisteredCellInfo++;
if (numRegisteredCellInfo > 1) {
- log("more than one registered CellInfo. Can't " +
- "tell which is active. Bailing.");
+ if (VDBG) logw("more than one registered CellInfo." +
+ " Can't tell which is active. Bailing.");
return;
}
if (cellInfo instanceof CellInfoCdma) {
@@ -984,7 +987,7 @@
CellIdentityWcdma cellId = ((CellInfoWcdma) cellInfo).getCellIdentity();
latencyBroadcast.putExtra(EXTRA_CELL_ID, cellId);
} else {
- if (DBG) logw("Registered cellinfo is unrecognized");
+ if (VDBG) logw("Registered cellinfo is unrecognized");
return;
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index f7b01be..c6bf4c5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -114,7 +114,7 @@
}
if (DBG) {
- Slog.d(TAG, "showNotification " + notifyType
+ Slog.d(TAG, "showNotification id=" + id + " " + notifyType
+ " transportType=" + getTransportName(transportType)
+ " extraInfo=" + extraInfo + " highPriority=" + highPriority);
}
@@ -187,7 +187,7 @@
try {
mNotificationManager.notifyAsUser(NOTIFICATION_ID, id, notification, UserHandle.ALL);
} catch (NullPointerException npe) {
- Slog.d(TAG, "setNotificationVisible: visible notificationManager npe=" + npe);
+ Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
}
}
@@ -198,7 +198,7 @@
try {
mNotificationManager.cancelAsUser(NOTIFICATION_ID, id, UserHandle.ALL);
} catch (NullPointerException npe) {
- Slog.d(TAG, "setNotificationVisible: cancel notificationManager npe=" + npe);
+ Slog.d(TAG, "setNotificationVisible: cancel notificationManager error", npe);
}
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6d96a10..0c80166 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -32,7 +32,6 @@
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.LinkProperties;
@@ -73,6 +72,7 @@
import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices;
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
+import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
import com.android.server.net.BaseNetworkObserver;
import java.io.FileDescriptor;
@@ -199,7 +199,8 @@
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
mTetherMasterSM.start();
- mUpstreamNetworkMonitor = new UpstreamNetworkMonitor();
+ mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
+ mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
mStateReceiver = new StateReceiver();
IntentFilter filter = new IntentFilter();
@@ -519,8 +520,8 @@
}
/**
- * Creates a proxy {@link ResultReceiver} which enables tethering if the provsioning result is
- * successful before firing back up to the wrapped receiver.
+ * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result
+ * is successful before firing back up to the wrapped receiver.
*
* @param type The type of tethering being enabled.
* @param receiver A ResultReceiver which will be called back with an int resultCode.
@@ -889,7 +890,11 @@
public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
- UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
+ UsbManager usbManager = mContext.getSystemService(UsbManager.class);
+ if (usbManager == null) {
+ return enable ? ConnectivityManager.TETHER_ERROR_MASTER_ERROR
+ : ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ }
synchronized (mPublicSync) {
if (enable) {
@@ -935,7 +940,7 @@
private void checkDunRequired() {
int secureSetting = 2;
- TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
if (tm != null) {
secureSetting = tm.getTetherApnRequired();
}
@@ -1026,181 +1031,6 @@
}
}
- /**
- * A NetworkCallback class that relays information of interest to the
- * tethering master state machine thread for subsequent processing.
- */
- class UpstreamNetworkCallback extends NetworkCallback {
- @Override
- public void onAvailable(Network network) {
- mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network);
- }
-
- @Override
- public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
- mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0,
- new NetworkState(null, null, newNc, network, null, null));
- }
-
- @Override
- public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
- mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0,
- new NetworkState(null, newLp, null, network, null, null));
- }
-
- @Override
- public void onLost(Network network) {
- mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
- UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network);
- }
- }
-
- /**
- * A class to centralize all the network and link properties information
- * pertaining to the current and any potential upstream network.
- *
- * Calling #start() registers two callbacks: one to track the system default
- * network and a second to specifically observe TYPE_MOBILE_DUN networks.
- *
- * The methods and data members of this class are only to be accessed and
- * modified from the tethering master state machine thread. Any other
- * access semantics would necessitate the addition of locking.
- *
- * TODO: Investigate whether more "upstream-specific" logic/functionality
- * could/should be moved here.
- */
- class UpstreamNetworkMonitor {
- static final int EVENT_ON_AVAILABLE = 1;
- static final int EVENT_ON_CAPABILITIES = 2;
- static final int EVENT_ON_LINKPROPERTIES = 3;
- static final int EVENT_ON_LOST = 4;
-
- final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
- NetworkCallback mDefaultNetworkCallback;
- NetworkCallback mDunTetheringCallback;
-
- void start() {
- stop();
-
- mDefaultNetworkCallback = new UpstreamNetworkCallback();
- getConnectivityManager().registerDefaultNetworkCallback(mDefaultNetworkCallback);
-
- final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .build();
- mDunTetheringCallback = new UpstreamNetworkCallback();
- getConnectivityManager().registerNetworkCallback(
- dunTetheringRequest, mDunTetheringCallback);
- }
-
- void stop() {
- if (mDefaultNetworkCallback != null) {
- getConnectivityManager().unregisterNetworkCallback(mDefaultNetworkCallback);
- mDefaultNetworkCallback = null;
- }
-
- if (mDunTetheringCallback != null) {
- getConnectivityManager().unregisterNetworkCallback(mDunTetheringCallback);
- mDunTetheringCallback = null;
- }
-
- mNetworkMap.clear();
- }
-
- NetworkState lookup(Network network) {
- return (network != null) ? mNetworkMap.get(network) : null;
- }
-
- NetworkState processCallback(int arg1, Object obj) {
- switch (arg1) {
- case EVENT_ON_AVAILABLE: {
- final Network network = (Network) obj;
- if (VDBG) {
- Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
- }
- if (!mNetworkMap.containsKey(network)) {
- mNetworkMap.put(network,
- new NetworkState(null, null, null, network, null, null));
- }
-
- final ConnectivityManager cm = getConnectivityManager();
-
- if (mDefaultNetworkCallback != null) {
- cm.requestNetworkCapabilities(mDefaultNetworkCallback);
- cm.requestLinkProperties(mDefaultNetworkCallback);
- }
-
- // Requesting updates for mDunTetheringCallback is not
- // necessary. Because it's a listen, it will already have
- // heard all NetworkCapabilities and LinkProperties updates
- // since UpstreamNetworkMonitor was started. Because we
- // start UpstreamNetworkMonitor before chooseUpstreamType()
- // is ever invoked (it can register a DUN request) this is
- // mostly safe. However, if a DUN network is already up for
- // some reason (unlikely, because DUN is restricted and,
- // unless the DUN network is shared with another APN, only
- // the system can request it and this is the only part of
- // the system that requests it) we won't know its
- // LinkProperties or NetworkCapabilities.
-
- return mNetworkMap.get(network);
- }
- case EVENT_ON_CAPABILITIES: {
- final NetworkState ns = (NetworkState) obj;
- if (!mNetworkMap.containsKey(ns.network)) {
- // Ignore updates for networks for which we have not yet
- // received onAvailable() - which should never happen -
- // or for which we have already received onLost().
- return null;
- }
- if (VDBG) {
- Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
- ns.network, ns.networkCapabilities));
- }
-
- final NetworkState prev = mNetworkMap.get(ns.network);
- mNetworkMap.put(ns.network,
- new NetworkState(null, prev.linkProperties, ns.networkCapabilities,
- ns.network, null, null));
- return mNetworkMap.get(ns.network);
- }
- case EVENT_ON_LINKPROPERTIES: {
- final NetworkState ns = (NetworkState) obj;
- if (!mNetworkMap.containsKey(ns.network)) {
- // Ignore updates for networks for which we have not yet
- // received onAvailable() - which should never happen -
- // or for which we have already received onLost().
- return null;
- }
- if (VDBG) {
- Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
- ns.network, ns.linkProperties));
- }
-
- final NetworkState prev = mNetworkMap.get(ns.network);
- mNetworkMap.put(ns.network,
- new NetworkState(null, ns.linkProperties, prev.networkCapabilities,
- ns.network, null, null));
- return mNetworkMap.get(ns.network);
- }
- case EVENT_ON_LOST: {
- final Network network = (Network) obj;
- if (VDBG) {
- Log.d(TAG, "EVENT_ON_LOST for " + network);
- }
- return mNetworkMap.remove(network);
- }
- default:
- return null;
- }
- }
- }
-
// Needed because the canonical source of upstream truth is just the
// upstream interface name, |mCurrentUpstreamIface|. This is ripe for
// future simplification, once the upstream Network is canonical.
@@ -1253,8 +1083,7 @@
private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
- private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
- private NetworkCallback mMobileUpstreamCallback;
+ private int mPreviousMobileApn = ConnectivityManager.TYPE_NONE;
private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
@@ -1292,13 +1121,13 @@
protected boolean turnOnUpstreamMobileConnection(int apnType) {
if (apnType == ConnectivityManager.TYPE_NONE) { return false; }
- if (apnType != mMobileApnReserved) {
+ if (apnType != mPreviousMobileApn) {
// Unregister any previous mobile upstream callback because
// this request, if any, will be different.
turnOffUpstreamMobileConnection();
}
- if (mMobileUpstreamCallback != null) {
+ if (mUpstreamNetworkMonitor.mobileNetworkRequested()) {
// Looks like we already filed a request for this apnType.
return true;
}
@@ -1307,42 +1136,25 @@
case ConnectivityManager.TYPE_MOBILE_DUN:
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
- mMobileApnReserved = apnType;
+ mPreviousMobileApn = apnType;
break;
default:
return false;
}
- final NetworkRequest.Builder builder = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- if (apnType == ConnectivityManager.TYPE_MOBILE_DUN) {
- builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
- } else {
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
- final NetworkRequest mobileUpstreamRequest = builder.build();
+ // TODO: This should be called by the code that observes
+ // configuration changes, once the above code in this function
+ // is simplified (i.e. eradicated).
+ mUpstreamNetworkMonitor.mobileUpstreamRequiresDun(
+ apnType == ConnectivityManager.TYPE_MOBILE_DUN);
- // The UpstreamNetworkMonitor's callback will be notified.
- // Therefore, to avoid duplicate notifications, we only register a no-op.
- mMobileUpstreamCallback = new NetworkCallback();
-
- // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
- // moderate callback time (once timeout callbacks are implemented). This might
- // be useful for updating some UI. Additionally, we should definitely log a
- // message to aid in any subsequent debugging
- if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
- getConnectivityManager().requestNetwork(
- mobileUpstreamRequest, mMobileUpstreamCallback, 0, apnType);
+ mUpstreamNetworkMonitor.registerMobileNetworkRequest();
return true;
}
protected void turnOffUpstreamMobileConnection() {
- if (mMobileUpstreamCallback != null) {
- getConnectivityManager().unregisterNetworkCallback(mMobileUpstreamCallback);
- mMobileUpstreamCallback = null;
- }
- mMobileApnReserved = ConnectivityManager.TYPE_NONE;
+ mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
+ mPreviousMobileApn = ConnectivityManager.TYPE_NONE;
}
protected boolean turnOnMasterTetherSettings() {
@@ -1658,7 +1470,6 @@
@Override
public void exit() {
- // TODO: examine if we should check the return value.
turnOffUpstreamMobileConnection();
mUpstreamNetworkMonitor.stop();
stopListeningForSimChanges();
@@ -1715,9 +1526,7 @@
mTryCell = !mTryCell;
break;
case EVENT_UPSTREAM_CALLBACK: {
- // First: always update local state about every network.
- final NetworkState ns = mUpstreamNetworkMonitor.processCallback(
- message.arg1, message.obj);
+ final NetworkState ns = (NetworkState) message.obj;
if (ns == null || !pertainsToCurrentUpstream(ns)) {
// TODO: In future, this is where upstream evaluation and selection
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index afc6247..a5876dd 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1586,9 +1586,6 @@
public void exit() {
// We assume that everything is reset after stopping the daemons.
interrupt();
- for (LocalSocket socket : mSockets) {
- IoUtils.closeQuietly(socket);
- }
agentDisconnect();
try {
mContext.unregisterReceiver(mBroadcastReceiver);
@@ -1601,8 +1598,26 @@
Log.v(TAG, "Waiting");
synchronized (TAG) {
Log.v(TAG, "Executing");
- execute();
- monitorDaemons();
+ try {
+ execute();
+ monitorDaemons();
+ interrupted(); // Clear interrupt flag if execute called exit.
+ } catch (InterruptedException e) {
+ } finally {
+ for (LocalSocket socket : mSockets) {
+ IoUtils.closeQuietly(socket);
+ }
+ // This sleep is necessary for racoon to successfully complete sending delete
+ // message to server.
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ }
+ for (String daemon : mDaemons) {
+ SystemService.stop(daemon);
+ }
+ }
+ agentDisconnect();
}
}
@@ -1801,18 +1816,6 @@
Log.i(TAG, "Aborting", e);
updateState(DetailedState.FAILED, e.getMessage());
exit();
- } finally {
- // Kill the daemons if they fail to stop.
- if (!initFinished) {
- for (String daemon : mDaemons) {
- SystemService.stop(daemon);
- }
- }
-
- // Do not leave an unstable state.
- if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) {
- agentDisconnect();
- }
}
}
@@ -1820,28 +1823,17 @@
* Monitor the daemons we started, moving to disconnected state if the
* underlying services fail.
*/
- private void monitorDaemons() {
+ private void monitorDaemons() throws InterruptedException{
if (!mNetworkInfo.isConnected()) {
return;
}
-
- try {
- while (true) {
- Thread.sleep(2000);
- for (int i = 0; i < mDaemons.length; i++) {
- if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
- return;
- }
+ while (true) {
+ Thread.sleep(2000);
+ for (int i = 0; i < mDaemons.length; i++) {
+ if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
+ return;
}
}
- } catch (InterruptedException e) {
- Log.d(TAG, "interrupted during monitorDaemons(); stopping services");
- } finally {
- for (String daemon : mDaemons) {
- SystemService.stop(daemon);
- }
-
- agentDisconnect();
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
new file mode 100644
index 0000000..927dfd5
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -0,0 +1,287 @@
+/*
+ * 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.server.connectivity.tethering;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.NetworkState;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.StateMachine;
+
+import java.util.HashMap;
+
+
+/**
+ * A class to centralize all the network and link properties information
+ * pertaining to the current and any potential upstream network.
+ *
+ * Calling #start() registers two callbacks: one to track the system default
+ * network and a second to specifically observe TYPE_MOBILE_DUN networks.
+ *
+ * The methods and data members of this class are only to be accessed and
+ * modified from the tethering master state machine thread. Any other
+ * access semantics would necessitate the addition of locking.
+ *
+ * TODO: Move upstream selection logic here.
+ *
+ * @hide
+ */
+public class UpstreamNetworkMonitor {
+ private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName();
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+
+ public static final int EVENT_ON_AVAILABLE = 1;
+ public static final int EVENT_ON_CAPABILITIES = 2;
+ public static final int EVENT_ON_LINKPROPERTIES = 3;
+ public static final int EVENT_ON_LOST = 4;
+
+ private final Context mContext;
+ private final StateMachine mTarget;
+ private final int mWhat;
+ private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
+ private ConnectivityManager mCM;
+ private NetworkCallback mDefaultNetworkCallback;
+ private NetworkCallback mDunTetheringCallback;
+ private NetworkCallback mMobileNetworkCallback;
+ private boolean mDunRequired;
+
+ public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
+ mContext = ctx;
+ mTarget = tgt;
+ mWhat = what;
+ }
+
+ @VisibleForTesting
+ public UpstreamNetworkMonitor(StateMachine tgt, int what, ConnectivityManager cm) {
+ this(null, tgt, what);
+ mCM = cm;
+ }
+
+ public void start() {
+ stop();
+
+ mDefaultNetworkCallback = new UpstreamNetworkCallback();
+ cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
+
+ final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ .build();
+ mDunTetheringCallback = new UpstreamNetworkCallback();
+ cm().registerNetworkCallback(dunTetheringRequest, mDunTetheringCallback);
+ }
+
+ public void stop() {
+ releaseMobileNetworkRequest();
+
+ releaseCallback(mDefaultNetworkCallback);
+ mDefaultNetworkCallback = null;
+
+ releaseCallback(mDunTetheringCallback);
+ mDunTetheringCallback = null;
+
+ mNetworkMap.clear();
+ }
+
+ public void mobileUpstreamRequiresDun(boolean dunRequired) {
+ final boolean valueChanged = (mDunRequired != dunRequired);
+ mDunRequired = dunRequired;
+ if (valueChanged && mobileNetworkRequested()) {
+ releaseMobileNetworkRequest();
+ registerMobileNetworkRequest();
+ }
+ }
+
+ public boolean mobileNetworkRequested() {
+ return (mMobileNetworkCallback != null);
+ }
+
+ public void registerMobileNetworkRequest() {
+ if (mMobileNetworkCallback != null) return;
+
+ final NetworkRequest.Builder builder = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ if (mDunRequired) {
+ builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
+ } else {
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+ final NetworkRequest mobileUpstreamRequest = builder.build();
+
+ // The existing default network and DUN callbacks will be notified.
+ // Therefore, to avoid duplicate notifications, we only register a no-op.
+ mMobileNetworkCallback = new NetworkCallback();
+
+ // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
+ // moderate callback time (once timeout callbacks are implemented). This might
+ // be useful for updating some UI. Additionally, we should definitely log a
+ // message to aid in any subsequent debugging
+ if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
+
+ cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback);
+ }
+
+ public void releaseMobileNetworkRequest() {
+ if (mMobileNetworkCallback == null) return;
+
+ cm().unregisterNetworkCallback(mMobileNetworkCallback);
+ mMobileNetworkCallback = null;
+ }
+
+ public NetworkState lookup(Network network) {
+ return (network != null) ? mNetworkMap.get(network) : null;
+ }
+
+ private void handleAvailable(Network network) {
+ if (VDBG) {
+ Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
+ }
+ if (!mNetworkMap.containsKey(network)) {
+ mNetworkMap.put(network,
+ new NetworkState(null, null, null, network, null, null));
+ }
+
+ final ConnectivityManager cm = cm();
+
+ if (mDefaultNetworkCallback != null) {
+ cm.requestNetworkCapabilities(mDefaultNetworkCallback);
+ cm.requestLinkProperties(mDefaultNetworkCallback);
+ }
+
+ // Requesting updates for mDunTetheringCallback is not
+ // necessary. Because it's a listen, it will already have
+ // heard all NetworkCapabilities and LinkProperties updates
+ // since UpstreamNetworkMonitor was started. Because we
+ // start UpstreamNetworkMonitor before chooseUpstreamType()
+ // is ever invoked (it can register a DUN request) this is
+ // mostly safe. However, if a DUN network is already up for
+ // some reason (unlikely, because DUN is restricted and,
+ // unless the DUN network is shared with another APN, only
+ // the system can request it and this is the only part of
+ // the system that requests it) we won't know its
+ // LinkProperties or NetworkCapabilities.
+
+ notifyTarget(EVENT_ON_AVAILABLE, network);
+ }
+
+ private void handleNetCap(Network network, NetworkCapabilities newNc) {
+ if (!mNetworkMap.containsKey(network)) {
+ // Ignore updates for networks for which we have not yet
+ // received onAvailable() - which should never happen -
+ // or for which we have already received onLost().
+ return;
+ }
+ if (VDBG) {
+ Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
+ network, newNc));
+ }
+
+ final NetworkState prev = mNetworkMap.get(network);
+ mNetworkMap.put(network,
+ new NetworkState(null, prev.linkProperties, newNc,
+ network, null, null));
+ notifyTarget(EVENT_ON_CAPABILITIES, network);
+ }
+
+ private void handleLinkProp(Network network, LinkProperties newLp) {
+ if (!mNetworkMap.containsKey(network)) {
+ // Ignore updates for networks for which we have not yet
+ // received onAvailable() - which should never happen -
+ // or for which we have already received onLost().
+ return;
+ }
+ if (VDBG) {
+ Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
+ network, newLp));
+ }
+
+ final NetworkState prev = mNetworkMap.get(network);
+ mNetworkMap.put(network,
+ new NetworkState(null, newLp, prev.networkCapabilities,
+ network, null, null));
+ notifyTarget(EVENT_ON_LINKPROPERTIES, network);
+ }
+
+ private void handleLost(Network network) {
+ if (!mNetworkMap.containsKey(network)) {
+ // Ignore updates for networks for which we have not yet
+ // received onAvailable() - which should never happen -
+ // or for which we have already received onLost().
+ return;
+ }
+ if (VDBG) {
+ Log.d(TAG, "EVENT_ON_LOST for " + network);
+ }
+ notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
+ }
+
+ // Fetch (and cache) a ConnectivityManager only if and when we need one.
+ private ConnectivityManager cm() {
+ if (mCM == null) {
+ mCM = mContext.getSystemService(ConnectivityManager.class);
+ }
+ return mCM;
+ }
+
+ /**
+ * A NetworkCallback class that relays information of interest to the
+ * tethering master state machine thread for subsequent processing.
+ */
+ private class UpstreamNetworkCallback extends NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ mTarget.getHandler().post(() -> handleAvailable(network));
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
+ mTarget.getHandler().post(() -> handleNetCap(network, newNc));
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
+ mTarget.getHandler().post(() -> handleLinkProp(network, newLp));
+ }
+
+ @Override
+ public void onLost(Network network) {
+ mTarget.getHandler().post(() -> handleLost(network));
+ }
+ }
+
+ private void releaseCallback(NetworkCallback cb) {
+ if (cb != null) cm().unregisterNetworkCallback(cb);
+ }
+
+ private void notifyTarget(int which, Network network) {
+ notifyTarget(which, mNetworkMap.get(network));
+ }
+
+ private void notifyTarget(int which, NetworkState netstate) {
+ mTarget.sendMessage(mWhat, which, 0, netstate);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/AbstractStatsBase.java b/services/core/java/com/android/server/pm/AbstractStatsBase.java
index 612c476..0053f58 100644
--- a/services/core/java/com/android/server/pm/AbstractStatsBase.java
+++ b/services/core/java/com/android/server/pm/AbstractStatsBase.java
@@ -60,12 +60,12 @@
return new AtomicFile(fname);
}
- void writeNow(final T data) {
+ protected void writeNow(final T data) {
writeImpl(data);
mLastTimeWritten.set(SystemClock.elapsedRealtime());
}
- boolean maybeWriteAsync(final T data) {
+ protected boolean maybeWriteAsync(final T data) {
if (SystemClock.elapsedRealtime() - mLastTimeWritten.get() < WRITE_INTERVAL_MS
&& !PackageManagerService.DEBUG_DEXOPT) {
return false;
@@ -105,7 +105,7 @@
protected abstract void writeInternal(T data);
- void read(T data) {
+ protected void read(T data) {
if (mLock) {
synchronized (data) {
synchronized (mFileLock) {
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index cec1058..601a219 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -42,12 +42,18 @@
* {@hide}
*/
public class BackgroundDexOptService extends JobService {
- static final String TAG = "BackgroundDexOptService";
+ private static final String TAG = "BackgroundDexOptService";
- static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+ private static final boolean DEBUG = false;
- static final int JOB_IDLE_OPTIMIZE = 800;
- static final int JOB_POST_BOOT_UPDATE = 801;
+ private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+
+ private static final int JOB_IDLE_OPTIMIZE = 800;
+ private static final int JOB_POST_BOOT_UPDATE = 801;
+
+ private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG
+ ? TimeUnit.MINUTES.toMillis(1)
+ : TimeUnit.DAYS.toMillis(1);
private static ComponentName sDexoptServiceName = new ComponentName(
"android",
@@ -69,7 +75,7 @@
*/
final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
- private final File dataDir = Environment.getDataDirectory();
+ private final File mDataDir = Environment.getDataDirectory();
public static void schedule(Context context) {
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
@@ -86,7 +92,7 @@
js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
- .setPeriodic(TimeUnit.DAYS.toMillis(1))
+ .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
.build());
if (DEBUG_DEXOPT) {
@@ -120,7 +126,7 @@
private long getLowStorageThreshold() {
@SuppressWarnings("deprecation")
- final long lowThreshold = StorageManager.from(this).getStorageLowBytes(dataDir);
+ final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir);
if (lowThreshold == 0) {
Log.e(TAG, "Invalid low storage threshold");
}
@@ -134,114 +140,127 @@
// This job has already been superseded. Do not start it.
return false;
}
-
- // Load low battery threshold from the system config. This is a 0-100 integer.
- final int lowBatteryThreshold = getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
-
- final long lowThreshold = getLowStorageThreshold();
-
- mAbortPostBootUpdate.set(false);
new Thread("BackgroundDexOptService_PostBootUpdate") {
@Override
public void run() {
- for (String pkg : pkgs) {
- if (mAbortPostBootUpdate.get()) {
- // JobScheduler requested an early abort.
- return;
- }
- if (mExitPostBootUpdate.get()) {
- // Different job, which supersedes this one, is running.
- break;
- }
- if (getBatteryLevel() < lowBatteryThreshold) {
- // Rather bail than completely drain the battery.
- break;
- }
- long usableSpace = dataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- // Rather bail than completely fill up the disk.
- Log.w(TAG, "Aborting background dex opt job due to low storage: " +
- usableSpace);
- break;
- }
+ postBootUpdate(jobParams, pm, pkgs);
+ }
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Updating package " + pkg);
- }
+ }.start();
+ return true;
+ }
- // Update package if needed. Note that there can be no race between concurrent
- // jobs because PackageDexOptimizer.performDexOpt is synchronized.
+ private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
+ ArraySet<String> pkgs) {
+ // Load low battery threshold from the system config. This is a 0-100 integer.
+ final int lowBatteryThreshold = getResources().getInteger(
+ com.android.internal.R.integer.config_lowBatteryWarningLevel);
+ final long lowThreshold = getLowStorageThreshold();
- // checkProfiles is false to avoid merging profiles during boot which
- // might interfere with background compilation (b/28612421).
- // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
- // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
- // trade-off worth doing to save boot time work.
- pm.performDexOpt(pkg,
- /* checkProfiles */ false,
- PackageManagerService.REASON_BOOT,
- /* force */ false);
- }
- // Ran to completion, so we abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
+ mAbortPostBootUpdate.set(false);
+
+ for (String pkg : pkgs) {
+ if (mAbortPostBootUpdate.get()) {
+ // JobScheduler requested an early abort.
+ return;
+ }
+ if (mExitPostBootUpdate.get()) {
+ // Different job, which supersedes this one, is running.
+ break;
+ }
+ if (getBatteryLevel() < lowBatteryThreshold) {
+ // Rather bail than completely drain the battery.
+ break;
+ }
+ long usableSpace = mDataDir.getUsableSpace();
+ if (usableSpace < lowThreshold) {
+ // Rather bail than completely fill up the disk.
+ Log.w(TAG, "Aborting background dex opt job due to low storage: " +
+ usableSpace);
+ break;
+ }
+
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Updating package " + pkg);
+ }
+
+ // Update package if needed. Note that there can be no race between concurrent
+ // jobs because PackageDexOptimizer.performDexOpt is synchronized.
+
+ // checkProfiles is false to avoid merging profiles during boot which
+ // might interfere with background compilation (b/28612421).
+ // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
+ // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
+ // trade-off worth doing to save boot time work.
+ pm.performDexOpt(pkg,
+ /* checkProfiles */ false,
+ PackageManagerService.REASON_BOOT,
+ /* force */ false);
+ }
+ // Ran to completion, so we abandon our timeslice and do not reschedule.
+ jobFinished(jobParams, /* reschedule */ false);
+ }
+
+ private boolean runIdleOptimization(final JobParameters jobParams,
+ final PackageManagerService pm, final ArraySet<String> pkgs) {
+ new Thread("BackgroundDexOptService_IdleOptimization") {
+ @Override
+ public void run() {
+ idleOptimization(jobParams, pm, pkgs);
}
}.start();
return true;
}
- private boolean runIdleOptimization(final JobParameters jobParams,
- final PackageManagerService pm, final ArraySet<String> pkgs) {
+ private void idleOptimization(JobParameters jobParams, PackageManagerService pm,
+ ArraySet<String> pkgs) {
+ Log.i(TAG, "Performing idle optimizations");
// If post-boot update is still running, request that it exits early.
mExitPostBootUpdate.set(true);
mAbortIdleOptimization.set(false);
final long lowThreshold = getLowStorageThreshold();
-
- new Thread("BackgroundDexOptService_IdleOptimization") {
- @Override
- public void run() {
- for (String pkg : pkgs) {
- if (mAbortIdleOptimization.get()) {
- // JobScheduler requested an early abort.
- return;
- }
- if (sFailedPackageNames.contains(pkg)) {
- // Skip previously failing package
- continue;
- }
-
- long usableSpace = dataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- // Rather bail than completely fill up the disk.
- Log.w(TAG, "Aborting background dex opt job due to low storage: " +
- usableSpace);
- break;
- }
-
- // Conservatively add package to the list of failing ones in case performDexOpt
- // never returns.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.add(pkg);
- }
- // Optimize package if needed. Note that there can be no race between
- // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
- if (pm.performDexOpt(pkg,
- /* checkProfiles */ true,
- PackageManagerService.REASON_BACKGROUND_DEXOPT,
- /* force */ false)) {
- // Dexopt succeeded, remove package from the list of failing ones.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.remove(pkg);
- }
- }
- }
- // Ran to completion, so we abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
+ for (String pkg : pkgs) {
+ if (mAbortIdleOptimization.get()) {
+ // JobScheduler requested an early abort.
+ return;
}
- }.start();
- return true;
+
+ synchronized (sFailedPackageNames) {
+ if (sFailedPackageNames.contains(pkg)) {
+ // Skip previously failing package
+ continue;
+ }
+ }
+
+ long usableSpace = mDataDir.getUsableSpace();
+ if (usableSpace < lowThreshold) {
+ // Rather bail than completely fill up the disk.
+ Log.w(TAG, "Aborting background dex opt job due to low storage: " +
+ usableSpace);
+ break;
+ }
+
+ // Conservatively add package to the list of failing ones in case performDexOpt
+ // never returns.
+ synchronized (sFailedPackageNames) {
+ sFailedPackageNames.add(pkg);
+ }
+ // Optimize package if needed. Note that there can be no race between
+ // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
+ if (pm.performDexOpt(pkg,
+ /* checkProfiles */ true,
+ PackageManagerService.REASON_BACKGROUND_DEXOPT,
+ /* force */ false)) {
+ // Dexopt succeeded, remove package from the list of failing ones.
+ synchronized (sFailedPackageNames) {
+ sFailedPackageNames.remove(pkg);
+ }
+ }
+ }
+ // Ran to completion, so we abandon our timeslice and do not reschedule.
+ jobFinished(jobParams, /* reschedule */ false);
}
@Override
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 5016ec0..a6f9243 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -1013,7 +1013,7 @@
permissions.clear();
}
permissions.add(permissionGrant.name);
- grantRuntimePermissionsLPw(pkg, permissions, false,
+ grantRuntimePermissionsLPw(pkg, permissions,
permissionGrant.fixed, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1f83d9e..98249dd1 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -54,6 +54,7 @@
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
+ public static final int FLAG_USE_QUOTA = 1 << 12;
private final boolean mIsolated;
@@ -198,15 +199,44 @@
}
}
- public void getAppSize(String uuid, String packageName, int userId, int flags, long ceDataInode,
- String codePath, PackageStats stats) throws InstallerException {
+ public void getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId,
+ long[] ceDataInodes, String[] codePaths, PackageStats stats)
+ throws InstallerException {
if (!checkBeforeRemote()) return;
try {
- final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, ceDataInode,
- codePath);
+ final long[] res = mInstalld.getAppSize(uuid, packageNames, userId, flags,
+ appId, ceDataInodes, codePaths);
stats.codeSize += res[0];
stats.dataSize += res[1];
stats.cacheSize += res[2];
+ stats.externalCodeSize += res[3];
+ stats.externalDataSize += res[4];
+ stats.externalCacheSize += res[5];
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats)
+ throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ final long[] res = mInstalld.getUserSize(uuid, userId, flags, appIds);
+ stats.codeSize += res[0];
+ stats.dataSize += res[1];
+ stats.cacheSize += res[2];
+ stats.externalCodeSize += res[3];
+ stats.externalDataSize += res[4];
+ stats.externalCacheSize += res[5];
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public long[] getExternalSize(String uuid, int userId, int flags) throws InstallerException {
+ if (!checkBeforeRemote()) return new long[4];
+ try {
+ return mInstalld.getExternalSize(uuid, userId, flags);
} catch (Exception e) {
throw InstallerException.from(e);
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 30ff32b..aeac7f6 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -217,26 +217,11 @@
dexoptNeeded);
}
- final String dexoptType;
- String oatDir = null;
- boolean isOdexLocation = (dexoptNeeded < 0);
- switch (Math.abs(dexoptNeeded)) {
- case DexFile.NO_DEXOPT_NEEDED:
- continue;
- case DexFile.DEX2OAT_FROM_SCRATCH:
- case DexFile.DEX2OAT_FOR_BOOT_IMAGE:
- case DexFile.DEX2OAT_FOR_FILTER:
- case DexFile.DEX2OAT_FOR_RELOCATION:
- dexoptType = "dex2oat";
- oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
- break;
- case DexFile.PATCHOAT_FOR_RELOCATION:
- dexoptType = "patchoat";
- break;
- default:
- throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
+ if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
+ continue;
}
+ String oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
String sharedLibrariesPath = null;
if (sharedLibraries != null && sharedLibraries.length != 0) {
StringBuilder sb = new StringBuilder();
@@ -248,7 +233,7 @@
}
sharedLibrariesPath = sb.toString();
}
- Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ Log.i(TAG, "Running dexopt on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
+ " target-filter=" + targetCompilerFilter + " oatDir = " + oatDir
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7ce5aa8..7a547f0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -253,6 +253,7 @@
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.pm.Settings.VersionInfo;
+import com.android.server.pm.dex.DexManager;
import com.android.server.storage.DeviceStorageMonitorInternal;
import dalvik.system.CloseGuard;
@@ -295,6 +296,7 @@
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -370,6 +372,9 @@
private static final boolean DISABLE_EPHEMERAL_APPS = false;
private static final boolean HIDE_EPHEMERAL_APIS = true;
+ private static final boolean ENABLE_QUOTA =
+ SystemProperties.getBoolean("persist.fw.quota", false);
+
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
@@ -709,6 +714,9 @@
final PackageInstallerService mInstallerService;
private final PackageDexOptimizer mPackageDexOptimizer;
+ // DexManager handles the usage of dex files (e.g. secondary files, whether or not a package
+ // is used by other apps).
+ private final DexManager mDexManager;
private AtomicInteger mNextMoveId = new AtomicInteger();
private final MoveCallbacks mMoveCallbacks;
@@ -2113,6 +2121,7 @@
mInstaller = installer;
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
+ mDexManager = new DexManager();
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
@@ -2706,6 +2715,21 @@
}
mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this);
+
+ // Read and update the usage of dex files.
+ // Do this at the end of PM init so that all the packages have their
+ // data directory reconciled.
+ // At this point we know the code paths of the packages, so we can validate
+ // the disk file and build the internal cache.
+ // The usage file is expected to be small so loading and verifying it
+ // should take a fairly small time compare to the other activities (e.g. package
+ // scanning).
+ final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
+ final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+ for (int userId : currentUserIds) {
+ userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
+ }
+ mDexManager.load(userPackages);
} // synchronized (mPackages)
} // synchronized (mInstallLock)
@@ -7362,7 +7386,14 @@
@Override
public void notifyDexLoad(String loadingPackageName, List<String> dexPaths, String loaderIsa) {
- // TODO(calin): b/32871170
+ int userId = UserHandle.getCallingUserId();
+ ApplicationInfo ai = getApplicationInfo(loadingPackageName, /*flags*/ 0, userId);
+ if (ai == null) {
+ Slog.w(TAG, "Loading a package that does not exist for the calling user. package="
+ + loadingPackageName + ", user=" + userId);
+ return;
+ }
+ mDexManager.notifyDexLoad(ai, dexPaths, loaderIsa, userId);
}
// TODO: this is not used nor needed. Delete it.
@@ -16878,20 +16909,28 @@
return false;
}
}
+
+ final String[] packageNames = { packageName };
+ final long[] ceDataInodes = { ps.getCeDataInode(userId) };
+ final String[] codePaths = { ps.codePathString };
+
try {
- mInstaller.getAppSize(ps.volumeUuid, packageName, userId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE,
- ps.getCeDataInode(userId), ps.codePathString, stats);
+ mInstaller.getAppSize(ps.volumeUuid, packageNames, userId, 0,
+ ps.appId, ceDataInodes, codePaths, stats);
+
+ // For now, ignore code size of packages on system partition
+ if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) {
+ stats.codeSize = 0;
+ }
+
+ // External clients expect these to be tracked separately
+ stats.dataSize -= stats.cacheSize;
+
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
return false;
}
- // For now, ignore code size of packages on system partition
- if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) {
- stats.codeSize = 0;
- }
-
return true;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index cfd0af7..45887e1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -24,11 +24,13 @@
import android.content.Intent;
import android.content.pm.PackageParser;
import android.content.pm.ResolveInfo;
+import android.os.Build;
import android.os.RemoteException;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.util.ArraySet;
import android.util.Log;
+import dalvik.system.VMRuntime;
import libcore.io.Libcore;
import java.io.File;
@@ -197,4 +199,17 @@
}
return sb.toString();
}
+
+ /**
+ * Verifies that the given string {@code isa} is a valid supported isa on
+ * the running device.
+ */
+ public static boolean checkISA(String isa) {
+ for (String abi : Build.SUPPORTED_ABIS) {
+ if (VMRuntime.getInstructionSet(abi).equals(isa)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
new file mode 100644
index 0000000..6d06838
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2016 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.server.pm.dex;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.ApplicationInfo;
+
+import android.util.Slog;
+
+import com.android.server.pm.PackageManagerServiceUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class keeps track of how dex files are used.
+ * Every time it gets a notification about a dex file being loaded it tracks
+ * its owning package and records it in PackageDexUsage (package-dex-usage.list).
+ *
+ * TODO(calin): Extract related dexopt functionality from PackageManagerService
+ * into this class.
+ */
+public class DexManager {
+ private static final String TAG = "DexManager";
+
+ private static final boolean DEBUG = false;
+
+ // Maps package name to code locations.
+ // It caches the code locations for the installed packages. This allows for
+ // faster lookups (no locks) when finding what package owns the dex file.
+ private final Map<String, PackageCodeLocations> mPackageCodeLocationsCache;
+
+ // PackageDexUsage handles the actual I/O operations. It is responsible to
+ // encode and save the dex usage data.
+ private final PackageDexUsage mPackageDexUsage;
+
+ // Possible outcomes of a dex search.
+ private static int DEX_SEARCH_NOT_FOUND = 0; // dex file not found
+ private static int DEX_SEARCH_FOUND_PRIMARY = 1; // dex file is the primary/base apk
+ private static int DEX_SEARCH_FOUND_SPLIT = 2; // dex file is a split apk
+ private static int DEX_SEARCH_FOUND_SECONDARY = 3; // dex file is a secondary dex
+
+ public DexManager() {
+ mPackageCodeLocationsCache = new HashMap<>();
+ mPackageDexUsage = new PackageDexUsage();
+ }
+
+ /**
+ * Notify about dex files loads.
+ * Note that this method is invoked when apps load dex files and it should
+ * return as fast as possible.
+ *
+ * @param loadingPackage the package performing the load
+ * @param dexPaths the list of dex files being loaded
+ * @param loaderIsa the ISA of the app loading the dex files
+ * @param loaderUserId the user id which runs the code loading the dex files
+ */
+ public void notifyDexLoad(ApplicationInfo loadingAppInfo, List<String> dexPaths,
+ String loaderIsa, int loaderUserId) {
+ try {
+ notifyDexLoadInternal(loadingAppInfo, dexPaths, loaderIsa, loaderUserId);
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception while notifying dex load for package " +
+ loadingAppInfo.packageName, e);
+ }
+ }
+
+ private void notifyDexLoadInternal(ApplicationInfo loadingAppInfo, List<String> dexPaths,
+ String loaderIsa, int loaderUserId) {
+ if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
+ Slog.w(TAG, "Loading dex files " + dexPaths + " in unsupported ISA: " +
+ loaderIsa + "?");
+ return;
+ }
+
+ for (String dexPath : dexPaths) {
+ // Find the owning package name.
+ DexSearchResult searchResult = getDexPackage(loadingAppInfo, dexPath, loaderUserId);
+
+ if (DEBUG) {
+ Slog.i(TAG, loadingAppInfo.packageName
+ + " loads from " + searchResult + " : " + loaderUserId + " : " + dexPath);
+ }
+
+ if (searchResult.mOutcome != DEX_SEARCH_NOT_FOUND) {
+ // TODO(calin): extend isUsedByOtherApps check to detect the cases where
+ // different apps share the same runtime. In that case we should not mark the dex
+ // file as isUsedByOtherApps. Currently this is a safe approximation.
+ boolean isUsedByOtherApps = !loadingAppInfo.packageName.equals(
+ searchResult.mOwningPackageName);
+ boolean primaryOrSplit = searchResult.mOutcome == DEX_SEARCH_FOUND_PRIMARY ||
+ searchResult.mOutcome == DEX_SEARCH_FOUND_SPLIT;
+
+ if (primaryOrSplit && !isUsedByOtherApps) {
+ // If the dex file is the primary apk (or a split) and not isUsedByOtherApps
+ // do not record it. This case does not bring any new usable information
+ // and can be safely skipped.
+ continue;
+ }
+
+ // Record dex file usage. If the current usage is a new pattern (e.g. new secondary,
+ // or UsedBytOtherApps), record will return true and we trigger an async write
+ // to disk to make sure we don't loose the data in case of a reboot.
+ if (mPackageDexUsage.record(searchResult.mOwningPackageName,
+ dexPath, loaderUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit)) {
+ mPackageDexUsage.maybeWriteAsync();
+ }
+ } else {
+ // This can happen in a few situations:
+ // - bogus dex loads
+ // - recent installs/uninstalls that we didn't detect.
+ // - new installed splits
+ // If we can't find the owner of the dex we simply do not track it. The impact is
+ // that the dex file will not be considered for offline optimizations.
+ // TODO(calin): add hooks for install/uninstall notifications to
+ // capture new or obsolete packages.
+ if (DEBUG) {
+ Slog.i(TAG, "Could not find owning package for dex file: " + dexPath);
+ }
+ }
+ }
+ }
+
+ /**
+ * Read the dex usage from disk and populate the code cache locations.
+ * @param existingPackages a map containing information about what packages
+ * are available to what users. Only packages in this list will be
+ * recognized during notifyDexLoad().
+ */
+ public void load(Map<Integer, List<PackageInfo>> existingPackages) {
+ try {
+ loadInternal(existingPackages);
+ } catch (Exception e) {
+ mPackageDexUsage.clear();
+ Slog.w(TAG, "Exception while loading package dex usage. " +
+ "Starting with a fresh state.", e);
+ }
+ }
+
+ private void loadInternal(Map<Integer, List<PackageInfo>> existingPackages) {
+ Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
+ // Cache the code locations for the installed packages. This allows for
+ // faster lookups (no locks) when finding what package owns the dex file.
+ for (Map.Entry<Integer, List<PackageInfo>> entry : existingPackages.entrySet()) {
+ List<PackageInfo> packageInfoList = entry.getValue();
+ int userId = entry.getKey();
+ for (PackageInfo pi : packageInfoList) {
+ // Cache the code locations.
+ PackageCodeLocations pcl = mPackageCodeLocationsCache.get(pi.packageName);
+ if (pcl != null) {
+ pcl.mergeAppDataDirs(pi.applicationInfo, userId);
+ } else {
+ mPackageCodeLocationsCache.put(pi.packageName,
+ new PackageCodeLocations(pi.applicationInfo, userId));
+ }
+ // Cache a map from package name to the set of user ids who installed the package.
+ // We will use it to sync the data and remove obsolete entries from
+ // mPackageDexUsage.
+ Set<Integer> users = putIfAbsent(
+ packageToUsersMap, pi.packageName, new HashSet<>());
+ users.add(userId);
+ }
+ }
+
+ mPackageDexUsage.read();
+ mPackageDexUsage.syncData(packageToUsersMap);
+ }
+
+ /**
+ * Get the package dex usage for the given package name.
+ * @return the package data or null if there is no data available for this package.
+ */
+ public PackageDexUsage.PackageUseInfo getPackageUseInfo(String packageName) {
+ return mPackageDexUsage.getPackageUseInfo(packageName);
+ }
+
+ /**
+ * Retrieves the package which owns the given dexPath.
+ */
+ private DexSearchResult getDexPackage(
+ ApplicationInfo loadingAppInfo, String dexPath, int userId) {
+ // Ignore framework code.
+ // TODO(calin): is there a better way to detect it?
+ if (dexPath.startsWith("/system/framework/")) {
+ new DexSearchResult("framework", DEX_SEARCH_NOT_FOUND);
+ }
+
+ // First, check if the package which loads the dex file actually owns it.
+ // Most of the time this will be true and we can return early.
+ PackageCodeLocations loadingPackageCodeLocations =
+ new PackageCodeLocations(loadingAppInfo, userId);
+ int outcome = loadingPackageCodeLocations.searchDex(dexPath, userId);
+ if (outcome != DEX_SEARCH_NOT_FOUND) {
+ // TODO(calin): evaluate if we bother to detect symlinks at the dexPath level.
+ return new DexSearchResult(loadingPackageCodeLocations.mPackageName, outcome);
+ }
+
+ // The loadingPackage does not own the dex file.
+ // Perform a reverse look-up in the cache to detect if any package has ownership.
+ // Note that we can have false negatives if the cache falls out of date.
+ for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) {
+ outcome = pcl.searchDex(dexPath, userId);
+ if (outcome != DEX_SEARCH_NOT_FOUND) {
+ return new DexSearchResult(pcl.mPackageName, outcome);
+ }
+ }
+
+ // Cache miss. Return not found for the moment.
+ //
+ // TODO(calin): this may be because of a newly installed package, an update
+ // or a new added user. We can either perform a full look up again or register
+ // observers to be notified of package/user updates.
+ return new DexSearchResult(null, DEX_SEARCH_NOT_FOUND);
+ }
+
+ private static <K,V> V putIfAbsent(Map<K,V> map, K key, V newValue) {
+ V existingValue = map.putIfAbsent(key, newValue);
+ return existingValue == null ? newValue : existingValue;
+ }
+
+ /**
+ * Convenience class to store the different locations where a package might
+ * own code.
+ */
+ private static class PackageCodeLocations {
+ private final String mPackageName;
+ private final String mBaseCodePath;
+ private final Set<String> mSplitCodePaths;
+ // Maps user id to the application private directory.
+ private final Map<Integer, Set<String>> mAppDataDirs;
+
+ public PackageCodeLocations(ApplicationInfo ai, int userId) {
+ mPackageName = ai.packageName;
+ mBaseCodePath = ai.sourceDir;
+ mSplitCodePaths = new HashSet<>();
+ if (ai.splitSourceDirs != null) {
+ for (String split : ai.splitSourceDirs) {
+ mSplitCodePaths.add(split);
+ }
+ }
+ mAppDataDirs = new HashMap<>();
+ mergeAppDataDirs(ai, userId);
+ }
+
+ public void mergeAppDataDirs(ApplicationInfo ai, int userId) {
+ Set<String> dataDirs = putIfAbsent(mAppDataDirs, userId, new HashSet<>());
+ dataDirs.add(ai.dataDir);
+ }
+
+ public int searchDex(String dexPath, int userId) {
+ // First check that this package is installed or active for the given user.
+ // If we don't have a data dir it means this user is trying to load something
+ // unavailable for them.
+ Set<String> userDataDirs = mAppDataDirs.get(userId);
+ if (userDataDirs == null) {
+ Slog.w(TAG, "Trying to load a dex path which does not exist for the current " +
+ "user. dexPath=" + dexPath + ", userId=" + userId);
+ return DEX_SEARCH_NOT_FOUND;
+ }
+
+ if (mBaseCodePath.equals(dexPath)) {
+ return DEX_SEARCH_FOUND_PRIMARY;
+ }
+ if (mSplitCodePaths.contains(dexPath)) {
+ return DEX_SEARCH_FOUND_SPLIT;
+ }
+ for (String dataDir : userDataDirs) {
+ if (dexPath.startsWith(dataDir)) {
+ return DEX_SEARCH_FOUND_SECONDARY;
+ }
+ }
+
+ // TODO(calin): What if we get a symlink? e.g. data dir may be a symlink,
+ // /data/data/ -> /data/user/0/.
+ if (DEBUG) {
+ try {
+ String dexPathReal = PackageManagerServiceUtils.realpath(new File(dexPath));
+ if (dexPathReal != dexPath) {
+ Slog.d(TAG, "Dex loaded with symlink. dexPath=" +
+ dexPath + " dexPathReal=" + dexPathReal);
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ return DEX_SEARCH_NOT_FOUND;
+ }
+ }
+
+ /**
+ * Convenience class to store ownership search results.
+ */
+ private class DexSearchResult {
+ private String mOwningPackageName;
+ private int mOutcome;
+
+ public DexSearchResult(String owningPackageName, int outcome) {
+ this.mOwningPackageName = owningPackageName;
+ this.mOutcome = outcome;
+ }
+
+ @Override
+ public String toString() {
+ return mOwningPackageName + "-" + mOutcome;
+ }
+ }
+
+
+}
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
new file mode 100644
index 0000000..10384a2
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2016 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.server.pm.dex;
+
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.os.Build;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.FastPrintWriter;
+import com.android.server.pm.AbstractStatsBase;
+import com.android.server.pm.PackageManagerServiceUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import dalvik.system.VMRuntime;
+import libcore.io.IoUtils;
+
+/**
+ * Stat file which store usage information about dex files.
+ */
+public class PackageDexUsage extends AbstractStatsBase<Void> {
+ private final static String TAG = "PackageDexUsage";
+
+ private final static int PACKAGE_DEX_USAGE_VERSION = 1;
+ private final static String PACKAGE_DEX_USAGE_VERSION_HEADER =
+ "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__";
+
+ private final static String SPLIT_CHAR = ",";
+ private final static String DEX_LINE_CHAR = "#";
+
+ // Map which structures the information we have on a package.
+ // Maps package name to package data (which stores info about UsedByOtherApps and
+ // secondary dex files.).
+ // Access to this map needs synchronized.
+ @GuardedBy("mPackageUseInfoMap")
+ private Map<String, PackageUseInfo> mPackageUseInfoMap;
+
+ public PackageDexUsage() {
+ super("package-dex-usage.list", "PackageDexUsage_DiskWriter", /*lock*/ false);
+ mPackageUseInfoMap = new HashMap<>();
+ }
+
+ /**
+ * Record a dex file load.
+ *
+ * Note this is called when apps load dex files and as such it should return
+ * as fast as possible.
+ *
+ * @param loadingPackage the package performing the load
+ * @param dexPath the path of the dex files being loaded
+ * @param ownerUserId the user id which runs the code loading the dex files
+ * @param loaderIsa the ISA of the app loading the dex files
+ * @param isUsedByOtherApps whether or not this dex file was not loaded by its owning package
+ * @param primaryOrSplit whether or not the dex file is a primary/split dex. True indicates
+ * the file is either primary or a split. False indicates the file is secondary dex.
+ * @return true if the dex load constitutes new information, or false if this information
+ * has been seen before.
+ */
+ public boolean record(String owningPackageName, String dexPath, int ownerUserId,
+ String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit) {
+ if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
+ throw new IllegalArgumentException("loaderIsa " + loaderIsa + " is unsupported");
+ }
+ synchronized (mPackageUseInfoMap) {
+ PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(owningPackageName);
+ if (packageUseInfo == null) {
+ // This is the first time we see the package.
+ packageUseInfo = new PackageUseInfo();
+ if (primaryOrSplit) {
+ // If we have a primary or a split apk, set isUsedByOtherApps.
+ // We do not need to record the loaderIsa or the owner because we compile
+ // primaries for all users and all ISAs.
+ packageUseInfo.mIsUsedByOtherApps = isUsedByOtherApps;
+ } else {
+ // For secondary dex files record the loaderISA and the owner. We'll need
+ // to know under which user to compile and for what ISA.
+ packageUseInfo.mDexUseInfoMap.put(
+ dexPath, new DexUseInfo(isUsedByOtherApps, ownerUserId, loaderIsa));
+ }
+ mPackageUseInfoMap.put(owningPackageName, packageUseInfo);
+ return true;
+ } else {
+ // We already have data on this package. Amend it.
+ if (primaryOrSplit) {
+ // We have a possible update on the primary apk usage. Merge
+ // isUsedByOtherApps information and return if there was an update.
+ return packageUseInfo.merge(isUsedByOtherApps);
+ } else {
+ DexUseInfo newData = new DexUseInfo(
+ isUsedByOtherApps, ownerUserId, loaderIsa);
+ DexUseInfo existingData = packageUseInfo.mDexUseInfoMap.get(dexPath);
+ if (existingData == null) {
+ // It's the first time we see this dex file.
+ packageUseInfo.mDexUseInfoMap.put(dexPath, newData);
+ return true;
+ } else {
+ if (ownerUserId != existingData.mOwnerUserId) {
+ // Oups, this should never happen, the DexManager who calls this should
+ // do the proper checks and not call record if the user does not own the
+ // dex path.
+ // Secondary dex files are stored in the app user directory. A change in
+ // owningUser for the same path means that something went wrong at some
+ // higher level, and the loaderUser was allowed to cross
+ // user-boundaries and access data from what we know to be the owner
+ // user.
+ throw new IllegalArgumentException("Trying to change ownerUserId for "
+ + " dex path " + dexPath + " from " + existingData.mOwnerUserId
+ + " to " + ownerUserId);
+ }
+ // Merge the information into the existing data.
+ // Returns true if there was an update.
+ return existingData.merge(newData);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Convenience method for sync reads which does not force the user to pass a useless
+ * (Void) null.
+ */
+ public void read() {
+ read((Void) null);
+ }
+
+ /**
+ * Convenience method for async writes which does not force the user to pass a useless
+ * (Void) null.
+ */
+ public void maybeWriteAsync() {
+ maybeWriteAsync((Void) null);
+ }
+
+ @Override
+ protected void writeInternal(Void data) {
+ AtomicFile file = getFile();
+ FileOutputStream f = null;
+
+ try {
+ f = file.startWrite();
+ OutputStreamWriter osw = new OutputStreamWriter(f);
+ write(osw);
+ osw.flush();
+ file.finishWrite(f);
+ } catch (IOException e) {
+ if (f != null) {
+ file.failWrite(f);
+ }
+ Slog.e(TAG, "Failed to write usage for dex files", e);
+ }
+ }
+
+ /**
+ * File format:
+ *
+ * file_magic_version
+ * package_name_1
+ * #dex_file_path_1_1
+ * user_1_1, used_by_other_app_1_1, user_isa_1_1_1, user_isa_1_1_2
+ * #dex_file_path_1_2
+ * user_1_2, used_by_other_app_1_2, user_isa_1_2_1, user_isa_1_2_2
+ * ...
+ * package_name_2
+ * #dex_file_path_2_1
+ * user_2_1, used_by_other_app_2_1, user_isa_2_1_1, user_isa_2_1_2
+ * #dex_file_path_2_2,
+ * user_2_2, used_by_other_app_2_2, user_isa_2_2_1, user_isa_2_2_2
+ * ...
+ */
+ /* package */ void write(Writer out) {
+ // Make a clone to avoid locking while writing to disk.
+ Map<String, PackageUseInfo> packageUseInfoMapClone = clonePackageUseInfoMap();
+
+ FastPrintWriter fpw = new FastPrintWriter(out);
+
+ // Write the header.
+ fpw.print(PACKAGE_DEX_USAGE_VERSION_HEADER);
+ fpw.println(PACKAGE_DEX_USAGE_VERSION);
+
+ for (Map.Entry<String, PackageUseInfo> pEntry : packageUseInfoMapClone.entrySet()) {
+ // Write the package line.
+ String packageName = pEntry.getKey();
+ PackageUseInfo packageUseInfo = pEntry.getValue();
+
+ fpw.println(String.join(SPLIT_CHAR, packageName,
+ writeBoolean(packageUseInfo.mIsUsedByOtherApps)));
+
+ // Write dex file lines.
+ for (Map.Entry<String, DexUseInfo> dEntry : packageUseInfo.mDexUseInfoMap.entrySet()) {
+ String dexPath = dEntry.getKey();
+ DexUseInfo dexUseInfo = dEntry.getValue();
+ fpw.println(DEX_LINE_CHAR + dexPath);
+ fpw.print(String.join(SPLIT_CHAR, Integer.toString(dexUseInfo.mOwnerUserId),
+ writeBoolean(dexUseInfo.mIsUsedByOtherApps)));
+ for (String isa : dexUseInfo.mLoaderIsas) {
+ fpw.print(SPLIT_CHAR + isa);
+ }
+ fpw.println();
+ }
+ }
+ fpw.flush();
+ }
+
+ @Override
+ protected void readInternal(Void data) {
+ AtomicFile file = getFile();
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new InputStreamReader(file.openRead()));
+ read(in);
+ } catch (FileNotFoundException expected) {
+ // The file may not be there. E.g. When we first take the OTA with this feature.
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to parse package dex usage.", e);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ /* package */ void read(Reader reader) throws IOException {
+ Map<String, PackageUseInfo> data = new HashMap<>();
+ BufferedReader in = new BufferedReader(reader);
+ // Read header, do version check.
+ String versionLine = in.readLine();
+ if (versionLine == null) {
+ throw new IllegalStateException("No version line found.");
+ } else {
+ if (!versionLine.startsWith(PACKAGE_DEX_USAGE_VERSION_HEADER)) {
+ // TODO(calin): the caller is responsible to clear the file.
+ throw new IllegalStateException("Invalid version line: " + versionLine);
+ }
+ int version = Integer.parseInt(
+ versionLine.substring(PACKAGE_DEX_USAGE_VERSION_HEADER.length()));
+ if (version != PACKAGE_DEX_USAGE_VERSION) {
+ throw new IllegalStateException("Unexpected version: " + version);
+ }
+ }
+
+ String s = null;
+ String currentPakage = null;
+ PackageUseInfo currentPakageData = null;
+
+ Set<String> supportedIsas = new HashSet<>();
+ for (String abi : Build.SUPPORTED_ABIS) {
+ supportedIsas.add(VMRuntime.getInstructionSet(abi));
+ }
+ while ((s = in.readLine()) != null) {
+ if (s.startsWith(DEX_LINE_CHAR)) {
+ // This is the start of the the dex lines.
+ // We expect two lines for each dex entry:
+ // #dexPaths
+ // onwerUserId,isUsedByOtherApps,isa1,isa2
+ if (currentPakage == null) {
+ throw new IllegalStateException(
+ "Malformed PackageDexUsage file. Expected package line before dex line.");
+ }
+
+ // First line is the dex path.
+ String dexPath = s.substring(DEX_LINE_CHAR.length());
+ // Next line is the dex data.
+ s = in.readLine();
+ if (s == null) {
+ throw new IllegalStateException("Could not fine dexUseInfo for line: " + s);
+ }
+
+ // We expect at least 3 elements (isUsedByOtherApps, userId, isa).
+ String[] elems = s.split(SPLIT_CHAR);
+ if (elems.length < 3) {
+ throw new IllegalStateException("Invalid PackageDexUsage line: " + s);
+ }
+ int ownerUserId = Integer.parseInt(elems[0]);
+ boolean isUsedByOtherApps = readBoolean(elems[1]);
+ DexUseInfo dexUseInfo = new DexUseInfo(isUsedByOtherApps, ownerUserId);
+ for (int i = 2; i < elems.length; i++) {
+ String isa = elems[i];
+ if (supportedIsas.contains(isa)) {
+ dexUseInfo.mLoaderIsas.add(elems[i]);
+ } else {
+ // Should never happen unless someone crafts the file manually.
+ // In theory it could if we drop a supported ISA after an OTA but we don't
+ // do that.
+ Slog.wtf(TAG, "Unsupported ISA when parsing PackageDexUsage: " + isa);
+ }
+ }
+ if (supportedIsas.isEmpty()) {
+ Slog.wtf(TAG, "Ignore dexPath when parsing PackageDexUsage because of " +
+ "unsupported isas. dexPath=" + dexPath);
+ continue;
+ }
+ currentPakageData.mDexUseInfoMap.put(dexPath, dexUseInfo);
+ } else {
+ // This is a package line.
+ // We expect it to be: `packageName,isUsedByOtherApps`.
+ String[] elems = s.split(SPLIT_CHAR);
+ if (elems.length != 2) {
+ throw new IllegalStateException("Invalid PackageDexUsage line: " + s);
+ }
+ currentPakage = elems[0];
+ currentPakageData = new PackageUseInfo();
+ currentPakageData.mIsUsedByOtherApps = readBoolean(elems[1]);
+ data.put(currentPakage, currentPakageData);
+ }
+ }
+
+ synchronized (mPackageUseInfoMap) {
+ mPackageUseInfoMap.clear();
+ mPackageUseInfoMap.putAll(data);
+ }
+ }
+
+ /**
+ * Syncs the existing data with the set of available packages by removing obsolete entries.
+ */
+ public void syncData(Map<String, Set<Integer>> packageToUsersMap) {
+ synchronized (mPackageUseInfoMap) {
+ Iterator<Map.Entry<String, PackageUseInfo>> pIt =
+ mPackageUseInfoMap.entrySet().iterator();
+ while (pIt.hasNext()) {
+ Map.Entry<String, PackageUseInfo> pEntry = pIt.next();
+ String packageName = pEntry.getKey();
+ PackageUseInfo packageUseInfo = pEntry.getValue();
+ Set<Integer> users = packageToUsersMap.get(packageName);
+ if (users == null) {
+ // The package doesn't exist anymore, remove the record.
+ pIt.remove();
+ } else {
+ // The package exists but we can prune the entries associated with non existing
+ // users.
+ Iterator<Map.Entry<String, DexUseInfo>> dIt =
+ packageUseInfo.mDexUseInfoMap.entrySet().iterator();
+ while (dIt.hasNext()) {
+ DexUseInfo dexUseInfo = dIt.next().getValue();
+ if (!users.contains(dexUseInfo.mOwnerUserId)) {
+ // User was probably removed. Delete its dex usage info.
+ dIt.remove();
+ }
+ }
+ if (!packageUseInfo.mIsUsedByOtherApps
+ && packageUseInfo.mDexUseInfoMap.isEmpty()) {
+ // The package is not used by other apps and we removed all its dex files
+ // records. Remove the entire package record as well.
+ pIt.remove();
+ }
+ }
+ }
+ }
+ }
+
+ public PackageUseInfo getPackageUseInfo(String packageName) {
+ synchronized (mPackageUseInfoMap) {
+ return mPackageUseInfoMap.get(packageName);
+ }
+ }
+
+ public void clear() {
+ synchronized (mPackageUseInfoMap) {
+ mPackageUseInfoMap.clear();
+ }
+ }
+ // Creates a deep copy of the class' mPackageUseInfoMap.
+ private Map<String, PackageUseInfo> clonePackageUseInfoMap() {
+ Map<String, PackageUseInfo> clone = new HashMap<>();
+ synchronized (mPackageUseInfoMap) {
+ for (Map.Entry<String, PackageUseInfo> e : mPackageUseInfoMap.entrySet()) {
+ clone.put(e.getKey(), new PackageUseInfo(e.getValue()));
+ }
+ }
+ return clone;
+ }
+
+ private String writeBoolean(boolean bool) {
+ return bool ? "1" : "0";
+ }
+
+ private boolean readBoolean(String bool) {
+ if ("0".equals(bool)) return false;
+ if ("1".equals(bool)) return true;
+ throw new IllegalArgumentException("Unknown bool encoding: " + bool);
+ }
+
+ private boolean contains(int[] array, int elem) {
+ for (int i = 0; i < array.length; i++) {
+ if (elem == array[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String dump() {
+ StringWriter sw = new StringWriter();
+ write(sw);
+ return sw.toString();
+ }
+
+ /**
+ * Stores data on how a package and its dex files are used.
+ */
+ public static class PackageUseInfo {
+ // This flag is for the primary and split apks. It is set to true whenever one of them
+ // is loaded by another app.
+ private boolean mIsUsedByOtherApps;
+ // Map dex paths to their data (isUsedByOtherApps, owner id, loader isa).
+ private final Map<String, DexUseInfo> mDexUseInfoMap;
+
+ public PackageUseInfo() {
+ mIsUsedByOtherApps = false;
+ mDexUseInfoMap = new HashMap<>();
+ }
+
+ // Creates a deep copy of the `other`.
+ public PackageUseInfo(PackageUseInfo other) {
+ mIsUsedByOtherApps = other.mIsUsedByOtherApps;
+ mDexUseInfoMap = new HashMap<>();
+ for (Map.Entry<String, DexUseInfo> e : other.mDexUseInfoMap.entrySet()) {
+ mDexUseInfoMap.put(e.getKey(), new DexUseInfo(e.getValue()));
+ }
+ }
+
+ private boolean merge(boolean isUsedByOtherApps) {
+ boolean oldIsUsedByOtherApps = mIsUsedByOtherApps;
+ mIsUsedByOtherApps = mIsUsedByOtherApps || isUsedByOtherApps;
+ return oldIsUsedByOtherApps != this.mIsUsedByOtherApps;
+ }
+
+ public boolean isUsedByOtherApps() {
+ return mIsUsedByOtherApps;
+ }
+
+ public Map<String, DexUseInfo> getDexUseInfoMap() {
+ return mDexUseInfoMap;
+ }
+ }
+
+ /**
+ * Stores data about a loaded dex files.
+ */
+ public static class DexUseInfo {
+ private boolean mIsUsedByOtherApps;
+ private final int mOwnerUserId;
+ private final Set<String> mLoaderIsas;
+
+ public DexUseInfo(boolean isUsedByOtherApps, int ownerUserId) {
+ this(isUsedByOtherApps, ownerUserId, null);
+ }
+
+ public DexUseInfo(boolean isUsedByOtherApps, int ownerUserId, String loaderIsa) {
+ mIsUsedByOtherApps = isUsedByOtherApps;
+ mOwnerUserId = ownerUserId;
+ mLoaderIsas = new HashSet<>();
+ if (loaderIsa != null) {
+ mLoaderIsas.add(loaderIsa);
+ }
+ }
+
+ // Creates a deep copy of the `other`.
+ public DexUseInfo(DexUseInfo other) {
+ mIsUsedByOtherApps = other.mIsUsedByOtherApps;
+ mOwnerUserId = other.mOwnerUserId;
+ mLoaderIsas = new HashSet<>(other.mLoaderIsas);
+ }
+
+ private boolean merge(DexUseInfo dexUseInfo) {
+ boolean oldIsUsedByOtherApps = mIsUsedByOtherApps;
+ mIsUsedByOtherApps = mIsUsedByOtherApps || dexUseInfo.mIsUsedByOtherApps;
+ boolean updateIsas = mLoaderIsas.addAll(dexUseInfo.mLoaderIsas);
+ return updateIsas || (oldIsUsedByOtherApps != mIsUsedByOtherApps);
+ }
+
+ public boolean isUsedByOtherApps() {
+ return mIsUsedByOtherApps;
+ }
+
+ public int getOwnerUserId() {
+ return mOwnerUserId;
+ }
+
+ public Set<String> getLoaderIsas() {
+ return mLoaderIsas;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
index b260e4e..b704eb1 100644
--- a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
@@ -20,7 +20,7 @@
import java.io.File;
import java.io.IOException;
-import libcore.tzdata.update.TzDataBundleInstaller;
+import libcore.tzdata.update2.TimeZoneBundleInstaller;
/**
* An install receiver responsible for installing timezone data updates.
@@ -29,18 +29,19 @@
private static final String TAG = "TZDataInstallReceiver";
+ private static final File SYSTEM_TZ_DATA_FILE = new File("/system/usr/share/zoneinfo/tzdata");
private static final File TZ_DATA_DIR = new File("/data/misc/zoneinfo");
private static final String UPDATE_DIR_NAME = TZ_DATA_DIR.getPath() + "/updates/";
private static final String UPDATE_METADATA_DIR_NAME = "metadata/";
private static final String UPDATE_VERSION_FILE_NAME = "version";
private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_bundle.zip";
- private final TzDataBundleInstaller installer;
+ private final TimeZoneBundleInstaller installer;
public TzDataInstallReceiver() {
super(UPDATE_DIR_NAME, UPDATE_CONTENT_FILE_NAME, UPDATE_METADATA_DIR_NAME,
UPDATE_VERSION_FILE_NAME);
- installer = new TzDataBundleInstaller(TAG, TZ_DATA_DIR);
+ installer = new TimeZoneBundleInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR);
}
@Override
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index ecdc71e..531f946 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -17,30 +17,30 @@
#define LOG_TAG "BatteryStatsService"
//#define LOG_NDEBUG 0
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
#include <android_runtime/AndroidRuntime.h>
#include <jni.h>
#include <ScopedLocalRef.h>
#include <ScopedPrimitiveArray.h>
-#include <cutils/log.h>
+#include <log/log.h>
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/power.h>
#include <suspend/autosuspend.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <semaphore.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
namespace android
{
diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp
index c54d732..4d85d9a 100644
--- a/services/core/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp
@@ -17,24 +17,25 @@
#define LOG_NDEBUG 0
#define LOG_TAG "VpnJni"
-#include <cutils/log.h>
-#include "netutils/ifc.h"
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
-
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/route.h>
#include <linux/ipv6_route.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+
+#include "netutils/ifc.h"
#include "jni.h"
#include "JNIHelp.h"
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 2187c57..336351e 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -30,7 +30,7 @@
LOCAL_CERTIFICATE := platform
# These are not normally accessible from apps so they must be explicitly included.
-LOCAL_JNI_SHARED_LIBRARIES := libservicestestsjni \
+LOCAL_JNI_SHARED_LIBRARIES := \
libbacktrace \
libbase \
libbinder \
@@ -47,36 +47,3 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_PACKAGE)
-
-#########################################################################
-# Build JNI Shared Library
-#########################################################################
-
-LOCAL_PATH:= $(LOCAL_PATH)/jni
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Wall -Wextra -Werror
-
-LOCAL_C_INCLUDES := \
- libpcap \
- hardware/google/apf
-
-LOCAL_SRC_FILES := $(call all-cpp-files-under)
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- liblog \
- libcutils \
- libnativehelper \
- libnetdaidl
-
-LOCAL_STATIC_LIBRARIES := \
- libpcap \
- libapf
-
-LOCAL_MODULE := libservicestestsjni
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 69d27f2..1189dae 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -23,6 +23,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -53,6 +54,7 @@
import android.net.INetworkRecommendationProvider;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.RecommendationRequest;
@@ -60,6 +62,7 @@
import android.net.ScoredNetwork;
import android.net.WifiKey;
import android.net.wifi.WifiConfiguration;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -134,9 +137,10 @@
mNetworkScoreService.systemRunning();
- verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
- new ComponentName(NEW_SCORER.packageName,
- NEW_SCORER.recommendationServiceClassName))),
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(new ComponentName(NEW_SCORER.packageName,
+ NEW_SCORER.recommendationServiceClassName))),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
@@ -145,11 +149,11 @@
@Test
public void testRequestScores_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
- .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestScores(null);
- fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
+ fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
@@ -182,11 +186,11 @@
@Test
public void testRequestRecommendation_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
- .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
- fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
+ fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
@@ -259,7 +263,7 @@
@Test
public void testUpdateScores_notActiveScorer() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ bindToScorer(false /*callerIsScorer*/);
try {
mNetworkScoreService.updateScores(new ScoredNetwork[0]);
@@ -271,7 +275,7 @@
@Test
public void testUpdateScores_oneRegisteredCache() throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mNetworkScoreCache, CACHE_FILTER_NONE);
@@ -286,7 +290,7 @@
@Test
public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mNetworkScoreCache, CACHE_FILTER_NONE);
@@ -320,9 +324,9 @@
}
@Test
- public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
+ bindToScorer(false /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.clearScores();
@@ -333,9 +337,9 @@
}
@Test
- public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
+ bindToScorer(true /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
mNetworkScoreService.clearScores();
@@ -343,7 +347,7 @@
@Test
public void testClearScores_activeScorer() throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
@@ -353,10 +357,10 @@
}
@Test
- public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
+ public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ bindToScorer(false /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
@@ -380,9 +384,9 @@
}
@Test
- public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
+ bindToScorer(false /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
@@ -394,9 +398,9 @@
}
@Test
- public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
- eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+ eq(permission.REQUEST_NETWORK_SCORES), anyString());
try {
mNetworkScoreService.registerNetworkScoreCache(
@@ -408,9 +412,9 @@
}
@Test
- public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
- eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+ eq(permission.REQUEST_NETWORK_SCORES), anyString());
try {
mNetworkScoreService.unregisterNetworkScoreCache(
@@ -446,6 +450,42 @@
assertFalse(stringWriter.toString().isEmpty());
}
+ @Test
+ public void testIsCallerActiveScorer_noBoundService() throws Exception {
+ mNetworkScoreService.systemRunning();
+
+ assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ }
+
+ @Test
+ public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
+ bindToScorer(false /*callerIsScorer*/);
+
+ assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ }
+
+ @Test
+ public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
+ bindToScorer(true /*callerIsScorer*/);
+
+ assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ }
+
+ @Test
+ public void testGetActiveScorerPackage_notActive() throws Exception {
+ mNetworkScoreService.systemRunning();
+
+ assertNull(mNetworkScoreService.getActiveScorerPackage());
+ }
+
+ @Test
+ public void testGetActiveScorerPackage_active() throws Exception {
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
+ mNetworkScoreService.systemRunning();
+
+ assertEquals(NEW_SCORER.packageName, mNetworkScoreService.getActiveScorerPackage());
+ }
+
// "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
private void injectProvider() {
final ComponentName componentName = new ComponentName(NEW_SCORER.packageName,
@@ -465,4 +505,14 @@
});
mNetworkScoreService.systemRunning();
}
+
+ private void bindToScorer(boolean callerIsScorer) {
+ final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
+ NetworkScorerAppData appData = new NetworkScorerAppData(NEW_SCORER.packageName,
+ callingUid, NEW_SCORER.recommendationServiceClassName);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
+ when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
+ isA(UserHandle.class))).thenReturn(true);
+ mNetworkScoreService.systemRunning();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
new file mode 100644
index 0000000..2a7cbc2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.server.pm;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageStats;
+import android.os.UserHandle;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+
+public class InstallerTest extends AndroidTestCase {
+ private static final String TAG = "InstallerTest";
+
+ private Installer mInstaller;
+
+ @Override
+ public void setUp() throws Exception {
+ mInstaller = new Installer(getContext());
+ mInstaller.onStart();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mInstaller = null;
+ }
+
+ public void testGetAppSize() throws Exception {
+ final PackageManager pm = getContext().getPackageManager();
+ for (ApplicationInfo app : pm.getInstalledApplications(0)) {
+ final int userId = UserHandle.getUserId(app.uid);
+ final int appId = UserHandle.getAppId(app.uid);
+
+ final String[] packageNames = pm.getPackagesForUid(app.uid);
+ final long[] ceDataInodes = new long[packageNames.length];
+ final String[] codePaths = new String[packageNames.length];
+
+ for (int i = 0; i < packageNames.length; i++) {
+ final ApplicationInfo info = pm.getApplicationInfo(packageNames[i], 0);
+ codePaths[i] = info.getCodePath();
+ }
+
+ final PackageStats stats = new PackageStats(app.packageName);
+ final PackageStats quotaStats = new PackageStats(app.packageName);
+
+ mInstaller.getAppSize(app.volumeUuid, packageNames, userId, 0,
+ appId, ceDataInodes, codePaths, stats);
+
+ mInstaller.getAppSize(app.volumeUuid, packageNames, userId, Installer.FLAG_USE_QUOTA,
+ appId, ceDataInodes, codePaths, quotaStats);
+
+ checkEquals(Arrays.toString(packageNames) + " UID=" + app.uid, stats, quotaStats);
+ }
+ }
+
+ public void testGetUserSize() throws Exception {
+ int[] appIds = null;
+
+ final PackageManager pm = getContext().getPackageManager();
+ for (ApplicationInfo app : pm.getInstalledApplications(0)) {
+ final int appId = UserHandle.getAppId(app.uid);
+ if (!ArrayUtils.contains(appIds, appId)) {
+ appIds = ArrayUtils.appendInt(appIds, appId);
+ }
+ }
+
+ final PackageStats stats = new PackageStats("android");
+ final PackageStats quotaStats = new PackageStats("android");
+
+ mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, 0,
+ appIds, stats);
+
+ mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, Installer.FLAG_USE_QUOTA,
+ appIds, quotaStats);
+
+ checkEquals(Arrays.toString(appIds), stats, quotaStats);
+ }
+
+ public void testGetExternalSize() throws Exception {
+
+ final long[] stats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, 0);
+
+ final long[] quotaStats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM,
+ Installer.FLAG_USE_QUOTA);
+
+ for (int i = 0; i < stats.length; i++) {
+ checkEquals("#" + i, stats[i], quotaStats[i]);
+ }
+ }
+
+ private static void checkEquals(String msg, PackageStats a, PackageStats b) {
+ checkEquals(msg + " codeSize", a.codeSize, b.codeSize);
+ checkEquals(msg + " dataSize", a.dataSize, b.dataSize);
+ checkEquals(msg + " cacheSize", a.cacheSize, b.cacheSize);
+ checkEquals(msg + " externalCodeSize", a.externalCodeSize, b.externalCodeSize);
+ checkEquals(msg + " externalDataSize", a.externalDataSize, b.externalDataSize);
+ checkEquals(msg + " externalCacheSize", a.externalCacheSize, b.externalCacheSize);
+ }
+
+ private static void checkEquals(String msg, long expected, long actual) {
+ if (expected != actual) {
+ Log.e(TAG, msg + " expected " + expected + " actual " + actual);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
new file mode 100644
index 0000000..b655f3a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2016 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.server.pm.dex;
+
+import android.os.Build;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import dalvik.system.VMRuntime;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
+import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DexManagerTests {
+ private DexManager mDexManager;
+
+ private TestData mFooUser0;
+ private TestData mBarUser0;
+ private TestData mBarUser1;
+ private TestData mInvalidIsa;
+ private TestData mDoesNotExist;
+
+ private int mUser0;
+ private int mUser1;
+ @Before
+ public void setup() {
+
+ mUser0 = 0;
+ mUser1 = 1;
+
+ String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+ String foo = "foo";
+ String bar = "bar";
+
+ mFooUser0 = new TestData(foo, isa, mUser0);
+ mBarUser0 = new TestData(bar, isa, mUser0);
+ mBarUser1 = new TestData(bar, isa, mUser1);
+ mInvalidIsa = new TestData("INVALID", "INVALID_ISA", mUser0);
+ mDoesNotExist = new TestData("DOES.NOT.EXIST", isa, mUser1);
+
+
+ mDexManager = new DexManager();
+
+ // Foo and Bar are available to user0.
+ // Only Bar is available to user1;
+ Map<Integer, List<PackageInfo>> existingPackages = new HashMap<>();
+ existingPackages.put(mUser0, Arrays.asList(mFooUser0.mPackageInfo, mBarUser0.mPackageInfo));
+ existingPackages.put(mUser1, Arrays.asList(mBarUser1.mPackageInfo));
+ mDexManager.load(existingPackages);
+ }
+
+ @Test
+ public void testNotifyPrimaryUse() {
+ // The main dex file and splits are re-loaded by the app.
+ notifyDexLoad(mFooUser0, mFooUser0.getBaseAndSplitDexPaths(), mUser0);
+
+ // Package is not used by others, so we should get nothing back.
+ assertNull(getPackageUseInfo(mFooUser0));
+ }
+
+ @Test
+ public void testNotifyPrimaryForeignUse() {
+ // Foo loads Bar main apks.
+ notifyDexLoad(mFooUser0, mBarUser0.getBaseAndSplitDexPaths(), mUser0);
+
+ // Bar is used by others now and should be in our records
+ PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+ assertNotNull(pui);
+ assertTrue(pui.isUsedByOtherApps());
+ assertTrue(pui.getDexUseInfoMap().isEmpty());
+ }
+
+ @Test
+ public void testNotifySecondary() {
+ // Foo loads its own secondary files.
+ List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+ notifyDexLoad(mFooUser0, fooSecondaries, mUser0);
+
+ PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+ assertNotNull(pui);
+ assertFalse(pui.isUsedByOtherApps());
+ assertEquals(fooSecondaries.size(), pui.getDexUseInfoMap().size());
+ assertSecondaryUse(mFooUser0, pui, fooSecondaries, /*isUsedByOtherApps*/false, mUser0);
+ }
+
+ @Test
+ public void testNotifySecondaryForeign() {
+ // Foo loads bar secondary files.
+ List<String> barSecondaries = mBarUser0.getSecondaryDexPaths();
+ notifyDexLoad(mFooUser0, barSecondaries, mUser0);
+
+ PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+ assertNotNull(pui);
+ assertFalse(pui.isUsedByOtherApps());
+ assertEquals(barSecondaries.size(), pui.getDexUseInfoMap().size());
+ assertSecondaryUse(mFooUser0, pui, barSecondaries, /*isUsedByOtherApps*/true, mUser0);
+ }
+
+ @Test
+ public void testNotifySequence() {
+ // Foo loads its own secondary files.
+ List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+ notifyDexLoad(mFooUser0, fooSecondaries, mUser0);
+ // Foo loads Bar own secondary files.
+ List<String> barSecondaries = mBarUser0.getSecondaryDexPaths();
+ notifyDexLoad(mFooUser0, barSecondaries, mUser0);
+ // Foo loads Bar primary files.
+ notifyDexLoad(mFooUser0, mBarUser0.getBaseAndSplitDexPaths(), mUser0);
+ // Bar loads its own secondary files.
+ notifyDexLoad(mBarUser0, barSecondaries, mUser0);
+ // Bar loads some own secondary files which foo didn't load.
+ List<String> barSecondariesForOwnUse = mBarUser0.getSecondaryDexPathsForOwnUse();
+ notifyDexLoad(mBarUser0, barSecondariesForOwnUse, mUser0);
+
+ // Check bar usage. Should be used by other app (for primary and barSecondaries).
+ PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+ assertNotNull(pui);
+ assertTrue(pui.isUsedByOtherApps());
+ assertEquals(barSecondaries.size() + barSecondariesForOwnUse.size(),
+ pui.getDexUseInfoMap().size());
+
+ assertSecondaryUse(mFooUser0, pui, barSecondaries, /*isUsedByOtherApps*/true, mUser0);
+ assertSecondaryUse(mFooUser0, pui, barSecondariesForOwnUse,
+ /*isUsedByOtherApps*/false, mUser0);
+
+ // Check foo usage. Should not be used by other app.
+ pui = getPackageUseInfo(mFooUser0);
+ assertNotNull(pui);
+ assertFalse(pui.isUsedByOtherApps());
+ assertEquals(fooSecondaries.size(), pui.getDexUseInfoMap().size());
+ assertSecondaryUse(mFooUser0, pui, fooSecondaries, /*isUsedByOtherApps*/false, mUser0);
+ }
+
+ @Test
+ public void testPackageUseInfoNotFound() {
+ // Assert we don't get back data we did not previously record.
+ assertNull(getPackageUseInfo(mFooUser0));
+ }
+
+ @Test
+ public void testInvalidIsa() {
+ // Notifying with an invalid ISA should be ignored.
+ notifyDexLoad(mInvalidIsa, mInvalidIsa.getSecondaryDexPaths(), mUser0);
+ assertNull(getPackageUseInfo(mInvalidIsa));
+ }
+
+ @Test
+ public void testNotExistingPackate() {
+ // Notifying about the load of a package which was previously not
+ // register in DexManager#load should be ignored.
+ notifyDexLoad(mDoesNotExist, mDoesNotExist.getBaseAndSplitDexPaths(), mUser0);
+ assertNull(getPackageUseInfo(mDoesNotExist));
+ }
+
+ @Test
+ public void testCrossUserAttempt() {
+ // Bar from User1 tries to load secondary dex files from User0 Bar.
+ // Request should be ignored.
+ notifyDexLoad(mBarUser1, mBarUser0.getSecondaryDexPaths(), mUser1);
+ assertNull(getPackageUseInfo(mBarUser1));
+ }
+
+ @Test
+ public void testPackageNotInstalledForUser() {
+ // User1 tries to load Foo which is installed for User0 but not for User1.
+ // Note that the PackageManagerService already filters this out but we
+ // still check that nothing goes unexpected in DexManager.
+ notifyDexLoad(mBarUser0, mFooUser0.getBaseAndSplitDexPaths(), mUser1);
+ assertNull(getPackageUseInfo(mBarUser1));
+ }
+
+ private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
+ List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId) {
+ for (String dex : secondaries) {
+ DexUseInfo dui = pui.getDexUseInfoMap().get(dex);
+ assertNotNull(dui);
+ assertEquals(isUsedByOtherApps, dui.isUsedByOtherApps());
+ assertEquals(ownerUserId, dui.getOwnerUserId());
+ assertEquals(1, dui.getLoaderIsas().size());
+ assertTrue(dui.getLoaderIsas().contains(testData.mLoaderIsa));
+ }
+ }
+
+ private void notifyDexLoad(TestData testData, List<String> dexPaths, int loaderUserId) {
+ mDexManager.notifyDexLoad(testData.mPackageInfo.applicationInfo, dexPaths,
+ testData.mLoaderIsa, loaderUserId);
+ }
+
+ private PackageUseInfo getPackageUseInfo(TestData testData) {
+ return mDexManager.getPackageUseInfo(testData.mPackageInfo.packageName);
+ }
+
+ private static PackageInfo getMockPackageInfo(String packageName, int userId) {
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = packageName;
+ pi.applicationInfo = getMockApplicationInfo(packageName, userId);
+ return pi;
+ }
+
+ private static ApplicationInfo getMockApplicationInfo(String packageName, int userId) {
+ ApplicationInfo ai = new ApplicationInfo();
+ String codeDir = "/data/app/" + packageName;
+ ai.setBaseCodePath(codeDir + "/base.dex");
+ ai.setSplitCodePaths(new String[] {codeDir + "/split-1.dex", codeDir + "/split-2.dex"});
+ ai.dataDir = "/data/user/" + userId + "/" + packageName;
+ ai.packageName = packageName;
+ return ai;
+ }
+
+ private static class TestData {
+ private final PackageInfo mPackageInfo;
+ private final String mLoaderIsa;
+
+ private TestData(String packageName, String loaderIsa, int userId) {
+ mPackageInfo = getMockPackageInfo(packageName, userId);
+ mLoaderIsa = loaderIsa;
+ }
+
+ private String getPackageName() {
+ return mPackageInfo.packageName;
+ }
+
+ List<String> getSecondaryDexPaths() {
+ List<String> paths = new ArrayList<>();
+ paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary1.dex");
+ paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary2.dex");
+ paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary3.dex");
+ return paths;
+ }
+
+ List<String> getSecondaryDexPathsForOwnUse() {
+ List<String> paths = new ArrayList<>();
+ paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary4.dex");
+ paths.add(mPackageInfo.applicationInfo.dataDir + "/secondary5.dex");
+ return paths;
+ }
+
+ List<String> getBaseAndSplitDexPaths() {
+ List<String> paths = new ArrayList<>();
+ paths.add(mPackageInfo.applicationInfo.sourceDir);
+ for (String split : mPackageInfo.applicationInfo.splitSourceDirs) {
+ paths.add(split);
+ }
+ return paths;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
new file mode 100644
index 0000000..5a42841
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2016 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.server.pm.dex;
+
+import android.os.Build;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import dalvik.system.VMRuntime;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
+import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PackageDexUsageTests {
+ private PackageDexUsage mPackageDexUsage;
+
+ private TestData mFooBaseUser0;
+ private TestData mFooSplit1User0;
+ private TestData mFooSplit2UsedByOtherApps0;
+ private TestData mFooSecondary1User0;
+ private TestData mFooSecondary1User1;
+ private TestData mFooSecondary2UsedByOtherApps0;
+ private TestData mInvalidIsa;
+
+ private TestData mBarBaseUser0;
+ private TestData mBarSecondary1User0;
+ private TestData mBarSecondary2User1;
+
+ @Before
+ public void setup() {
+ mPackageDexUsage = new PackageDexUsage();
+
+ String fooPackageName = "com.google.foo";
+ String fooCodeDir = "/data/app/com.google.foo/";
+ String fooDataDir = "/data/user/0/com.google.foo/";
+
+ String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+
+ mFooBaseUser0 = new TestData(fooPackageName,
+ fooCodeDir + "base.apk", 0, isa, false, true);
+
+ mFooSplit1User0 = new TestData(fooPackageName,
+ fooCodeDir + "split-1.apk", 0, isa, false, true);
+
+ mFooSplit2UsedByOtherApps0 = new TestData(fooPackageName,
+ fooCodeDir + "split-2.apk", 0, isa, true, true);
+
+ mFooSecondary1User0 = new TestData(fooPackageName,
+ fooDataDir + "sec-1.dex", 0, isa, false, false);
+
+ mFooSecondary1User1 = new TestData(fooPackageName,
+ fooDataDir + "sec-1.dex", 1, isa, false, false);
+
+ mFooSecondary2UsedByOtherApps0 = new TestData(fooPackageName,
+ fooDataDir + "sec-2.dex", 0, isa, true, false);
+
+ mInvalidIsa = new TestData(fooPackageName,
+ fooCodeDir + "base.apk", 0, "INVALID_ISA", false, true);
+
+ String barPackageName = "com.google.bar";
+ String barCodeDir = "/data/app/com.google.bar/";
+ String barDataDir = "/data/user/0/com.google.bar/";
+ String barDataDir1 = "/data/user/1/com.google.bar/";
+
+ mBarBaseUser0 = new TestData(barPackageName,
+ barCodeDir + "base.apk", 0, isa, false, true);
+ mBarSecondary1User0 = new TestData(barPackageName,
+ barDataDir + "sec-1.dex", 0, isa, false, false);
+ mBarSecondary2User1 = new TestData(barPackageName,
+ barDataDir1 + "sec-2.dex", 1, isa, false, false);
+ }
+
+ @Test
+ public void testRecordPrimary() {
+ // Assert new information.
+ assertTrue(record(mFooBaseUser0));
+
+ assertPackageDexUsage(mFooBaseUser0);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooBaseUser0);
+ }
+
+ @Test
+ public void testRecordSplit() {
+ // Assert new information.
+ assertTrue(record(mFooSplit1User0));
+
+ assertPackageDexUsage(mFooSplit1User0);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooSplit1User0);
+ }
+
+ @Test
+ public void testRecordSplitPrimarySequence() {
+ // Assert new information.
+ assertTrue(record(mFooBaseUser0));
+ // Assert no new information.
+ assertFalse(record(mFooSplit1User0));
+
+ assertPackageDexUsage(mFooBaseUser0);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooBaseUser0);
+
+ // Write Split2 which is used by other apps.
+ // Assert new information.
+ assertTrue(record(mFooSplit2UsedByOtherApps0));
+ assertPackageDexUsage(mFooSplit2UsedByOtherApps0);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooSplit2UsedByOtherApps0);
+ }
+
+ @Test
+ public void testRecordSecondary() {
+ assertTrue(record(mFooSecondary1User0));
+
+ assertPackageDexUsage(null, mFooSecondary1User0);
+ writeAndReadBack();
+ assertPackageDexUsage(null, mFooSecondary1User0);
+
+ // Recording again does not add more data.
+ assertFalse(record(mFooSecondary1User0));
+ assertPackageDexUsage(null, mFooSecondary1User0);
+ }
+
+ @Test
+ public void testRecordBaseAndSecondarySequence() {
+ // Write split.
+ assertTrue(record(mFooSplit2UsedByOtherApps0));
+ // Write secondary.
+ assertTrue(record(mFooSecondary1User0));
+
+ // Check.
+ assertPackageDexUsage(mFooSplit2UsedByOtherApps0, mFooSecondary1User0);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooSplit2UsedByOtherApps0, mFooSecondary1User0);
+
+ // Write another secondary.
+ assertTrue(record(mFooSecondary2UsedByOtherApps0));
+
+ // Check.
+ assertPackageDexUsage(
+ mFooSplit2UsedByOtherApps0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
+ writeAndReadBack();
+ assertPackageDexUsage(
+ mFooSplit2UsedByOtherApps0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
+ }
+
+ @Test
+ public void testMultiplePackages() {
+ assertTrue(record(mFooBaseUser0));
+ assertTrue(record(mFooSecondary1User0));
+ assertTrue(record(mFooSecondary2UsedByOtherApps0));
+ assertTrue(record(mBarBaseUser0));
+ assertTrue(record(mBarSecondary1User0));
+ assertTrue(record(mBarSecondary2User1));
+
+ assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
+ assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
+ assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
+ }
+
+ @Test
+ public void testPackageNotFound() {
+ assertNull(mPackageDexUsage.getPackageUseInfo("missing.package"));
+ }
+
+ @Test
+ public void testAttemptToChangeOwner() {
+ assertTrue(record(mFooSecondary1User0));
+ try {
+ record(mFooSecondary1User1);
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testInvalidIsa() {
+ try {
+ record(mInvalidIsa);
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testReadWriteEmtpy() {
+ // Expect no exceptions when writing/reading without data.
+ writeAndReadBack();
+ }
+
+ @Test
+ public void testSyncData() {
+ // Write some records.
+ assertTrue(record(mFooBaseUser0));
+ assertTrue(record(mFooSecondary1User0));
+ assertTrue(record(mFooSecondary2UsedByOtherApps0));
+ assertTrue(record(mBarBaseUser0));
+ assertTrue(record(mBarSecondary1User0));
+ assertTrue(record(mBarSecondary2User1));
+
+ // Verify all is good.
+ assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
+ assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
+ writeAndReadBack();
+ assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
+ assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
+
+ // Simulate that only user 1 is available.
+ Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
+ packageToUsersMap.put(mBarSecondary2User1.mPackageName,
+ new HashSet<>(Arrays.asList(mBarSecondary2User1.mOwnerUserId)));
+ mPackageDexUsage.syncData(packageToUsersMap);
+
+ // Assert that only user 1 files are there.
+ assertPackageDexUsage(mBarBaseUser0, mBarSecondary2User1);
+ assertNull(mPackageDexUsage.getPackageUseInfo(mFooBaseUser0.mPackageName));
+ }
+
+ private void assertPackageDexUsage(TestData primary, TestData... secondaries) {
+ String packageName = primary == null ? secondaries[0].mPackageName : primary.mPackageName;
+ boolean primaryUsedByOtherApps = primary == null ? false : primary.mUsedByOtherApps;
+ PackageUseInfo pInfo = mPackageDexUsage.getPackageUseInfo(packageName);
+
+ // Check package use info
+ assertNotNull(pInfo);
+ assertEquals(primaryUsedByOtherApps, pInfo.isUsedByOtherApps());
+ Map<String, DexUseInfo> dexUseInfoMap = pInfo.getDexUseInfoMap();
+ assertEquals(secondaries.length, dexUseInfoMap.size());
+
+ // Check dex use info
+ for (TestData testData : secondaries) {
+ DexUseInfo dInfo = dexUseInfoMap.get(testData.mDexFile);
+ assertNotNull(dInfo);
+ assertEquals(testData.mUsedByOtherApps, dInfo.isUsedByOtherApps());
+ assertEquals(testData.mOwnerUserId, dInfo.getOwnerUserId());
+ assertEquals(1, dInfo.getLoaderIsas().size());
+ assertTrue(dInfo.getLoaderIsas().contains(testData.mLoaderIsa));
+ }
+ }
+
+ private boolean record(TestData testData) {
+ return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile,
+ testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps,
+ testData.mPrimaryOrSplit);
+ }
+
+ private void writeAndReadBack() {
+ try {
+ StringWriter writer = new StringWriter();
+ mPackageDexUsage.write(writer);
+
+ mPackageDexUsage = new PackageDexUsage();
+ mPackageDexUsage.read(new StringReader(writer.toString()));
+ } catch (IOException e) {
+ fail("Unexpected IOException: " + e.getMessage());
+ }
+ }
+
+ private static class TestData {
+ private final String mPackageName;
+ private final String mDexFile;
+ private final int mOwnerUserId;
+ private final String mLoaderIsa;
+ private final boolean mUsedByOtherApps;
+ private final boolean mPrimaryOrSplit;
+
+ private TestData(String packageName, String dexFile, int ownerUserId,
+ String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit) {
+ mPackageName = packageName;
+ mDexFile = dexFile;
+ mOwnerUserId = ownerUserId;
+ mLoaderIsa = loaderIsa;
+ mUsedByOtherApps = isUsedByOtherApps;
+ mPrimaryOrSplit = primaryOrSplit;
+ }
+
+ }
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2c16ca0..a6da9e9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -843,6 +843,58 @@
"signal_pco_receiver_string_array";
/**
+ * Defines carrier-specific actions which act upon
+ * android.intent.action.CARRIER_SIGNAL_REDIRECTED, used for customization of the
+ * default carrier app
+ * Format: "CARRIER_ACTION_IDX, ..."
+ * Where {@code CARRIER_ACTION_IDX} is an integer defined in
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * Example:
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
+ * disable_metered_apns}
+ * @hide
+ */
+ public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY =
+ "carrier_default_actions_on_redirection_string_array";
+
+ /**
+ * Defines carrier-specific actions which act upon
+ * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+ * and configured signal args:
+ * {@link com.android.internal.telephony.TelephonyIntents#EXTRA_APN_TYPE_KEY apnType},
+ * {@link com.android.internal.telephony.TelephonyIntents#EXTRA_ERROR_CODE_KEY errorCode}
+ * used for customization of the default carrier app
+ * Format:
+ * {
+ * "APN_1, ERROR_CODE_1 : CARRIER_ACTION_IDX_1, CARRIER_ACTION_IDX_2...",
+ * "APN_1, ERROR_CODE_2 : CARRIER_ACTION_IDX_1 "
+ * }
+ * Where {@code APN_1} is a string defined in
+ * {@link com.android.internal.telephony.PhoneConstants PhoneConstants}
+ * Example: "default"
+ *
+ * {@code ERROR_CODE_1} is an integer defined in
+ * {@link com.android.internal.telephony.dataconnection.DcFailCause DcFailure}
+ * Example:
+ * {@link com.android.internal.telephony.dataconnection.DcFailCause#MISSING_UNKNOWN_APN}
+ *
+ * {@code CARRIER_ACTION_IDX_1} is an integer defined in
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * Example:
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS}
+ * @hide
+ */
+ public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DCFAILURE_STRING_ARRAY =
+ "carrier_default_actions_on_dcfailure_string_array";
+
+ /**
+ * Defines a list of acceptable redirection url for default carrier app
+ * @hides
+ */
+ public static final String KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY =
+ "carrier_default_redirection_url_string_array";
+
+ /**
* Determines whether the carrier supports making non-emergency phone calls while the phone is
* in emergency callback mode. Default value is {@code true}, meaning that non-emergency calls
* are allowed in emergency callback mode.
@@ -905,6 +957,13 @@
public static final int CDMA_ROAMING_MODE_AFFILIATED = 1;
/** @hide */
public static final int CDMA_ROAMING_MODE_ANY = 2;
+ /**
+ * Boolean indicating if support is provided for directly dialing FDN number from FDN list.
+ * If false, this feature is not supported.
+ * @hide
+ */
+ public static final String KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL =
+ "support_direct_fdn_dialing_bool";
/**
* Report IMEI as device id even if it's a CDMA/LTE phone.
@@ -1034,7 +1093,7 @@
* is returned.
* @hide
*/
- public static final String FILTERED_CNAP_NAMES_STRING_ARRAY = "filtered_cnap_names_string_array";
+ public static final String KEY_FILTERED_CNAP_NAMES_STRING_ARRAY = "filtered_cnap_names_string_array";
/**
* Determine whether user can change Wi-Fi Calling preference in roaming.
@@ -1176,6 +1235,7 @@
sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
+ sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
@@ -1221,6 +1281,15 @@
sDefaults.putStringArray(KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY, null);
sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
+ // Default carrier app configurations
+ sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY,
+ new String[]{
+ "4, 1"
+ //4: CARRIER_ACTION_DISABLE_METERED_APNS
+ //1: CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
+ });
+ sDefaults.putStringArray(KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY, null);
+
// Rat families: {GPRS, EDGE}, {EVDO, EVDO_A, EVDO_B}, {UMTS, HSPA, HSDPA, HSUPA, HSPAP},
// {LTE, LTE_CA}
// Order is important - lowest precidence first
@@ -1236,7 +1305,7 @@
sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
- sDefaults.putStringArray(FILTERED_CNAP_NAMES_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
}
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 0334254..811c996 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -233,6 +233,13 @@
*/
public static final int DIALED_ON_WRONG_SLOT = 56;
+ /**
+ * The network does not accept the emergency call request because IMEI was used as
+ * identification and this cability is not supported by the network.
+ * {@hide}
+ */
+ public static final int IMEI_NOT_ACCEPTED = 57;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -241,14 +248,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 57
+ // NextId: 58
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = DIALED_ON_WRONG_SLOT;
+ public static final int MAXIMUM_VALID_VALUE = IMEI_NOT_ACCEPTED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -370,6 +377,8 @@
return "DATA_LIMIT_REACHED";
case DIALED_ON_WRONG_SLOT:
return "DIALED_ON_WRONG_SLOT";
+ case IMEI_NOT_ACCEPTED:
+ return "IMEI_NOT_ACCEPTED";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4c8eda0..5a15009 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -905,8 +905,10 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @hide
*/
- /** {@hide} */
+ @SystemApi
public String getImei() {
return getImei(getDefaultSim());
}
@@ -918,8 +920,10 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @param slotId of which deviceID is returned
+ *
+ * @hide
*/
- /** {@hide} */
+ @SystemApi
public String getImei(int slotId) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
diff --git a/services/tests/servicestests/src/android/net/util/BlockingSocketReaderTest.java b/tests/net/java/android/net/util/BlockingSocketReaderTest.java
similarity index 100%
rename from services/tests/servicestests/src/android/net/util/BlockingSocketReaderTest.java
rename to tests/net/java/android/net/util/BlockingSocketReaderTest.java
diff --git a/services/tests/servicestests/src/android/net/util/ConnectivityPacketSummaryTest.java b/tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
similarity index 100%
rename from services/tests/servicestests/src/android/net/util/ConnectivityPacketSummaryTest.java
rename to tests/net/java/android/net/util/ConnectivityPacketSummaryTest.java
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index d62c30d..46b6403 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -1103,6 +1103,29 @@
UNAVAILABLE
}
+ private static class CallbackInfo {
+ public final CallbackState state;
+ public final Network network;
+ public final Object arg;
+ public CallbackInfo(CallbackState s, Network n, Object o) {
+ state = s; network = n; arg = o;
+ }
+ public String toString() {
+ return String.format("%s (%s)", state, network);
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof CallbackInfo)) return false;
+ // Ignore timeMs, since it's unpredictable.
+ CallbackInfo other = (CallbackInfo) o;
+ return (state == other.state) && Objects.equals(network, other.network);
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hash(state, network);
+ }
+ }
+
/**
* Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
* this class receives, by calling expectCallback() exactly once each time a callback is
@@ -1114,21 +1137,6 @@
// the linger timeout.
private final static int TIMEOUT_MS = 50;
- private class CallbackInfo {
- public final CallbackState state;
- public final Network network;
- public Object arg;
- public CallbackInfo(CallbackState s, Network n, Object o) {
- state = s; network = n; arg = o;
- }
- public String toString() { return String.format("%s (%s)", state, network); }
- public boolean equals(Object o) {
- if (!(o instanceof CallbackInfo)) return false;
- // Ignore timeMs, since it's unpredictable.
- CallbackInfo other = (CallbackInfo) o;
- return state == other.state && Objects.equals(network, other.network);
- }
- }
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
protected void setLastCallback(CallbackState state, Network network, Object o) {
@@ -1155,17 +1163,24 @@
setLastCallback(CallbackState.LOST, network, null);
}
+ CallbackInfo nextCallback(int timeoutMs) {
+ CallbackInfo cb = null;
+ try {
+ cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+ if (cb == null) {
+ // LinkedBlockingQueue.poll() returns null if it timeouts.
+ fail("Did not receive callback after " + timeoutMs + "ms");
+ }
+ return cb;
+ }
+
void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
CallbackInfo expected = new CallbackInfo(
state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
- CallbackInfo actual;
- try {
- actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
- assertEquals("Unexpected callback:", expected, actual);
- } catch (InterruptedException e) {
- fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
- actual = null; // Or the compiler can't tell it's never used uninitialized.
- }
+ CallbackInfo actual = nextCallback(timeoutMs);
+ assertEquals("Unexpected callback:", expected, actual);
if (state == CallbackState.LOSING) {
String msg = String.format(
"Invalid linger time value %d, must be between %d and %d",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
new file mode 100644
index 0000000..b2a9a49
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.server.connectivity.tethering;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.reset;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.IConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UpstreamNetworkMonitorTest {
+ private static final int EVENT_UNM_UPDATE = 1;
+
+ @Mock private Context mContext;
+ @Mock private IConnectivityManager mCS;
+
+ private TestConnectivityManager mCM;
+ private UpstreamNetworkMonitor mUNM;
+
+ @Before public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ reset(mContext);
+ reset(mCS);
+
+ mCM = new TestConnectivityManager(mContext, mCS);
+ mUNM = new UpstreamNetworkMonitor(null, EVENT_UNM_UPDATE, (ConnectivityManager) mCM);
+ }
+
+ @Test
+ public void testDoesNothingBeforeStarted() {
+ UpstreamNetworkMonitor unm = new UpstreamNetworkMonitor(null, null, EVENT_UNM_UPDATE);
+ assertFalse(unm.mobileNetworkRequested());
+ // Given a null Context, and therefore a null ConnectivityManager,
+ // these would cause an exception, if they actually attempted anything.
+ unm.mobileUpstreamRequiresDun(true);
+ unm.mobileUpstreamRequiresDun(false);
+ }
+
+ @Test
+ public void testDefaultNetworkIsTracked() throws Exception {
+ assertEquals(0, mCM.trackingDefault.size());
+
+ mUNM.start();
+ assertEquals(1, mCM.trackingDefault.size());
+
+ mUNM.stop();
+ assertTrue(mCM.isEmpty());
+ }
+
+ @Test
+ public void testListensForDunNetworks() throws Exception {
+ assertTrue(mCM.listening.isEmpty());
+
+ mUNM.start();
+ assertFalse(mCM.listening.isEmpty());
+ assertTrue(mCM.isListeningForDun());
+
+ mUNM.stop();
+ assertTrue(mCM.isEmpty());
+ }
+
+ @Test
+ public void testCanRequestMobileNetwork() throws Exception {
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.start();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.mobileUpstreamRequiresDun(false);
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.registerMobileNetworkRequest();
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertEquals(1, mCM.requested.size());
+ assertFalse(mCM.isDunRequested());
+
+ mUNM.stop();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertTrue(mCM.isEmpty());
+ }
+
+ @Test
+ public void testCanRequestDunNetwork() throws Exception {
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.start();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.mobileUpstreamRequiresDun(true);
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.registerMobileNetworkRequest();
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertEquals(1, mCM.requested.size());
+ assertTrue(mCM.isDunRequested());
+
+ mUNM.stop();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertTrue(mCM.isEmpty());
+ }
+
+ private static class TestConnectivityManager extends ConnectivityManager {
+ public Set<NetworkCallback> trackingDefault = new HashSet<>();
+ public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>();
+ public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>();
+
+ public TestConnectivityManager(Context ctx, IConnectivityManager svc) {
+ super(ctx, svc);
+ }
+
+ boolean isEmpty() {
+ return trackingDefault.isEmpty() &&
+ listening.isEmpty() &&
+ requested.isEmpty();
+ }
+
+ boolean isListeningForDun() {
+ for (NetworkRequest req : listening.values()) {
+ if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean isDunRequested() {
+ for (NetworkRequest req : requested.values()) {
+ if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void requestNetwork(NetworkRequest req, NetworkCallback cb) {
+ assertFalse(requested.containsKey(cb));
+ requested.put(cb, req);
+ }
+
+ @Override
+ public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) {
+ assertFalse(listening.containsKey(cb));
+ listening.put(cb, req);
+ }
+
+ @Override
+ public void registerDefaultNetworkCallback(NetworkCallback cb) {
+ assertFalse(trackingDefault.contains(cb));
+ trackingDefault.add(cb);
+ }
+
+ @Override
+ public void unregisterNetworkCallback(NetworkCallback cb) {
+ if (trackingDefault.contains(cb)) {
+ trackingDefault.remove(cb);
+ } else if (listening.containsKey(cb)) {
+ listening.remove(cb);
+ } else if (requested.containsKey(cb)) {
+ requested.remove(cb);
+ }
+
+ assertFalse(trackingDefault.contains(cb));
+ assertFalse(listening.containsKey(cb));
+ assertFalse(requested.containsKey(cb));
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 9e897bf..18c1245 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -59,7 +59,7 @@
int addOrUpdateNetwork(in WifiConfiguration config);
- boolean addPasspointConfiguration(in PasspointConfiguration config);
+ boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config);
boolean removePasspointConfiguration(in String fqdn);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3b7f721..958279b 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -608,6 +608,7 @@
* if there has been a report of it having no internet access, and, it never have had
* internet access in the past.
*/
+ @SystemApi
public boolean hasNoInternetAccess() {
return numNoInternetAccessReports > 0 && !validatedInternetAccess;
}
@@ -621,6 +622,17 @@
public boolean noInternetAccessExpected;
/**
+ * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
+ * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
+ * this configuration and selects "don't ask again".
+ * @hide
+ */
+ @SystemApi
+ public boolean isNoInternetAccessExpected() {
+ return noInternetAccessExpected;
+ }
+
+ /**
* @hide
* Last time the system was connected to this configuration.
*/
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 674c161..ab6b3e3 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -842,31 +842,31 @@
}
/**
- * Add a Passpoint configuration. The configuration provides a credential
+ * Add or update a Passpoint configuration. The configuration provides a credential
* for connecting to Passpoint networks that are operated by the Passpoint
* service provider specified in the configuration.
*
* Each configuration is uniquely identified by its FQDN (Fully Qualified Domain
- * Name). In the case when there is an existing configuration with the same base
- * domain, the new configuration will replace the existing configuration.
+ * Name). In the case when there is an existing configuration with the same
+ * FQDN, the new configuration will replace the existing configuration.
*
* @param config The Passpoint configuration to be added
- * @return true on success or false on failure
+ * @return true on success
* @hide
*/
- public boolean addPasspointConfiguration(PasspointConfiguration config) {
+ public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
try {
- return mService.addPasspointConfiguration(config);
+ return mService.addOrUpdatePasspointConfiguration(config);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Remove a Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
+ * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
*
* @param fqdn The FQDN of the passpoint configuration to be removed
- * @return true on success or false on failure
+ * @return true on success
* @hide
*/
public boolean removePasspointConfiguration(String fqdn) {
@@ -880,7 +880,9 @@
/**
* Return the list of installed Passpoint configurations.
*
- * @return A list of PasspointConfiguration or null
+ * An empty list will be returned when no configurations are installed.
+ *
+ * @return A list of {@link PasspointConfiguration}
* @hide
*/
public List<PasspointConfiguration> getPasspointConfigurations() {
@@ -1073,7 +1075,6 @@
}
}
- /* Keep this list in sync with wifi_hal.h */
/** @hide */
public static final int WIFI_FEATURE_INFRA = 0x0001; // Basic infrastructure mode
/** @hide */
@@ -1087,7 +1088,7 @@
/** @hide */
public static final int WIFI_FEATURE_SCANNER = 0x0020; // WifiScanner APIs
/** @hide */
- public static final int WIFI_FEATURE_AWARE = 0x0040; // Wi-Fi AWare networking
+ public static final int WIFI_FEATURE_AWARE = 0x0040; // Wi-Fi AWare networking
/** @hide */
public static final int WIFI_FEATURE_D2D_RTT = 0x0080; // Device-to-device RTT
/** @hide */
@@ -1105,13 +1106,28 @@
/** @hide */
public static final int WIFI_FEATURE_EPR = 0x4000; // Enhanced power reporting
/** @hide */
- public static final int WIFI_FEATURE_AP_STA = 0x8000; // Support for AP STA Concurrency
+ public static final int WIFI_FEATURE_AP_STA = 0x8000; // AP STA Concurrency
/** @hide */
- public static final int WIFI_FEATURE_LINK_LAYER_STATS = 0x10000; // Link layer stats collection
+ public static final int WIFI_FEATURE_LINK_LAYER_STATS = 0x10000; // Link layer stats collection
/** @hide */
- public static final int WIFI_FEATURE_LOGGER = 0x20000; // WiFi Logger
+ public static final int WIFI_FEATURE_LOGGER = 0x20000; // WiFi Logger
/** @hide */
- public static final int WIFI_FEATURE_HAL_EPNO = 0x40000; // WiFi PNO enhanced
+ public static final int WIFI_FEATURE_HAL_EPNO = 0x40000; // Enhanced PNO
+ /** @hide */
+ public static final int WIFI_FEATURE_RSSI_MONITOR = 0x80000; // RSSI Monitor
+ /** @hide */
+ public static final int WIFI_FEATURE_MKEEP_ALIVE = 0x100000; // mkeep_alive
+ /** @hide */
+ public static final int WIFI_FEATURE_CONFIG_NDO = 0x200000; // ND offload
+ /** @hide */
+ public static final int WIFI_FEATURE_TRANSMIT_POWER = 0x400000; // Capture transmit power
+ /** @hide */
+ public static final int WIFI_FEATURE_CONTROL_ROAMING = 0x800000; // Control firmware roaming
+ /** @hide */
+ public static final int WIFI_FEATURE_IE_WHITELIST = 0x1000000; // Probe IE white listing
+ /** @hide */
+ public static final int WIFI_FEATURE_SCAN_RAND = 0x2000000; // Random MAC & Probe seq
+
private int getSupportedFeatures() {
try {
@@ -1763,6 +1779,7 @@
* Interface for callback invocation on an application action
* @hide
*/
+ @SystemApi
public interface ActionListener {
/** The operation succeeded */
public void onSuccess();
@@ -1974,6 +1991,7 @@
*
* @hide
*/
+ @SystemApi
public void connect(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
// Use INVALID_NETWORK_ID for arg1 when passing a config object
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/AttachCallback.java
similarity index 76%
rename from wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
rename to wifi/java/android/net/wifi/aware/AttachCallback.java
index 1e8dbd9..c368b46 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
+++ b/wifi/java/android/net/wifi/aware/AttachCallback.java
@@ -18,16 +18,14 @@
/**
* Base class for Aware attach callbacks. Should be extended by applications and set when calling
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. These are callbacks
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. These are callbacks
* applying to the Aware connection as a whole - not to specific publish or subscribe sessions -
- * for that see {@link WifiAwareDiscoverySessionCallback}.
- *
- * @hide PROPOSED_AWARE_API
+ * for that see {@link DiscoverySessionCallback}.
*/
-public class WifiAwareAttachCallback {
+public class AttachCallback {
/**
* Called when Aware attach operation
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}
* is completed and that we can now start discovery sessions or connections.
*
* @param session The Aware object on which we can execute further Aware operations - e.g.
@@ -39,7 +37,7 @@
/**
* Called when Aware attach operation
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} failed.
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)} failed.
*/
public void onAttachFailed() {
/* empty */
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/wifi/java/android/net/wifi/aware/Characteristics.aidl
similarity index 94%
rename from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
rename to wifi/java/android/net/wifi/aware/Characteristics.aidl
index a35e71d..77305e9 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
+++ b/wifi/java/android/net/wifi/aware/Characteristics.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.aware;
-parcelable WifiAwareCharacteristics;
+parcelable Characteristics;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java
similarity index 82%
rename from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
rename to wifi/java/android/net/wifi/aware/Characteristics.java
index 092aa34..70474fd 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/Characteristics.java
@@ -22,10 +22,8 @@
/**
* The characteristics of the Wi-Fi Aware implementation.
- *
- * @hide PROPOSED_AWARE_API
*/
-public class WifiAwareCharacteristics implements Parcelable {
+public final class Characteristics implements Parcelable {
/** @hide */
public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length";
/** @hide */
@@ -37,7 +35,7 @@
private Bundle mCharacteristics = new Bundle();
/** @hide : should not be created by apps */
- public WifiAwareCharacteristics(Bundle characteristics) {
+ public Characteristics(Bundle characteristics) {
mCharacteristics = characteristics;
}
@@ -58,7 +56,7 @@
* message exchange. Restricts the parameters of the
* {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
* {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}
* variants.
*
* @return A positive integer, maximum length of byte array for Aware messaging.
@@ -89,17 +87,17 @@
return 0;
}
- public static final Creator<WifiAwareCharacteristics> CREATOR =
- new Creator<WifiAwareCharacteristics>() {
+ public static final Creator<Characteristics> CREATOR =
+ new Creator<Characteristics>() {
@Override
- public WifiAwareCharacteristics createFromParcel(Parcel in) {
- WifiAwareCharacteristics c = new WifiAwareCharacteristics(in.readBundle());
+ public Characteristics createFromParcel(Parcel in) {
+ Characteristics c = new Characteristics(in.readBundle());
return c;
}
@Override
- public WifiAwareCharacteristics[] newArray(int size) {
- return new WifiAwareCharacteristics[size];
+ public Characteristics[] newArray(int size) {
+ return new Characteristics[size];
}
};
}
diff --git a/wifi/java/android/net/wifi/aware/ConfigRequest.java b/wifi/java/android/net/wifi/aware/ConfigRequest.java
index 4b21b15..6a5957b 100644
--- a/wifi/java/android/net/wifi/aware/ConfigRequest.java
+++ b/wifi/java/android/net/wifi/aware/ConfigRequest.java
@@ -22,7 +22,7 @@
/**
* Defines a request object to configure a Wi-Fi Aware network. Built using
* {@link ConfigRequest.Builder}. Configuration is requested using
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}.
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}.
* Note that the actual achieved configuration may be different from the
* requested configuration - since different applications may request different
* configurations.
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
similarity index 78%
rename from wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
rename to wifi/java/android/net/wifi/aware/DiscoverySession.java
index 2812ad4..adf189b 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.net.wifi.RttManager;
import android.util.Log;
@@ -29,21 +28,19 @@
/**
* A class representing a single publish or subscribe Aware session. This object
* will not be created directly - only its child classes are available:
- * {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This
+ * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
* class provides functionality common to both publish and subscribe discovery sessions:
* <ul>
- * <li>Sending messages: {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[])} or
- * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} methods.
+ * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or
+ * {@link #sendMessage(PeerHandle, int, byte[], int)} methods.
* <li>Creating a network-specifier when requesting a Aware connection:
- * {@link #createNetworkSpecifier(WifiAwareManager.PeerHandle, byte[])}.
+ * {@link #createNetworkSpecifier(PeerHandle, byte[])}.
* </ul>
* The {@link #destroy()} method must be called to destroy discovery sessions once they are
* no longer needed.
- *
- * @hide PROPOSED_AWARE_API
*/
-public class WifiAwareDiscoveryBaseSession {
- private static final String TAG = "WifiAwareDiscBaseSsn";
+public class DiscoverySession {
+ private static final String TAG = "DiscoverySession";
private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
@@ -62,7 +59,7 @@
/**
* Return the maximum permitted retry count when sending messages using
- * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}.
+ * {@link #sendMessage(PeerHandle, int, byte[], int)}.
*
* @return Maximum retry count when sending messages.
*/
@@ -71,7 +68,7 @@
}
/** @hide */
- public WifiAwareDiscoveryBaseSession(WifiAwareManager manager, int clientId, int sessionId) {
+ public DiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
if (VDBG) {
Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId="
+ clientId + ", sessionId=" + sessionId);
@@ -93,7 +90,7 @@
* This operation must be done on a session which is no longer needed. Otherwise system
* resources will continue to be utilized until the application exits. The only
* exception is a session for which we received a termination callback,
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}.
+ * {@link DiscoverySessionCallback#onSessionTerminated()}.
*/
public void destroy() {
WifiAwareManager mgr = mMgr.get();
@@ -139,23 +136,23 @@
/**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
- * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+ * {@link DiscoverySessionCallback} indicate message was transmitted successfully,
+ * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
* failed (possibly after several retries) -
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
+ * {@link DiscoverySessionCallback#onMessageSendFailed(int)}.
* <p>
* The peer will get a callback indicating a message was received using
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
* integer ID will be returned in the callbacks indicating message send success or
@@ -167,7 +164,7 @@
* (note: no retransmissions are attempted in other failure cases). A value of 0
* indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
*/
- public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+ public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
@Nullable byte[] message, int retryCount) {
if (mTerminated) {
Log.w(TAG, "sendMessage: called on terminated session");
@@ -186,25 +183,25 @@
/**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
- * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+ * {@link DiscoverySessionCallback} indicate message was transmitted successfully,
+ * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
* failed (possibly after several retries) -
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
+ * {@link DiscoverySessionCallback#onMessageSendFailed(int)}.
* <p>
* The peer will get a callback indicating a message was received using
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}.
- * Equivalent to {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}
+ * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)}
* with a {@code retryCount} of 0.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
* integer ID will be returned in the callbacks indicating message send success or
@@ -212,16 +209,16 @@
* can be arbitrary and non-unique.
* @param message The message to be transmitted.
*/
- public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+ public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
@Nullable byte[] message) {
sendMessage(peerHandle, messageId, message, 0);
}
/**
* Start a ranging operation with the specified peers. The peer IDs are obtained from an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])} operation - can
* only range devices which are part of an ongoing discovery session.
*
@@ -230,7 +227,7 @@
* {@link android.net.wifi.RttManager.RttParams#bssid} member must be set to
* a peer ID - not to a MAC address.
* @param listener The listener to receive the results of the ranging session.
- * @hide PROPOSED_AWARE_SYSTEM_API
+ * @hide
* [TODO: b/28847998 - track RTT API & visilibity]
*/
public void startRanging(RttManager.RttParams[] params, RttManager.RttListener listener) {
@@ -265,9 +262,9 @@
* and a Publisher is a RESPONDER.
*
* @param peerHandle The peer's handle obtained through
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
* from only that peer. A RESPONDER may specified a null - indicating that
* it will accept connection requests from any device.
@@ -283,7 +280,7 @@
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifier(@Nullable WifiAwareManager.PeerHandle peerHandle,
+ public String createNetworkSpecifier(@Nullable PeerHandle peerHandle,
@Nullable byte[] token) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifier: called on terminated session");
@@ -295,7 +292,7 @@
return null;
}
- int role = this instanceof WifiAwareSubscribeDiscoverySession
+ int role = this instanceof SubscribeDiscoverySession
? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
new file mode 100644
index 0000000..33da182
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2016 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.net.wifi.aware;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+
+/**
+ * Base class for Aware session events callbacks. Should be extended by
+ * applications wanting notifications. The callbacks are set when a
+ * publish or subscribe session is created using
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
+ * android.os.Handler)}.
+ * <p>
+ * A single callback is set at session creation - it cannot be replaced.
+ */
+public class DiscoverySessionCallback {
+ /**
+ * Called when a publish operation is started successfully in response to a
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
+ * android.os.Handler)} operation.
+ *
+ * @param session The {@link PublishDiscoverySession} used to control the
+ * discovery session.
+ */
+ public void onPublishStarted(@NonNull PublishDiscoverySession session) {
+ /* empty */
+ }
+
+ /**
+ * Called when a subscribe operation is started successfully in response to a
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
+ * android.os.Handler)} operation.
+ *
+ * @param session The {@link SubscribeDiscoverySession} used to control the
+ * discovery session.
+ */
+ public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) {
+ /* empty */
+ }
+
+ /**
+ * Called when a publish or subscribe discovery session configuration update request
+ * succeeds. Called in response to
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ */
+ public void onSessionConfigUpdated() {
+ /* empty */
+ }
+
+ /**
+ * Called when a publish or subscribe discovery session cannot be created:
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
+ * android.os.Handler)}, or when a configuration update fails:
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ * <p>
+ * For discovery session updates failure leaves the session running with its previous
+ * configuration - the discovery session is not terminated.
+ */
+ public void onSessionConfigFailed() {
+ /* empty */
+ }
+
+ /**
+ * Called when a discovery session (publish or subscribe) terminates. Termination may be due
+ * to user-request (either directly through {@link DiscoverySession#destroy()} or
+ * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
+ * or {@link SubscribeConfig.Builder#setTtlSec(int)}).
+ */
+ public void onSessionTerminated() {
+ /* empty */
+ }
+
+ /**
+ * Called when a discovery (publish or subscribe) operation results in a
+ * service discovery.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ * @param serviceSpecificInfo The service specific information (arbitrary
+ * byte array) provided by the peer as part of its discovery
+ * configuration.
+ * @param matchFilter The filter which resulted in this service discovery.
+ */
+ public void onServiceDiscovered(PeerHandle peerHandle,
+ byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
+ /* empty */
+ }
+
+ /**
+ * Called in response to
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}
+ * when a message is transmitted successfully - i.e. when it was received successfully by the
+ * peer (corresponds to an ACK being received).
+ * <p>
+ * Note that either this callback or
+ * {@link DiscoverySessionCallback#onMessageSendFailed(int)} will be
+ * received - never both.
+ *
+ * @param messageId The arbitrary message ID specified when sending the message.
+ */
+ public void onMessageSendSucceeded(@SuppressWarnings("unused") int messageId) {
+ /* empty */
+ }
+
+ /**
+ * Called when message transmission fails - when no ACK is received from the peer.
+ * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
+ * the {@link DiscoverySession#sendMessage(PeerHandle, int,
+ * byte[], int)} method) - this event is received after all retries are exhausted.
+ * <p>
+ * Note that either this callback or
+ * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
+ * - never both.
+ *
+ * @param messageId The arbitrary message ID specified when sending the message.
+ */
+ public void onMessageSendFailed(@SuppressWarnings("unused") int messageId) {
+ /* empty */
+ }
+
+ /**
+ * Called when a message is received from a discovery session peer - in response to the
+ * peer's {@link DiscoverySession#sendMessage(PeerHandle, int,
+ * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle,
+ * int, byte[], int)}.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ * @param message A byte array containing the message.
+ */
+ public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
+ /* empty */
+ }
+}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index 9c92807..794c142 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -23,7 +23,7 @@
import android.net.wifi.aware.IWifiAwareEventCallback;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
-import android.net.wifi.aware.WifiAwareCharacteristics;
+import android.net.wifi.aware.Characteristics;
import android.net.wifi.RttManager;
/**
@@ -37,7 +37,7 @@
void enableUsage();
void disableUsage();
boolean isUsageEnabled();
- WifiAwareCharacteristics getCharacteristics();
+ Characteristics getCharacteristics();
// client API
void connect(in IBinder binder, in String callingPackage, in IWifiAwareEventCallback callback,
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
similarity index 95%
rename from wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
rename to wifi/java/android/net/wifi/aware/IdentityChangedListener.java
index e8f52cd4..cae8706 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
+++ b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
@@ -25,10 +25,8 @@
* interface may also be useful if the application uses alternative (non-Aware) discovery but needs
* to set up a Aware connection. The provided Aware discovery interface MAC address can then be used
* in {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
- *
- * @hide PROPOSED_AWARE_API
*/
-public class WifiAwareIdentityChangedListener {
+public class IdentityChangedListener {
/**
* @param mac The MAC address of the Aware discovery interface. The application must have the
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address,
diff --git a/wifi/java/android/net/wifi/aware/PeerHandle.java b/wifi/java/android/net/wifi/aware/PeerHandle.java
new file mode 100644
index 0000000..bbe9f54
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/PeerHandle.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 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.net.wifi.aware;
+
+/**
+ * Opaque object used to represent a Wi-Fi Aware peer. Obtained from discovery sessions in
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}, used
+ * when sending messages e,g, {@link PublishDiscoverySession#sendMessage(PeerHandle, int, byte[])},
+ * or when configuring a network link to a peer, e.g.
+ * {@link PublishDiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}.
+ */
+public class PeerHandle {
+ /** @hide */
+ public PeerHandle(int peerId) {
+ this.peerId = peerId;
+ }
+
+ /** @hide */
+ public int peerId;
+}
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index 3925bd7..a996844 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -33,11 +33,9 @@
/**
* Defines the configuration of a Aware publish session. Built using
* {@link PublishConfig.Builder}. A publish session is created using
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
* android.os.Handler)} or updated using
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
- *
- * @hide PROPOSED_AWARE_API
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)}.
*/
public final class PublishConfig implements Parcelable {
/** @hide */
@@ -184,7 +182,7 @@
*
* @hide
*/
- public void assertValid(WifiAwareCharacteristics characteristics)
+ public void assertValid(Characteristics characteristics)
throws IllegalArgumentException {
WifiAwareUtils.validateServiceName(mServiceName);
@@ -322,12 +320,11 @@
* Sets the number of times an unsolicited (configured using
* {@link PublishConfig.Builder#setPublishType(int)}) publish session
* will be broadcast. When the count is reached an event will be
- * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}
- * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
- * {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
+ * generated for {@link DiscoverySessionCallback#onSessionTerminated()}
+ * [unless {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param publishCount Number of publish packets to broadcast.
@@ -348,12 +345,11 @@
* {@link PublishConfig.Builder#setPublishType(int)}) publish session
* will be alive - broadcasting a packet. When the TTL is reached
* an event will be generated for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with
- * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
+ * {@link DiscoverySessionCallback#onSessionTerminated()} [unless
* {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param ttlSec Lifetime of a publish session in seconds.
@@ -371,7 +367,7 @@
/**
* Configure whether a publish terminate notification
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported
+ * {@link DiscoverySessionCallback#onSessionTerminated()} is reported
* back to the callback.
*
* @param enable If true the terminate callback will be called when the
diff --git a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java
similarity index 69%
rename from wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
rename to wifi/java/android/net/wifi/aware/PublishDiscoverySession.java
index 68786d1..1c99c87 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java
@@ -21,32 +21,30 @@
/**
* A class representing a Aware publish session. Created when
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
* android.os.Handler)} is called and a discovery session is created and returned in
- * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See
- * baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This
+ * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}. See
+ * baseline functionality of all discovery sessions in {@link DiscoverySession}. This
* object allows updating an existing/running publish discovery session using
* {@link #updatePublish(PublishConfig)}.
- *
- * @hide PROPOSED_AWARE_API
*/
-public class WifiAwarePublishDiscoverySession extends WifiAwareDiscoveryBaseSession {
- private static final String TAG = "WifiAwarePublishDiscSsn";
+public class PublishDiscoverySession extends DiscoverySession {
+ private static final String TAG = "PublishDiscoverySession";
/** @hide */
- public WifiAwarePublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
+ public PublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
super(manager, clientId, sessionId);
}
/**
* Re-configure the currently active publish session. The
- * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used
+ * {@link DiscoverySessionCallback} is not replaced - the same listener used
* at creation is still used. The results of the configuration are returned using
- * {@link WifiAwareDiscoverySessionCallback}:
+ * {@link DiscoverySessionCallback}:
* <ul>
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration
* update succeeded.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration
* update failed. The publish discovery session is still running using its previous
* configuration (i.e. update failure does not terminate the session).
* </ul>
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 0fe69a8..3397c4b 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -33,11 +33,9 @@
/**
* Defines the configuration of a Aware subscribe session. Built using
* {@link SubscribeConfig.Builder}. Subscribe is done using
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
* android.os.Handler)} or
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
- *
- * @hide PROPOSED_AWARE_API
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
*/
public final class SubscribeConfig implements Parcelable {
/** @hide */
@@ -212,7 +210,7 @@
*
* @hide
*/
- public void assertValid(WifiAwareCharacteristics characteristics)
+ public void assertValid(Characteristics characteristics)
throws IllegalArgumentException {
WifiAwareUtils.validateServiceName(mServiceName);
@@ -355,11 +353,10 @@
* Sets the number of times an active (
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
* will broadcast. When the count is reached an event will be
- * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}
- * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}.
+ * generated for {@link DiscoverySessionCallback#onSessionTerminated()}.
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param subscribeCount Number of subscribe packets to broadcast.
@@ -380,11 +377,10 @@
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
* will be alive - i.e. broadcasting a packet. When the TTL is reached
* an event will be generated for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with
- * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}.
+ * {@link DiscoverySessionCallback#onSessionTerminated()}.
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param ttlSec Lifetime of a subscribe session in seconds.
@@ -404,8 +400,8 @@
* Sets the match style of the subscription - how are matches from a
* single match session (corresponding to the same publish action on the
* peer) reported to the host (using the
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], List)}). The options are: only report the first match and ignore the rest
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[],
+ * java.util.List)}). The options are: only report the first match and ignore the rest
* {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
* match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
*
@@ -424,7 +420,7 @@
/**
* Configure whether a subscribe terminate notification
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported
+ * {@link DiscoverySessionCallback#onSessionTerminated()} is reported
* back to the callback.
*
* @param enable If true the terminate callback will be called when the
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java
similarity index 74%
rename from wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
rename to wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java
index a0ec809..ca88a90 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java
@@ -22,35 +22,33 @@
/**
* A class representing a Aware subscribe session. Created when
* {@link WifiAwareSession#subscribe(SubscribeConfig,
- * WifiAwareDiscoverySessionCallback, android.os.Handler)}
+ * DiscoverySessionCallback, android.os.Handler)}
* is called and a discovery session is created and returned in
- * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}.
- * See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}.
+ * {@link DiscoverySessionCallback#onSubscribeStarted(SubscribeDiscoverySession)}.
+ * See baseline functionality of all discovery sessions in {@link DiscoverySession}.
* This object allows updating an existing/running subscribe discovery session using
* {@link #updateSubscribe(SubscribeConfig)}.
- *
- * @hide PROPOSED_AWARE_API
*/
-public class WifiAwareSubscribeDiscoverySession extends WifiAwareDiscoveryBaseSession {
- private static final String TAG = "WifiAwareSubsDiscSsn";
+public class SubscribeDiscoverySession extends DiscoverySession {
+ private static final String TAG = "SubscribeDiscSession";
/**
* {@hide}
*/
- public WifiAwareSubscribeDiscoverySession(WifiAwareManager manager, int clientId,
+ public SubscribeDiscoverySession(WifiAwareManager manager, int clientId,
int sessionId) {
super(manager, clientId, sessionId);
}
/**
* Re-configure the currently active subscribe session. The
- * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used
+ * {@link DiscoverySessionCallback} is not replaced - the same listener used
* at creation is still used. The results of the configuration are returned using
- * {@link WifiAwareDiscoverySessionCallback}:
+ * {@link DiscoverySessionCallback}:
* <ul>
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration
* update succeeded.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration
* update failed. The subscribe discovery session is still running using its previous
* configuration (i.e. update failure does not terminate the session).
* </ul>
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
deleted file mode 100644
index fdf0d01..0000000
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2016 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.net.wifi.aware;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * Base class for Aware session events callbacks. Should be extended by
- * applications wanting notifications. The callbacks are set when a
- * publish or subscribe session is created using
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} or
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)}.
- * <p>
- * A single callback is set at session creation - it cannot be replaced.
- *
- * @hide PROPOSED_AWARE_API
- */
-public class WifiAwareDiscoverySessionCallback {
- /** @hide */
- @IntDef({
- TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SessionTerminateCodes {
- }
-
- /**
- * Indicates that publish or subscribe session is done - all the
- * requested operations (per {@link PublishConfig} or
- * {@link SubscribeConfig}) have been executed. Failure reason flag for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback.
- */
- public static final int TERMINATE_REASON_DONE = 100;
-
- /**
- * Indicates that publish or subscribe session is terminated due to a
- * failure.
- * Failure reason flag for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback.
- */
- public static final int TERMINATE_REASON_FAIL = 101;
-
- /**
- * Called when a publish operation is started successfully in response to a
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} operation.
- *
- * @param session The {@link WifiAwarePublishDiscoverySession} used to control the
- * discovery session.
- */
- public void onPublishStarted(@NonNull WifiAwarePublishDiscoverySession session) {
- /* empty */
- }
-
- /**
- * Called when a subscribe operation is started successfully in response to a
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} operation.
- *
- * @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the
- * discovery session.
- */
- public void onSubscribeStarted(@NonNull WifiAwareSubscribeDiscoverySession session) {
- /* empty */
- }
-
- /**
- * Called when a publish or subscribe discovery session configuration update request
- * succeeds. Called in response to
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
- */
- public void onSessionConfigUpdated() {
- /* empty */
- }
-
- /**
- * Called when a publish or subscribe discovery session cannot be created:
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} or
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)}, or when a configuration update fails:
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
- * <p>
- * For discovery session updates failure leaves the session running with its previous
- * configuration - the discovery session is not terminated.
- */
- public void onSessionConfigFailed() {
- /* empty */
- }
-
- /**
- * Called when a discovery session (publish or subscribe) terminates. Termination may be due
- * to user-request (either directly through {@link WifiAwareDiscoveryBaseSession#destroy()} or
- * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
- * or {@link SubscribeConfig.Builder#setTtlSec(int)}) or due to a failure.
- *
- * @param reason The termination reason using
- * {@code WifiAwareDiscoverySessionCallback.TERMINATE_*} codes.
- */
- public void onSessionTerminated(@SessionTerminateCodes int reason) {
- /* empty */
- }
-
- /**
- * Called when a discovery (publish or subscribe) operation results in a
- * service discovery.
- *
- * @param peerHandle An opaque handle to the peer matching our discovery operation.
- * @param serviceSpecificInfo The service specific information (arbitrary
- * byte array) provided by the peer as part of its discovery
- * configuration.
- * @param matchFilter The filter which resulted in this service discovery.
- */
- public void onServiceDiscovered(WifiAwareManager.PeerHandle peerHandle,
- byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
- /* empty */
- }
-
- /**
- * Called in response to
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
- * when a message is transmitted successfully - i.e. when it was received successfully by the
- * peer (corresponds to an ACK being received).
- * <p>
- * Note that either this callback or
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)} will be
- * received - never both.
- *
- * @param messageId The arbitrary message ID specified when sending the message.
- */
- public void onMessageSendSucceeded(@SuppressWarnings("unused") int messageId) {
- /* empty */
- }
-
- /**
- * Called when message transmission fails - when no ACK is received from the peer.
- * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
- * the {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
- * byte[], int)} method) - this event is received after all retries are exhausted.
- * <p>
- * Note that either this callback or
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
- * - never both.
- *
- * @param messageId The arbitrary message ID specified when sending the message.
- */
- public void onMessageSendFailed(@SuppressWarnings("unused") int messageId) {
- /* empty */
- }
-
- /**
- * Called when a message is received from a discovery session peer - in response to the
- * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
- * byte[])} or {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle,
- * int, byte[], int)}.
- *
- * @param peerHandle An opaque handle to the peer matching our discovery operation.
- * @param message A byte array containing the message.
- */
- public void onMessageReceived(WifiAwareManager.PeerHandle peerHandle, byte[] message) {
- /* empty */
- }
-}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 029794d..043925ed 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -58,14 +58,14 @@
* The class provides access to:
* <ul>
* <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
- * {@link #attach(WifiAwareAttachCallback, Handler)}.
+ * {@link #attach(AttachCallback, Handler)}.
* <li>Create discovery sessions (publish or subscribe sessions). Refer to
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} and
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, Handler)}.
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} and
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}.
* <li>Create a Aware network specifier to be used with
* {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
* to set-up a Aware connection with a peer. Refer to
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])} and
+ * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])} and
* {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
* </ul>
* <p>
@@ -75,37 +75,37 @@
* broadcast. Note that this broadcast is not sticky - you should register for it and then
* check the above API to avoid a race condition.
* <p>
- * An application must use {@link #attach(WifiAwareAttachCallback, Handler)} to initialize a
+ * An application must use {@link #attach(AttachCallback, Handler)} to initialize a
* Aware cluster - before making any other Aware operation. Aware cluster membership is a
* device-wide operation - the API guarantees that the device is in a cluster or joins a
* Aware cluster (or starts one if none can be found). Information about attach success (or
- * failure) are returned in callbacks of {@link WifiAwareAttachCallback}. Proceed with Aware
+ * failure) are returned in callbacks of {@link AttachCallback}. Proceed with Aware
* discovery or connection setup only after receiving confirmation that Aware attach
- * succeeded - {@link WifiAwareAttachCallback#onAttached(WifiAwareSession)}. When an
+ * succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an
* application is finished using Aware it <b>must</b> use the
* {@link WifiAwareSession#destroy()} API to indicate to the Aware service that the device
* may detach from the Aware cluster. The device will actually disable Aware once the last
* application detaches.
* <p>
* Once a Aware attach is confirmed use the
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)}
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
* or
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
* Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the
- * provided callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
- * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}
+ * provided callback object {@link DiscoverySessionCallback}. Specifically, the
+ * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}
* and
- * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
- * WifiAwareSubscribeDiscoverySession)}
- * return {@link WifiAwarePublishDiscoverySession} and
- * {@link WifiAwareSubscribeDiscoverySession}
+ * {@link DiscoverySessionCallback#onSubscribeStarted(
+ *SubscribeDiscoverySession)}
+ * return {@link PublishDiscoverySession} and
+ * {@link SubscribeDiscoverySession}
* objects respectively on which additional session operations can be performed, e.g. updating
- * the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
+ * the session {@link PublishDiscoverySession#updatePublish(PublishConfig)} and
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
* also be used to send messages using the
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(PeerHandle, int, byte[])} APIs. When an
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an
* application is finished with a discovery session it <b>must</b> terminate it using the
- * {@link WifiAwareDiscoveryBaseSession#destroy()} API.
+ * {@link DiscoverySession#destroy()} API.
* <p>
* Creating connections between Aware devices is managed by the standard
* {@link ConnectivityManager#requestNetwork(NetworkRequest,
@@ -116,10 +116,8 @@
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
* {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])}.
+ * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}.
* </ul>
- *
- * @hide PROPOSED_AWARE_API
*/
public class WifiAwareManager {
private static final String TAG = "WifiAwareManager";
@@ -226,7 +224,7 @@
* Connection creation role is that of INITIATOR. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])
+ * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])
* @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
@@ -235,7 +233,7 @@
* Connection creation role is that of RESPONDER. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])
+ * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])
* @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
@@ -305,9 +303,8 @@
* limitations on configurations, e.g. the maximum service name length.
*
* @return An object specifying configuration limitations of Aware.
- * @hide PROPOSED_AWARE_API
*/
- public WifiAwareCharacteristics getCharacteristics() {
+ public Characteristics getCharacteristics() {
try {
return mService.getCharacteristics();
} catch (RemoteException e) {
@@ -328,12 +325,12 @@
* attachCallback}.
*
* @param attachCallback A callback for attach events, extended from
- * {@link WifiAwareAttachCallback}.
+ * {@link AttachCallback}.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* attachCallback} object. If a null is provided then the application's main thread will be
* used.
*/
- public void attach(@NonNull WifiAwareAttachCallback attachCallback, @Nullable Handler handler) {
+ public void attach(@NonNull AttachCallback attachCallback, @Nullable Handler handler) {
attach(handler, null, attachCallback, null);
}
@@ -353,28 +350,28 @@
* on startup and whenever it is updated (it is randomized at regular intervals for privacy).
* The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
* permission to execute this attach request. Otherwise, use the
- * {@link #attach(WifiAwareAttachCallback, Handler)} version. Note that aside from permission
+ * {@link #attach(AttachCallback, Handler)} version. Note that aside from permission
* requirements this listener will wake up the host at regular intervals causing higher power
* consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
*
* @param attachCallback A callback for attach events, extended from
- * {@link WifiAwareAttachCallback}.
+ * {@link AttachCallback}.
* @param identityChangedListener A listener for changed identity, extended from
- * {@link WifiAwareIdentityChangedListener}.
+ * {@link IdentityChangedListener}.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
* application's main thread will be used.
*/
- public void attach(@NonNull WifiAwareAttachCallback attachCallback,
- @NonNull WifiAwareIdentityChangedListener identityChangedListener,
+ public void attach(@NonNull AttachCallback attachCallback,
+ @NonNull IdentityChangedListener identityChangedListener,
@Nullable Handler handler) {
attach(handler, null, attachCallback, identityChangedListener);
}
/** @hide */
public void attach(Handler handler, ConfigRequest configRequest,
- WifiAwareAttachCallback attachCallback,
- WifiAwareIdentityChangedListener identityChangedListener) {
+ AttachCallback attachCallback,
+ IdentityChangedListener identityChangedListener) {
if (VDBG) {
Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback
+ ", configRequest=" + configRequest + ", identityChangedListener="
@@ -409,7 +406,7 @@
/** @hide */
public void publish(int clientId, Looper looper, PublishConfig publishConfig,
- WifiAwareDiscoverySessionCallback callback) {
+ DiscoverySessionCallback callback) {
if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig);
try {
@@ -437,7 +434,7 @@
/** @hide */
public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig,
- WifiAwareDiscoverySessionCallback callback) {
+ DiscoverySessionCallback callback) {
if (VDBG) {
if (VDBG) {
Log.v(TAG,
@@ -672,14 +669,14 @@
}
/**
- * Constructs a {@link WifiAwareAttachCallback} using the specified looper.
+ * Constructs a {@link AttachCallback} using the specified looper.
* All callbacks will delivered on the thread of the specified looper.
*
* @param looper The looper on which to execute the callbacks.
*/
WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder,
- final WifiAwareAttachCallback attachCallback,
- final WifiAwareIdentityChangedListener identityChangedListener) {
+ final AttachCallback attachCallback,
+ final IdentityChangedListener identityChangedListener) {
mAwareManager = new WeakReference<>(mgr);
mLooper = looper;
mBinder = binder;
@@ -828,14 +825,14 @@
private final WeakReference<WifiAwareManager> mAwareManager;
private final boolean mIsPublish;
- private final WifiAwareDiscoverySessionCallback mOriginalCallback;
+ private final DiscoverySessionCallback mOriginalCallback;
private final int mClientId;
private final Handler mHandler;
- private WifiAwareDiscoveryBaseSession mSession;
+ private DiscoverySession mSession;
WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper,
- boolean isPublish, WifiAwareDiscoverySessionCallback originalCallback,
+ boolean isPublish, DiscoverySessionCallback originalCallback,
int clientId) {
mAwareManager = new WeakReference<>(mgr);
mIsPublish = isPublish;
@@ -1006,13 +1003,13 @@
}
if (mIsPublish) {
- WifiAwarePublishDiscoverySession session = new WifiAwarePublishDiscoverySession(mgr,
+ PublishDiscoverySession session = new PublishDiscoverySession(mgr,
mClientId, sessionId);
mSession = session;
mOriginalCallback.onPublishStarted(session);
} else {
- WifiAwareSubscribeDiscoverySession
- session = new WifiAwareSubscribeDiscoverySession(mgr, mClientId, sessionId);
+ SubscribeDiscoverySession
+ session = new SubscribeDiscoverySession(mgr, mClientId, sessionId);
mSession = session;
mOriginalCallback.onSubscribeStarted(session);
}
@@ -1027,18 +1024,7 @@
Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?");
}
mAwareManager.clear();
- mOriginalCallback.onSessionTerminated(reason);
+ mOriginalCallback.onSessionTerminated();
}
}
-
- /** @hide PROPOSED_AWARE_API */
- public static class PeerHandle {
- /** @hide */
- public PeerHandle(int peerId) {
- this.peerId = peerId;
- }
-
- /** @hide */
- public int peerId;
- }
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 005895a..8696920 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -30,8 +30,6 @@
/**
* This class represents a Wi-Fi Aware session - an attachment to the Wi-Fi Aware service through
* which the app can execute discovery operations.
- *
- * @hide PROPOSED_AWARE_API
*/
public class WifiAwareSession {
private static final String TAG = "WifiAwareSession";
@@ -65,7 +63,7 @@
* session-wide destroy.
* <p>
* An application may re-attach after a destroy using
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, Handler)} .
+ * {@link WifiAwareManager#attach(AttachCallback, Handler)} .
*/
public void destroy() {
WifiAwareManager mgr = mMgr.get();
@@ -95,22 +93,22 @@
/**
* Issue a request to the Aware service to create a new Aware publish discovery session, using
* the specified {@code publishConfig} configuration. The results of the publish operation
- * are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}:
+ * are routed to the callbacks of {@link DiscoverySessionCallback}:
* <ul>
* <li>
- * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(
- * WifiAwarePublishDiscoverySession)}
+ * {@link DiscoverySessionCallback#onPublishStarted(
+ *PublishDiscoverySession)}
* is called when the publish session is created and provides a handle to the session.
* Further operations on the publish session can be executed on that object.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the
* publish operation failed.
* </ul>
* <p>
* Other results of the publish session operations will also be routed to callbacks
* on the {@code callback} object. The resulting publish session can be modified using
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)}.
* <p>
- * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to
+ * An application must use the {@link DiscoverySession#destroy()} to
* terminate the publish discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
* <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
@@ -118,13 +116,13 @@
*
* @param publishConfig The {@link PublishConfig} specifying the
* configuration of the requested publish session.
- * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
+ * @param callback A {@link DiscoverySessionCallback} derived object to be used for
* session event callbacks.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* callback} object. If a null is provided then the application's main thread will be used.
*/
public void publish(@NonNull PublishConfig publishConfig,
- @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
+ @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -141,22 +139,22 @@
/**
* Issue a request to the Aware service to create a new Aware subscribe discovery session, using
* the specified {@code subscribeConfig} configuration. The results of the subscribe
- * operation are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}:
+ * operation are routed to the callbacks of {@link DiscoverySessionCallback}:
* <ul>
* <li>
- * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
- * WifiAwareSubscribeDiscoverySession)}
+ * {@link DiscoverySessionCallback#onSubscribeStarted(
+ *SubscribeDiscoverySession)}
* is called when the subscribe session is created and provides a handle to the session.
* Further operations on the subscribe session can be executed on that object.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the
* subscribe operation failed.
* </ul>
* <p>
* Other results of the subscribe session operations will also be routed to callbacks
* on the {@code callback} object. The resulting subscribe session can be modified using
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
* <p>
- * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to
+ * An application must use the {@link DiscoverySession#destroy()} to
* terminate the subscribe discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
* <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
@@ -164,13 +162,13 @@
*
* @param subscribeConfig The {@link SubscribeConfig} specifying the
* configuration of the requested subscribe session.
- * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
+ * @param callback A {@link DiscoverySessionCallback} derived object to be used for
* session event callbacks.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* callback} object. If a null is provided then the application's main thread will be used.
*/
public void subscribe(@NonNull SubscribeConfig subscribeConfig,
- @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
+ @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -193,7 +191,7 @@
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
* when using Aware discovery use the alternative network specifier method -
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySession#createNetworkSpecifier(PeerHandle,
* byte[])}.
*
* @param role The role of this device:
diff --git a/wifi/java/android/net/wifi/aware/package.html b/wifi/java/android/net/wifi/aware/package.html
index 1a990d8..d5d962f6 100644
--- a/wifi/java/android/net/wifi/aware/package.html
+++ b/wifi/java/android/net/wifi/aware/package.html
@@ -23,7 +23,7 @@
If your application only works with Wi-Fi Aware (i.e. it should only be installed on devices which
support Wi-Fi Aware), declare so with a <a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
- {@code <uses-feature>}</a>
+ {@code <uses-feature>}</a>
element in the manifest file:</p>
<pre>
<manifest ...>
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 24c0127..a396d87 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -67,19 +67,19 @@
public Context mockContext;
@Mock
- public WifiAwareAttachCallback mockCallback;
+ public AttachCallback mockCallback;
@Mock
- public WifiAwareDiscoverySessionCallback mockSessionCallback;
+ public DiscoverySessionCallback mockSessionCallback;
@Mock
public IWifiAwareManager mockAwareService;
@Mock
- public WifiAwarePublishDiscoverySession mockPublishSession;
+ public PublishDiscoverySession mockPublishSession;
@Mock
- public WifiAwareSubscribeDiscoverySession mockSubscribeSession;
+ public SubscribeDiscoverySession mockSubscribeSession;
@Mock
public RttManager.RttListener mockRttListener;
@@ -276,7 +276,7 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
- final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873);
+ final PeerHandle peerHandle = new PeerHandle(873);
final String string1 = "hey from here...";
final byte[] matchFilter = { 1, 12, 2, 31, 32 };
final int messageId = 2123;
@@ -290,10 +290,9 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
- ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(
- WifiAwareManager.PeerHandle.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
+ ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class);
ArgumentCaptor<List<byte[]>> matchFilterCaptor = ArgumentCaptor.forClass(
(Class) List.class);
@@ -377,7 +376,6 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
- final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE;
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession);
@@ -387,8 +385,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
@@ -404,10 +402,10 @@
inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
sessionProxyCallback.capture());
sessionProxyCallback.getValue().onSessionStarted(sessionId);
- sessionProxyCallback.getValue().onSessionTerminated(reason);
+ sessionProxyCallback.getValue().onSessionTerminated(0);
mMockLooper.dispatchAll();
inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
- inOrder.verify(mockSessionCallback).onSessionTerminated(reason);
+ inOrder.verify(mockSessionCallback).onSessionTerminated();
// (3) failure when trying to update: NOP
publishSession.getValue().updatePublish(publishConfig);
@@ -428,7 +426,7 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
- final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873);
+ final PeerHandle peerHandle = new PeerHandle(873);
final String string1 = "hey from here...";
final byte[] matchFilter = { 1, 12, 3, 31, 32 }; // bad data!
final int messageId = 2123;
@@ -442,10 +440,9 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor
- .forClass(WifiAwareSubscribeDiscoverySession.class);
- ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(
- WifiAwareManager.PeerHandle.class);
+ ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor
+ .forClass(SubscribeDiscoverySession.class);
+ ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class);
// (0) connect + success
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
@@ -516,7 +513,6 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
- final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE;
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockSubscribeSession);
@@ -526,8 +522,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor
- .forClass(WifiAwareSubscribeDiscoverySession.class);
+ ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor
+ .forClass(SubscribeDiscoverySession.class);
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
@@ -543,10 +539,10 @@
inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
sessionProxyCallback.capture());
sessionProxyCallback.getValue().onSessionStarted(sessionId);
- sessionProxyCallback.getValue().onSessionTerminated(reason);
+ sessionProxyCallback.getValue().onSessionTerminated(0);
mMockLooper.dispatchAll();
inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture());
- inOrder.verify(mockSessionCallback).onSessionTerminated(reason);
+ inOrder.verify(mockSessionCallback).onSessionTerminated();
// (3) failure when trying to update: NOP
subscribeSession.getValue().updateSubscribe(subscribeConfig);
@@ -892,8 +888,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor
.forClass(RttManager.ParcelableRttParams.class);
ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor
@@ -953,7 +949,7 @@
public void testNetworkSpecifierWithClient() throws Exception {
final int clientId = 4565;
final int sessionId = 123;
- final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(123412);
+ final PeerHandle peerHandle = new PeerHandle(123412);
final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
final String token = "Some arbitrary token string - can really be anything";
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
@@ -967,8 +963,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);