summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt50
-rw-r--r--api/system-current.txt51
-rw-r--r--api/test-current.txt50
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl2
-rw-r--r--core/java/android/net/NetworkPolicy.java145
-rw-r--r--core/java/android/net/NetworkPolicyManager.java2
-rwxr-xr-xcore/java/android/provider/Settings.java16
-rw-r--r--core/java/android/service/vr/IVrListener.aidl2
-rw-r--r--core/java/android/service/vr/VrListenerService.java32
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java20
-rw-r--r--core/java/android/util/RecurrenceRule.java257
-rw-r--r--core/java/android/view/WindowManager.java11
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java4
-rw-r--r--core/proto/android/providers/settings.proto1
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/res/res/values/strings.xml12
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--core/tests/coretests/src/android/util/RecurrenceRuleTest.java146
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java29
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java18
-rw-r--r--proto/src/metrics_constants.proto5
-rw-r--r--services/Android.mk1
-rw-r--r--services/art-profile17
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java13
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags13
-rw-r--r--services/core/java/com/android/server/am/VrController.java7
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java233
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java10
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java12
-rw-r--r--services/core/java/com/android/server/timezone/IntentHelperImpl.java5
-rw-r--r--services/core/java/com/android/server/timezone/RulesManagerService.java22
-rw-r--r--services/core/java/com/android/server/vr/VrManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/vr/VrManagerService.java79
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java14
-rw-r--r--services/core/java/com/android/server/wm/Task.java11
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java46
-rw-r--r--services/java/com/android/server/SystemServer.java5
-rw-r--r--services/retaildemo/Android.mk12
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java178
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java868
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java105
-rw-r--r--services/tests/notification/Android.mk1
-rw-r--r--services/tests/servicestests/Android.mk1
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java79
-rw-r--r--services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java164
-rw-r--r--services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java484
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java43
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java46
-rw-r--r--telephony/java/android/telephony/SubscriptionPlan.java396
-rw-r--r--telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl3
56 files changed, 1274 insertions, 2537 deletions
diff --git a/api/current.txt b/api/current.txt
index 15354357e293..2428da1a4390 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37768,8 +37768,10 @@ package android.service.wallpaper {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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);
@@ -52264,6 +52301,11 @@ package dalvik.system {
method protected synchronized java.lang.Package getPackage(java.lang.String);
}
+ public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.ClassLoader);
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader);
+ }
+
public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
ctor public DexClassLoader(java.lang.String, java.lang.String, java.lang.String, java.lang.ClassLoader);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 8e3c840fa8ab..47e47ac6f1be 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -146,7 +146,6 @@ package android {
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 @@ package android.service.wallpaper {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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);
@@ -56294,6 +56330,11 @@ package dalvik.system {
method protected synchronized java.lang.Package getPackage(java.lang.String);
}
+ public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.ClassLoader);
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader);
+ }
+
public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
ctor public DexClassLoader(java.lang.String, java.lang.String, java.lang.String, java.lang.ClassLoader);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index cbf8e0610967..62f8418b4a71 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -37978,8 +37978,10 @@ package android.service.wallpaper {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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 @@ package android.telephony {
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);
@@ -52701,6 +52738,11 @@ package dalvik.system {
method protected synchronized java.lang.Package getPackage(java.lang.String);
}
+ public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.ClassLoader);
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader);
+ }
+
public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
ctor public DexClassLoader(java.lang.String, java.lang.String, java.lang.String, java.lang.ClassLoader);
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 7b948a7a933e..181e4a26d9b8 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -71,7 +71,5 @@ interface INetworkPolicyManager {
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 edf9a28d27f5..5df742c5a394 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 @@ import java.util.Objects;
* @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 class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
return 0;
}
+ public Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator() {
+ return cycleRule.cycleIterator();
+ }
+
/**
* Test if given measurement is over {@link #warningBytes}.
*/
@@ -141,7 +157,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
* 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 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
@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 class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
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 3fe9b0d74538..81c49a339d53 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -254,7 +254,7 @@ public class NetworkPolicyManager {
/** {@hide} */
public static Iterator<Pair<ZonedDateTime, ZonedDateTime>> cycleIterator(NetworkPolicy policy) {
- return SubscriptionPlan.convert(policy).cycleIterator();
+ return policy.cycleIterator();
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f5597b8eac8e..53c82e6c5237 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10132,22 +10132,6 @@ public final class Settings {
public static final String DEVICE_DEMO_MODE = "device_demo_mode";
/**
- * Retail mode specific settings. This is encoded as a key=value list, separated by commas.
- * Ex: "user_inactivity_timeout_ms=30000,warning_dialog_timeout_ms=10000". The following
- * keys are supported:
- *
- * <pre>
- * user_inactivity_timeout_ms (long)
- * warning_dialog_timeout_ms (long)
- * </pre>
- * <p>
- * Type: string
- *
- * @hide
- */
- public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
-
- /**
* Indicates the maximum time that an app is blocked for the network rules to get updated.
*
* Type: long
diff --git a/core/java/android/service/vr/IVrListener.aidl b/core/java/android/service/vr/IVrListener.aidl
index afb13d316503..acca3fa66ae4 100644
--- a/core/java/android/service/vr/IVrListener.aidl
+++ b/core/java/android/service/vr/IVrListener.aidl
@@ -20,5 +20,5 @@ import android.content.ComponentName;
/** @hide */
oneway interface IVrListener {
- void focusedActivityChanged(in ComponentName component);
+ void focusedActivityChanged(in ComponentName component, boolean running2dInVr, int pid);
}
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index 5da4560f688d..fa3d065d28a7 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -70,8 +70,10 @@ public abstract class VrListenerService extends Service {
private final IVrListener.Stub mBinder = new IVrListener.Stub() {
@Override
- public void focusedActivityChanged(ComponentName component) {
- mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, component).sendToTarget();
+ public void focusedActivityChanged(
+ ComponentName component, boolean running2dInVr, int pid) {
+ mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, running2dInVr ? 1 : 0,
+ pid, component).sendToTarget();
}
};
@@ -84,7 +86,8 @@ public abstract class VrListenerService extends Service {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ON_CURRENT_VR_ACTIVITY_CHANGED: {
- VrListenerService.this.onCurrentVrActivityChanged((ComponentName) msg.obj);
+ VrListenerService.this.onCurrentVrActivityChanged(
+ (ComponentName) msg.obj, msg.arg1 == 1, msg.arg2);
} break;
}
}
@@ -120,6 +123,29 @@ public abstract class VrListenerService extends Service {
}
/**
+ * An extended version of onCurrentVrActivityChanged
+ *
+ * <p>This will be called when this service is initially bound, but is not
+ * guaranteed to be called before onUnbind. In general, this is intended to be used to
+ * determine when user focus has transitioned between two VR activities, or between a
+ * VR activity and a 2D activity. This should be overridden instead of the above
+ * onCurrentVrActivityChanged as that version is deprecated.</p>
+ *
+ * @param component the {@link ComponentName} of the VR activity or the 2D intent.
+ * @param running2dInVr true if the component is a 2D component.
+ * @param pid the process the component is running in.
+ *
+ * @see android.app.Activity#setVrModeEnabled
+ * @see android.R.attr#enableVrMode
+ * @hide
+ */
+ public void onCurrentVrActivityChanged(
+ ComponentName component, boolean running2dInVr, int pid) {
+ // Override to implement. Default to old behaviour of sending null for 2D.
+ onCurrentVrActivityChanged(running2dInVr ? null : component);
+ }
+
+ /**
* Checks if the given component is enabled in user settings.
*
* <p>If this component is not enabled in the user's settings, it will not be started when
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e4d3142ccefe..424967f0e011 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -547,12 +547,11 @@ public abstract class WallpaperService extends Service {
/**
* 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 @@ public abstract class WallpaperService extends Service {
}
/**
- * 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 @@ public abstract class WallpaperService extends Service {
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 000000000000..1fe638d6b76b
--- /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 8e550dc1cb54..4041bcf7e3cb 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2599,5 +2599,16 @@ public interface WindowManager extends ViewManager {
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 3d8c85e684cb..3188d3005cae 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1694,10 +1694,10 @@ public class XmlUtils {
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/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index e212c432558c..fa645f4d4c6a 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -315,7 +315,6 @@ message GlobalSettingsProto {
SettingProto boot_count = 270;
SettingProto safe_boot_disallowed = 271;
SettingProto device_demo_mode = 272;
- SettingProto retail_demo_mode_constants = 273;
SettingProto database_downgrade_reason = 274;
SettingProto contacts_database_wal_enabled = 275;
SettingProto multi_sim_voice_call_subscription = 276;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c052e5145190..4a2ef3228d5e 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/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8c26db43fc41..65c52792226b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4538,22 +4538,10 @@
<!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
<string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
- <!-- Title of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
- <string name="reset_retail_demo_mode_title">Reset device?</string>
- <!-- Text of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
- <string name="reset_retail_demo_mode_text">Tap to reset device</string>
<!-- Text of dialog shown when starting a demo user for the first time [CHAR LIMIT=40] -->
<string name="demo_starting_message">Starting demo\u2026</string>
<!-- Text of dialog shown when starting a new demo user in retail demo mode [CHAR LIMIT=40] -->
<string name="demo_restarting_message">Resetting device\u2026</string>
- <!-- Title of the dialog shown when user inactivity times out in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_user_inactivity_timeout_title">Reset device?</string>
- <!-- Warning message shown when user inactivity times out in retail demo mode [CHAR LIMIT=none] -->
- <string name="demo_user_inactivity_timeout_countdown">You\u2019ll lose any changes and the demo will start again in <xliff:g id="timeout" example="9">%1$s</xliff:g> seconds\u2026</string>
- <!-- Text of button to allow user to abort countdown and continue current session in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_user_inactivity_timeout_left_button">Cancel</string>
- <!-- Text of button to allow user to abort countdown and immediately start another session in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_user_inactivity_timeout_right_button">Reset now</string>
<!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] -->
<string name="suspended_widget_accessibility">Disabled <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 949fd166c14c..e292c9dfbe67 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -304,7 +304,6 @@ public class SettingsBackupTest {
Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
Settings.Global.SAFE_BOOT_DISALLOWED,
Settings.Global.SAMPLING_PROFILER_MS,
Settings.Global.SELINUX_STATUS,
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 000000000000..42b6048b533a
--- /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 c346898e2911..b01fc8541957 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.NetworkTemplate;
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 @@ public class NetworkPolicyEditor {
@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/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index b328933cd1c5..819ee3ee57ff 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -915,9 +915,6 @@ class SettingsProtoDumpUtil {
Settings.Global.DEVICE_DEMO_MODE,
GlobalSettingsProto.DEVICE_DEMO_MODE);
dumpSetting(s, p,
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
- GlobalSettingsProto.RETAIL_DEMO_MODE_CONSTANTS);
- dumpSetting(s, p,
Settings.Global.DATABASE_DOWNGRADE_REASON,
GlobalSettingsProto.DATABASE_DOWNGRADE_REASON);
dumpSetting(s, p,
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 38b2969265cb..6eea030ef0f3 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 44cf003b3dcb..fe8373ffa127 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 @@ public class SysuiColorExtractor extends ColorExtractor {
*/
@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 28a45aae6892..ed4b131cd83f 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 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen
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 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen
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 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen
}
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 9b113d8463fd..ad177a7e849f 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.telephony.TelephonyProperties;
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.telephony.TelephonyManager;
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 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
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 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
.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 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
.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/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 81ec6a7c72a9..4e728f68890a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -19,13 +19,14 @@ package com.android.systemui.qs.tiles;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.os.SystemProperties;
import android.service.quicksettings.Tile;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
-
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.net.DataUsageController;
@@ -38,7 +39,6 @@ import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.qs.CellTileView;
import com.android.systemui.qs.CellTileView.SignalIcon;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.SignalTileView;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -46,8 +46,17 @@ import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTileImpl<SignalState> {
- static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
- "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
+ private static final ComponentName CELLULAR_SETTING_COMPONENT = new ComponentName(
+ "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity");
+ private static final ComponentName DATA_PLAN_CELLULAR_COMPONENT = new ComponentName(
+ "com.android.settings", "com.android.settings.Settings$DataPlanUsageSummaryActivity");
+
+ private static final Intent CELLULAR_SETTINGS =
+ new Intent().setComponent(CELLULAR_SETTING_COMPONENT);
+ private static final Intent DATA_PLAN_CELLULAR_SETTINGS =
+ new Intent().setComponent(DATA_PLAN_CELLULAR_COMPONENT);
+
+ private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
private final NetworkController mController;
private final DataUsageController mDataController;
@@ -90,7 +99,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
public Intent getLongClickIntent() {
- return CELLULAR_SETTINGS;
+ return getCellularSettingIntent(mContext);
}
@Override
@@ -103,7 +112,9 @@ public class CellularTile extends QSTileImpl<SignalState> {
if (mDataController.isMobileDataSupported()) {
showDetail(true);
} else {
- mActivityStarter.postStartActivityDismissingKeyguard(CELLULAR_SETTINGS, 0);
+ mActivityStarter
+ .postStartActivityDismissingKeyguard(getCellularSettingIntent(mContext),
+ 0 /* delay */);
}
}
@@ -240,7 +251,28 @@ public class CellularTile extends QSTileImpl<SignalState> {
public void setMobileDataEnabled(boolean enabled) {
mDetailAdapter.setMobileDataEnabled(enabled);
}
- };
+ }
+
+ static Intent getCellularSettingIntent(Context context) {
+ // TODO(b/62349208): We should replace feature flag check below with data plans
+ // availability check. If the data plans are available we display the data plans usage
+ // summary otherwise we display data usage summary without data plans.
+ boolean isDataPlanFeatureEnabled =
+ SystemProperties.getBoolean(ENABLE_SETTINGS_DATA_PLAN, false /* default */);
+ context.getPackageManager()
+ .setComponentEnabledSetting(
+ DATA_PLAN_CELLULAR_COMPONENT,
+ isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ context.getPackageManager()
+ .setComponentEnabledSetting(
+ CELLULAR_SETTING_COMPONENT,
+ isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ return isDataPlanFeatureEnabled ? DATA_PLAN_CELLULAR_SETTINGS : CELLULAR_SETTINGS;
+ }
private final class CellularDetailAdapter implements DetailAdapter {
@@ -258,7 +290,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
public Intent getSettingsIntent() {
- return CELLULAR_SETTINGS;
+ return getCellularSettingIntent(mContext);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index b7964512a2fa..8b62beb861ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -14,18 +14,16 @@
package com.android.systemui.qs.tiles;
-import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.service.quicksettings.Tile;
import android.widget.Switch;
-
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.DataSaverController;
@@ -57,9 +55,8 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements
@Override
public Intent getLongClickIntent() {
- return CellularTile.CELLULAR_SETTINGS;
+ return CellularTile.getCellularSettingIntent(mContext);
}
-
@Override
protected void handleClick() {
if (mState.value
@@ -73,12 +70,7 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements
dialog.setTitle(com.android.internal.R.string.data_saver_enable_title);
dialog.setMessage(com.android.internal.R.string.data_saver_description);
dialog.setPositiveButton(com.android.internal.R.string.data_saver_enable_button,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- toggleDataSaver();
- }
- });
+ (OnClickListener) (dialogInterface, which) -> toggleDataSaver());
dialog.setNegativeButton(com.android.internal.R.string.cancel, null);
dialog.setShowForAllUsers(true);
dialog.show();
@@ -126,4 +118,4 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements
public void onDataSaverChanged(boolean isDataSaving) {
refreshState(isDataSaving);
}
-} \ No newline at end of file
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 53190869513b..6167d85f33c7 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4252,6 +4252,11 @@ message MetricsEvent {
// OS: O MR
FIELD_RANKED_POSITION = 1087;
+ // OPEN: Settings > Data plan usage
+ // CATEGORY: SETTINGS
+ // OS: O MR
+ DATA_PLAN_USAGE_SUMMARY = 1088;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/Android.mk b/services/Android.mk
index 6a73d5f65351..0986e0a4aad4 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -34,7 +34,6 @@ services := \
net \
print \
restrictions \
- retaildemo \
usage \
usb \
voiceinteraction
diff --git a/services/art-profile b/services/art-profile
index bd6ed23fa993..140465a1c35e 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -11901,23 +11901,6 @@ PLcom/android/server/restrictions/RestrictionsManagerService$RestrictionsManager
PLcom/android/server/restrictions/RestrictionsManagerService;->-wrap0(Lcom/android/server/restrictions/RestrictionsManagerService;Ljava/lang/String;)Landroid/os/IBinder;
PLcom/android/server/restrictions/RestrictionsManagerService;-><init>(Landroid/content/Context;)V
PLcom/android/server/restrictions/RestrictionsManagerService;->onStart()V
-PLcom/android/server/retaildemo/RetailDemoModeService$1;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService;)V
-PLcom/android/server/retaildemo/RetailDemoModeService$1;->onUserActivity()V
-PLcom/android/server/retaildemo/RetailDemoModeService$Injector;-><init>(Landroid/content/Context;)V
-PLcom/android/server/retaildemo/RetailDemoModeService$Injector;->getContentResolver()Landroid/content/ContentResolver;
-PLcom/android/server/retaildemo/RetailDemoModeService$Injector;->getContext()Landroid/content/Context;
-PLcom/android/server/retaildemo/RetailDemoModeService$Injector;->publishLocalService(Lcom/android/server/retaildemo/RetailDemoModeService;Landroid/app/RetailDemoModeServiceInternal;)V
-PLcom/android/server/retaildemo/RetailDemoModeService$MainHandler;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService;Landroid/os/Looper;)V
-PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;->-wrap0(Lcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;)V
-PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService;Landroid/os/Handler;)V
-PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;->refreshTimeoutConstants()V
-PLcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;->register()V
-PLcom/android/server/retaildemo/RetailDemoModeService;->-get1(Lcom/android/server/retaildemo/RetailDemoModeService;)Lcom/android/server/retaildemo/RetailDemoModeService$Injector;
-PLcom/android/server/retaildemo/RetailDemoModeService;->-wrap2(Lcom/android/server/retaildemo/RetailDemoModeService;Ljava/lang/Class;Ljava/lang/Object;)V
-PLcom/android/server/retaildemo/RetailDemoModeService;-><init>(Landroid/content/Context;)V
-PLcom/android/server/retaildemo/RetailDemoModeService;-><init>(Lcom/android/server/retaildemo/RetailDemoModeService$Injector;)V
-PLcom/android/server/retaildemo/RetailDemoModeService;->onBootPhase(I)V
-PLcom/android/server/retaildemo/RetailDemoModeService;->onStart()V
PLcom/android/server/search/SearchManagerService$GlobalSearchProviderObserver;-><init>(Lcom/android/server/search/SearchManagerService;Landroid/content/ContentResolver;)V
PLcom/android/server/search/SearchManagerService$Lifecycle$1;-><init>(Lcom/android/server/search/SearchManagerService$Lifecycle;I)V
PLcom/android/server/search/SearchManagerService$Lifecycle$1;->run()V
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index a02802859ca7..41de97c8bcbb 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -698,6 +698,7 @@ public class BackupManagerService implements BackupManagerServiceInterface {
final SparseArray<Operation> mCurrentOperations = new SparseArray<Operation>();
final Object mCurrentOpLock = new Object();
final Random mTokenGenerator = new Random();
+ final AtomicInteger mNextToken = new AtomicInteger();
final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<AdbParams>();
@@ -770,15 +771,13 @@ public class BackupManagerService implements BackupManagerServiceInterface {
@GuardedBy("mQueueLock")
ArrayList<FullBackupEntry> mFullBackupQueue;
- // Utility: build a new random integer token
+ // Utility: build a new random integer token. The low bits are the ordinal of the
+ // operation for near-time uniqueness, and the upper bits are random for app-
+ // side unpredictability.
@Override
public int generateRandomIntegerToken() {
- int token;
- do {
- synchronized (mTokenGenerator) {
- token = mTokenGenerator.nextInt();
- }
- } while (token < 0);
+ int token = mTokenGenerator.nextInt() & ~0xFF;
+ token |= (mNextToken.incrementAndGet() & 0xFF);
return token;
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 68f8c1bb182f..b516a91715d5 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -268,3 +268,16 @@ option java_package com.android.server
# 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/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index 048bef7b19f5..feddfe3a2169 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -163,6 +163,7 @@ final class VrController {
ComponentName requestedPackage;
ComponentName callingPackage;
int userId;
+ int processId = -1;
boolean changed = false;
synchronized (mGlobalAmLock) {
vrMode = record.requestedVrComponent != null;
@@ -172,11 +173,15 @@ final class VrController {
// Tell the VrController that a VR mode change is requested.
changed = changeVrModeLocked(vrMode, record.app);
+
+ if (record.app != null) {
+ processId = record.app.pid;
+ }
}
// Tell VrManager that a VR mode changed is requested, VrManager will handle
// notifying all non-AM dependencies if needed.
- vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage);
+ vrService.setVrMode(vrMode, requestedPackage, userId, processId, callingPackage);
return changed;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 38f1c076727f..f70486a8b889 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 @@ package com.android.server.net;
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_UID_REMOVED;
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.Preconditions.checkNotNull;
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.SubscriptionPlan;
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.ArrayUtils;
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 libcore.io.IoUtils;
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.io.PrintWriter;
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// 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 class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// clear any existing policy and read from disk
mNetworkPolicy.clear();
+ mSubscriptionPlans.clear();
mUidPolicy.clear();
FileInputStream fis = null;
@@ -1787,12 +1804,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
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 class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
.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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@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 8e2097ae2609..d36d2f187e53 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 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// 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 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// 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 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- 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/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c68854286a19..0c72326095a6 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -53,6 +53,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -197,6 +198,9 @@ public final class PowerManagerService extends SystemService
// System property indicating that the screen should remain off until an explicit user action
private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
+ // System Property indicating that retail demo mode is currently enabled.
+ private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
+
// Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason
private static final String REASON_SHUTDOWN = "shutdown";
private static final String REASON_REBOOT = "reboot";
@@ -805,6 +809,9 @@ public final class PowerManagerService extends SystemService
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DOUBLE_TAP_TO_WAKE),
false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.DEVICE_DEMO_MODE),
+ false, mSettingsObserver, UserHandle.USER_SYSTEM);
IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
if (vrManager != null) {
try {
@@ -912,6 +919,11 @@ public final class PowerManagerService extends SystemService
}
}
+ final String retailDemoValue = UserManager.isDeviceInDemoMode(mContext) ? "1" : "0";
+ if (!retailDemoValue.equals(SystemProperties.get(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED))) {
+ SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, retailDemoValue);
+ }
+
final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
index 3ffbb2d61fd5..11928b964ec5 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.content.IntentFilter;
import android.os.PatternMatcher;
import android.util.Slog;
-import java.util.regex.Pattern;
-
/**
* The bona fide implementation of {@link IntentHelper}.
*/
@@ -75,6 +75,7 @@ final class IntentHelperImpl implements IntentHelper {
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 d97ba2d0d78b..1c5aa600580a 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_NONE;
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 @@ public final class RulesManagerService extends IRulesManager.Stub {
if (checkTokenBytes != null) {
checkToken = createCheckTokenOrThrow(checkTokenBytes);
}
+ EventLogTags.writeTimezoneRequestInstall(toStringOrNull(checkToken));
synchronized (this) {
if (distroParcelFileDescriptor == null) {
@@ -254,6 +254,8 @@ public final class RulesManagerService extends IRulesManager.Stub {
@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 @@ public final class RulesManagerService extends IRulesManager.Stub {
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 @@ public final class RulesManagerService extends IRulesManager.Stub {
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 @@ public final class RulesManagerService extends IRulesManager.Stub {
if (checkTokenBytes != null) {
checkToken = createCheckTokenOrThrow(checkTokenBytes);
}
+ EventLogTags.writeTimezoneRequestUninstall(toStringOrNull(checkToken));
synchronized(this) {
if (callback == null) {
throw new NullPointerException("callback == null");
@@ -337,6 +343,7 @@ public final class RulesManagerService extends IRulesManager.Stub {
@Override
public void run() {
+ EventLogTags.writeTimezoneUninstallStarted(toStringOrNull(mCheckToken));
boolean success = false;
try {
success = mInstaller.stageUninstall();
@@ -344,8 +351,12 @@ public final class RulesManagerService extends IRulesManager.Stub {
// 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 @@ public final class RulesManagerService extends IRulesManager.Stub {
if (checkTokenBytes != null) {
checkToken = createCheckTokenOrThrow(checkTokenBytes);
}
+ EventLogTags.writeTimezoneRequestNothing(toStringOrNull(checkToken));
mPackageTracker.recordCheckResult(checkToken, success);
+ EventLogTags.writeTimezoneNothingComplete(toStringOrNull(checkToken));
}
@Override
@@ -445,6 +458,7 @@ public final class RulesManagerService extends IRulesManager.Stub {
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 @@ public final class RulesManagerService extends IRulesManager.Stub {
return "Unknown";
}
}
+
+ private static String toStringOrNull(Object obj) {
+ return obj == null ? null : obj.toString();
+ }
}
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 1f7564027166..bdd9de011186 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -52,10 +52,11 @@ public abstract class VrManagerInternal {
* @param enabled {@code true} to enable VR mode.
* @param packageName The package name of the requested VrListenerService to bind.
* @param userId the user requesting the VrListenerService component.
+ * @param processId the process the component is running in.
* @param calling the component currently using VR mode, or null to leave unchanged.
*/
public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
- int userId, @NonNull ComponentName calling);
+ int userId, int processId, @NonNull ComponentName calling);
/**
* Set whether the system has acquired a sleep token.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index b10c9a3fd2ac..a6b8d94fb6b5 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -128,6 +128,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
private boolean mVrModeAllowed;
private boolean mVrModeEnabled;
private boolean mPersistentVrModeEnabled;
+ private boolean mRunning2dInVr;
+ private int mVrAppProcessId;
private EnabledComponentsObserver mComponentObserver;
private ManagedApplicationService mCurrentVrService;
private ComponentName mDefaultVrService;
@@ -178,7 +180,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
consumeAndApplyPendingStateLocked();
if (mBootsToVr && !mVrModeEnabled) {
- setVrMode(true, mDefaultVrService, 0, null);
+ setVrMode(true, mDefaultVrService, 0, -1, null);
}
} else {
// Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
@@ -187,12 +189,12 @@ public class VrManagerService extends SystemService implements EnabledComponentC
// Set pending state to current state.
mPendingState = (mVrModeEnabled && mCurrentVrService != null)
- ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
- mCurrentVrService.getUserId(), mCurrentVrModeComponent)
+ ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
+ mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
: null;
// Unbind current VR service and do necessary callbacks.
- updateCurrentVrServiceLocked(false, null, 0, null);
+ updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
}
}
}
@@ -274,26 +276,33 @@ public class VrManagerService extends SystemService implements EnabledComponentC
private static class VrState {
final boolean enabled;
+ final boolean running2dInVr;
final int userId;
+ final int processId;
final ComponentName targetPackageName;
final ComponentName callingPackage;
final long timestamp;
final boolean defaultPermissionsGranted;
- VrState(boolean enabled, ComponentName targetPackageName, int userId,
- ComponentName callingPackage) {
+
+ VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+ int processId, ComponentName callingPackage) {
this.enabled = enabled;
+ this.running2dInVr = running2dInVr;
this.userId = userId;
+ this.processId = processId;
this.targetPackageName = targetPackageName;
this.callingPackage = callingPackage;
this.defaultPermissionsGranted = false;
this.timestamp = System.currentTimeMillis();
}
- VrState(boolean enabled, ComponentName targetPackageName, int userId,
- ComponentName callingPackage, boolean defaultPermissionsGranted) {
+ VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+ int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
this.enabled = enabled;
+ this.running2dInVr = running2dInVr;
this.userId = userId;
+ this.processId = processId;
this.targetPackageName = targetPackageName;
this.callingPackage = callingPackage;
this.defaultPermissionsGranted = defaultPermissionsGranted;
@@ -394,8 +403,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
// There is an active service, update it if needed
- updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
- mCurrentVrService.getUserId(), mCurrentVrModeComponent);
+ updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
+ mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
+ mVrAppProcessId, mCurrentVrModeComponent);
}
}
@@ -531,9 +541,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC
*/
private final class LocalService extends VrManagerInternal {
@Override
- public void setVrMode(boolean enabled, ComponentName packageName, int userId,
+ public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
ComponentName callingPackage) {
- VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+ VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
}
@Override
@@ -710,14 +720,16 @@ public class VrManagerService extends SystemService implements EnabledComponentC
* Note: Must be called while holding {@code mLock}.
*
* @param enabled new state for VR mode.
+ * @param running2dInVr true if we have a top-level 2D intent.
* @param component new component to be bound as a VR listener.
* @param userId user owning the component to be bound.
- * @param calling the component currently using VR mode.
+ * @param processId the process hosting the activity specified by calling.
+ * @param calling the component currently using VR mode or a 2D intent.
*
* @return {@code true} if the component/user combination specified is valid.
*/
- private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
- int userId, ComponentName calling) {
+ private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
+ @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
boolean sendUpdatedCaller = false;
final long identity = Binder.clearCallingIdentity();
@@ -777,6 +789,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
sendUpdatedCaller = true;
}
mCurrentVrModeComponent = calling;
+ mRunning2dInVr = running2dInVr;
+ mVrAppProcessId = processId;
if (mCurrentVrModeUser != userId) {
mCurrentVrModeUser = userId;
@@ -794,11 +808,13 @@ public class VrManagerService extends SystemService implements EnabledComponentC
if (mCurrentVrService != null && sendUpdatedCaller) {
final ComponentName c = mCurrentVrModeComponent;
+ final boolean b = running2dInVr;
+ final int pid = processId;
mCurrentVrService.sendEvent(new PendingEvent() {
@Override
public void runEvent(IInterface service) throws RemoteException {
IVrListener l = (IVrListener) service;
- l.focusedActivityChanged(c);
+ l.focusedActivityChanged(c, b, pid);
}
});
}
@@ -1001,20 +1017,20 @@ public class VrManagerService extends SystemService implements EnabledComponentC
*/
private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
if (mPendingState != null) {
- updateCurrentVrServiceLocked(mPendingState.enabled,
- mPendingState.targetPackageName, mPendingState.userId,
+ updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
+ mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
mPendingState.callingPackage);
mPendingState = null;
} else if (disconnectIfNoPendingState) {
- updateCurrentVrServiceLocked(false, null, 0, null);
+ updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
}
}
private void logStateLocked() {
ComponentName currentBoundService = (mCurrentVrService == null) ? null :
mCurrentVrService.getComponent();
- VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
- mCurrentVrModeComponent, mWasDefaultGranted);
+ VrState current = new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
+ mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted);
if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
mLoggingDeque.removeFirst();
}
@@ -1058,27 +1074,24 @@ public class VrManagerService extends SystemService implements EnabledComponentC
* Implementation of VrManagerInternal calls. These are callable from system services.
*/
private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
- int userId, @NonNull ComponentName callingPackage) {
+ int userId, int processId, @NonNull ComponentName callingPackage) {
synchronized (mLock) {
VrState pending;
ComponentName targetListener;
- ComponentName foregroundVrComponent;
// If the device is in persistent VR mode, then calls to disable VR mode are ignored,
// and the system default VR listener is used.
boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
- if (!enabled && mPersistentVrModeEnabled) {
+ boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
+ if (running2dInVr) {
targetListener = mDefaultVrService;
-
- // Current foreground component isn't a VR one (in 2D app case)
- foregroundVrComponent = null;
} else {
targetListener = targetPackageName;
- foregroundVrComponent = callingPackage;
}
- pending = new VrState(
- targetEnabledState, targetListener, userId, foregroundVrComponent);
+
+ pending = new VrState(targetEnabledState, running2dInVr, targetListener,
+ userId, processId, callingPackage);
if (!mVrModeAllowed) {
// We're not allowed to be in VR mode. Make this state pending. This will be
@@ -1103,8 +1116,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC
mPendingState = null;
}
- updateCurrentVrServiceLocked(
- targetEnabledState, targetListener, userId, foregroundVrComponent);
+ updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
+ userId, processId, callingPackage);
}
}
@@ -1113,7 +1126,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
setPersistentModeAndNotifyListenersLocked(enabled);
// Disabling persistent mode when not showing a VR should disable the overall vr mode.
if (!enabled && mCurrentVrModeComponent == null) {
- setVrMode(false, null, 0, null);
+ setVrMode(false, null, 0, -1, null);
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05f4626259d7..a37b2e56b0d0 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// 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 cc3b146e8e0d..e5055e92828e 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 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
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 802f9edc92dc..1bece6903eac 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 @@ class TaskSnapshotSurface implements StartingSurface {
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 @@ class TaskSnapshotSurface implements StartingSurface {
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));
-
- 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;
+ 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();
}
- 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/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 85747287cf93..3757b7d0c53d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -99,7 +99,6 @@ import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.broadcastradio.BroadcastRadioService;
import com.android.server.restrictions.RestrictionsManagerService;
-import com.android.server.retaildemo.RetailDemoModeService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.soundtrigger.SoundTriggerService;
@@ -1536,10 +1535,6 @@ public final class SystemServer {
mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
traceEnd();
- traceBeginAndSlog("StartRetailDemoModeService");
- mSystemServiceManager.startService(RetailDemoModeService.class);
- traceEnd();
-
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
traceBeginAndSlog("StartAutoFillService");
mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
diff --git a/services/retaildemo/Android.mk b/services/retaildemo/Android.mk
deleted file mode 100644
index 670c6bfa1e6a..000000000000
--- a/services/retaildemo/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.retaildemo
-
-LOCAL_SRC_FILES += \
- $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
deleted file mode 100644
index 90c58d0279a7..000000000000
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.retaildemo;
-
-import android.app.AppGlobals;
-import android.app.PackageInstallObserver;
-import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * Helper class for installing preloaded APKs
- */
-class PreloadAppsInstaller {
- private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
- private static String TAG = PreloadAppsInstaller.class.getSimpleName();
- private static final String PRELOAD_APK_EXT = ".apk.preload";
- private static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private final IPackageManager mPackageManager;
- private final File preloadsAppsDirectory;
- private final Context mContext;
-
- private final Map<String, String> mApkToPackageMap;
-
- PreloadAppsInstaller(Context context) {
- this(context, AppGlobals.getPackageManager(), Environment.getDataPreloadsAppsDirectory());
- }
-
- @VisibleForTesting
- PreloadAppsInstaller(Context context, IPackageManager packageManager, File preloadsAppsDirectory) {
- mContext = context;
- mPackageManager = packageManager;
- mApkToPackageMap = Collections.synchronizedMap(new ArrayMap<>());
- this.preloadsAppsDirectory = preloadsAppsDirectory;
- }
-
- void installApps(int userId) {
- File[] files = preloadsAppsDirectory.listFiles();
- AppInstallCounter counter = new AppInstallCounter(mContext, userId);
- if (ArrayUtils.isEmpty(files)) {
- counter.setExpectedAppsCount(0);
- return;
- }
- int expectedCount = 0;
- for (File file : files) {
- String apkName = file.getName();
- if (apkName.endsWith(PRELOAD_APK_EXT) && file.isFile()) {
- String packageName = mApkToPackageMap.get(apkName);
- if (packageName != null) {
- try {
- expectedCount++;
- installExistingPackage(packageName, userId, counter);
- } catch (Exception e) {
- Slog.e(TAG, "Failed to install existing package " + packageName, e);
- }
- } else {
- try {
- installPackage(file, userId, counter);
- expectedCount++;
- } catch (Exception e) {
- Slog.e(TAG, "Failed to install package from " + file, e);
- }
- }
- }
- }
- counter.setExpectedAppsCount(expectedCount);
- }
-
- private void installExistingPackage(String packageName, int userId,
- AppInstallCounter counter) {
- if (DEBUG) {
- Log.d(TAG, "installExistingPackage " + packageName + " u" + userId);
- }
- try {
- mPackageManager.installExistingPackageAsUser(packageName, userId,
- 0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } finally {
- counter.appInstallFinished();
- }
- }
-
- private void installPackage(File file, final int userId, AppInstallCounter counter)
- throws IOException, RemoteException {
- final String apkName = file.getName();
- if (DEBUG) {
- Log.d(TAG, "installPackage " + apkName + " u" + userId);
- }
- mPackageManager.installPackageAsUser(file.getPath(), new PackageInstallObserver() {
- @Override
- public void onPackageInstalled(String basePackageName, int returnCode, String msg,
- Bundle extras) {
- if (DEBUG) {
- Log.d(TAG, "Package " + basePackageName + " installed u" + userId
- + " returnCode: " + returnCode + " msg: " + msg);
- }
- // Don't notify the counter for now, we'll do it in installExistingPackage
- if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
- mApkToPackageMap.put(apkName, basePackageName);
- // Install on user 0 so that the package is cached when demo user is re-created
- installExistingPackage(basePackageName, UserHandle.USER_SYSTEM, counter);
- } else if (returnCode == PackageManager.INSTALL_FAILED_ALREADY_EXISTS) {
- // This can only happen in first session after a reboot
- if (!mApkToPackageMap.containsKey(apkName)) {
- mApkToPackageMap.put(apkName, basePackageName);
- }
- installExistingPackage(basePackageName, userId, counter);
- } else {
- Log.e(TAG, "Package " + basePackageName + " cannot be installed from "
- + apkName + ": " + msg + " (returnCode " + returnCode + ")");
- counter.appInstallFinished();
- }
- }
- }.getBinder(), 0, SYSTEM_SERVER_PACKAGE_NAME, userId);
- }
-
- private static class AppInstallCounter {
- private int expectedCount = -1; // -1 means expectedCount not set
- private int finishedCount;
- private final Context mContext;
- private final int userId;
-
- AppInstallCounter(Context context, int userId) {
- mContext = context;
- this.userId = userId;
- }
-
- synchronized void appInstallFinished() {
- this.finishedCount++;
- checkIfAllFinished();
- }
-
- synchronized void setExpectedAppsCount(int expectedCount) {
- this.expectedCount = expectedCount;
- checkIfAllFinished();
- }
-
- private void checkIfAllFinished() {
- if (expectedCount == finishedCount) {
- Log.i(TAG, "All preloads finished installing for user " + userId);
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, "1", userId);
- }
- }
- }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
deleted file mode 100644
index 711d4d9d8a91..000000000000
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.retaildemo;
-
-import android.Manifest;
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.RetailDemoModeServiceInternal;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.media.AudioManager;
-import android.media.AudioSystem;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.KeyValueListParser;
-import android.util.Slog;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.LocalServices;
-import com.android.server.PreloadsFileCacheExpirationJobService;
-import com.android.server.ServiceThread;
-import com.android.server.SystemService;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener;
-
-import java.io.File;
-import java.util.ArrayList;
-
-public class RetailDemoModeService extends SystemService {
- private static final boolean DEBUG = false;
-
- private static final String TAG = RetailDemoModeService.class.getSimpleName();
- private static final String DEMO_USER_NAME = "Demo";
- private static final String ACTION_RESET_DEMO =
- "com.android.server.retaildemo.ACTION_RESET_DEMO";
- @VisibleForTesting
- static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
-
- private static final int MSG_TURN_SCREEN_ON = 0;
- private static final int MSG_INACTIVITY_TIME_OUT = 1;
- private static final int MSG_START_NEW_SESSION = 2;
-
- private static final long SCREEN_WAKEUP_DELAY = 2500;
- private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000;
- private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 90000;
- private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 0;
- private static final long MILLIS_PER_SECOND = 1000;
-
- @VisibleForTesting
- static final int[] VOLUME_STREAMS_TO_MUTE = {
- AudioSystem.STREAM_RING,
- AudioSystem.STREAM_MUSIC
- };
-
- // Tron Vars
- private static final String DEMO_SESSION_COUNT = "retail_demo_session_count";
- private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration";
-
- boolean mDeviceInDemoMode;
- boolean mIsCarrierDemoMode;
- int mCurrentUserId = UserHandle.USER_SYSTEM;
- long mUserInactivityTimeout;
- long mWarningDialogTimeout;
- private Injector mInjector;
- Handler mHandler;
- private ServiceThread mHandlerThread;
- private String[] mCameraIdsWithFlash;
- private PreloadAppsInstaller mPreloadAppsInstaller;
-
- final Object mActivityLock = new Object();
- // Whether the newly created demo user has interacted with the screen yet
- @GuardedBy("mActivityLock")
- boolean mUserUntouched;
- @GuardedBy("mActivityLock")
- long mFirstUserActivityTime;
- @GuardedBy("mActivityLock")
- long mLastUserActivityTime;
-
- private boolean mSafeBootRestrictionInitialState;
- private int mPackageVerifierEnableInitialState;
-
- private IntentReceiver mBroadcastReceiver = null;
-
- private final class IntentReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!mDeviceInDemoMode) {
- return;
- }
- final String action = intent.getAction();
- switch (action) {
- case Intent.ACTION_SCREEN_OFF:
- mHandler.removeMessages(MSG_TURN_SCREEN_ON);
- mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY);
- break;
- case ACTION_RESET_DEMO:
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- break;
- }
- }
- };
-
- final class MainHandler extends Handler {
-
- MainHandler(Looper looper) {
- super(looper, null, true);
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (!mDeviceInDemoMode) {
- return;
- }
- switch (msg.what) {
- case MSG_TURN_SCREEN_ON:
- if (mInjector.isWakeLockHeld()) {
- mInjector.releaseWakeLock();
- }
- mInjector.acquireWakeLock();
- break;
- case MSG_INACTIVITY_TIME_OUT:
- if (!mIsCarrierDemoMode && isDemoLauncherDisabled()) {
- Slog.i(TAG, "User inactivity timeout reached");
- showInactivityCountdownDialog();
- }
- break;
- case MSG_START_NEW_SESSION:
- if (DEBUG) {
- Slog.d(TAG, "Switching to a new demo user");
- }
- removeMessages(MSG_START_NEW_SESSION);
- removeMessages(MSG_INACTIVITY_TIME_OUT);
- if (!mIsCarrierDemoMode && mCurrentUserId != UserHandle.USER_SYSTEM) {
- logSessionDuration();
- }
-
- final UserManager um = mInjector.getUserManager();
- UserInfo demoUser = null;
- if (mIsCarrierDemoMode) {
- // Re-use the existing demo user in carrier demo mode.
- for (UserInfo user : um.getUsers()) {
- if (user.isDemo()) {
- demoUser = user;
- break;
- }
- }
- }
-
- if (demoUser == null) {
- // User in carrier demo mode should survive reboots.
- final int flags = UserInfo.FLAG_DEMO
- | (mIsCarrierDemoMode ? 0 : UserInfo.FLAG_EPHEMERAL);
- demoUser = um.createUser(DEMO_USER_NAME, flags);
- }
-
- if (demoUser != null && mCurrentUserId != demoUser.id) {
- setupDemoUser(demoUser);
- mInjector.switchUser(demoUser.id);
- }
- break;
- }
- }
- }
-
- @VisibleForTesting
- class SettingsObserver extends ContentObserver {
-
- private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms";
- private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms";
-
- private final Uri mDeviceDemoModeUri = Settings.Global
- .getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- private final Uri mDeviceProvisionedUri = Settings.Global
- .getUriFor(Settings.Global.DEVICE_PROVISIONED);
- private final Uri mRetailDemoConstantsUri = Settings.Global
- .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS);
-
- private final KeyValueListParser mParser = new KeyValueListParser(',');
-
- public SettingsObserver(Handler handler) {
- super(handler);
- }
-
- public void register() {
- final ContentResolver cr = mInjector.getContentResolver();
- cr.registerContentObserver(mDeviceDemoModeUri, false, this, UserHandle.USER_SYSTEM);
- cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM);
- cr.registerContentObserver(mRetailDemoConstantsUri, false, this,
- UserHandle.USER_SYSTEM);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (mRetailDemoConstantsUri.equals(uri)) {
- refreshTimeoutConstants();
- return;
- }
-
- // If device is provisioned and left demo mode - run the cleanup in demo folder
- if (isDeviceProvisioned()) {
- if (UserManager.isDeviceInDemoMode(getContext())) {
- startDemoMode();
- } else {
- mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
-
- // Run on the bg thread to not block the fg thread
- BackgroundThread.getHandler().post(() -> {
- if (!deletePreloadsFolderContents()) {
- Slog.w(TAG, "Failed to delete preloads folder contents");
- }
- PreloadsFileCacheExpirationJobService.schedule(mInjector.getContext());
- });
-
- stopDemoMode();
-
- if (mInjector.isWakeLockHeld()) {
- mInjector.releaseWakeLock();
- }
- }
- }
- }
-
- private void refreshTimeoutConstants() {
- try {
- mParser.setString(Settings.Global.getString(mInjector.getContentResolver(),
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS));
- } catch (IllegalArgumentException exc) {
- Slog.e(TAG, "Invalid string passed to KeyValueListParser");
- // Consuming the exception to fall back to default values.
- }
- mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT,
- WARNING_DIALOG_TIMEOUT_DEFAULT);
- mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT,
- USER_INACTIVITY_TIMEOUT_DEFAULT);
- mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN);
- }
- }
-
- private void showInactivityCountdownDialog() {
- UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
- mWarningDialogTimeout, MILLIS_PER_SECOND);
- dialog.setNegativeButtonClickListener(null);
- dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- }
- });
- dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() {
- @Override
- public void onCountDownExpired() {
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- }
- });
- dialog.show();
- }
-
- public RetailDemoModeService(Context context) {
- this(new Injector(context));
- }
-
- @VisibleForTesting
- RetailDemoModeService(Injector injector) {
- super(injector.getContext());
-
- mInjector = injector;
- synchronized (mActivityLock) {
- mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
- }
- }
-
- boolean isDemoLauncherDisabled() {
- int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- try {
- final IPackageManager iPm = mInjector.getIPackageManager();
- final String demoLauncherComponent =
- getContext().getString(R.string.config_demoModeLauncherComponent);
- enabledState = iPm.getComponentEnabledSetting(
- ComponentName.unflattenFromString(demoLauncherComponent), mCurrentUserId);
- } catch (RemoteException re) {
- Slog.e(TAG, "Error retrieving demo launcher enabled setting", re);
- }
- return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
- }
-
- private void setupDemoUser(UserInfo userInfo) {
- final UserManager um = mInjector.getUserManager();
- final UserHandle user = UserHandle.of(userInfo.id);
- um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
- um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
- um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
- um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
- um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
- um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
- // Set this to false because the default is true on user creation
- um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
- // Disallow rebooting in safe mode - controlled by user 0
- um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
- if (mIsCarrierDemoMode) {
- // Enable SMS in carrier demo mode.
- um.setUserRestriction(UserManager.DISALLOW_SMS, false, user);
- }
-
- Settings.Secure.putIntForUser(mInjector.getContentResolver(),
- Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
- Settings.Global.putInt(mInjector.getContentResolver(),
- Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-
- grantRuntimePermissionToCamera(user);
- clearPrimaryCallLog();
-
- if (!mIsCarrierDemoMode) {
- // Enable demo launcher.
- final String demoLauncher = getContext().getString(
- R.string.config_demoModeLauncherComponent);
- if (!TextUtils.isEmpty(demoLauncher)) {
- final ComponentName componentToEnable =
- ComponentName.unflattenFromString(demoLauncher);
- final String packageName = componentToEnable.getPackageName();
- try {
- final IPackageManager iPm = AppGlobals.getPackageManager();
- iPm.setComponentEnabledSetting(componentToEnable,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id);
- iPm.setApplicationEnabledSetting(packageName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
- } catch (RemoteException re) {
- // Internal, shouldn't happen
- }
- }
- } else {
- // Set the carrier demo mode setting for the demo user.
- final String carrierDemoModeSetting = getContext().getString(
- R.string.config_carrierDemoModeSetting);
- Settings.Secure.putIntForUser(getContext().getContentResolver(),
- carrierDemoModeSetting, 1, userInfo.id);
-
- // Enable packages for carrier demo mode.
- final String packageList = getContext().getString(
- R.string.config_carrierDemoModePackages);
- final String[] packageNames = packageList == null ? new String[0]
- : TextUtils.split(packageList, ",");
- final IPackageManager iPm = AppGlobals.getPackageManager();
- for (String packageName : packageNames) {
- try {
- iPm.setApplicationEnabledSetting(packageName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
- } catch (RemoteException re) {
- Slog.e(TAG, "Error enabling application: " + packageName, re);
- }
- }
- }
- }
-
- private void grantRuntimePermissionToCamera(UserHandle user) {
- final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- final PackageManager pm = mInjector.getPackageManager();
- final ResolveInfo handler = pm.resolveActivityAsUser(cameraIntent,
- PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- user.getIdentifier());
- if (handler == null || handler.activityInfo == null) {
- return;
- }
- try {
- pm.grantRuntimePermission(handler.activityInfo.packageName,
- Manifest.permission.ACCESS_FINE_LOCATION, user);
- } catch (Exception e) {
- // Ignore
- }
- }
-
- private void clearPrimaryCallLog() {
- final ContentResolver resolver = mInjector.getContentResolver();
-
- // Deleting primary user call log so that it doesn't get copied to the new demo user
- final Uri uri = CallLog.Calls.CONTENT_URI;
- try {
- resolver.delete(uri, null, null);
- } catch (Exception e) {
- Slog.w(TAG, "Deleting call log failed: " + e);
- }
- }
-
- void logSessionDuration() {
- final int sessionDuration;
- synchronized (mActivityLock) {
- sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000);
- }
- mInjector.logSessionDuration(sessionDuration);
- }
-
- private boolean isDeviceProvisioned() {
- return Settings.Global.getInt(
- mInjector.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- }
-
- /**
- * Deletes contents of {@link Environment#getDataPreloadsDirectory()},
- * but leave {@link Environment#getDataPreloadsFileCacheDirectory()}
- * @return true if contents was sucessfully deleted
- */
- private boolean deletePreloadsFolderContents() {
- final File dir = mInjector.getDataPreloadsDirectory();
- final File[] files = FileUtils.listFilesOrEmpty(dir);
- final File fileCacheDirectory = mInjector.getDataPreloadsFileCacheDirectory();
- Slog.i(TAG, "Deleting contents of " + dir);
- boolean success = true;
- for (File file : files) {
- if (file.isFile()) {
- if (!file.delete()) {
- success = false;
- Slog.w(TAG, "Cannot delete file " + file);
- }
- } else {
- // Do not remove file_cache dir
- if (!file.equals(fileCacheDirectory)) {
- if (!FileUtils.deleteContentsAndDir(file)) {
- success = false;
- Slog.w(TAG, "Cannot delete dir and its content " + file);
- }
- } else {
- Slog.i(TAG, "Skipping directory with file cache " + file);
- }
- }
- }
- return success;
- }
-
- private void registerBroadcastReceiver() {
- if (mBroadcastReceiver != null) {
- return;
- }
-
- final IntentFilter filter = new IntentFilter();
- if (!mIsCarrierDemoMode) {
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- }
- filter.addAction(ACTION_RESET_DEMO);
- mBroadcastReceiver = new IntentReceiver();
- getContext().registerReceiver(mBroadcastReceiver, filter);
- }
-
- private void unregisterBroadcastReceiver() {
- if (mBroadcastReceiver != null) {
- getContext().unregisterReceiver(mBroadcastReceiver);
- mBroadcastReceiver = null;
- }
- }
-
- private String[] getCameraIdsWithFlash() {
- ArrayList<String> cameraIdsList = new ArrayList<String>();
- final CameraManager cm = mInjector.getCameraManager();
- if (cm != null) {
- try {
- for (String cameraId : cm.getCameraIdList()) {
- CameraCharacteristics c = cm.getCameraCharacteristics(cameraId);
- if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) {
- cameraIdsList.add(cameraId);
- }
- }
- } catch (CameraAccessException e) {
- Slog.e(TAG, "Unable to access camera while getting camera id list", e);
- }
- }
- return cameraIdsList.toArray(new String[cameraIdsList.size()]);
- }
-
- private void muteVolumeStreams() {
- for (int stream : VOLUME_STREAMS_TO_MUTE) {
- mInjector.getAudioManager().setStreamVolume(stream,
- mInjector.getAudioManager().getStreamMinVolume(stream), 0);
- }
- }
-
- private void startDemoMode() {
- mDeviceInDemoMode = true;
-
- mPreloadAppsInstaller = mInjector.getPreloadAppsInstaller();
- mInjector.initializeWakeLock();
- if (mCameraIdsWithFlash == null) {
- mCameraIdsWithFlash = getCameraIdsWithFlash();
- }
- registerBroadcastReceiver();
-
- final String carrierDemoModeSetting =
- getContext().getString(R.string.config_carrierDemoModeSetting);
- mIsCarrierDemoMode = !TextUtils.isEmpty(carrierDemoModeSetting)
- && (Settings.Secure.getInt(getContext().getContentResolver(),
- carrierDemoModeSetting, 0) == 1);
-
- mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-
- mSafeBootRestrictionInitialState = mInjector.getUserManager().hasUserRestriction(
- UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM);
- mPackageVerifierEnableInitialState = Settings.Global.getInt(mInjector.getContentResolver(),
- Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
- }
-
- private void stopDemoMode() {
- mPreloadAppsInstaller = null;
- mCameraIdsWithFlash = null;
- mInjector.destroyWakeLock();
- unregisterBroadcastReceiver();
-
- if (mDeviceInDemoMode) {
- mInjector.getUserManager().setUserRestriction(UserManager.DISALLOW_SAFE_BOOT,
- mSafeBootRestrictionInitialState, UserHandle.SYSTEM);
- Settings.Global.putInt(mInjector.getContentResolver(),
- Settings.Global.PACKAGE_VERIFIER_ENABLE,
- mPackageVerifierEnableInitialState);
- }
-
- mDeviceInDemoMode = false;
- mIsCarrierDemoMode = false;
- }
-
- @Override
- public void onStart() {
- if (DEBUG) {
- Slog.d(TAG, "Service starting up");
- }
- mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND,
- false);
- mHandlerThread.start();
- mHandler = new MainHandler(mHandlerThread.getLooper());
- mInjector.publishLocalService(this, mLocalService);
- }
-
- @Override
- public void onBootPhase(int bootPhase) {
- switch (bootPhase) {
- case PHASE_THIRD_PARTY_APPS_CAN_START:
- final SettingsObserver settingsObserver = new SettingsObserver(mHandler);
- settingsObserver.register();
- settingsObserver.refreshTimeoutConstants();
- break;
- case PHASE_BOOT_COMPLETED:
- if (UserManager.isDeviceInDemoMode(getContext())) {
- startDemoMode();
- }
- break;
- }
- }
-
- @Override
- public void onSwitchUser(int userId) {
- if (!mDeviceInDemoMode) {
- return;
- }
- if (DEBUG) {
- Slog.d(TAG, "onSwitchUser: " + userId);
- }
- final UserInfo ui = mInjector.getUserManager().getUserInfo(userId);
- if (!ui.isDemo()) {
- Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
- return;
- }
- if (!mIsCarrierDemoMode && !mInjector.isWakeLockHeld()) {
- mInjector.acquireWakeLock();
- }
- mCurrentUserId = userId;
- mInjector.getActivityManagerInternal().updatePersistentConfigurationForUser(
- mInjector.getSystemUsersConfiguration(), userId);
-
- mInjector.turnOffAllFlashLights(mCameraIdsWithFlash);
- muteVolumeStreams();
- if (!mInjector.getWifiManager().isWifiEnabled()) {
- mInjector.getWifiManager().setWifiEnabled(true);
- }
-
- // Disable lock screen for demo users.
- mInjector.getLockPatternUtils().setLockScreenDisabled(true, userId);
-
- if (!mIsCarrierDemoMode) {
- // Show reset notification (except in carrier demo mode).
- mInjector.getNotificationManager().notifyAsUser(TAG, SystemMessage.NOTE_RETAIL_RESET,
- mInjector.createResetNotification(), UserHandle.of(userId));
-
- synchronized (mActivityLock) {
- mUserUntouched = true;
- }
- mInjector.logSessionCount(1);
- mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mPreloadAppsInstaller.installApps(userId);
- }
- });
- }
- }
-
- private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
- private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
-
- @Override
- public void onUserActivity() {
- if (!mDeviceInDemoMode || mIsCarrierDemoMode) {
- return;
- }
- long timeOfActivity = SystemClock.uptimeMillis();
- synchronized (mActivityLock) {
- if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
- return;
- }
- mLastUserActivityTime = timeOfActivity;
- if (mUserUntouched && isDemoLauncherDisabled()) {
- Slog.d(TAG, "retail_demo first touch");
- mUserUntouched = false;
- mFirstUserActivityTime = timeOfActivity;
- }
- }
- mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
- mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout);
- }
- };
-
- static class Injector {
- private Context mContext;
- private UserManager mUm;
- private PackageManager mPm;
- private NotificationManager mNm;
- private ActivityManagerService mAms;
- private ActivityManagerInternal mAmi;
- private AudioManager mAudioManager;
- private PowerManager mPowerManager;
- private CameraManager mCameraManager;
- private PowerManager.WakeLock mWakeLock;
- private WifiManager mWifiManager;
- private Configuration mSystemUserConfiguration;
- private PendingIntent mResetDemoPendingIntent;
- private PreloadAppsInstaller mPreloadAppsInstaller;
-
- Injector(Context context) {
- mContext = context;
- }
-
- Context getContext() {
- return mContext;
- }
-
- WifiManager getWifiManager() {
- if (mWifiManager == null) {
- mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- }
- return mWifiManager;
- }
-
- UserManager getUserManager() {
- if (mUm == null) {
- mUm = getContext().getSystemService(UserManager.class);
- }
- return mUm;
- }
-
- void switchUser(int userId) {
- if (mAms == null) {
- mAms = (ActivityManagerService) ActivityManager.getService();
- }
- mAms.switchUser(userId);
- }
-
- AudioManager getAudioManager() {
- if (mAudioManager == null) {
- mAudioManager = getContext().getSystemService(AudioManager.class);
- }
- return mAudioManager;
- }
-
- private PowerManager getPowerManager() {
- if (mPowerManager == null) {
- mPowerManager = (PowerManager) getContext().getSystemService(
- Context.POWER_SERVICE);
- }
- return mPowerManager;
- }
-
- NotificationManager getNotificationManager() {
- if (mNm == null) {
- mNm = NotificationManager.from(getContext());
- }
- return mNm;
- }
-
- ActivityManagerInternal getActivityManagerInternal() {
- if (mAmi == null) {
- mAmi = LocalServices.getService(ActivityManagerInternal.class);
- }
- return mAmi;
- }
-
- CameraManager getCameraManager() {
- if (mCameraManager == null) {
- mCameraManager = (CameraManager) getContext().getSystemService(
- Context.CAMERA_SERVICE);
- }
- return mCameraManager;
- }
-
- PackageManager getPackageManager() {
- if (mPm == null) {
- mPm = getContext().getPackageManager();
- }
- return mPm;
- }
-
- IPackageManager getIPackageManager() {
- return AppGlobals.getPackageManager();
- }
-
- ContentResolver getContentResolver() {
- return getContext().getContentResolver();
- }
-
- PreloadAppsInstaller getPreloadAppsInstaller() {
- if (mPreloadAppsInstaller == null) {
- mPreloadAppsInstaller = new PreloadAppsInstaller(getContext());
- }
- return mPreloadAppsInstaller;
- }
-
- void systemPropertiesSet(String key, String value) {
- SystemProperties.set(key, value);
- }
-
- void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
- for (String cameraId : cameraIdsWithFlash) {
- try {
- getCameraManager().setTorchMode(cameraId, false);
- } catch (CameraAccessException e) {
- Slog.e(TAG, "Unable to access camera " + cameraId
- + " while turning off flash", e);
- }
- }
- }
-
- void initializeWakeLock() {
- if (mWakeLock == null) {
- mWakeLock = getPowerManager().newWakeLock(
- PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
- }
- }
-
- void destroyWakeLock() {
- mWakeLock = null;
- }
-
- boolean isWakeLockHeld() {
- return mWakeLock != null && mWakeLock.isHeld();
- }
-
- void acquireWakeLock() {
- mWakeLock.acquire();
- }
-
- void releaseWakeLock() {
- mWakeLock.release();
- }
-
- void logSessionDuration(int duration) {
- MetricsLogger.histogram(getContext(), DEMO_SESSION_DURATION, duration);
- }
-
- void logSessionCount(int count) {
- MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, count);
- }
-
- Configuration getSystemUsersConfiguration() {
- if (mSystemUserConfiguration == null) {
- Settings.System.getConfiguration(getContentResolver(),
- mSystemUserConfiguration = new Configuration());
- }
- return mSystemUserConfiguration;
- }
-
- LockPatternUtils getLockPatternUtils() {
- return new LockPatternUtils(getContext());
- }
-
- Notification createResetNotification() {
- return new Notification.Builder(getContext(), SystemNotificationChannels.RETAIL_MODE)
- .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title))
- .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text))
- .setOngoing(true)
- .setSmallIcon(R.drawable.platlogo)
- .setShowWhen(false)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setContentIntent(getResetDemoPendingIntent())
- .setColor(getContext().getColor(R.color.system_notification_accent_color))
- .build();
- }
-
- private PendingIntent getResetDemoPendingIntent() {
- if (mResetDemoPendingIntent == null) {
- Intent intent = new Intent(ACTION_RESET_DEMO);
- mResetDemoPendingIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
- }
- return mResetDemoPendingIntent;
- }
-
- File getDataPreloadsDirectory() {
- return Environment.getDataPreloadsDirectory();
- }
-
- File getDataPreloadsFileCacheDirectory() {
- return Environment.getDataPreloadsFileCacheDirectory();
- }
-
- void publishLocalService(RetailDemoModeService service,
- RetailDemoModeServiceInternal localService) {
- service.publishLocalService(RetailDemoModeServiceInternal.class, localService);
- }
- }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
deleted file mode 100644
index 013eab8679a8..000000000000
--- a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.retaildemo;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.os.CountDownTimer;
-import android.view.WindowManager;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-public class UserInactivityCountdownDialog extends AlertDialog {
-
- private OnCountDownExpiredListener mOnCountDownExpiredListener;
- private CountDownTimer mCountDownTimer;
- private long mCountDownDuration;
- private long mRefreshInterval;
-
- UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) {
- super(context);
- mCountDownDuration = duration;
- mRefreshInterval = refreshInterval;
-
- getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
- WindowManager.LayoutParams attrs = getWindow().getAttributes();
- attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- getWindow().setAttributes(attrs);
-
- setTitle(R.string.demo_user_inactivity_timeout_title);
- setMessage(getContext().getString(R.string.demo_user_inactivity_timeout_countdown,
- duration));
- }
-
- public void setOnCountDownExpiredListener(
- OnCountDownExpiredListener onCountDownExpiredListener) {
- mOnCountDownExpiredListener = onCountDownExpiredListener;
- }
-
- public void setPositiveButtonClickListener(OnClickListener onClickListener) {
- setButton(Dialog.BUTTON_POSITIVE,
- getContext().getString(R.string.demo_user_inactivity_timeout_right_button),
- onClickListener);
- }
-
- public void setNegativeButtonClickListener(OnClickListener onClickListener) {
- setButton(Dialog.BUTTON_NEGATIVE,
- getContext().getString(R.string.demo_user_inactivity_timeout_left_button),
- onClickListener);
- }
-
- @Override
- public void show() {
- super.show();
- final TextView messageView = findViewById(R.id.message);
- messageView.post(new Runnable() {
- @Override
- public void run() {
- mCountDownTimer = new CountDownTimer(mCountDownDuration, mRefreshInterval) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- String msg = getContext().getString(
- R.string.demo_user_inactivity_timeout_countdown,
- millisUntilFinished / 1000);
- messageView.setText(msg);
- }
-
- @Override
- public void onFinish() {
- dismiss();
- if (mOnCountDownExpiredListener != null)
- mOnCountDownExpiredListener.onCountDownExpired();
- }
- }.start();
- }
- });
- }
-
- @Override
- public void onStop() {
- if (mCountDownTimer != null) {
- mCountDownTimer.cancel();
- }
- }
-
- interface OnCountDownExpiredListener {
- void onCountDownExpired();
- }
-}
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index 0ffe6e4db6b8..597a5849a1a0 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -18,7 +18,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
services.core \
services.devicepolicy \
services.net \
- services.retaildemo \
services.usage \
guava \
android-support-test \
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 0ff11c1f58f8..507b4830e455 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -19,7 +19,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
services.core \
services.devicepolicy \
services.net \
- services.retaildemo \
services.usage \
guava \
android-support-test \
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 11e383c25ef0..8decb968c8fb 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.DATA_CYCLE_USE_PLATFORM_DEF
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.NetworkCapabilities;
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.filters.MediumTest;
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.ElementType;
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 @@ public class NetworkPolicyManagerServiceTest {
@After
public void resetClock() throws Exception {
- SubscriptionPlan.sNowOverride = -1;
+ RecurrenceRule.sClock = Clock.systemDefaultZone();
}
@Test
@@ -785,9 +786,9 @@ public class NetworkPolicyManagerServiceTest {
}
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 @@ public class NetworkPolicyManagerServiceTest {
}
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 @@ public class NetworkPolicyManagerServiceTest {
}
@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 @@ public class NetworkPolicyManagerServiceTest {
}
@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 @@ public class NetworkPolicyManagerServiceTest {
}
@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 @@ public class NetworkPolicyManagerServiceTest {
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 @@ public class NetworkPolicyManagerServiceTest {
}
private void setCurrentTimeMillis(long currentTimeMillis) {
- SubscriptionPlan.sNowOverride = currentTimeMillis;
+ RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTimeMillis),
+ ZoneId.systemDefault());
mStartTime = currentTimeMillis;
mElapsedRealtime = 0L;
}
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
deleted file mode 100644
index cf27a503efd4..000000000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.retaildemo;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.IPackageInstallObserver2;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.FileUtils;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentResolver;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class PreloadAppsInstallerTest {
- private static final int TEST_DEMO_USER = 111;
-
- private Context mContext;
- private @Mock IPackageManager mIpm;
- private MockContentResolver mContentResolver;
- private File mPreloadsAppsDirectory;
- private String[] mPreloadedApps =
- new String[] {"test1.apk.preload", "test2.apk.preload", "test3.apk.preload"};
- private ArrayList<String> mPreloadedAppPaths = new ArrayList<>();
-
- private PreloadAppsInstaller mInstaller;
-
- @BeforeClass
- @AfterClass
- public static void clearSettingsProvider() {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
- mContentResolver = new MockContentResolver(mContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- when(mContext.getContentResolver()).thenReturn(mContentResolver);
- initializePreloadedApps();
- Settings.Secure.putStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, "0", TEST_DEMO_USER);
-
- mInstaller = new PreloadAppsInstaller(mContext, mIpm, mPreloadsAppsDirectory);
- }
-
- private void initializePreloadedApps() throws Exception {
- mPreloadsAppsDirectory = new File(InstrumentationRegistry.getContext().getFilesDir(),
- "test_preload_apps_dir");
- mPreloadsAppsDirectory.mkdir();
- for (String name : mPreloadedApps) {
- final File f = new File(mPreloadsAppsDirectory, name);
- f.createNewFile();
- mPreloadedAppPaths.add(f.getPath());
- }
- }
-
- @After
- public void tearDown() {
- if (mPreloadsAppsDirectory != null) {
- FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
- }
- }
-
- @Test
- public void testInstallApps() throws Exception {
- mInstaller.installApps(TEST_DEMO_USER);
- for (String path : mPreloadedAppPaths) {
- ArgumentCaptor<IPackageInstallObserver2> observer =
- ArgumentCaptor.forClass(IPackageInstallObserver2.class);
- verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
- anyString(), eq(TEST_DEMO_USER));
- observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
- null, null);
- // Verify that we try to install the package in system user.
- verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
- 0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
- }
- assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
- "1",
- Settings.Secure.getStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
- }
-
- @Test
- public void testInstallApps_noPreloads() throws Exception {
- // Delete all files in preloaded apps directory - no preloaded apps
- FileUtils.deleteContents(mPreloadsAppsDirectory);
- mInstaller.installApps(TEST_DEMO_USER);
- assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
- "1",
- Settings.Secure.getStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
- }
-
- @Test
- public void testInstallApps_installationFails() throws Exception {
- mInstaller.installApps(TEST_DEMO_USER);
- for (int i = 0; i < mPreloadedAppPaths.size(); ++i) {
- ArgumentCaptor<IPackageInstallObserver2> observer =
- ArgumentCaptor.forClass(IPackageInstallObserver2.class);
- final String path = mPreloadedAppPaths.get(i);
- verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
- anyString(), eq(TEST_DEMO_USER));
- if (i == 0) {
- observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_FAILED_DEXOPT,
- null, null);
- continue;
- }
- observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
- null, null);
- // Verify that we try to install the package in system user.
- verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
- 0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
- }
- assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
- "1",
- Settings.Secure.getStringForUser(mContentResolver,
- Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
deleted file mode 100644
index a93f64396d57..000000000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.retaildemo;
-
-import static com.android.server.retaildemo.RetailDemoModeService.SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.app.ActivityManagerInternal;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.RetailDemoModeServiceInternal;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentProvider;
-import android.test.mock.MockContentResolver;
-import android.util.ArrayMap;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.SystemService;
-import com.android.server.retaildemo.RetailDemoModeService.Injector;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.compat.ArgumentMatcher;
-
-import java.io.File;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RetailDemoModeServiceTest {
- private static final int TEST_DEMO_USER = 111;
- private static final long SETUP_COMPLETE_TIMEOUT_MS = 2000; // 2 sec
- private static final String TEST_CAMERA_PKG = "test.cameraapp";
- private static final String TEST_PRELOADS_DIR_NAME = "test_preloads";
-
- private Context mContext;
- private @Mock UserManager mUm;
- private @Mock PackageManager mPm;
- private @Mock IPackageManager mIpm;
- private @Mock NotificationManager mNm;
- private @Mock ActivityManagerInternal mAmi;
- private @Mock AudioManager mAudioManager;
- private @Mock WifiManager mWifiManager;
- private @Mock LockPatternUtils mLockPatternUtils;
- private @Mock JobScheduler mJobScheduler;
- private MockPreloadAppsInstaller mPreloadAppsInstaller;
- private MockContentResolver mContentResolver;
- private MockContactsProvider mContactsProvider;
- private Configuration mConfiguration;
- private File mTestPreloadsDir;
- private CountDownLatch mLatch;
-
- private RetailDemoModeService mService;
- private TestInjector mInjector;
-
- @BeforeClass
- @AfterClass
- public static void clearSettingsProvider() {
- FakeSettingsProvider.clearSettingsProvider();
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
- when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn(
- Context.JOB_SCHEDULER_SERVICE);
- when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
- when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
- mContentResolver = new MockContentResolver(mContext);
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- mContactsProvider = new MockContactsProvider(mContext);
- mContentResolver.addProvider(CallLog.AUTHORITY, mContactsProvider);
- when(mContext.getContentResolver()).thenReturn(mContentResolver);
- mPreloadAppsInstaller = new MockPreloadAppsInstaller(mContext);
- mConfiguration = new Configuration();
- mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(),
- TEST_PRELOADS_DIR_NAME);
-
- Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
- Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
- Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1);
-
- // Initialize RetailDemoModeService
- mInjector = new TestInjector();
- mService = new RetailDemoModeService(mInjector);
- mService.onStart();
- }
-
- @After
- public void tearDown() {
- if (mTestPreloadsDir != null) {
- FileUtils.deleteContentsAndDir(mTestPreloadsDir);
- }
- }
-
- @Test
- public void testDemoUserSetup() throws Exception {
- mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
-
- mLatch = new CountDownLatch(1);
- final UserInfo userInfo = new UserInfo();
- userInfo.id = TEST_DEMO_USER;
- when(mUm.createUser(anyString(), anyInt())).thenReturn(userInfo);
-
- setCameraPackage(TEST_CAMERA_PKG);
- mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
- assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
- "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
- final ArgumentCaptor<IntentFilter> intentFilter =
- ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
- assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
- intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
-
- // Wait for the setup to complete.
- mLatch.await(SETUP_COMPLETE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- ArgumentCaptor<Integer> flags = ArgumentCaptor.forClass(Integer.class);
- verify(mUm).createUser(anyString(), flags.capture());
- assertTrue("FLAG_DEMO not set during user creation",
- (flags.getValue() & UserInfo.FLAG_DEMO) != 0);
- assertTrue("FLAG_EPHEMERAL not set during user creation",
- (flags.getValue() & UserInfo.FLAG_EPHEMERAL) != 0);
- // Verify if necessary restrictions are being set.
- final UserHandle user = UserHandle.of(TEST_DEMO_USER);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
- verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
- // Verify if necessary settings are updated.
- assertEquals("SKIP_FIRST_USE_HINTS setting is not set for demo user",
- Settings.Secure.getIntForUser(mContentResolver,
- Settings.Secure.SKIP_FIRST_USE_HINTS, TEST_DEMO_USER),
- 1);
- assertEquals("PACKAGE_VERIFIER_ENABLE settings should be set to 0 for demo user",
- Settings.Global.getInt(mContentResolver,
- Settings.Global.PACKAGE_VERIFIER_ENABLE),
- 0);
- // Verify if camera is granted location permission.
- verify(mPm).grantRuntimePermission(TEST_CAMERA_PKG,
- Manifest.permission.ACCESS_FINE_LOCATION, user);
- // Verify call logs are cleared.
- assertTrue("Call logs should be deleted", mContactsProvider.isCallLogDeleted());
- }
-
- @Test
- public void testSettingsObserver_disableDemoMode() throws Exception {
- final RetailDemoModeService.SettingsObserver observer =
- mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
- final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- when(mUm.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM))
- .thenReturn(false);
- Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
- // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
- observer.onChange(false, deviceDemoModeUri);
- final ArgumentCaptor<BroadcastReceiver> receiver =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
-
- Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
- new File(mTestPreloadsDir, "dir1").mkdirs();
- new File(mTestPreloadsDir, "file1").createNewFile();
- Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 0);
- observer.onChange(false, deviceDemoModeUri);
- verify(mContext).unregisterReceiver(receiver.getValue());
- verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, false, UserHandle.SYSTEM);
- assertEquals("Package verifier enable value has not been reset", 1,
- Settings.Global.getInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE));
- Thread.sleep(20); // Wait for the deletion to complete.
- // verify that the preloaded directory is emptied.
- assertEquals("Preloads directory is not emptied",
- 0, mTestPreloadsDir.list().length);
- // Verify that the expiration job was scheduled
- verify(mJobScheduler).schedule(any(JobInfo.class));
- }
-
- @Test
- public void testSettingsObserver_enableDemoMode() throws Exception {
- final RetailDemoModeService.SettingsObserver observer =
- mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
- final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
- observer.onChange(false, deviceDemoModeUri);
- assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
- "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
- final ArgumentCaptor<IntentFilter> intentFilter =
- ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
- assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
- intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
- }
-
- @Test
- public void testSwitchToDemoUser() {
- // To make the RetailDemoModeService update it's internal state.
- mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
- final RetailDemoModeService.SettingsObserver observer =
- mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
- observer.onChange(false, Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE));
-
- final UserInfo userInfo = new UserInfo(TEST_DEMO_USER, "demo_user",
- UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
- when(mUm.getUserInfo(TEST_DEMO_USER)).thenReturn(userInfo);
- when(mWifiManager.isWifiEnabled()).thenReturn(false);
- final int minVolume = -111;
- for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
- when(mAudioManager.getStreamMinVolume(stream)).thenReturn(minVolume);
- }
-
- mService.onSwitchUser(TEST_DEMO_USER);
- verify(mAmi).updatePersistentConfigurationForUser(mConfiguration, TEST_DEMO_USER);
- for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
- verify(mAudioManager).setStreamVolume(stream, minVolume, 0);
- }
- verify(mLockPatternUtils).setLockScreenDisabled(true, TEST_DEMO_USER);
- verify(mWifiManager).setWifiEnabled(true);
- }
-
- private void setCameraPackage(String pkgName) {
- final ResolveInfo ri = new ResolveInfo();
- final ActivityInfo ai = new ActivityInfo();
- ai.packageName = pkgName;
- ri.activityInfo = ai;
- when(mPm.resolveActivityAsUser(
- argThat(new IntentMatcher(MediaStore.ACTION_IMAGE_CAPTURE)),
- anyInt(),
- eq(TEST_DEMO_USER))).thenReturn(ri);
- }
-
- private class IntentMatcher extends ArgumentMatcher<Intent> {
- private final Intent mIntent;
-
- IntentMatcher(String action) {
- mIntent = new Intent(action);
- }
-
- @Override
- public boolean matchesObject(Object argument) {
- if (argument instanceof Intent) {
- return ((Intent) argument).filterEquals(mIntent);
- }
- return false;
- }
-
- @Override
- public String toString() {
- return "Expected: " + mIntent;
- }
- }
-
- private class MockContactsProvider extends MockContentProvider {
- private boolean mCallLogDeleted;
-
- MockContactsProvider(Context context) {
- super(context);
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- if (CallLog.Calls.CONTENT_URI.equals(uri)) {
- mCallLogDeleted = true;
- }
- return 0;
- }
-
- public boolean isCallLogDeleted() {
- return mCallLogDeleted;
- }
- }
-
- private class MockPreloadAppsInstaller extends PreloadAppsInstaller {
- MockPreloadAppsInstaller(Context context) {
- super(context);
- }
-
- @Override
- public void installApps(int userId) {
- }
- }
-
- private class TestInjector extends Injector {
- private ArrayMap<String, String> mSystemProperties = new ArrayMap<>();
-
- TestInjector() {
- super(mContext);
- }
-
- @Override
- Context getContext() {
- return mContext;
- }
-
- @Override
- UserManager getUserManager() {
- return mUm;
- }
-
- @Override
- WifiManager getWifiManager() {
- return mWifiManager;
- }
-
- @Override
- void switchUser(int userId) {
- if (mLatch != null) {
- mLatch.countDown();
- }
- }
-
- @Override
- AudioManager getAudioManager() {
- return mAudioManager;
- }
-
- @Override
- NotificationManager getNotificationManager() {
- return mNm;
- }
-
- @Override
- ActivityManagerInternal getActivityManagerInternal() {
- return mAmi;
- }
-
- @Override
- PackageManager getPackageManager() {
- return mPm;
- }
-
- @Override
- IPackageManager getIPackageManager() {
- return mIpm;
- }
-
- @Override
- ContentResolver getContentResolver() {
- return mContentResolver;
- }
-
- @Override
- PreloadAppsInstaller getPreloadAppsInstaller() {
- return mPreloadAppsInstaller;
- }
-
- @Override
- void systemPropertiesSet(String key, String value) {
- mSystemProperties.put(key, value);
- }
-
- @Override
- void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
- }
-
- @Override
- void initializeWakeLock() {
- }
-
- @Override
- void destroyWakeLock() {
- }
-
- @Override
- boolean isWakeLockHeld() {
- return false;
- }
-
- @Override
- void acquireWakeLock() {
- }
-
- @Override
- void releaseWakeLock() {
- }
-
- @Override
- void logSessionDuration(int duration) {
- }
-
- @Override
- void logSessionCount(int count) {
- }
-
- @Override
- Configuration getSystemUsersConfiguration() {
- return mConfiguration;
- }
-
- @Override
- LockPatternUtils getLockPatternUtils() {
- return mLockPatternUtils;
- }
-
- @Override
- Notification createResetNotification() {
- return null;
- }
-
- @Override
- File getDataPreloadsDirectory() {
- return mTestPreloadsDir;
- }
-
- @Override
- File getDataPreloadsFileCacheDirectory() {
- return new File(mTestPreloadsDir, "file_cache");
- }
-
- @Override
- void publishLocalService(RetailDemoModeService service,
- RetailDemoModeServiceInternal localService) {
- }
-
- String systemPropertiesGet(String key) {
- return mSystemProperties.get(key);
- }
- }
-}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8b3a804d35f9..0001d42f4329 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -26,6 +26,7 @@ import android.content.Context;
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 @@ public class CarrierConfigManager {
"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 @@ public class CarrierConfigManager {
/**
* 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 @@ public class CarrierConfigManager {
*
* @hide
*/
+ @Deprecated
public static final int DATA_CYCLE_USE_PLATFORM_DEFAULT = -1;
/**
@@ -1408,6 +1425,7 @@ public class CarrierConfigManager {
* 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 @@ public class CarrierConfigManager {
* <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 @@ public class CarrierConfigManager {
* <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 @@ public class CarrierConfigManager {
}
}
+ /** {@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 89c9134f2be2..503bf820c9a0 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -18,8 +18,8 @@ package android.telephony;
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 @@ public class SubscriptionManager {
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 @@ public class SubscriptionManager {
}
}
- /** {@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 @@ public class SubscriptionManager {
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 da7661aeb787..c9419c535b82 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -19,45 +19,31 @@ package android.telephony;
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 @@ public final class SubscriptionPlan implements Parcelable {
@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 @@ public final class SubscriptionPlan implements Parcelable {
@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 @@ public final class SubscriptionPlan implements Parcelable {
@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 final class SubscriptionPlan implements Parcelable {
}
};
- public @Type int getType() {
- return type;
- }
-
- public ZonedDateTime getStart() {
- return start;
- }
-
- public ZonedDateTime getEnd() {
- return end;
+ /** {@hide} */
+ public @NonNull RecurrenceRule getCycleRule() {
+ return cycleRule;
}
+ /** 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 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.
+ * 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() {
- 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;
- }
+ return cycleRule.cycleIterator();
}
+ /**
+ * Builder for a {@link SubscriptionPlan}.
+ */
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 (dataUsageTime < TIME_UNKNOWN) {
- throw new IllegalArgumentException("Time must be positive or TIME_UNKNOWN");
+ if (dataUsageBytes < 0) {
+ throw new IllegalArgumentException("Usage bytes must be positive");
}
- 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 d77b27f8295a..511573170bb0 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -28,4 +28,7 @@ interface ICarrierConfigLoader {
void notifyConfigChangedForSubId(int subId);
void updateConfigForPhoneId(int phoneId, String simState);
+
+ String getDefaultCarrierServicePackageName();
+
}