Merge "Unhide DelegateLastClassLoader." into oc-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index dd9ff13..2428da1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37768,8 +37768,10 @@
method public android.view.SurfaceHolder getSurfaceHolder();
method public boolean isPreview();
method public boolean isVisible();
+ method public void notifyColorsChanged();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ method public android.app.WallpaperColors onComputeColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -39536,7 +39538,7 @@
method public android.os.PersistableBundle getConfigForSubId(int);
method public void notifyConfigChangedForSubId(int);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
- field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
+ field public static final deprecated int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
@@ -39578,9 +39580,10 @@
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+ field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
- field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
- field public static final java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
+ field public static final deprecated java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
+ field public static final deprecated java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
field public static final java.lang.String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
@@ -39637,7 +39640,7 @@
field public static final java.lang.String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
field public static final java.lang.String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
field public static final java.lang.String KEY_MMS_USER_AGENT_STRING = "userAgent";
- field public static final java.lang.String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
+ field public static final deprecated java.lang.String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
@@ -40149,8 +40152,10 @@
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
method public static int getDefaultVoiceSubscriptionId();
+ method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
method public boolean isNetworkRoaming(int);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
@@ -40164,6 +40169,38 @@
method public void onSubscriptionsChanged();
}
+ public final class SubscriptionPlan implements android.os.Parcelable {
+ method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+ method public int describeContents();
+ method public int getDataLimitBehavior();
+ method public long getDataLimitBytes();
+ method public long getDataUsageBytes();
+ method public long getDataUsageTime();
+ method public java.lang.CharSequence getSummary();
+ method public java.lang.CharSequence getTitle();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final long BYTES_UNKNOWN = -1L; // 0xffffffffffffffffL
+ field public static final long BYTES_UNLIMITED = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionPlan> CREATOR;
+ field public static final int LIMIT_BEHAVIOR_BILLED = 1; // 0x1
+ field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0
+ field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2
+ field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff
+ field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+ }
+
+ public static class SubscriptionPlan.Builder {
+ method public android.telephony.SubscriptionPlan build();
+ method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+ method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
+ method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+ method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
+ method public android.telephony.SubscriptionPlan.Builder setTitle(java.lang.CharSequence);
+ }
+
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
diff --git a/api/system-current.txt b/api/system-current.txt
index 61d2833..47e47ac 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -146,7 +146,6 @@
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
- field public static final java.lang.String MANAGE_FALLBACK_SUBSCRIPTION_PLANS = "android.permission.MANAGE_FALLBACK_SUBSCRIPTION_PLANS";
field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
@@ -41097,8 +41096,10 @@
method public android.view.SurfaceHolder getSurfaceHolder();
method public boolean isPreview();
method public boolean isVisible();
+ method public void notifyColorsChanged();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ method public android.app.WallpaperColors onComputeColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -43083,7 +43084,7 @@
method public void notifyConfigChangedForSubId(int);
method public void updateConfigForPhoneId(int, java.lang.String);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
- field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
+ field public static final deprecated int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
@@ -43125,9 +43126,10 @@
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+ field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
- field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
- field public static final java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
+ field public static final deprecated java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
+ field public static final deprecated java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
field public static final java.lang.String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
@@ -43184,7 +43186,7 @@
field public static final java.lang.String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
field public static final java.lang.String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
field public static final java.lang.String KEY_MMS_USER_AGENT_STRING = "userAgent";
- field public static final java.lang.String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
+ field public static final deprecated java.lang.String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
@@ -43698,8 +43700,10 @@
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
method public static int getDefaultVoiceSubscriptionId();
+ method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
method public boolean isNetworkRoaming(int);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
@@ -43713,6 +43717,38 @@
method public void onSubscriptionsChanged();
}
+ public final class SubscriptionPlan implements android.os.Parcelable {
+ method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+ method public int describeContents();
+ method public int getDataLimitBehavior();
+ method public long getDataLimitBytes();
+ method public long getDataUsageBytes();
+ method public long getDataUsageTime();
+ method public java.lang.CharSequence getSummary();
+ method public java.lang.CharSequence getTitle();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final long BYTES_UNKNOWN = -1L; // 0xffffffffffffffffL
+ field public static final long BYTES_UNLIMITED = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionPlan> CREATOR;
+ field public static final int LIMIT_BEHAVIOR_BILLED = 1; // 0x1
+ field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0
+ field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2
+ field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff
+ field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+ }
+
+ public static class SubscriptionPlan.Builder {
+ method public android.telephony.SubscriptionPlan build();
+ method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+ method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
+ method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+ method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
+ method public android.telephony.SubscriptionPlan.Builder setTitle(java.lang.CharSequence);
+ }
+
public final class TelephonyHistogram implements android.os.Parcelable {
ctor public TelephonyHistogram(int, int, int);
ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
diff --git a/api/test-current.txt b/api/test-current.txt
index a49c14a..62f8418 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -37978,8 +37978,10 @@
method public android.view.SurfaceHolder getSurfaceHolder();
method public boolean isPreview();
method public boolean isVisible();
+ method public void notifyColorsChanged();
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+ method public android.app.WallpaperColors onComputeColors();
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
method public void onDestroy();
@@ -39762,7 +39764,7 @@
method public android.os.PersistableBundle getConfigForSubId(int);
method public void notifyConfigChangedForSubId(int);
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
- field public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
+ field public static final deprecated int DATA_CYCLE_THRESHOLD_DISABLED = -2; // 0xfffffffe
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
@@ -39804,9 +39806,10 @@
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+ field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
- field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
- field public static final java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
+ field public static final deprecated java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
+ field public static final deprecated java.lang.String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
field public static final java.lang.String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
@@ -39863,7 +39866,7 @@
field public static final java.lang.String KEY_MMS_UA_PROF_TAG_NAME_STRING = "uaProfTagName";
field public static final java.lang.String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
field public static final java.lang.String KEY_MMS_USER_AGENT_STRING = "userAgent";
- field public static final java.lang.String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
+ field public static final deprecated java.lang.String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
field public static final java.lang.String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final java.lang.String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
field public static final java.lang.String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
@@ -40375,8 +40378,10 @@
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
method public static int getDefaultVoiceSubscriptionId();
+ method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
method public boolean isNetworkRoaming(int);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
@@ -40390,6 +40395,38 @@
method public void onSubscriptionsChanged();
}
+ public final class SubscriptionPlan implements android.os.Parcelable {
+ method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+ method public int describeContents();
+ method public int getDataLimitBehavior();
+ method public long getDataLimitBytes();
+ method public long getDataUsageBytes();
+ method public long getDataUsageTime();
+ method public java.lang.CharSequence getSummary();
+ method public java.lang.CharSequence getTitle();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final long BYTES_UNKNOWN = -1L; // 0xffffffffffffffffL
+ field public static final long BYTES_UNLIMITED = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionPlan> CREATOR;
+ field public static final int LIMIT_BEHAVIOR_BILLED = 1; // 0x1
+ field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0
+ field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2
+ field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff
+ field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+ }
+
+ public static class SubscriptionPlan.Builder {
+ method public android.telephony.SubscriptionPlan build();
+ method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+ method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
+ method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+ method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
+ method public android.telephony.SubscriptionPlan.Builder setTitle(java.lang.CharSequence);
+ }
+
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 7b948a7..181e4a2 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -71,7 +71,5 @@
SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
- String getSubscriptionPlanOwner(int subId);
-
void factoryReset(String subscriber);
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index edf9a28..5df742c 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -16,16 +16,21 @@
package android.net;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
+import android.util.Pair;
+import android.util.RecurrenceRule;
+
+import com.android.internal.util.Preconditions;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Iterator;
import java.util.Objects;
/**
@@ -35,10 +40,8 @@
* @hide
*/
public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
- /**
- * Current Version of the Backup Serializer.
- */
- private static final int BACKUP_VERSION = 1;
+ private static final int VERSION_INIT = 1;
+ private static final int VERSION_RULE = 2;
public static final int CYCLE_NONE = -1;
public static final long WARNING_DISABLED = -1;
@@ -46,8 +49,7 @@
public static final long SNOOZE_NEVER = -1;
public NetworkTemplate template;
- @Deprecated public int cycleDay = CYCLE_NONE;
- @Deprecated public String cycleTimezone = "UTC";
+ public RecurrenceRule cycleRule;
public long warningBytes = WARNING_DISABLED;
public long limitBytes = LIMIT_DISABLED;
public long lastWarningSnooze = SNOOZE_NEVER;
@@ -57,7 +59,12 @@
private static final long DEFAULT_MTU = 1500;
- public NetworkPolicy() {
+ public static RecurrenceRule buildRule(int cycleDay, ZoneId cycleTimezone) {
+ if (cycleDay != NetworkPolicy.CYCLE_NONE) {
+ return RecurrenceRule.buildRecurringMonthly(cycleDay, cycleTimezone);
+ } else {
+ return RecurrenceRule.buildNever();
+ }
}
@Deprecated
@@ -67,12 +74,19 @@
SNOOZE_NEVER, metered, false);
}
+ @Deprecated
public NetworkPolicy(NetworkTemplate template, int cycleDay, String cycleTimezone,
long warningBytes, long limitBytes, long lastWarningSnooze, long lastLimitSnooze,
boolean metered, boolean inferred) {
- this.template = checkNotNull(template, "missing NetworkTemplate");
- this.cycleDay = cycleDay;
- this.cycleTimezone = checkNotNull(cycleTimezone, "missing cycleTimezone");
+ this(template, buildRule(cycleDay, ZoneId.of(cycleTimezone)), warningBytes,
+ limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
+ }
+
+ public NetworkPolicy(NetworkTemplate template, RecurrenceRule cycleRule, long warningBytes,
+ long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered,
+ boolean inferred) {
+ this.template = Preconditions.checkNotNull(template, "missing NetworkTemplate");
+ this.cycleRule = Preconditions.checkNotNull(cycleRule, "missing RecurrenceRule");
this.warningBytes = warningBytes;
this.limitBytes = limitBytes;
this.lastWarningSnooze = lastWarningSnooze;
@@ -81,23 +95,21 @@
this.inferred = inferred;
}
- public NetworkPolicy(Parcel in) {
- template = in.readParcelable(null);
- cycleDay = in.readInt();
- cycleTimezone = in.readString();
- warningBytes = in.readLong();
- limitBytes = in.readLong();
- lastWarningSnooze = in.readLong();
- lastLimitSnooze = in.readLong();
- metered = in.readInt() != 0;
- inferred = in.readInt() != 0;
+ private NetworkPolicy(Parcel source) {
+ template = source.readParcelable(null);
+ cycleRule = source.readParcelable(null);
+ warningBytes = source.readLong();
+ limitBytes = source.readLong();
+ lastWarningSnooze = source.readLong();
+ lastLimitSnooze = source.readLong();
+ metered = source.readInt() != 0;
+ inferred = source.readInt() != 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(template, flags);
- dest.writeInt(cycleDay);
- dest.writeString(cycleTimezone);
+ dest.writeParcelable(cycleRule, flags);
dest.writeLong(warningBytes);
dest.writeLong(limitBytes);
dest.writeLong(lastWarningSnooze);
@@ -111,6 +123,10 @@
return 0;
}
+ public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ return cycleRule.cycleIterator();
+ }
+
/**
* Test if given measurement is over {@link #warningBytes}.
*/
@@ -141,7 +157,7 @@
* Test if this policy has a cycle defined, after which usage should reset.
*/
public boolean hasCycle() {
- return cycleDay != CYCLE_NONE;
+ return cycleRule.cycleIterator().hasNext();
}
@Override
@@ -159,7 +175,7 @@
@Override
public int hashCode() {
- return Objects.hash(template, cycleDay, cycleTimezone, warningBytes, limitBytes,
+ return Objects.hash(template, cycleRule, warningBytes, limitBytes,
lastWarningSnooze, lastLimitSnooze, metered, inferred);
}
@@ -167,30 +183,29 @@
public boolean equals(Object obj) {
if (obj instanceof NetworkPolicy) {
final NetworkPolicy other = (NetworkPolicy) obj;
- return cycleDay == other.cycleDay && warningBytes == other.warningBytes
+ return warningBytes == other.warningBytes
&& limitBytes == other.limitBytes
&& lastWarningSnooze == other.lastWarningSnooze
&& lastLimitSnooze == other.lastLimitSnooze && metered == other.metered
&& inferred == other.inferred
- && Objects.equals(cycleTimezone, other.cycleTimezone)
- && Objects.equals(template, other.template);
+ && Objects.equals(template, other.template)
+ && Objects.equals(cycleRule, other.cycleRule);
}
return false;
}
@Override
public String toString() {
- final StringBuilder builder = new StringBuilder("NetworkPolicy");
- builder.append("[").append(template).append("]:");
- builder.append(" cycleDay=").append(cycleDay);
- builder.append(", cycleTimezone=").append(cycleTimezone);
- builder.append(", warningBytes=").append(warningBytes);
- builder.append(", limitBytes=").append(limitBytes);
- builder.append(", lastWarningSnooze=").append(lastWarningSnooze);
- builder.append(", lastLimitSnooze=").append(lastLimitSnooze);
- builder.append(", metered=").append(metered);
- builder.append(", inferred=").append(inferred);
- return builder.toString();
+ return new StringBuilder("NetworkPolicy{")
+ .append("template=").append(template)
+ .append(" cycleRule=").append(cycleRule)
+ .append(" warningBytes=").append(warningBytes)
+ .append(" limitBytes=").append(limitBytes)
+ .append(" lastWarningSnooze=").append(lastWarningSnooze)
+ .append(" lastLimitSnooze=").append(lastLimitSnooze)
+ .append(" metered=").append(metered)
+ .append(" inferred=").append(inferred)
+ .append("}").toString();
}
public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
@@ -209,10 +224,9 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos);
- out.writeInt(BACKUP_VERSION);
+ out.writeInt(VERSION_RULE);
out.write(template.getBytesForBackup());
- out.writeInt(cycleDay);
- BackupUtils.writeString(out, cycleTimezone);
+ cycleRule.writeToStream(out);
out.writeLong(warningBytes);
out.writeLong(limitBytes);
out.writeLong(lastWarningSnooze);
@@ -224,21 +238,36 @@
public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException,
BackupUtils.BadVersionException {
- int version = in.readInt();
- if (version < 1 || version > BACKUP_VERSION) {
- throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
+ final int version = in.readInt();
+ switch (version) {
+ case VERSION_INIT: {
+ NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
+ int cycleDay = in.readInt();
+ String cycleTimeZone = BackupUtils.readString(in);
+ long warningBytes = in.readLong();
+ long limitBytes = in.readLong();
+ long lastWarningSnooze = in.readLong();
+ long lastLimitSnooze = in.readLong();
+ boolean metered = in.readInt() == 1;
+ boolean inferred = in.readInt() == 1;
+ return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes,
+ limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
+ }
+ case VERSION_RULE: {
+ NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
+ RecurrenceRule cycleRule = new RecurrenceRule(in);
+ long warningBytes = in.readLong();
+ long limitBytes = in.readLong();
+ long lastWarningSnooze = in.readLong();
+ long lastLimitSnooze = in.readLong();
+ boolean metered = in.readInt() == 1;
+ boolean inferred = in.readInt() == 1;
+ return new NetworkPolicy(template, cycleRule, warningBytes,
+ limitBytes, lastWarningSnooze, lastLimitSnooze, metered, inferred);
+ }
+ default: {
+ throw new BackupUtils.BadVersionException("Unknown backup version: " + version);
+ }
}
-
- NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
- int cycleDay = in.readInt();
- String cycleTimeZone = BackupUtils.readString(in);
- long warningBytes = in.readLong();
- long limitBytes = in.readLong();
- long lastWarningSnooze = in.readLong();
- long lastLimitSnooze = in.readLong();
- boolean metered = in.readInt() == 1;
- boolean inferred = in.readInt() == 1;
- return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes, limitBytes,
- lastWarningSnooze, lastLimitSnooze, metered, inferred);
}
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 3fe9b0d..81c49a3 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -254,7 +254,7 @@
/** {@hide} */
public static Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator(NetworkPolicy policy) {
- return SubscriptionPlan.convert(policy).cycleIterator();
+ return policy.cycleIterator();
}
/**
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e4d3142..424967f 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -547,12 +547,11 @@
/**
* Notifies the engine that wallpaper colors changed significantly.
- * This will trigger a {@link #onComputeWallpaperColors()} call.
- * @hide
+ * This will trigger a {@link #onComputeColors()} call.
*/
- public void invalidateColors() {
+ public void notifyColorsChanged() {
try {
- mConnection.onWallpaperColorsChanged(onComputeWallpaperColors());
+ mConnection.onWallpaperColorsChanged(onComputeColors());
} catch (RemoteException e) {
Log.w(TAG, "Can't invalidate wallpaper colors because " +
"wallpaper connection was lost", e);
@@ -560,19 +559,18 @@
}
/**
- * Notifies the system about what colors the wallpaper is using.
+ * Called by the system when it needs to know what colors the wallpaper is using.
* You might return null if no color information is available at the moment. In that case
- * you might want to call {@link #invalidateColors()} in a near future.
+ * you might want to call {@link #notifyColorsChanged()} in a near future.
* <p>
- * The simplest way of creating A {@link android.app.WallpaperColors} object is by using
+ * The simplest way of creating a {@link android.app.WallpaperColors} object is by using
* {@link android.app.WallpaperColors#fromBitmap(Bitmap)} or
* {@link android.app.WallpaperColors#fromDrawable(Drawable)}, but you can also specify
- * your main colors and dark text support explicitly using one of the constructors.
+ * your main colors by constructing a {@link android.app.WallpaperColors} object manually.
*
* @return Wallpaper colors.
- * @hide
*/
- public @Nullable WallpaperColors onComputeWallpaperColors() {
+ public @Nullable WallpaperColors onComputeColors() {
return null;
}
@@ -1212,7 +1210,7 @@
mEngine = engine;
mActiveEngines.add(engine);
engine.attach(this);
- engine.invalidateColors();
+ engine.notifyColorsChanged();
return;
}
case DO_DETACH: {
diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java
new file mode 100644
index 0000000..1fe638d
--- /dev/null
+++ b/core/java/android/util/RecurrenceRule.java
@@ -0,0 +1,257 @@
+/*
+ * 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 android.util;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.time.Clock;
+import java.time.LocalTime;
+import java.time.Period;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Iterator;
+import java.util.Objects;
+
+/**
+ * Description of an event that should recur over time at a specific interval
+ * between two anchor points in time.
+ *
+ * @hide
+ */
+public class RecurrenceRule implements Parcelable {
+ private static final String TAG = "RecurrenceRule";
+ private static final boolean DEBUG = true;
+
+ private static final int VERSION_INIT = 0;
+
+ /** {@hide} */
+ @VisibleForTesting
+ public static Clock sClock = Clock.systemDefaultZone();
+
+ public final ZonedDateTime start;
+ public final ZonedDateTime end;
+ public final Period period;
+
+ public RecurrenceRule(ZonedDateTime start, ZonedDateTime end, Period period) {
+ this.start = start;
+ this.end = end;
+ this.period = period;
+ }
+
+ @Deprecated
+ public static RecurrenceRule buildNever() {
+ return new RecurrenceRule(null, null, null);
+ }
+
+ @Deprecated
+ public static RecurrenceRule buildRecurringMonthly(int dayOfMonth, ZoneId zone) {
+ // Assume we started last January, since it has all possible days
+ final ZonedDateTime now = ZonedDateTime.now(sClock).withZoneSameInstant(zone);
+ final ZonedDateTime start = ZonedDateTime.of(
+ now.toLocalDate().minusYears(1).withMonth(1).withDayOfMonth(dayOfMonth),
+ LocalTime.MIDNIGHT, zone);
+ return new RecurrenceRule(start, null, Period.ofMonths(1));
+ }
+
+ private RecurrenceRule(Parcel source) {
+ start = convertZonedDateTime(source.readString());
+ end = convertZonedDateTime(source.readString());
+ period = convertPeriod(source.readString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(convertZonedDateTime(start));
+ dest.writeString(convertZonedDateTime(end));
+ dest.writeString(convertPeriod(period));
+ }
+
+ public RecurrenceRule(DataInputStream in) throws IOException {
+ final int version = in.readInt();
+ switch (version) {
+ case VERSION_INIT:
+ start = convertZonedDateTime(BackupUtils.readString(in));
+ end = convertZonedDateTime(BackupUtils.readString(in));
+ period = convertPeriod(BackupUtils.readString(in));
+ default:
+ throw new ProtocolException("Unknown version " + version);
+ }
+ }
+
+ public void writeToStream(DataOutputStream out) throws IOException {
+ out.writeInt(VERSION_INIT);
+ BackupUtils.writeString(out, convertZonedDateTime(start));
+ BackupUtils.writeString(out, convertZonedDateTime(end));
+ BackupUtils.writeString(out, convertPeriod(period));
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder("RecurrenceRule{")
+ .append("start=").append(start)
+ .append(" end=").append(end)
+ .append(" period=").append(period)
+ .append("}").toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(start, end, period);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof RecurrenceRule) {
+ final RecurrenceRule other = (RecurrenceRule) obj;
+ return Objects.equals(start, other.start)
+ && Objects.equals(end, other.end)
+ && Objects.equals(period, other.period);
+ }
+ return false;
+ }
+
+ public static final Parcelable.Creator<RecurrenceRule> CREATOR = new Parcelable.Creator<RecurrenceRule>() {
+ @Override
+ public RecurrenceRule createFromParcel(Parcel source) {
+ return new RecurrenceRule(source);
+ }
+
+ @Override
+ public RecurrenceRule[] newArray(int size) {
+ return new RecurrenceRule[size];
+ }
+ };
+
+ @Deprecated
+ public boolean isMonthly() {
+ return start != null
+ && period != null
+ && period.getYears() == 0
+ && period.getMonths() == 1
+ && period.getDays() == 0;
+ }
+
+ public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ if (period != null) {
+ return new RecurringIterator();
+ } else {
+ return new NonrecurringIterator();
+ }
+ }
+
+ private class NonrecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> {
+ boolean hasNext;
+
+ public NonrecurringIterator() {
+ hasNext = (start != null) && (end != null);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return hasNext;
+ }
+
+ @Override
+ public Pair<ZonedDateTime, ZonedDateTime> next() {
+ hasNext = false;
+ return new Pair<>(start, end);
+ }
+ }
+
+ private class RecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> {
+ int i;
+ ZonedDateTime cycleStart;
+ ZonedDateTime cycleEnd;
+
+ public RecurringIterator() {
+ final ZonedDateTime anchor = (end != null) ? end
+ : ZonedDateTime.now(sClock).withZoneSameInstant(start.getZone());
+ if (DEBUG) Log.d(TAG, "Resolving using anchor " + anchor);
+
+ updateCycle();
+
+ // Walk forwards until we find first cycle after now
+ while (anchor.toEpochSecond() > cycleEnd.toEpochSecond()) {
+ i++;
+ updateCycle();
+ }
+
+ // Walk backwards until we find first cycle before now
+ while (anchor.toEpochSecond() <= cycleStart.toEpochSecond()) {
+ i--;
+ updateCycle();
+ }
+ }
+
+ private void updateCycle() {
+ cycleStart = roundBoundaryTime(start.plus(period.multipliedBy(i)));
+ cycleEnd = roundBoundaryTime(start.plus(period.multipliedBy(i + 1)));
+ }
+
+ private ZonedDateTime roundBoundaryTime(ZonedDateTime boundary) {
+ if (isMonthly() && (boundary.getDayOfMonth() < start.getDayOfMonth())) {
+ // When forced to end a monthly cycle early, we want to count
+ // that entire day against the boundary.
+ return ZonedDateTime.of(boundary.toLocalDate(), LocalTime.MAX, start.getZone());
+ } else {
+ return boundary;
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return cycleStart.toEpochSecond() >= start.toEpochSecond();
+ }
+
+ @Override
+ public Pair<ZonedDateTime, ZonedDateTime> next() {
+ if (DEBUG) Log.d(TAG, "Cycle " + i + " from " + cycleStart + " to " + cycleEnd);
+ Pair<ZonedDateTime, ZonedDateTime> p = new Pair<>(cycleStart, cycleEnd);
+ i--;
+ updateCycle();
+ return p;
+ }
+ }
+
+ public static String convertZonedDateTime(ZonedDateTime time) {
+ return time != null ? time.toString() : null;
+ }
+
+ public static ZonedDateTime convertZonedDateTime(String time) {
+ return time != null ? ZonedDateTime.parse(time) : null;
+ }
+
+ public static String convertPeriod(Period period) {
+ return period != null ? period.toString() : null;
+ }
+
+ public static Period convertPeriod(String period) {
+ return period != null ? Period.parse(period) : null;
+ }
+}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8e550dc..4041bcf 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2599,5 +2599,16 @@
encoder.addProperty("type", type);
encoder.addProperty("flags", flags);
}
+
+ /**
+ * @hide
+ * @return True if the layout parameters will cause the window to cover the full screen;
+ * false otherwise.
+ */
+ public boolean isFullscreen() {
+ return x == 0 && y == 0
+ && width == WindowManager.LayoutParams.MATCH_PARENT
+ && height == WindowManager.LayoutParams.MATCH_PARENT;
+ }
}
}
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 3d8c85e..3188d30 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1694,10 +1694,10 @@
return in.getAttributeValue(null, name);
}
- public static void writeStringAttribute(XmlSerializer out, String name, String value)
+ public static void writeStringAttribute(XmlSerializer out, String name, CharSequence value)
throws IOException {
if (value != null) {
- out.attribute(null, name, value);
+ out.attribute(null, name, value.toString());
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c052e5145..4a2ef32 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3156,12 +3156,6 @@
<permission android:name="android.permission.MANAGE_NETWORK_POLICY"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows an application to manage fallback subscription plans.
- Note that another app providing plans for an explicit HNI will always
- take precidence over these fallback plans. @hide -->
- <permission android:name="android.permission.MANAGE_FALLBACK_SUBSCRIPTION_PLANS"
- android:protectionLevel="signature|privileged" />
-
<!-- @SystemApi @hide @deprecated use UPDATE_DEVICE_STATS instead -->
<permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
android:protectionLevel="signature|privileged" />
diff --git a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
new file mode 100644
index 0000000..42b6048
--- /dev/null
+++ b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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 android.util;
+
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.Period;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Iterator;
+
+@SmallTest
+public class RecurrenceRuleTest extends TestCase {
+
+ static Clock sOriginalClock;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ sOriginalClock = RecurrenceRule.sClock;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ RecurrenceRule.sClock = sOriginalClock;
+ }
+
+ private void setClock(Instant instant) {
+ RecurrenceRule.sClock = Clock.fixed(instant, ZoneId.systemDefault());
+ }
+
+ public void testSimpleMonth() throws Exception {
+ setClock(Instant.parse("2015-11-20T10:15:30.00Z"));
+ final RecurrenceRule r = new RecurrenceRule(
+ ZonedDateTime.parse("2010-11-14T00:00:00.000Z"),
+ null,
+ Period.ofMonths(1));
+
+ assertTrue(r.isMonthly());
+
+ final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ assertTrue(it.hasNext());
+ assertEquals(Pair.create(
+ ZonedDateTime.parse("2015-11-14T00:00:00.00Z"),
+ ZonedDateTime.parse("2015-12-14T00:00:00.00Z")), it.next());
+ assertTrue(it.hasNext());
+ assertEquals(Pair.create(
+ ZonedDateTime.parse("2015-10-14T00:00:00.00Z"),
+ ZonedDateTime.parse("2015-11-14T00:00:00.00Z")), it.next());
+ }
+
+ public void testSimpleDays() throws Exception {
+ setClock(Instant.parse("2015-01-01T10:15:30.00Z"));
+ final RecurrenceRule r = new RecurrenceRule(
+ ZonedDateTime.parse("2010-11-14T00:11:00.000Z"),
+ ZonedDateTime.parse("2010-11-20T00:11:00.000Z"),
+ Period.ofDays(3));
+
+ assertFalse(r.isMonthly());
+
+ final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ assertTrue(it.hasNext());
+ assertEquals(Pair.create(
+ ZonedDateTime.parse("2010-11-17T00:11:00.00Z"),
+ ZonedDateTime.parse("2010-11-20T00:11:00.00Z")), it.next());
+ assertTrue(it.hasNext());
+ assertEquals(Pair.create(
+ ZonedDateTime.parse("2010-11-14T00:11:00.00Z"),
+ ZonedDateTime.parse("2010-11-17T00:11:00.00Z")), it.next());
+ assertFalse(it.hasNext());
+ }
+
+ public void testNotRecurring() throws Exception {
+ setClock(Instant.parse("2015-01-01T10:15:30.00Z"));
+ final RecurrenceRule r = new RecurrenceRule(
+ ZonedDateTime.parse("2010-11-14T00:11:00.000Z"),
+ ZonedDateTime.parse("2010-11-20T00:11:00.000Z"),
+ null);
+
+ assertFalse(r.isMonthly());
+
+ final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ assertTrue(it.hasNext());
+ assertEquals(Pair.create(
+ ZonedDateTime.parse("2010-11-14T00:11:00.000Z"),
+ ZonedDateTime.parse("2010-11-20T00:11:00.000Z")), it.next());
+ assertFalse(it.hasNext());
+ }
+
+ public void testNever() throws Exception {
+ setClock(Instant.parse("2015-01-01T10:15:30.00Z"));
+ final RecurrenceRule r = RecurrenceRule.buildNever();
+
+ assertFalse(r.isMonthly());
+
+ final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ assertFalse(it.hasNext());
+ }
+
+ public void testSane() throws Exception {
+ final RecurrenceRule r = new RecurrenceRule(
+ ZonedDateTime.parse("1980-01-31T00:00:00.000Z"),
+ ZonedDateTime.parse("2030-01-31T00:00:00.000Z"),
+ Period.ofMonths(1));
+
+ final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = r.cycleIterator();
+ ZonedDateTime lastStart = null;
+ int months = 0;
+ while (it.hasNext()) {
+ final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
+
+ // Make sure cycle has reasonable length
+ final long length = cycle.second.toEpochSecond() - cycle.first.toEpochSecond();
+ assertTrue(cycle + " must be more than 4 weeks", length >= 2419200);
+ assertTrue(cycle + " must be less than 5 weeks", length <= 3024000);
+
+ // Make sure we have no gaps
+ if (lastStart != null) {
+ assertEquals(lastStart, cycle.second);
+ }
+ lastStart = cycle.first;
+ months++;
+ }
+
+ assertEquals(600, months);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index c346898..b01fc85 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -30,10 +30,12 @@
import android.net.wifi.WifiInfo;
import android.os.AsyncTask;
import android.text.TextUtils;
-import android.text.format.Time;
+import android.util.RecurrenceRule;
import com.google.android.collect.Lists;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
/**
@@ -129,35 +131,36 @@
@Deprecated
private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
// TODO: move this into framework to share with NetworkPolicyManagerService
- final int cycleDay;
- final String cycleTimezone;
+ final RecurrenceRule cycleRule;
final boolean metered;
if (template.getMatchRule() == MATCH_WIFI) {
- cycleDay = CYCLE_NONE;
- cycleTimezone = Time.TIMEZONE_UTC;
+ cycleRule = RecurrenceRule.buildNever();
metered = false;
} else {
- final Time time = new Time();
- time.setToNow();
- cycleDay = time.monthDay;
- cycleTimezone = time.timezone;
+ cycleRule = RecurrenceRule.buildRecurringMonthly(ZonedDateTime.now().getDayOfMonth(),
+ ZoneId.systemDefault());
metered = true;
}
- return new NetworkPolicy(template, cycleDay, cycleTimezone, WARNING_DISABLED,
+ return new NetworkPolicy(template, cycleRule, WARNING_DISABLED,
LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true);
}
+ @Deprecated
public int getPolicyCycleDay(NetworkTemplate template) {
final NetworkPolicy policy = getPolicy(template);
- return (policy != null) ? policy.cycleDay : CYCLE_NONE;
+ if (policy != null && policy.cycleRule.isMonthly()) {
+ return policy.cycleRule.start.getDayOfMonth();
+ } else {
+ return CYCLE_NONE;
+ }
}
+ @Deprecated
public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) {
final NetworkPolicy policy = getOrCreatePolicy(template);
- policy.cycleDay = cycleDay;
- policy.cycleTimezone = cycleTimezone;
+ policy.cycleRule = NetworkPolicy.buildRule(cycleDay, ZoneId.of(cycleTimezone));
policy.inferred = false;
policy.clearSnooze();
writeAsync();
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 38b2969..6eea030 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -273,6 +273,9 @@
<!-- Doze: the brightness value to use for the higher brightness AOD mode -->
<integer name="config_doze_aod_brightness_high">27</integer>
+ <!-- Doze: the brightness value to use for the sunlight AOD mode -->
+ <integer name="config_doze_aod_brightness_sunlight">28</integer>
+
<!-- Doze: whether the double tap sensor reports 2D touch coordinates -->
<bool name="doze_double_tap_reports_touch_coordinates">false</bool>
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 44cf003..fe8373f 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -98,7 +98,7 @@
*/
@Override
public GradientColors getColors(int which) {
- return getColors(which, TYPE_NORMAL);
+ return getColors(which, TYPE_DARK);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 28a45aa..ed4b131 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -39,6 +39,7 @@
private final int mHighBrightness;
private final int mLowBrightness;
+ private final int mSunlightBrightness;
public DozeScreenBrightness(Context context, DozeMachine.Service service,
SensorManager sensorManager, Sensor lightSensor, Handler handler) {
@@ -52,6 +53,8 @@
R.integer.config_doze_aod_brightness_low);
mHighBrightness = context.getResources().getInteger(
R.integer.config_doze_aod_brightness_high);
+ mSunlightBrightness = context.getResources().getInteger(
+ R.integer.config_doze_aod_brightness_sunlight);
}
@Override
@@ -83,9 +86,12 @@
}
private int computeBrightness(int sensorValue) {
- // The sensor reports 0 for off, 1 for low brightness and 2 for high brightness.
- // We currently use DozeScreenState for screen off, so we treat off as low brightness.
- if (sensorValue >= 2) {
+ // The sensor reports 0 for off, 1 for low brightness, 2 for high brightness, and 3 for
+ // sunlight. We currently use DozeScreenState for screen off, so we treat off as low
+ // brightness.
+ if (sensorValue >= 3) {
+ return mSunlightBrightness;
+ } else if (sensorValue == 2) {
return mHighBrightness;
} else {
return mLowBrightness;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 9b113d8..ad177a7 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -25,8 +25,10 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.HardwareUiLayout;
+import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.volume.VolumeDialogMotion.LogAccelerateInterpolator;
import com.android.systemui.volume.VolumeDialogMotion.LogDecelerateInterpolator;
@@ -65,6 +67,7 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import android.util.MathUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -112,6 +115,8 @@
private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
+ private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
+
private final Context mContext;
private final GlobalActionsManager mWindowManagerFuncs;
private final AudioManager mAudioManager;
@@ -1291,7 +1296,7 @@
.alpha(1)
.translationX(0)
.setDuration(300)
- .setInterpolator(new LogDecelerateInterpolator())
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setUpdateListener(animation -> {
int alpha = (int) ((Float) animation.getAnimatedValue()
* ScrimController.GRADIENT_SCRIM_ALPHA * 255);
@@ -1329,9 +1334,8 @@
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(animation -> {
float frac = animation.getAnimatedFraction();
- float alpha = frac *(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY
- - ScrimController.GRADIENT_SCRIM_ALPHA)
- + ScrimController.GRADIENT_SCRIM_ALPHA;
+ float alpha = NotificationUtils.interpolate(
+ ScrimController.GRADIENT_SCRIM_ALPHA, SHUTDOWN_SCRIM_ALPHA, frac);
mGradientDrawable.setAlpha((int) (alpha * 255));
})
.start();
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 68f8c1b..b516a91 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -268,3 +268,16 @@
# GestureLauncherService.java
# ---------------------------
40100 camera_gesture_triggered (gesture_on_time|2|3), (sensor1_on_time|2|3), (sensor2_on_time|2|3), (event_extra|1|1)
+
+# ---------------------------
+# timezone/RulesManagerService.java
+# ---------------------------
+51600 timezone_trigger_check (token|3)
+51610 timezone_request_install (token|3)
+51611 timezone_install_started (token|3)
+51612 timezone_install_complete (token|3), (result|1)
+51620 timezone_request_uninstall (token|3)
+51621 timezone_uninstall_started (token|3)
+51622 timezone_uninstall_complete (token|3), (result|1)
+51630 timezone_request_nothing (token|3)
+51631 timezone_nothing_complete (token|3)
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 38f1c07..f70486a 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -18,7 +18,6 @@
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
-import static android.Manifest.permission.MANAGE_FALLBACK_SUBSCRIPTION_PLANS;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.READ_PHONE_STATE;
@@ -28,7 +27,6 @@
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
@@ -76,9 +74,11 @@
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.readStringAttribute;
import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
+import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
@@ -157,14 +157,15 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.Formatter;
-import android.text.format.Time;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.Pair;
+import android.util.RecurrenceRule;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.TrustedTime;
@@ -180,6 +181,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
@@ -192,7 +194,6 @@
import com.google.android.collect.Lists;
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
@@ -205,6 +206,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
+import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
@@ -257,7 +259,8 @@
private static final int VERSION_SWITCH_APP_ID = 8;
private static final int VERSION_ADDED_NETWORK_ID = 9;
private static final int VERSION_SWITCH_UID = 10;
- private static final int VERSION_LATEST = VERSION_SWITCH_UID;
+ private static final int VERSION_ADDED_CYCLE = 11;
+ private static final int VERSION_LATEST = VERSION_ADDED_CYCLE;
/**
* Max items written to {@link #ProcStateSeqHistory}.
@@ -275,6 +278,7 @@
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
+ private static final String TAG_SUBSCRIPTION_PLAN = "subscription-plan";
private static final String TAG_UID_POLICY = "uid-policy";
private static final String TAG_APP_POLICY = "app-policy";
private static final String TAG_WHITELIST = "whitelist";
@@ -286,8 +290,11 @@
private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
private static final String ATTR_NETWORK_ID = "networkId";
- private static final String ATTR_CYCLE_DAY = "cycleDay";
- private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
+ @Deprecated private static final String ATTR_CYCLE_DAY = "cycleDay";
+ @Deprecated private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
+ private static final String ATTR_CYCLE_START = "cycleStart";
+ private static final String ATTR_CYCLE_END = "cycleEnd";
+ private static final String ATTR_CYCLE_PERIOD = "cyclePeriod";
private static final String ATTR_WARNING_BYTES = "warningBytes";
private static final String ATTR_LIMIT_BYTES = "limitBytes";
private static final String ATTR_LAST_SNOOZE = "lastSnooze";
@@ -298,6 +305,12 @@
private static final String ATTR_UID = "uid";
private static final String ATTR_APP_ID = "appId";
private static final String ATTR_POLICY = "policy";
+ private static final String ATTR_SUB_ID = "subId";
+ private static final String ATTR_TITLE = "title";
+ private static final String ATTR_SUMMARY = "summary";
+ private static final String ATTR_LIMIT_BEHAVIOR = "limitBehavior";
+ private static final String ATTR_USAGE_BYTES = "usageBytes";
+ private static final String ATTR_USAGE_TIME = "usageTime";
private static final String ACTION_ALLOW_BACKGROUND =
"com.android.server.net.action.ALLOW_BACKGROUND";
@@ -359,6 +372,9 @@
/** Currently active network rules for ifaces. */
final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
+ /** Defined subscription plans. */
+ final SparseArray<SubscriptionPlan[]> mSubscriptionPlans = new SparseArray<>();
+
/** Defined UID policies. */
@GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */
@@ -998,7 +1014,6 @@
// cycle boundary to recompute notifications.
// examine stats for each active policy
- final long currentTime = currentTimeMillis();
for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
// ignore policies that aren't relevant to user
@@ -1273,20 +1288,27 @@
continue;
}
- final int cycleDay = getCycleDayFromCarrierConfig(config, policy.cycleDay);
+ final int currentCycleDay;
+ if (policy.cycleRule.isMonthly()) {
+ currentCycleDay = policy.cycleRule.start.getDayOfMonth();
+ } else {
+ currentCycleDay = NetworkPolicy.CYCLE_NONE;
+ }
+
+ final int cycleDay = getCycleDayFromCarrierConfig(config, currentCycleDay);
final long warningBytes = getWarningBytesFromCarrierConfig(config,
policy.warningBytes);
final long limitBytes = getLimitBytesFromCarrierConfig(config,
policy.limitBytes);
- if (policy.cycleDay == cycleDay &&
+ if (currentCycleDay == cycleDay &&
policy.warningBytes == warningBytes &&
policy.limitBytes == limitBytes) {
continue;
}
policyUpdated = true;
- policy.cycleDay = cycleDay;
+ policy.cycleRule = NetworkPolicy.buildRule(cycleDay, ZoneId.systemDefault());
policy.warningBytes = warningBytes;
policy.limitBytes = limitBytes;
@@ -1456,7 +1478,6 @@
// TODO: reset any policy-disabled networks when any policy is removed
// completely, which is currently rare case.
- final long currentTime = currentTimeMillis();
for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
// shortcut when policy has no limit
@@ -1573,7 +1594,6 @@
// apply each policy that we found ifaces for; compute remaining data
// based on current cycle and historical stats, and push to kernel.
- final long currentTime = currentTimeMillis();
for (int i = mNetworkRules.size()-1; i >= 0; i--) {
final NetworkPolicy policy = mNetworkRules.keyAt(i);
final String[] ifaces = mNetworkRules.valueAt(i);
@@ -1721,20 +1741,16 @@
public NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
- // assume usage cycle starts today
- final Time time = new Time();
- time.setToNow();
-
- final String cycleTimezone = time.timezone;
-
- final int cycleDay = getCycleDayFromCarrierConfig(config, time.monthDay);
+ final int cycleDay = getCycleDayFromCarrierConfig(config,
+ ZonedDateTime.now().getDayOfMonth());
final long warningBytes = getWarningBytesFromCarrierConfig(config,
getPlatformDefaultWarningBytes());
final long limitBytes = getLimitBytesFromCarrierConfig(config,
getPlatformDefaultLimitBytes());
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
- final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
+ final RecurrenceRule cycleRule = NetworkPolicy.buildRule(cycleDay, ZoneId.systemDefault());
+ final NetworkPolicy policy = new NetworkPolicy(template, cycleRule,
warningBytes, limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
return policy;
}
@@ -1744,6 +1760,7 @@
// clear any existing policy and read from disk
mNetworkPolicy.clear();
+ mSubscriptionPlans.clear();
mUidPolicy.clear();
FileInputStream fis = null;
@@ -1787,12 +1804,24 @@
} else {
networkId = null;
}
- final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
- final String cycleTimezone;
- if (version >= VERSION_ADDED_TIMEZONE) {
- cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
+ final RecurrenceRule cycleRule;
+ if (version >= VERSION_ADDED_CYCLE) {
+ final String start = readStringAttribute(in, ATTR_CYCLE_START);
+ final String end = readStringAttribute(in, ATTR_CYCLE_END);
+ final String period = readStringAttribute(in, ATTR_CYCLE_PERIOD);
+ cycleRule = new RecurrenceRule(
+ RecurrenceRule.convertZonedDateTime(start),
+ RecurrenceRule.convertZonedDateTime(end),
+ RecurrenceRule.convertPeriod(period));
} else {
- cycleTimezone = Time.TIMEZONE_UTC;
+ final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
+ final String cycleTimezone;
+ if (version >= VERSION_ADDED_TIMEZONE) {
+ cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
+ } else {
+ cycleTimezone = "UTC";
+ }
+ cycleRule = NetworkPolicy.buildRule(cycleDay, ZoneId.of(cycleTimezone));
}
final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
@@ -1834,10 +1863,45 @@
final NetworkTemplate template = new NetworkTemplate(networkTemplate,
subscriberId, networkId);
if (template.isPersistable()) {
- mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
- cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
+ mNetworkPolicy.put(template, new NetworkPolicy(template, cycleRule,
+ warningBytes, limitBytes, lastWarningSnooze,
lastLimitSnooze, metered, inferred));
}
+
+ } else if (TAG_SUBSCRIPTION_PLAN.equals(tag)) {
+ final String start = readStringAttribute(in, ATTR_CYCLE_START);
+ final String end = readStringAttribute(in, ATTR_CYCLE_END);
+ final String period = readStringAttribute(in, ATTR_CYCLE_PERIOD);
+ final SubscriptionPlan.Builder builder = new SubscriptionPlan.Builder(
+ RecurrenceRule.convertZonedDateTime(start),
+ RecurrenceRule.convertZonedDateTime(end),
+ RecurrenceRule.convertPeriod(period));
+ builder.setTitle(readStringAttribute(in, ATTR_TITLE));
+ builder.setSummary(readStringAttribute(in, ATTR_SUMMARY));
+
+ final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES,
+ SubscriptionPlan.BYTES_UNKNOWN);
+ final int limitBehavior = readIntAttribute(in, ATTR_LIMIT_BEHAVIOR,
+ SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN);
+ if (limitBytes != SubscriptionPlan.BYTES_UNKNOWN
+ && limitBehavior != SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN) {
+ builder.setDataLimit(limitBytes, limitBehavior);
+ }
+
+ final long usageBytes = readLongAttribute(in, ATTR_USAGE_BYTES,
+ SubscriptionPlan.BYTES_UNKNOWN);
+ final long usageTime = readLongAttribute(in, ATTR_USAGE_TIME,
+ SubscriptionPlan.TIME_UNKNOWN);
+ if (usageBytes != SubscriptionPlan.BYTES_UNKNOWN
+ && usageTime != SubscriptionPlan.TIME_UNKNOWN) {
+ builder.setDataUsage(usageBytes, usageTime);
+ }
+
+ final int subId = readIntAttribute(in, ATTR_SUB_ID);
+ final SubscriptionPlan plan = builder.build();
+ mSubscriptionPlans.put(subId, ArrayUtils.appendElement(
+ SubscriptionPlan.class, mSubscriptionPlans.get(subId), plan));
+
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
final int policy = readIntAttribute(in, ATTR_POLICY);
@@ -1898,9 +1962,7 @@
} catch (FileNotFoundException e) {
// missing policy is okay, probably first boot
upgradeDefaultBackgroundDataUL();
- } catch (IOException e) {
- Log.wtf(TAG, "problem reading network policy", e);
- } catch (XmlPullParserException e) {
+ } catch (Exception e) {
Log.wtf(TAG, "problem reading network policy", e);
} finally {
IoUtils.closeQuietly(fis);
@@ -1994,8 +2056,12 @@
if (networkId != null) {
out.attribute(null, ATTR_NETWORK_ID, networkId);
}
- writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
- out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
+ writeStringAttribute(out, ATTR_CYCLE_START,
+ RecurrenceRule.convertZonedDateTime(policy.cycleRule.start));
+ writeStringAttribute(out, ATTR_CYCLE_END,
+ RecurrenceRule.convertZonedDateTime(policy.cycleRule.end));
+ writeStringAttribute(out, ATTR_CYCLE_PERIOD,
+ RecurrenceRule.convertPeriod(policy.cycleRule.period));
writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
@@ -2005,6 +2071,32 @@
out.endTag(null, TAG_NETWORK_POLICY);
}
+ // write all known subscription plans
+ for (int i = 0; i < mSubscriptionPlans.size(); i++) {
+ final int subId = mSubscriptionPlans.keyAt(i);
+ final SubscriptionPlan[] plans = mSubscriptionPlans.valueAt(i);
+ if (ArrayUtils.isEmpty(plans)) continue;
+
+ for (SubscriptionPlan plan : plans) {
+ out.startTag(null, TAG_SUBSCRIPTION_PLAN);
+ writeIntAttribute(out, ATTR_SUB_ID, subId);
+ final RecurrenceRule cycleRule = plan.getCycleRule();
+ writeStringAttribute(out, ATTR_CYCLE_START,
+ RecurrenceRule.convertZonedDateTime(cycleRule.start));
+ writeStringAttribute(out, ATTR_CYCLE_END,
+ RecurrenceRule.convertZonedDateTime(cycleRule.end));
+ writeStringAttribute(out, ATTR_CYCLE_PERIOD,
+ RecurrenceRule.convertPeriod(cycleRule.period));
+ writeStringAttribute(out, ATTR_TITLE, plan.getTitle());
+ writeStringAttribute(out, ATTR_SUMMARY, plan.getSummary());
+ writeLongAttribute(out, ATTR_LIMIT_BYTES, plan.getDataLimitBytes());
+ writeIntAttribute(out, ATTR_LIMIT_BEHAVIOR, plan.getDataLimitBehavior());
+ writeLongAttribute(out, ATTR_USAGE_BYTES, plan.getDataUsageBytes());
+ writeLongAttribute(out, ATTR_USAGE_TIME, plan.getDataUsageTime());
+ out.endTag(null, TAG_SUBSCRIPTION_PLAN);
+ }
+ }
+
// write all known uid policies
for (int i = 0; i < mUidPolicy.size(); i++) {
final int uid = mUidPolicy.keyAt(i);
@@ -2506,27 +2598,35 @@
}
final SubscriptionInfo si;
+ final PersistableBundle config;
final long token = Binder.clearCallingIdentity();
try {
si = mContext.getSystemService(SubscriptionManager.class)
.getActiveSubscriptionInfo(subId);
+ config = mCarrierConfigManager.getConfigForSubId(subId);
} finally {
Binder.restoreCallingIdentity(token);
}
- // First check: does caller have carrier access?
+ // First check: is caller the CarrierService?
if (si.isEmbedded() && si.canManageSubscription(mContext, callingPackage)) {
- Slog.v(TAG, "Granting access because " + callingPackage + " is carrier");
return;
}
- // Second check: was caller first to claim this HNI?
- // TODO: extend to support external data sources
+ // Second check: has the CarrierService delegated access?
+ if (config != null) {
+ final String overridePackage = config
+ .getString(CarrierConfigManager.KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING, null);
+ if (!TextUtils.isEmpty(overridePackage)
+ && Objects.equals(overridePackage, callingPackage)) {
+ return;
+ }
+ }
- // Final check: does caller have fallback permission?
- if (mContext.checkCallingOrSelfPermission(
- MANAGE_FALLBACK_SUBSCRIPTION_PLANS) == PERMISSION_GRANTED) {
- Slog.v(TAG, "Granting access because " + callingPackage + " is fallback");
+ // Third check: is caller the fallback/default CarrierService?
+ final String defaultPackage = mCarrierConfigManager.getDefaultCarrierServicePackageName();
+ if (!TextUtils.isEmpty(defaultPackage)
+ && Objects.equals(defaultPackage, callingPackage)) {
return;
}
@@ -2538,11 +2638,6 @@
public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
- // TODO: extend to support external data sources
- if (!"com.android.settings".equals(callingPackage)) {
- throw new UnsupportedOperationException();
- }
-
final String fake = SystemProperties.get("fw.fake_plan");
if (!TextUtils.isEmpty(fake)) {
final List<SubscriptionPlan> plans = new ArrayList<>();
@@ -2550,7 +2645,6 @@
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
.setTitle("G-Mobile")
- .setDataWarning(2 * TrafficStats.GB_IN_BYTES)
.setDataLimit(5 * TrafficStats.GB_IN_BYTES,
SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
.setDataUsage(1 * TrafficStats.GB_IN_BYTES,
@@ -2562,7 +2656,6 @@
.setTitle("G-Mobile is the carriers name who this plan belongs to")
.setSummary("Crazy unlimited bandwidth plan with incredibly long title "
+ "that should be cut off to prevent UI from looking terrible")
- .setDataWarning(2 * TrafficStats.GB_IN_BYTES)
.setDataLimit(5 * TrafficStats.GB_IN_BYTES,
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
.setDataUsage(1 * TrafficStats.GB_IN_BYTES,
@@ -2615,19 +2708,10 @@
return plans.toArray(new SubscriptionPlan[plans.size()]);
}
- final long token = Binder.clearCallingIdentity();
- try {
- final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- final NetworkTemplate template = NetworkTemplate
- .buildTemplateMobileAll(tm.getSubscriberId(subId));
- final NetworkPolicy policy = mNetworkPolicy.get(template);
- if (policy != null) {
- return new SubscriptionPlan[] { SubscriptionPlan.convert(policy) };
- } else {
- return new SubscriptionPlan[0];
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ return mSubscriptionPlans.get(subId);
}
- } finally {
- Binder.restoreCallingIdentity(token);
}
}
@@ -2635,22 +2719,19 @@
public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
- // TODO: extend to support external data sources
- if (!"com.android.settings".equals(callingPackage)) {
- throw new UnsupportedOperationException();
+ for (SubscriptionPlan plan : plans) {
+ Preconditions.checkNotNull(plan);
}
final long token = Binder.clearCallingIdentity();
try {
- final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- final NetworkTemplate template = NetworkTemplate
- .buildTemplateMobileAll(tm.getSubscriberId(subId));
- if (ArrayUtils.isEmpty(plans)) {
- mNetworkPolicy.remove(template);
- } else {
- final NetworkPolicy policy = SubscriptionPlan.convert(plans[0]);
- policy.template = template;
- mNetworkPolicy.put(template, policy);
+ maybeRefreshTrustedTime();
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ mSubscriptionPlans.put(subId, plans);
+ // TODO: update any implicit details from newly defined plans
+ handleNetworkPoliciesUpdateAL(false);
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2658,14 +2739,6 @@
}
@Override
- public String getSubscriptionPlanOwner(int subId) {
- mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-
- // TODO: extend to support external data sources
- return "com.android.settings";
- }
-
- @Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8e2097a..d36d2f1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5417,7 +5417,7 @@
// represent should be hidden or if we should hide the lockscreen. For attached app
// windows we defer the decision to the window it is attached to.
if (appWindow && attached == null) {
- if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
+ if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5456,7 +5456,7 @@
// separately, because both the "real fullscreen" opaque window and the one for the docked
// stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
- && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
+ && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
mTopDockedOpaqueWindowState = win;
if (mTopDockedOpaqueOrDimmingWindowState == null) {
mTopDockedOpaqueOrDimmingWindowState = win;
@@ -5481,12 +5481,6 @@
}
}
- private boolean isFullscreen(WindowManager.LayoutParams attrs) {
- return attrs.x == 0 && attrs.y == 0
- && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
- && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
- }
-
/** {@inheritDoc} */
@Override
public int finishPostLayoutPolicyLw() {
diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
index 3ffbb2d..11928b9 100644
--- a/services/core/java/com/android/server/timezone/IntentHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
@@ -16,6 +16,8 @@
package com.android.server.timezone;
+import com.android.server.EventLogTags;
+
import android.app.timezone.RulesUpdaterContract;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -24,8 +26,6 @@
import android.os.PatternMatcher;
import android.util.Slog;
-import java.util.regex.Pattern;
-
/**
* The bona fide implementation of {@link IntentHelper}.
*/
@@ -75,6 +75,7 @@
public void sendTriggerUpdateCheck(CheckToken checkToken) {
RulesUpdaterContract.sendBroadcast(
mContext, mUpdaterAppPackageName, checkToken.toByteArray());
+ EventLogTags.writeTimezoneTriggerCheck(checkToken.toString());
}
@Override
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index d97ba2d..1c5aa60 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.timezone;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.EventLogTags;
import com.android.server.SystemService;
import com.android.timezone.distro.DistroException;
import com.android.timezone.distro.DistroVersion;
@@ -56,8 +57,6 @@
import static android.app.timezone.RulesState.STAGED_OPERATION_UNINSTALL;
import static android.app.timezone.RulesState.STAGED_OPERATION_UNKNOWN;
-// TODO(nfuller) Add EventLog calls where useful in the system server.
-// TODO(nfuller) Check logging best practices in the system server.
// TODO(nfuller) Check error handling best practices in the system server.
public final class RulesManagerService extends IRulesManager.Stub {
@@ -203,6 +202,7 @@
if (checkTokenBytes != null) {
checkToken = createCheckTokenOrThrow(checkTokenBytes);
}
+ EventLogTags.writeTimezoneRequestInstall(toStringOrNull(checkToken));
synchronized (this) {
if (distroParcelFileDescriptor == null) {
@@ -254,6 +254,8 @@
@Override
public void run() {
+ EventLogTags.writeTimezoneInstallStarted(toStringOrNull(mCheckToken));
+
boolean success = false;
// Adopt the ParcelFileDescriptor into this try-with-resources so it is closed
// when we are done.
@@ -266,6 +268,7 @@
TimeZoneDistro distro = new TimeZoneDistro(is);
int installerResult = mInstaller.stageInstallWithErrorCode(distro);
int resultCode = mapInstallerResultToApiCode(installerResult);
+ EventLogTags.writeTimezoneInstallComplete(toStringOrNull(mCheckToken), resultCode);
sendFinishedStatus(mCallback, resultCode);
// All the installer failure modes are currently non-recoverable and won't be
@@ -273,6 +276,8 @@
success = true;
} catch (Exception e) {
Slog.w(TAG, "Failed to install distro.", e);
+ EventLogTags.writeTimezoneInstallComplete(
+ toStringOrNull(mCheckToken), Callback.ERROR_UNKNOWN_FAILURE);
sendFinishedStatus(mCallback, Callback.ERROR_UNKNOWN_FAILURE);
} finally {
// Notify the package tracker that the operation is now complete.
@@ -308,6 +313,7 @@
if (checkTokenBytes != null) {
checkToken = createCheckTokenOrThrow(checkTokenBytes);
}
+ EventLogTags.writeTimezoneRequestUninstall(toStringOrNull(checkToken));
synchronized(this) {
if (callback == null) {
throw new NullPointerException("callback == null");
@@ -337,6 +343,7 @@
@Override
public void run() {
+ EventLogTags.writeTimezoneUninstallStarted(toStringOrNull(mCheckToken));
boolean success = false;
try {
success = mInstaller.stageUninstall();
@@ -344,8 +351,12 @@
// against SUCCESS. More granular failures may be added in future.
int resultCode = success ? Callback.SUCCESS
: Callback.ERROR_UNKNOWN_FAILURE;
+ EventLogTags.writeTimezoneUninstallComplete(
+ toStringOrNull(mCheckToken), resultCode);
sendFinishedStatus(mCallback, resultCode);
} catch (Exception e) {
+ EventLogTags.writeTimezoneUninstallComplete(
+ toStringOrNull(mCheckToken), Callback.ERROR_UNKNOWN_FAILURE);
Slog.w(TAG, "Failed to uninstall distro.", e);
sendFinishedStatus(mCallback, Callback.ERROR_UNKNOWN_FAILURE);
} finally {
@@ -372,7 +383,9 @@
if (checkTokenBytes != null) {
checkToken = createCheckTokenOrThrow(checkTokenBytes);
}
+ EventLogTags.writeTimezoneRequestNothing(toStringOrNull(checkToken));
mPackageTracker.recordCheckResult(checkToken, success);
+ EventLogTags.writeTimezoneNothingComplete(toStringOrNull(checkToken));
}
@Override
@@ -445,6 +458,7 @@
pw.println("RulesManagerService state: " + toString());
pw.println("Active rules version (ICU, libcore): " + ICU.getTZDataVersion() + ","
+ ZoneInfoDB.getInstance().getVersion());
+ pw.println("Distro state: " + rulesState.toString());
mPackageTracker.dump(pw);
}
@@ -491,4 +505,8 @@
return "Unknown";
}
}
+
+ private static String toStringOrNull(Object obj) {
+ return obj == null ? null : obj.toString();
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05f4626..a37b2e5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2992,14 +2992,14 @@
// Don't include wallpaper in bounds calculation
if (!w.mIsWallpaper && !mutableIncludeFullDisplay.value) {
if (includeDecor) {
- final TaskStack stack = w.getStack();
- if (stack != null) {
- stack.getBounds(frame);
- }
+ final Task task = w.getTask();
+ if (task != null) {
+ task.getBounds(frame);
+ } else {
- // We want to screenshot with the exact bounds of the surface of the app. Thus,
- // intersect it with the frame.
- frame.intersect(w.mFrame);
+ // No task bounds? Too bad! Ain't no screenshot then.
+ return true;
+ }
} else {
final Rect wf = w.mFrame;
final Rect cr = w.mContentInsets;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc3b146..e5055e9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -624,6 +624,17 @@
return token != null ? token.findMainWindow() : null;
}
+ AppWindowToken getTopFullscreenAppToken() {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final AppWindowToken token = mChildren.get(i);
+ final WindowState win = token.findMainWindow();
+ if (win != null && win.mAttrs.isFullscreen()) {
+ return token;
+ }
+ }
+ return null;
+ }
+
AppWindowToken getTopVisibleAppToken() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final AppWindowToken token = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 802f9ed..1bece69 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -150,14 +150,27 @@
final int currentOrientation;
synchronized (service.mWindowMap) {
final WindowState mainWindow = token.findMainWindow();
- if (mainWindow == null) {
+ final Task task = token.getTask();
+ if (task == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token="
+ + token);
+ return null;
+ }
+ final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken();
+ if (topFullscreenToken == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
+ + task);
+ return null;
+ }
+ final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow();
+ if (mainWindow == null || topFullscreenWindow == null) {
Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+ token);
return null;
}
- sysUiVis = mainWindow.getSystemUiVisibility();
- windowFlags = mainWindow.getAttrs().flags;
- windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+ sysUiVis = topFullscreenWindow.getSystemUiVisibility();
+ windowFlags = topFullscreenWindow.getAttrs().flags;
+ windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags;
layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
layoutParams.type = TYPE_APPLICATION_STARTING;
@@ -170,22 +183,17 @@
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
layoutParams.systemUiVisibility = sysUiVis;
- final Task task = token.getTask();
- if (task != null) {
- layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
+ layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
- final TaskDescription taskDescription = task.getTaskDescription();
- if (taskDescription != null) {
- backgroundColor = taskDescription.getBackgroundColor();
- statusBarColor = taskDescription.getStatusBarColor();
- navigationBarColor = taskDescription.getNavigationBarColor();
- }
- taskBounds = new Rect();
- task.getBounds(taskBounds);
- } else {
- taskBounds = null;
+ final TaskDescription taskDescription = task.getTaskDescription();
+ if (taskDescription != null) {
+ backgroundColor = taskDescription.getBackgroundColor();
+ statusBarColor = taskDescription.getStatusBarColor();
+ navigationBarColor = taskDescription.getNavigationBarColor();
}
- currentOrientation = mainWindow.getConfiguration().orientation;
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ currentOrientation = topFullscreenWindow.getConfiguration().orientation;
}
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 11e383c..8decb96 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -34,7 +34,6 @@
import static android.telephony.CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG;
import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_THRESHOLD_BYTES_LONG;
import static android.telephony.CarrierConfigManager.KEY_MONTHLY_DATA_CYCLE_DAY_INT;
-import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.Time.TIMEZONE_UTC;
@@ -92,7 +91,6 @@
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkTemplate;
@@ -108,12 +106,12 @@
import android.support.test.runner.AndroidJUnit4;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
import android.util.Pair;
+import android.util.RecurrenceRule;
import android.util.TrustedTime;
import com.android.internal.telephony.PhoneConstants;
@@ -154,7 +152,10 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.time.Clock;
import java.time.Instant;
+import java.time.Period;
+import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Calendar;
@@ -396,7 +397,7 @@
@After
public void resetClock() throws Exception {
- SubscriptionPlan.sNowOverride = -1;
+ RecurrenceRule.sClock = Clock.systemDefaultZone();
}
@Test
@@ -785,9 +786,9 @@
}
private static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
- SubscriptionPlan.sNowOverride = currentTime;
- final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = NetworkPolicyManager
- .cycleIterator(policy);
+ RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime),
+ ZoneId.systemDefault());
+ final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = policy.cycleIterator();
while (it.hasNext()) {
final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next();
if (cycle.first.toInstant().toEpochMilli() < currentTime) {
@@ -799,8 +800,9 @@
}
private static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
- SubscriptionPlan.sNowOverride = currentTime;
- return NetworkPolicyManager.cycleIterator(policy).next().second.toInstant().toEpochMilli();
+ RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime),
+ ZoneId.systemDefault());
+ return policy.cycleIterator().next().second.toInstant().toEpochMilli();
}
@Test
@@ -894,38 +896,6 @@
}
@Test
- public void testNextCycleSane() throws Exception {
- final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
- final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
-
- // walk forwards, ensuring that cycle boundaries don't get stuck
- long currentCycle = computeNextCycleBoundary(parseTime("2011-08-01T00:00:00.000Z"), policy);
- for (int i = 0; i < 128; i++) {
- long nextCycle = computeNextCycleBoundary(currentCycle, policy);
- assertEqualsFuzzy(DAY_IN_MILLIS * 30, nextCycle - currentCycle, DAY_IN_MILLIS * 3);
- assertUnique(seen, nextCycle);
- currentCycle = nextCycle;
- }
- }
-
- @Test
- public void testLastCycleSane() throws Exception {
- final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
- final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
-
- // walk backwards, ensuring that cycle boundaries look sane
- long currentCycle = computeLastCycleBoundary(parseTime("2011-08-04T00:00:00.000Z"), policy);
- for (int i = 0; i < 128; i++) {
- long lastCycle = computeLastCycleBoundary(currentCycle, policy);
- assertEqualsFuzzy(DAY_IN_MILLIS * 30, currentCycle - lastCycle, DAY_IN_MILLIS * 3);
- assertUnique(seen, lastCycle);
- currentCycle = lastCycle;
- }
- }
-
- @Test
public void testCycleTodayJanuary() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
@@ -946,17 +916,6 @@
}
@Test
- public void testLastCycleBoundaryDST() throws Exception {
- final long currentTime = parseTime("1989-01-02T07:30:00.000Z");
- final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");
-
- final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 3, "America/Argentina/Buenos_Aires", 1024L, 1024L, false);
- final long actualCycle = computeLastCycleBoundary(currentTime, policy);
- assertTimeEquals(expectedCycle, actualCycle);
- }
-
- @Test
public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
@@ -1145,15 +1104,6 @@
}
@Test
- public void testConversion() throws Exception {
- NetworkTemplate template = NetworkTemplate.buildTemplateMobileWildcard();
- NetworkPolicy before = new NetworkPolicy(template, 12, "Israel", 123, 456, true);
- NetworkPolicy after = SubscriptionPlan.convert(SubscriptionPlan.convert(before));
- after.template = before.template;
- assertEquals(before, after);
- }
-
- @Test
public void testOnUidStateChanged_notifyAMS() throws Exception {
final long procStateSeq = 222;
callOnUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE, procStateSeq);
@@ -1472,7 +1422,9 @@
private NetworkPolicy buildDefaultFakeMobilePolicy() {
NetworkPolicy p = mService.buildDefaultMobilePolicy(FAKE_SUB_ID, FAKE_SUBSCRIBER_ID);
// set a deterministic cycle date
- p.cycleDay = DEFAULT_CYCLE_DAY;
+ p.cycleRule = new RecurrenceRule(
+ p.cycleRule.start.withDayOfMonth(DEFAULT_CYCLE_DAY),
+ p.cycleRule.end, Period.ofMonths(1));
return p;
}
@@ -1665,7 +1617,8 @@
}
private void setCurrentTimeMillis(long currentTimeMillis) {
- SubscriptionPlan.sNowOverride = currentTimeMillis;
+ RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTimeMillis),
+ ZoneId.systemDefault());
mStartTime = currentTimeMillis;
mElapsedRealtime = 0L;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8b3a804..0001d42 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -26,6 +26,7 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.service.carrier.CarrierService;
import com.android.ims.ImsReasonInfo;
import com.android.internal.telephony.ICarrierConfigLoader;
@@ -262,6 +263,17 @@
"config_ims_package_override_string";
/**
+ * Override the package that will manage {@link SubscriptionPlan}
+ * information instead of the {@link CarrierService} that defines this
+ * value.
+ *
+ * @see SubscriptionManager#getSubscriptionPlans(int)
+ * @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
+ */
+ public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING =
+ "config_plans_package_override_string";
+
+ /**
* Override the platform's notion of a network operator being considered roaming.
* Value is string array of SIDs to be considered roaming for 3GPP2 RATs.
*/
@@ -1379,12 +1391,16 @@
/**
* The day of the month (1-31) on which the data cycle rolls over.
* <p>
- * If the current month does not have this day, the cycle will roll over at the start of the
- * next month.
+ * If the current month does not have this day, the cycle will roll over at
+ * the start of the next month.
* <p>
- * This setting may be still overridden by explicit user choice. By default, the platform value
- * will be used.
+ * This setting may be still overridden by explicit user choice. By default,
+ * the platform value will be used.
+ *
+ * @deprecated replaced by
+ * {@link SubscriptionManager#setSubscriptionPlans(int, java.util.List)}
*/
+ @Deprecated
public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT =
"monthly_data_cycle_day_int";
@@ -1395,6 +1411,7 @@
*
* @hide
*/
+ @Deprecated
public static final int DATA_CYCLE_USE_PLATFORM_DEFAULT = -1;
/**
@@ -1408,6 +1425,7 @@
* default data limit, if one exists, will be disabled. A user selected data limit will not be
* overridden.
*/
+ @Deprecated
public static final int DATA_CYCLE_THRESHOLD_DISABLED = -2;
/**
@@ -1420,7 +1438,11 @@
* <p>
* This setting may be overridden by explicit user choice. By default, the platform value
* will be used.
+ *
+ * @deprecated replaced by
+ * {@link SubscriptionManager#setSubscriptionPlans(int, java.util.List)}
*/
+ @Deprecated
public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG =
"data_warning_threshold_bytes_long";
@@ -1434,7 +1456,11 @@
* <p>
* This setting may be overridden by explicit user choice. By default, the platform value
* will be used.
+ *
+ * @deprecated replaced by
+ * {@link SubscriptionManager#setSubscriptionPlans(int, java.util.List)}
*/
+ @Deprecated
public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG =
"data_limit_threshold_bytes_long";
@@ -1866,6 +1892,15 @@
}
}
+ /** {@hide} */
+ public String getDefaultCarrierServicePackageName() {
+ try {
+ return getICarrierConfigLoader().getDefaultCarrierServicePackageName();
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
/**
* Returns a new bundle with the default value for every supported configuration variable.
*
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 89c9134..503bf82 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.SdkConstant;
-import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemService;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -1542,7 +1542,20 @@
return false;
}
- /** {@pending} */
+ /**
+ * Get the description of the billing relationship plan between a carrier
+ * and a specific subscriber.
+ * <p>
+ * This method is only accessible to the following narrow set of apps:
+ * <ul>
+ * <li>The carrier app for this subscriberId, as determined by
+ * {@link TelephonyManager#hasCarrierPrivileges(int)}.
+ * <li>The carrier app explicitly delegated access through
+ * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+ * </ul>
+ *
+ * @param subId the subscriber this relationship applies to
+ */
public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
final INetworkPolicyManager npm = INetworkPolicyManager.Stub
.asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
@@ -1554,7 +1567,23 @@
}
}
- /** {@pending} */
+ /**
+ * Set the description of the billing relationship plan between a carrier
+ * and a specific subscriber.
+ * <p>
+ * This method is only accessible to the following narrow set of apps:
+ * <ul>
+ * <li>The carrier app for this subscriberId, as determined by
+ * {@link TelephonyManager#hasCarrierPrivileges(int)}.
+ * <li>The carrier app explicitly delegated access through
+ * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+ * </ul>
+ *
+ * @param subId the subscriber this relationship applies to
+ * @param plans the list of plans. The first plan is always the primary and
+ * most important plan. Any additional plans are secondary and
+ * may not be displayed or used by decision making logic.
+ */
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
final INetworkPolicyManager npm = INetworkPolicyManager.Stub
.asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
@@ -1565,15 +1594,4 @@
throw e.rethrowFromSystemServer();
}
}
-
- /** {@hide} */
- public String getSubscriptionPlanOwner(int subId) {
- final INetworkPolicyManager npm = INetworkPolicyManager.Stub
- .asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
- try {
- return npm.getSubscriptionPlanOwner(subId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
}
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index da7661ae..c9419c5 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -19,45 +19,31 @@
import android.annotation.BytesLong;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.NetworkPolicy;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
import android.util.Pair;
+import android.util.RecurrenceRule;
-import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.time.Instant;
-import java.time.LocalTime;
-import java.time.ZoneId;
+import java.time.Period;
import java.time.ZonedDateTime;
-import java.time.temporal.ChronoUnit;
-import java.time.temporal.TemporalUnit;
import java.util.Iterator;
-/** {@pending} */
+/**
+ * Description of a billing relationship plan between a carrier and a specific
+ * subscriber. This information is used to present more useful UI to users, such
+ * as explaining how much mobile data they have remaining, and what will happen
+ * when they run out.
+ *
+ * @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
+ * @see SubscriptionManager#getSubscriptionPlans(int)
+ */
public final class SubscriptionPlan implements Parcelable {
- private static final String TAG = "SubscriptionPlan";
- private static final boolean DEBUG = false;
-
- /** {@hide} */
- @IntDef(prefix = "TYPE_", value = {
- TYPE_NONRECURRING,
- TYPE_RECURRING_WEEKLY,
- TYPE_RECURRING_MONTHLY,
- TYPE_RECURRING_DAILY,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- public static final int TYPE_NONRECURRING = 0;
- public static final int TYPE_RECURRING_MONTHLY = 1;
- public static final int TYPE_RECURRING_WEEKLY = 2;
- public static final int TYPE_RECURRING_DAILY = 3;
-
/** {@hide} */
@IntDef(prefix = "LIMIT_BEHAVIOR_", value = {
LIMIT_BEHAVIOR_UNKNOWN,
@@ -68,51 +54,40 @@
@Retention(RetentionPolicy.SOURCE)
public @interface LimitBehavior {}
+ /** When a resource limit is hit, the behavior is unknown. */
public static final int LIMIT_BEHAVIOR_UNKNOWN = -1;
+ /** When a resource limit is hit, access is disabled. */
public static final int LIMIT_BEHAVIOR_DISABLED = 0;
+ /** When a resource limit is hit, the user is billed automatically. */
public static final int LIMIT_BEHAVIOR_BILLED = 1;
+ /** When a resource limit is hit, access is throttled to a slower rate. */
public static final int LIMIT_BEHAVIOR_THROTTLED = 2;
+ /** Value indicating a number of bytes is unknown. */
public static final long BYTES_UNKNOWN = -1;
+ /** Value indicating a number of bytes is unlimited. */
+ public static final long BYTES_UNLIMITED = Long.MAX_VALUE;
+
+ /** Value indicating a timestamp is unknown. */
public static final long TIME_UNKNOWN = -1;
- private final int type;
- private final ZonedDateTime start;
- private final ZonedDateTime end;
+ private final RecurrenceRule cycleRule;
private CharSequence title;
private CharSequence summary;
- private long dataWarningBytes = BYTES_UNKNOWN;
- private long dataWarningSnoozeTime = TIME_UNKNOWN;
private long dataLimitBytes = BYTES_UNKNOWN;
- private long dataLimitSnoozeTime = TIME_UNKNOWN;
private int dataLimitBehavior = LIMIT_BEHAVIOR_UNKNOWN;
private long dataUsageBytes = BYTES_UNKNOWN;
private long dataUsageTime = TIME_UNKNOWN;
- private SubscriptionPlan(@Type int type, ZonedDateTime start, ZonedDateTime end) {
- this.type = type;
- this.start = start;
- this.end = end;
+ private SubscriptionPlan(RecurrenceRule cycleRule) {
+ this.cycleRule = Preconditions.checkNotNull(cycleRule);
}
private SubscriptionPlan(Parcel source) {
- type = source.readInt();
- if (source.readInt() != 0) {
- start = ZonedDateTime.parse(source.readString());
- } else {
- start = null;
- }
- if (source.readInt() != 0) {
- end = ZonedDateTime.parse(source.readString());
- } else {
- end = null;
- }
+ cycleRule = source.readParcelable(null);
title = source.readCharSequence();
summary = source.readCharSequence();
- dataWarningBytes = source.readLong();
- dataWarningSnoozeTime = source.readLong();
dataLimitBytes = source.readLong();
- dataLimitSnoozeTime = source.readLong();
dataLimitBehavior = source.readInt();
dataUsageBytes = source.readLong();
dataUsageTime = source.readLong();
@@ -125,25 +100,10 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(type);
- if (start != null) {
- dest.writeInt(1);
- dest.writeString(start.toString());
- } else {
- dest.writeInt(0);
- }
- if (end != null) {
- dest.writeInt(1);
- dest.writeString(end.toString());
- } else {
- dest.writeInt(0);
- }
+ dest.writeParcelable(cycleRule, flags);
dest.writeCharSequence(title);
dest.writeCharSequence(summary);
- dest.writeLong(dataWarningBytes);
- dest.writeLong(dataWarningSnoozeTime);
dest.writeLong(dataLimitBytes);
- dest.writeLong(dataLimitSnoozeTime);
dest.writeInt(dataLimitBehavior);
dest.writeLong(dataUsageBytes);
dest.writeLong(dataUsageTime);
@@ -151,20 +111,15 @@
@Override
public String toString() {
- return new StringBuilder("SubscriptionPlan:")
- .append(" type=").append(type)
- .append(" start=").append(start)
- .append(" end=").append(end)
+ return new StringBuilder("SubscriptionPlan{")
+ .append("cycleRule=").append(cycleRule)
.append(" title=").append(title)
.append(" summary=").append(summary)
- .append(" dataWarningBytes=").append(dataWarningBytes)
- .append(" dataWarningSnoozeTime=").append(dataWarningSnoozeTime)
.append(" dataLimitBytes=").append(dataLimitBytes)
- .append(" dataLimitSnoozeTime=").append(dataLimitSnoozeTime)
.append(" dataLimitBehavior=").append(dataLimitBehavior)
.append(" dataUsageBytes=").append(dataUsageBytes)
.append(" dataUsageTime=").append(dataUsageTime)
- .toString();
+ .append("}").toString();
}
public static final Parcelable.Creator<SubscriptionPlan> CREATOR = new Parcelable.Creator<SubscriptionPlan>() {
@@ -179,296 +134,161 @@
}
};
- public @Type int getType() {
- return type;
+ /** {@hide} */
+ public @NonNull RecurrenceRule getCycleRule() {
+ return cycleRule;
}
- public ZonedDateTime getStart() {
- return start;
- }
-
- public ZonedDateTime getEnd() {
- return end;
- }
-
+ /** Return the short title of this plan. */
public @Nullable CharSequence getTitle() {
return title;
}
+ /** Return the short summary of this plan. */
public @Nullable CharSequence getSummary() {
return summary;
}
- public @BytesLong long getDataWarningBytes() {
- return dataWarningBytes;
- }
-
+ /**
+ * Return the usage threshold at which data access changes according to
+ * {@link #getDataLimitBehavior()}.
+ */
public @BytesLong long getDataLimitBytes() {
return dataLimitBytes;
}
+ /**
+ * Return the behavior of data access when usage reaches
+ * {@link #getDataLimitBytes()}.
+ */
public @LimitBehavior int getDataLimitBehavior() {
return dataLimitBehavior;
}
+ /**
+ * Return a snapshot of currently known mobile data usage at
+ * {@link #getDataUsageTime()}.
+ */
public @BytesLong long getDataUsageBytes() {
return dataUsageBytes;
}
+ /**
+ * Return the time at which {@link #getDataUsageBytes()} was valid.
+ */
public @CurrentTimeMillisLong long getDataUsageTime() {
return dataUsageTime;
}
- /** {@hide} */
- @VisibleForTesting
- public static long sNowOverride = -1;
-
- private static ZonedDateTime now(ZoneId zone) {
- return (sNowOverride != -1)
- ? ZonedDateTime.ofInstant(Instant.ofEpochMilli(sNowOverride), zone)
- : ZonedDateTime.now(zone);
- }
-
- /** {@hide} */
- public static SubscriptionPlan convert(NetworkPolicy policy) {
- final ZoneId zone = ZoneId.of(policy.cycleTimezone);
- final ZonedDateTime now = now(zone);
- final Builder builder;
- if (policy.cycleDay != NetworkPolicy.CYCLE_NONE) {
- // Assume we started last January, since it has all possible days
- ZonedDateTime start = ZonedDateTime.of(
- now.toLocalDate().minusYears(1).withMonth(1).withDayOfMonth(policy.cycleDay),
- LocalTime.MIDNIGHT, zone);
- builder = Builder.createRecurringMonthly(start);
- } else {
- Log.w(TAG, "Cycle not defined; assuming last 4 weeks non-recurring");
- ZonedDateTime end = now;
- ZonedDateTime start = end.minusWeeks(4);
- builder = Builder.createNonrecurring(start, end);
- }
- if (policy.warningBytes != NetworkPolicy.WARNING_DISABLED) {
- builder.setDataWarning(policy.warningBytes);
- }
- if (policy.lastWarningSnooze != NetworkPolicy.SNOOZE_NEVER) {
- builder.setDataWarningSnooze(policy.lastWarningSnooze);
- }
- if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
- builder.setDataLimit(policy.limitBytes, LIMIT_BEHAVIOR_DISABLED);
- }
- if (policy.lastLimitSnooze != NetworkPolicy.SNOOZE_NEVER) {
- builder.setDataLimitSnooze(policy.lastLimitSnooze);
- }
- return builder.build();
- }
-
- /** {@hide} */
- public static NetworkPolicy convert(SubscriptionPlan plan) {
- final NetworkPolicy policy = new NetworkPolicy();
- switch (plan.type) {
- case TYPE_RECURRING_MONTHLY:
- policy.cycleDay = plan.start.getDayOfMonth();
- policy.cycleTimezone = plan.start.getZone().getId();
- break;
- default:
- policy.cycleDay = NetworkPolicy.CYCLE_NONE;
- policy.cycleTimezone = "UTC";
- break;
- }
- policy.warningBytes = plan.dataWarningBytes;
- policy.limitBytes = plan.dataLimitBytes;
- policy.lastWarningSnooze = plan.dataWarningSnoozeTime;
- policy.lastLimitSnooze = plan.dataLimitSnoozeTime;
- policy.metered = true;
- policy.inferred = false;
- return policy;
- }
-
- /** {@hide} */
- public TemporalUnit getTemporalUnit() {
- switch (type) {
- case TYPE_RECURRING_DAILY: return ChronoUnit.DAYS;
- case TYPE_RECURRING_WEEKLY: return ChronoUnit.WEEKS;
- case TYPE_RECURRING_MONTHLY: return ChronoUnit.MONTHS;
- default: throw new IllegalArgumentException();
- }
+ /**
+ * Return an iterator that will return all valid data usage cycles based on
+ * any recurrence rules. The iterator starts from the currently active cycle
+ * and walks backwards through time.
+ */
+ public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ return cycleRule.cycleIterator();
}
/**
- * Return an iterator that returns data usage cycles.
- * <p>
- * For recurring plans, it starts at the currently active cycle, and then
- * walks backwards in time through each previous cycle, back to the defined
- * starting point and no further.
- * <p>
- * For non-recurring plans, it returns one single cycle.
+ * Builder for a {@link SubscriptionPlan}.
*/
- public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
- switch (type) {
- case TYPE_NONRECURRING:
- return new NonrecurringIterator();
- case TYPE_RECURRING_WEEKLY:
- case TYPE_RECURRING_MONTHLY:
- case TYPE_RECURRING_DAILY:
- return new RecurringIterator();
- default:
- throw new IllegalStateException("Unknown type: " + type);
- }
- }
-
- private class NonrecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> {
- boolean hasNext = true;
-
- @Override
- public boolean hasNext() {
- return hasNext;
- }
-
- @Override
- public Pair<ZonedDateTime, ZonedDateTime> next() {
- hasNext = false;
- return new Pair<>(start, end);
- }
- }
-
- private class RecurringIterator implements Iterator<Pair<ZonedDateTime, ZonedDateTime>> {
- TemporalUnit unit;
- long i;
- ZonedDateTime cycleStart;
- ZonedDateTime cycleEnd;
-
- public RecurringIterator() {
- final ZonedDateTime now = now(start.getZone());
- if (DEBUG) Log.d(TAG, "Resolving using now " + now);
-
- unit = getTemporalUnit();
- i = unit.between(start, now);
- updateCycle();
-
- // Walk forwards until we find first cycle after now
- while (cycleEnd.toEpochSecond() <= now.toEpochSecond()) {
- i++;
- updateCycle();
- }
-
- // Walk backwards until we find first cycle before now
- while (cycleStart.toEpochSecond() > now.toEpochSecond()) {
- i--;
- updateCycle();
- }
- }
-
- private void updateCycle() {
- cycleStart = roundBoundaryTime(start.plus(i, unit));
- cycleEnd = roundBoundaryTime(start.plus(i + 1, unit));
- }
-
- private ZonedDateTime roundBoundaryTime(ZonedDateTime boundary) {
- if ((type == TYPE_RECURRING_MONTHLY)
- && (boundary.getDayOfMonth() < start.getDayOfMonth())) {
- // When forced to end a monthly cycle early, we want to count
- // that entire day against the boundary.
- return ZonedDateTime.of(boundary.toLocalDate(), LocalTime.MAX, start.getZone());
- } else {
- return boundary;
- }
- }
-
- @Override
- public boolean hasNext() {
- return cycleStart.toEpochSecond() >= start.toEpochSecond();
- }
-
- @Override
- public Pair<ZonedDateTime, ZonedDateTime> next() {
- if (DEBUG) Log.d(TAG, "Cycle " + i + " from " + cycleStart + " to " + cycleEnd);
- Pair<ZonedDateTime, ZonedDateTime> p = new Pair<>(cycleStart, cycleEnd);
- i--;
- updateCycle();
- return p;
- }
- }
-
public static class Builder {
private final SubscriptionPlan plan;
- private Builder(@Type int type, ZonedDateTime start, ZonedDateTime end) {
- plan = new SubscriptionPlan(type, start, end);
+ /** {@hide} */
+ public Builder(ZonedDateTime start, ZonedDateTime end, Period period) {
+ plan = new SubscriptionPlan(new RecurrenceRule(start, end, period));
}
+ /**
+ * Start defining a {@link SubscriptionPlan} that covers a very specific
+ * window of time, and never automatically recurs.
+ */
public static Builder createNonrecurring(ZonedDateTime start, ZonedDateTime end) {
if (!end.isAfter(start)) {
throw new IllegalArgumentException(
"End " + end + " isn't after start " + start);
}
- return new Builder(TYPE_NONRECURRING, start, end);
+ return new Builder(start, end, null);
}
+ /**
+ * Start defining a {@link SubscriptionPlan} that will recur
+ * automatically every month. It will always recur on the same day of a
+ * particular month. When a particular month ends before the defined
+ * recurrence day, the plan will recur on the last instant of that
+ * month.
+ */
public static Builder createRecurringMonthly(ZonedDateTime start) {
- return new Builder(TYPE_RECURRING_MONTHLY, start, null);
+ return new Builder(start, null, Period.ofMonths(1));
}
+ /**
+ * Start defining a {@link SubscriptionPlan} that will recur
+ * automatically every week.
+ */
public static Builder createRecurringWeekly(ZonedDateTime start) {
- return new Builder(TYPE_RECURRING_WEEKLY, start, null);
+ return new Builder(start, null, Period.ofDays(7));
}
+ /**
+ * Start defining a {@link SubscriptionPlan} that will recur
+ * automatically every day.
+ */
public static Builder createRecurringDaily(ZonedDateTime start) {
- return new Builder(TYPE_RECURRING_DAILY, start, null);
+ return new Builder(start, null, Period.ofDays(1));
}
public SubscriptionPlan build() {
return plan;
}
+ /** Set the short title of this plan. */
public Builder setTitle(@Nullable CharSequence title) {
plan.title = title;
return this;
}
+ /** Set the short summary of this plan. */
public Builder setSummary(@Nullable CharSequence summary) {
plan.summary = summary;
return this;
}
- public Builder setDataWarning(@BytesLong long dataWarningBytes) {
- if (dataWarningBytes < BYTES_UNKNOWN) {
- throw new IllegalArgumentException("Warning must be positive or BYTES_UNKNOWN");
- }
- plan.dataWarningBytes = dataWarningBytes;
- return this;
- }
-
- /** {@hide} */
- public Builder setDataWarningSnooze(@CurrentTimeMillisLong long dataWarningSnoozeTime) {
- plan.dataWarningSnoozeTime = dataWarningSnoozeTime;
- return this;
- }
-
+ /**
+ * Set the usage threshold at which data access changes.
+ *
+ * @param dataLimitBytes the usage threshold at which data access
+ * changes
+ * @param dataLimitBehavior the behavior of data access when usage
+ * reaches the threshold
+ */
public Builder setDataLimit(@BytesLong long dataLimitBytes,
@LimitBehavior int dataLimitBehavior) {
- if (dataLimitBytes < BYTES_UNKNOWN) {
- throw new IllegalArgumentException("Limit must be positive or BYTES_UNKNOWN");
+ if (dataLimitBytes < 0) {
+ throw new IllegalArgumentException("Limit bytes must be positive");
+ }
+ if (dataLimitBehavior < 0) {
+ throw new IllegalArgumentException("Limit behavior must be defined");
}
plan.dataLimitBytes = dataLimitBytes;
plan.dataLimitBehavior = dataLimitBehavior;
return this;
}
- /** {@hide} */
- public Builder setDataLimitSnooze(@CurrentTimeMillisLong long dataLimitSnoozeTime) {
- plan.dataLimitSnoozeTime = dataLimitSnoozeTime;
- return this;
- }
-
+ /**
+ * Set a snapshot of currently known mobile data usage.
+ *
+ * @param dataUsageBytes the currently known mobile data usage
+ * @param dataUsageTime the time at which this snapshot was valid
+ */
public Builder setDataUsage(@BytesLong long dataUsageBytes,
@CurrentTimeMillisLong long dataUsageTime) {
- if (dataUsageBytes < BYTES_UNKNOWN) {
- throw new IllegalArgumentException("Usage must be positive or BYTES_UNKNOWN");
+ if (dataUsageBytes < 0) {
+ throw new IllegalArgumentException("Usage bytes must be positive");
}
- if (dataUsageTime < TIME_UNKNOWN) {
- throw new IllegalArgumentException("Time must be positive or TIME_UNKNOWN");
- }
- if ((dataUsageBytes == BYTES_UNKNOWN) != (dataUsageTime == TIME_UNKNOWN)) {
- throw new IllegalArgumentException("Must provide both usage and time or neither");
+ if (dataUsageTime < 0) {
+ throw new IllegalArgumentException("Usage time must be positive");
}
plan.dataUsageBytes = dataUsageBytes;
plan.dataUsageTime = dataUsageTime;
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index d77b27f..5115731 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -28,4 +28,7 @@
void notifyConfigChangedForSubId(int subId);
void updateConfigForPhoneId(int phoneId, String simState);
+
+ String getDefaultCarrierServicePackageName();
+
}