Merge "Remove call to Dependency.get() from BatteryControllerImpl."
diff --git a/Android.bp b/Android.bp
index 5070b5e..e7a3efc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -916,28 +916,6 @@
],
}
-// TODO: Don't rely on this list by switching package.html into package-info.java
-frameworks_base_subdirs = [
- "core/java",
- "graphics/java",
- "location/java",
- "media/java",
- "media/mca/effect/java",
- "media/mca/filterfw/java",
- "media/mca/filterpacks/java",
- "drm/java",
- "mms/java",
- "opengl/java",
- "sax/java",
- "telecomm/java",
- "telephony/common",
- "telephony/java",
- "wifi/java",
- "lowpan/java",
- "keystore/java",
- "rs/java",
-]
-
// Make the api/current.txt file available for use by modules in other
// directories.
filegroup {
@@ -1042,7 +1020,6 @@
"test-runner/src/**/*.java",
],
libs: framework_docs_only_libs,
- local_sourcepaths: frameworks_base_subdirs,
create_doc_stubs: true,
annotations_enabled: true,
api_levels_annotations_enabled: true,
@@ -1103,7 +1080,6 @@
":updatable-media-srcs",
],
libs: ["framework-internal-utils"],
- local_sourcepaths: frameworks_base_subdirs,
installable: false,
annotations_enabled: true,
previous_api: ":last-released-public-api-for-metalava-annotations",
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index e74e4a9..278a786 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -516,7 +516,7 @@
/** Creates a managed (work) profile under the current user, returning its userId. */
private int createManagedProfile() {
final UserInfo userInfo = mUm.createProfileForUser("TestProfile",
- UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
+ UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, mAm.getCurrentUser());
if (userInfo == null) {
throw new IllegalStateException("Creating managed profile failed. Most likely there is "
+ "already a pre-existing profile on the device.");
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4ee46f4..dfe7a90 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -1390,8 +1390,10 @@
private static final int MSG_FINISH_IDLE_OP = 8;
private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
- private static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
- private static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
+ @VisibleForTesting
+ static final int MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR = 11;
+ @VisibleForTesting
+ static final int MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR = 12;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -3327,8 +3329,7 @@
mHandler.sendEmptyMessage(MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR);
}
- @VisibleForTesting
- void updatePreIdleFactor() {
+ private void updatePreIdleFactor() {
synchronized (this) {
if (!shouldUseIdleTimeoutFactorLocked()) {
return;
@@ -3350,8 +3351,7 @@
}
}
- @VisibleForTesting
- void maybeDoImmediateMaintenance() {
+ private void maybeDoImmediateMaintenance() {
synchronized (this) {
if (mState == STATE_IDLE) {
long duration = SystemClock.elapsedRealtime() - mIdleStartTime;
@@ -3377,6 +3377,7 @@
void setIdleStartTimeForTest(long idleStartTime) {
synchronized (this) {
mIdleStartTime = idleStartTime;
+ maybeDoImmediateMaintenance();
}
}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index a0615aa..8a00c83 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -1179,7 +1179,7 @@
long token = Binder.clearCallingIdentity();
synchronized (this) {
if (mTelephony == null) {
- mTelephony = TelephonyManager.from(mContext);
+ mTelephony = mContext.getSystemService(TelephonyManager.class);
}
}
if (mTelephony != null) {
diff --git a/api/current.txt b/api/current.txt
index b1423b4..61013e8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4271,8 +4271,8 @@
method public android.app.AlertDialog show();
}
- public class AliasActivity extends android.app.Activity {
- ctor public AliasActivity();
+ @Deprecated public class AliasActivity extends android.app.Activity {
+ ctor @Deprecated public AliasActivity();
}
public class AppComponentFactory {
@@ -8445,6 +8445,7 @@
method public int describeContents();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp();
method public String getAddress();
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public String getAlias();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothClass getBluetoothClass();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getBondState();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public String getName();
@@ -8456,6 +8457,7 @@
field public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
field public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
field public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
+ field public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.action.ALIAS_CHANGED";
field public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";
field public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
field public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
@@ -9475,6 +9477,7 @@
method @Nullable public android.net.Uri canonicalize(@NonNull android.net.Uri);
method @NonNull public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
+ method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle);
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method @Nullable public final String getCallingFeatureId();
method @Nullable public final String getCallingPackage();
@@ -9485,6 +9488,7 @@
method @Nullable public abstract String getType(@NonNull android.net.Uri);
method @Nullable public final String getWritePermission();
method @Nullable public abstract android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues);
+ method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method protected boolean isTemporary();
method public void onConfigurationChanged(android.content.res.Configuration);
method public abstract boolean onCreate();
@@ -9510,6 +9514,7 @@
method public void shutdown();
method @Nullable public android.net.Uri uncanonicalize(@NonNull android.net.Uri);
method public abstract int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+ method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
}
public final class ContentProvider.CallingIdentity {
@@ -9528,10 +9533,12 @@
method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
method public void close();
method public int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
+ method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle) throws android.os.RemoteException;
method @Nullable public android.content.ContentProvider getLocalContentProvider();
method @Nullable public String[] getStreamTypes(@NonNull android.net.Uri, @NonNull String) throws android.os.RemoteException;
method @Nullable public String getType(@NonNull android.net.Uri) throws android.os.RemoteException;
method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues) throws android.os.RemoteException;
+ method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle) throws android.os.RemoteException;
method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException, android.os.RemoteException;
method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
method @Nullable public android.os.ParcelFileDescriptor openFile(@NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException, android.os.RemoteException;
@@ -9546,6 +9553,7 @@
method @Deprecated public boolean release();
method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
+ method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle) throws android.os.RemoteException;
}
public class ContentProviderOperation implements android.os.Parcelable {
@@ -9633,6 +9641,7 @@
method public static void cancelSync(android.content.SyncRequest);
method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri);
method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable String, @Nullable String[]);
+ method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.os.Bundle);
method @Deprecated public static android.content.SyncInfo getCurrentSync();
method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
method public static int getIsSyncable(android.accounts.Account, String);
@@ -9646,6 +9655,7 @@
method @Nullable public final String getType(@NonNull android.net.Uri);
method @NonNull public final android.content.ContentResolver.MimeTypeInfo getTypeInfo(@NonNull String);
method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues);
+ method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method public static boolean isSyncActive(android.accounts.Account, String);
method public static boolean isSyncPending(android.accounts.Account, String);
method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException;
@@ -9683,6 +9693,7 @@
method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri);
method public final void unregisterContentObserver(@NonNull android.database.ContentObserver);
method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+ method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
method public static void validateSyncExtrasBundle(android.os.Bundle);
method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
@@ -9695,12 +9706,16 @@
field public static final String EXTRA_TOTAL_COUNT = "android.content.extra.TOTAL_COUNT";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
+ field public static final String QUERY_ARG_GROUP_COLUMNS = "android:query-arg-group-columns";
field public static final String QUERY_ARG_LIMIT = "android:query-arg-limit";
field public static final String QUERY_ARG_OFFSET = "android:query-arg-offset";
field public static final String QUERY_ARG_SORT_COLLATION = "android:query-arg-sort-collation";
field public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
field public static final String QUERY_ARG_SORT_DIRECTION = "android:query-arg-sort-direction";
field public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
+ field public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by";
+ field public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having";
+ field public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit";
field public static final String QUERY_ARG_SQL_SELECTION = "android:query-arg-sql-selection";
field public static final String QUERY_ARG_SQL_SELECTION_ARGS = "android:query-arg-sql-selection-args";
field public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
@@ -30059,6 +30074,7 @@
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
+ method public boolean is6GHzBandSupported();
method @Deprecated public boolean isDeviceToApRttSupported();
method public boolean isEasyConnectSupported();
method public boolean isEnhancedOpenSupported();
@@ -39008,10 +39024,14 @@
field public static final String ACTION_VPN_SETTINGS = "android.settings.VPN_SETTINGS";
field public static final String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS";
field public static final String ACTION_WEBVIEW_SETTINGS = "android.settings.WEBVIEW_SETTINGS";
+ field public static final String ACTION_WIFI_ADD_NETWORKS = "android.settings.WIFI_ADD_NETWORKS";
field public static final String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
field public static final String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
field public static final String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
field public static final String ACTION_ZEN_MODE_PRIORITY_SETTINGS = "android.settings.ZEN_MODE_PRIORITY_SETTINGS";
+ field public static final int ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED = 1; // 0x1
+ field public static final int ADD_WIFI_RESULT_ALREADY_EXISTS = 2; // 0x2
+ field public static final int ADD_WIFI_RESULT_SUCCESS = 0; // 0x0
field public static final String AUTHORITY = "settings";
field public static final String EXTRA_ACCOUNT_TYPES = "account_types";
field public static final String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
@@ -39024,6 +39044,8 @@
field public static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
field public static final String EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME = "android.provider.extra.NOTIFICATION_LISTENER_COMPONENT_NAME";
field public static final String EXTRA_SUB_ID = "android.provider.extra.SUB_ID";
+ field public static final String EXTRA_WIFI_CONFIGURATION_LIST = "android.provider.extra.WIFI_CONFIGURATION_LIST";
+ field public static final String EXTRA_WIFI_CONFIGURATION_RESULT_LIST = "android.provider.extra.WIFI_CONFIGURATION_RESULT_LIST";
field public static final String INTENT_CATEGORY_USAGE_ACCESS_CONFIG = "android.intent.category.USAGE_ACCESS_CONFIG";
field public static final String METADATA_USAGE_ACCESS_REASON = "android.settings.metadata.USAGE_ACCESS_REASON";
}
@@ -45244,6 +45266,7 @@
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context);
method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList();
+ method @Nullable public java.util.List<android.telephony.SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList();
method public static int getActiveDataSubscriptionId();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount();
diff --git a/api/system-current.txt b/api/system-current.txt
index 62ab6d6..d91ecd4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1306,6 +1306,7 @@
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isEncrypted();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean removeBond();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setAlias(@NonNull String);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean);
@@ -2000,6 +2001,7 @@
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
+ method public boolean shouldCollectColorSamples();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
}
@@ -2012,6 +2014,7 @@
method public int getMaxCorrectionsByCategory();
method public int getMaxCorrectionsByPackageName();
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
}
public final class BrightnessCorrection implements android.os.Parcelable {
@@ -4846,7 +4849,7 @@
method public boolean isPortableHotspotSupported();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
- method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void registerSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback, @Nullable java.util.concurrent.Executor);
+ method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void registerSoftApCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback);
method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int);
@@ -8485,6 +8488,7 @@
public class SubscriptionInfo implements android.os.Parcelable {
method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
method public int getProfileClass();
+ method public boolean isGroupDisabled();
}
public class SubscriptionManager {
@@ -8567,6 +8571,7 @@
method @Deprecated public boolean getDataEnabled();
method @Deprecated public boolean getDataEnabled(int);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+ method @NonNull public static String getDefaultSimCountryIso();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
@@ -8598,7 +8603,9 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
+ method public boolean isModemEnabledForSlot(int);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
@@ -8619,6 +8626,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 44f736c..c6b02b9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1018,6 +1018,7 @@
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
+ method public boolean shouldCollectColorSamples();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
}
@@ -1030,6 +1031,7 @@
method public int getMaxCorrectionsByCategory();
method public int getMaxCorrectionsByPackageName();
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
}
public final class BrightnessCorrection implements android.os.Parcelable {
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 7e278e9..59544a9 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -508,7 +508,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.insert(resolveCallingPackage(), null, mUri, mContentValues);
+ provider.insert(resolveCallingPackage(), null, mUri, mContentValues, null);
}
}
@@ -522,7 +522,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.delete(resolveCallingPackage(), null, mUri, mWhere, null);
+ provider.delete(resolveCallingPackage(), null, mUri,
+ ContentResolver.createSqlQueryBundle(mWhere, null));
}
}
@@ -679,7 +680,8 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.update(resolveCallingPackage(), null, mUri, mContentValues, mWhere, null);
+ provider.update(resolveCallingPackage(), null, mUri, mContentValues,
+ ContentResolver.createSqlQueryBundle(mWhere, null));
}
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 8af925a..cf286e6 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -50,6 +50,7 @@
srcs: [
":statsd_aidl",
+ ":ICarStatsService.aidl",
"src/active_config_list.proto",
"src/anomaly/AlarmMonitor.cpp",
"src/anomaly/AlarmTracker.cpp",
@@ -64,6 +65,7 @@
"src/config/ConfigKey.cpp",
"src/config/ConfigListener.cpp",
"src/config/ConfigManager.cpp",
+ "src/external/CarStatsPuller.cpp",
"src/external/GpuStatsPuller.cpp",
"src/external/Perfetto.cpp",
"src/external/PowerStatsPuller.cpp",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c196c61..b0570fd 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -339,6 +339,7 @@
228 [(allow_from_any_uid) = true];
PerfettoUploaded perfetto_uploaded =
229 [(log_from_module) = "perfetto"];
+ VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
}
// Pulled events will start at field 10000.
@@ -408,6 +409,7 @@
SurfaceflingerStatsGlobalInfo surfaceflinger_stats_global_info = 10062;
SurfaceflingerStatsLayerInfo surfaceflinger_stats_layer_info = 10063;
ProcessMemorySnapshot process_memory_snapshot = 10064;
+ VmsClientStats vms_client_stats = 10065;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -3732,6 +3734,33 @@
optional Result result = 9;
}
+/**
+ * Logs when a Vehicle Maps Service client's connection state has changed
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/stats/VmsClientLog.java
+ */
+message VmsClientConnectionStateChanged {
+ // The UID of the VMS client app
+ optional int32 uid = 1 [(is_uid) = true];
+
+ enum State {
+ UNKNOWN = 0;
+ // Attempting to connect to the client
+ CONNECTING = 1;
+ // Client connection established
+ CONNECTED = 2;
+ // Client connection closed unexpectedly
+ DISCONNECTED = 3;
+ // Client connection closed by VMS
+ TERMINATED = 4;
+ // Error establishing the client connection
+ CONNECTION_ERROR = 5;
+ }
+
+ optional State state = 2;
+}
+
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
//////////////////////////////////////////////////////////////////////
@@ -7275,3 +7304,32 @@
optional int64 trace_uuid_lsb = 2;
optional int64 trace_uuid_msb = 3;
}
+
+/**
+ * Pulls client metrics on data transferred via Vehicle Maps Service.
+ * Metrics are keyed by uid + layer.
+ *
+ * Pulled from:
+ * packages/services/Car/service/src/com/android/car/stats/CarStatsService.java
+ */
+message VmsClientStats {
+ // UID of the VMS client app
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // VMS layer definition
+ optional int32 layer_type = 2;
+ optional int32 layer_channel = 3;
+ optional int32 layer_version = 4;
+
+ // Bytes and packets sent by the client for the layer
+ optional int64 tx_bytes = 5;
+ optional int64 tx_packets = 6;
+
+ // Bytes and packets received by the client for the layer
+ optional int64 rx_bytes = 7;
+ optional int64 rx_packets = 8;
+
+ // Bytes and packets dropped due to client error
+ optional int64 dropped_bytes = 9;
+ optional int64 dropped_packets = 10;
+}
diff --git a/cmds/statsd/src/external/CarStatsPuller.cpp b/cmds/statsd/src/external/CarStatsPuller.cpp
new file mode 100644
index 0000000..70c0456
--- /dev/null
+++ b/cmds/statsd/src/external/CarStatsPuller.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false
+#include "Log.h"
+
+#include <binder/IServiceManager.h>
+#include <com/android/internal/car/ICarStatsService.h>
+
+#include "CarStatsPuller.h"
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+
+using android::binder::Status;
+using com::android::internal::car::ICarStatsService;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+static std::mutex gCarStatsMutex;
+static sp<ICarStatsService> gCarStats = nullptr;
+
+class CarStatsDeathRecipient : public android::IBinder::DeathRecipient {
+ public:
+ CarStatsDeathRecipient() = default;
+ ~CarStatsDeathRecipient() override = default;
+
+ // android::IBinder::DeathRecipient override:
+ void binderDied(const android::wp<android::IBinder>& /* who */) override {
+ ALOGE("Car service has died");
+ std::lock_guard<std::mutex> lock(gCarStatsMutex);
+ if (gCarStats) {
+ sp<IBinder> binder = IInterface::asBinder(gCarStats);
+ binder->unlinkToDeath(this);
+ gCarStats = nullptr;
+ }
+ }
+};
+
+static sp<CarStatsDeathRecipient> gDeathRecipient = new CarStatsDeathRecipient();
+
+static sp<ICarStatsService> getCarService() {
+ std::lock_guard<std::mutex> lock(gCarStatsMutex);
+ if (!gCarStats) {
+ const sp<IBinder> binder = defaultServiceManager()->checkService(String16("car_stats"));
+ if (!binder) {
+ ALOGW("Car service is unavailable");
+ return nullptr;
+ }
+ gCarStats = interface_cast<ICarStatsService>(binder);
+ binder->linkToDeath(gDeathRecipient);
+ }
+ return gCarStats;
+}
+
+CarStatsPuller::CarStatsPuller(const int tagId) : StatsPuller(tagId) {
+}
+
+bool CarStatsPuller::PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) {
+ const sp<ICarStatsService> carService = getCarService();
+ if (!carService) {
+ return false;
+ }
+
+ vector<StatsLogEventWrapper> returned_value;
+ Status status = carService->pullData(mTagId, &returned_value);
+ if (!status.isOk()) {
+ ALOGW("CarStatsPuller::pull failed for %d", mTagId);
+ return false;
+ }
+
+ data->clear();
+ for (const StatsLogEventWrapper& it : returned_value) {
+ LogEvent::createLogEvents(it, *data);
+ }
+ VLOG("CarStatsPuller::pull succeeded for %d", mTagId);
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/CarStatsPuller.h b/cmds/statsd/src/external/CarStatsPuller.h
new file mode 100644
index 0000000..ca0f1a9
--- /dev/null
+++ b/cmds/statsd/src/external/CarStatsPuller.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Pull atoms from CarService.
+ */
+class CarStatsPuller : public StatsPuller {
+public:
+ explicit CarStatsPuller(const int tagId);
+ bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 5a76d1f..535fcfb 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -32,6 +32,7 @@
#include "../logd/LogEvent.h"
#include "../stats_log_util.h"
#include "../statscompanion_util.h"
+#include "CarStatsPuller.h"
#include "GpuStatsPuller.h"
#include "PowerStatsPuller.h"
#include "ResourceHealthManagerPuller.h"
@@ -272,6 +273,10 @@
{android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
{.puller =
new SurfaceflingerStatsPuller(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO)}},
+ // VmsClientStats
+ {android::util::VMS_CLIENT_STATS,
+ {.additiveFields = {5, 6, 7, 8, 9, 10},
+ .puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index db0bca0..a4b3058 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -376,7 +376,7 @@
private void runGetMaxPhones() throws RemoteException {
// This assumes the max number of SIMs is 2, which it currently is
if (TelephonyManager.MULTISIM_ALLOWED
- == mTelephonyService.isMultiSimSupported("com.android.commands.telecom")) {
+ == mTelephonyService.isMultiSimSupported("com.android.commands.telecom", null)) {
System.out.println("2");
} else {
System.out.println("1");
diff --git a/core/java/Android.bp b/core/java/Android.bp
index fb27f74..9a8e130 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -7,3 +7,8 @@
name: "IDropBoxManagerService.aidl",
srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],
}
+
+filegroup {
+ name: "ICarStatsService.aidl",
+ srcs: ["com/android/internal/car/ICarStatsService.aidl"],
+}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6d63fd09..590b3db 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -70,6 +70,7 @@
import android.util.DisplayMetrics;
import android.util.Singleton;
import android.util.Size;
+import android.view.IWindowContainer;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.procstats.ProcessStats;
@@ -2526,6 +2527,7 @@
// Index of the stack in the display's stack list, can be used for comparison of stack order
@UnsupportedAppUsage
public int position;
+ public IWindowContainer stackToken;
/**
* The full configuration the stack is currently running in.
* @hide
@@ -2559,6 +2561,7 @@
dest.writeInt(userId);
dest.writeInt(visible ? 1 : 0);
dest.writeInt(position);
+ dest.writeStrongInterface(stackToken);
if (topActivity != null) {
dest.writeInt(1);
topActivity.writeToParcel(dest, 0);
@@ -2590,6 +2593,7 @@
userId = source.readInt();
visible = source.readInt() > 0;
position = source.readInt();
+ stackToken = IWindowContainer.Stub.asInterface(source.readStrongBinder());
if (source.readInt() > 0) {
topActivity = ComponentName.readFromParcel(source);
}
diff --git a/core/java/android/app/AliasActivity.java b/core/java/android/app/AliasActivity.java
index 3756529..37be901 100644
--- a/core/java/android/app/AliasActivity.java
+++ b/core/java/android/app/AliasActivity.java
@@ -39,7 +39,10 @@
* To use this activity, you should include in the manifest for the associated
* component an entry named "android.app.alias". It is a reference to an XML
* resource describing an intent that launches the real application.
+ *
+ * @deprecated Use {@code <activity-alias>} or subclass Activity directly.
*/
+@Deprecated
public class AliasActivity extends Activity {
/**
* This is the name under which you should store in your component the
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 5661347..0113f69 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -92,7 +92,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
-import android.util.IconDrawableFactory;
import android.util.LauncherIcons;
import android.util.Log;
import android.view.Display;
@@ -1474,11 +1473,11 @@
@Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
- if (!isManagedProfile(user.getIdentifier())) {
+ if (!hasUserBadge(user.getIdentifier())) {
return icon;
}
Drawable badge = new LauncherIcons(mContext).getBadgeDrawable(
- com.android.internal.R.drawable.ic_corp_icon_badge_case,
+ getUserManager().getUserIconBadgeResId(user.getIdentifier()),
getUserBadgeColor(user));
return getBadgedDrawable(icon, badge, null, true);
}
@@ -1493,26 +1492,21 @@
return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
}
- @VisibleForTesting
- public static final int[] CORP_BADGE_LABEL_RES_ID = new int[] {
- com.android.internal.R.string.managed_profile_label_badge,
- com.android.internal.R.string.managed_profile_label_badge_2,
- com.android.internal.R.string.managed_profile_label_badge_3
- };
-
+ /** Returns the color of the user's actual badge (not the badge's shadow). */
private int getUserBadgeColor(UserHandle user) {
- return IconDrawableFactory.getUserBadgeColor(getUserManager(), user.getIdentifier());
+ return getUserManager().getUserBadgeColor(user.getIdentifier());
}
@Override
public Drawable getUserBadgeForDensity(UserHandle user, int density) {
- Drawable badgeColor = getManagedProfileIconForDensity(user,
+ // This is part of the shadow, not the main color, and is not actually corp-specific.
+ Drawable badgeColor = getProfileIconForDensity(user,
com.android.internal.R.drawable.ic_corp_badge_color, density);
if (badgeColor == null) {
return null;
}
Drawable badgeForeground = getDrawableForDensity(
- com.android.internal.R.drawable.ic_corp_badge_case, density);
+ getUserManager().getUserBadgeResId(user.getIdentifier()), density);
badgeForeground.setTint(getUserBadgeColor(user));
Drawable badge = new LayerDrawable(new Drawable[] {badgeColor, badgeForeground });
return badge;
@@ -1520,8 +1514,8 @@
@Override
public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
- Drawable badge = getManagedProfileIconForDensity(user,
- com.android.internal.R.drawable.ic_corp_badge_no_background, density);
+ Drawable badge = getProfileIconForDensity(user,
+ getUserManager().getUserBadgeNoBackgroundResId(user.getIdentifier()), density);
if (badge != null) {
badge.setTint(getUserBadgeColor(user));
}
@@ -1535,8 +1529,8 @@
return mContext.getResources().getDrawableForDensity(drawableId, density);
}
- private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
- if (isManagedProfile(user.getIdentifier())) {
+ private Drawable getProfileIconForDensity(UserHandle user, int drawableId, int density) {
+ if (hasUserBadge(user.getIdentifier())) {
return getDrawableForDensity(drawableId, density);
}
return null;
@@ -1544,12 +1538,7 @@
@Override
public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
- if (isManagedProfile(user.getIdentifier())) {
- int badge = getUserManager().getManagedProfileBadge(user.getIdentifier());
- int resourceId = CORP_BADGE_LABEL_RES_ID[badge % CORP_BADGE_LABEL_RES_ID.length];
- return Resources.getSystem().getString(resourceId, label);
- }
- return label;
+ return getUserManager().getBadgedLabelForUser(label, user);
}
@Override
@@ -2865,8 +2854,8 @@
return drawable;
}
- private boolean isManagedProfile(int userId) {
- return getUserManager().isManagedProfile(userId);
+ private boolean hasUserBadge(int userId) {
+ return getUserManager().hasBadge(userId);
}
/**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1e87ab1..4fb2196 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -171,8 +171,6 @@
import android.telephony.TelephonyRegistryManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
-import android.telephony.ims.ImsManager;
-import android.telephony.ims.RcsMessageManager;
import android.util.ArrayMap;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -625,22 +623,6 @@
return new SubscriptionManager(ctx.getOuterContext());
}});
- registerService(Context.TELEPHONY_RCS_MESSAGE_SERVICE, RcsMessageManager.class,
- new CachedServiceFetcher<RcsMessageManager>() {
- @Override
- public RcsMessageManager createService(ContextImpl ctx) {
- return new RcsMessageManager(ctx.getOuterContext());
- }
- });
-
- registerService(Context.TELEPHONY_IMS_SERVICE, ImsManager.class,
- new CachedServiceFetcher<ImsManager>() {
- @Override
- public ImsManager createService(ContextImpl ctx) {
- return new ImsManager(ctx.getOuterContext());
- }
- });
-
registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
new CachedServiceFetcher<CarrierConfigManager>() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c616044..19f42b6 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -173,13 +173,10 @@
* changed.
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
- *
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage
public static final String ACTION_ALIAS_CHANGED =
- "android.bluetooth.device.action.ALIAS_CHANGED";
+ "android.bluetooth.action.ALIAS_CHANGED";
/**
* Broadcast Action: Indicates a change in the bond state of a remote
@@ -1048,10 +1045,11 @@
* Get the Bluetooth alias of the remote device.
* <p>Alias is the locally modified name of a remote device.
*
- * @return the Bluetooth alias, or null if no alias or there was a problem
- * @hide
+ * @return the Bluetooth alias, the friendly device name if no alias, or
+ * null if there was a problem
*/
- @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.")
+ @Nullable
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public String getAlias() {
final IBluetooth service = sService;
if (service == null) {
@@ -1059,7 +1057,11 @@
return null;
}
try {
- return service.getRemoteAlias(this);
+ String alias = service.getRemoteAlias(this);
+ if (alias == null) {
+ return getName();
+ }
+ return alias;
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1076,8 +1078,9 @@
* @return true on success, false on error
* @hide
*/
- @UnsupportedAppUsage
- public boolean setAlias(String alias) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public boolean setAlias(@NonNull String alias) {
final IBluetooth service = sService;
if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
index 75e726b..0f67f6b 100644
--- a/core/java/android/companion/BluetoothDeviceFilterUtils.java
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -129,7 +129,7 @@
@UnsupportedAppUsage
public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) {
- return firstNotEmpty(device.getAliasName(), device.getAddress());
+ return firstNotEmpty(device.getAlias(), device.getAddress());
}
@UnsupportedAppUsage
diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java
index 197de97..5988dd3 100644
--- a/core/java/android/content/ContentInterface.java
+++ b/core/java/android/content/ContentInterface.java
@@ -53,23 +53,22 @@
public @Nullable Uri uncanonicalize(@NonNull Uri uri) throws RemoteException;
- public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
+ public boolean refresh(@NonNull Uri uri, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) throws RemoteException;
public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
throws RemoteException;
- public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
- throws RemoteException;
+ public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
+ @Nullable Bundle extras) throws RemoteException;
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] initialValues)
throws RemoteException;
- public int delete(@NonNull Uri uri, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException;
+ public int delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException;
- public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException;
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
+ throws RemoteException;
public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 17f1a07..2240823 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -299,7 +299,7 @@
@Override
public Uri insert(String callingPkg, @Nullable String featureId, Uri uri,
- ContentValues initialValues) {
+ ContentValues initialValues, Bundle extras) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = maybeGetUriWithoutUserId(uri);
@@ -317,7 +317,7 @@
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return maybeAddUserId(mInterface.insert(uri, initialValues), userId);
+ return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -403,8 +403,7 @@
}
@Override
- public int delete(String callingPkg, @Nullable String featureId, Uri uri, String selection,
- String[] selectionArgs) {
+ public int delete(String callingPkg, @Nullable String featureId, Uri uri, Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, featureId, uri, null)
@@ -415,7 +414,7 @@
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return mInterface.delete(uri, selection, selectionArgs);
+ return mInterface.delete(uri, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -426,7 +425,7 @@
@Override
public int update(String callingPkg, @Nullable String featureId, Uri uri,
- ContentValues values, String selection, String[] selectionArgs) {
+ ContentValues values, Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, featureId, uri, null)
@@ -437,7 +436,7 @@
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return mInterface.update(uri, values, selection, selectionArgs);
+ return mInterface.update(uri, values, extras);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -593,7 +592,7 @@
}
@Override
- public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle args,
+ public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle extras,
ICancellationSignal cancellationSignal) throws RemoteException {
uri = validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
@@ -605,7 +604,7 @@
final Pair<String, String> original = setCallingPackage(
new Pair<>(callingPkg, featureId));
try {
- return mInterface.refresh(uri, args,
+ return mInterface.refresh(uri, extras,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingPackage(original);
@@ -1494,29 +1493,34 @@
}
/**
- * Implement this to support refresh of content identified by {@code uri}. By default, this
- * method returns false; providers who wish to implement this should return true to signal the
- * client that the provider has tried refreshing with its own implementation.
+ * Implement this to support refresh of content identified by {@code uri}.
+ * By default, this method returns false; providers who wish to implement
+ * this should return true to signal the client that the provider has tried
+ * refreshing with its own implementation.
* <p>
- * This allows clients to request an explicit refresh of content identified by {@code uri}.
+ * This allows clients to request an explicit refresh of content identified
+ * by {@code uri}.
* <p>
- * Client code should only invoke this method when there is a strong indication (such as a user
- * initiated pull to refresh gesture) that the content is stale.
+ * Client code should only invoke this method when there is a strong
+ * indication (such as a user initiated pull to refresh gesture) that the
+ * content is stale.
* <p>
- * Remember to send {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)}
+ * Remember to send
+ * {@link ContentResolver#notifyChange(Uri, android.database.ContentObserver)}
* notifications when content changes.
*
* @param uri The Uri identifying the data to refresh.
- * @param args Additional options from the client. The definitions of these are specific to the
- * content provider being called.
- * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if
- * none. For example, if you called refresh on a particular uri, you should call
- * {@link CancellationSignal#throwIfCanceled()} to check whether the client has
- * canceled the refresh request.
+ * @param extras Additional options from the client. The definitions of
+ * these are specific to the content provider being called.
+ * @param cancellationSignal A signal to cancel the operation in progress,
+ * or {@code null} if none. For example, if you called refresh on
+ * a particular uri, you should call
+ * {@link CancellationSignal#throwIfCanceled()} to check whether
+ * the client has canceled the refresh request.
* @return true if the provider actually tried refreshing.
*/
@Override
- public boolean refresh(Uri uri, @Nullable Bundle args,
+ public boolean refresh(Uri uri, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) {
return false;
}
@@ -1545,20 +1549,42 @@
}
/**
- * Implement this to handle requests to insert a new row.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after inserting.
- * This method can be called from multiple threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * Implement this to handle requests to insert a new row. As a courtesy,
+ * call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after inserting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
+ *
* @param uri The content:// URI of the insertion request.
* @param values A set of column_name/value pairs to add to the database.
* @return The URI for the newly inserted item.
*/
- @Override
public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
/**
+ * Implement this to handle requests to insert a new row. As a courtesy,
+ * call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after inserting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * and Threads</a>.
+ *
+ * @param uri The content:// URI of the insertion request.
+ * @param values A set of column_name/value pairs to add to the database.
+ * @param extras A Bundle containing all additional information necessary
+ * for the insert.
+ * @return The URI for the newly inserted item.
+ */
+ @Override
+ public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable Bundle extras) {
+ return insert(uri, values);
+ }
+
+ /**
* Override this to handle requests to insert a set of new rows, or the
* default implementation will iterate over the values and call
* {@link #insert} on each of them.
@@ -1583,50 +1609,111 @@
}
/**
- * Implement this to handle requests to delete one or more rows.
- * The implementation should apply the selection clause when performing
+ * Implement this to handle requests to delete one or more rows. The
+ * implementation should apply the selection clause when performing
* deletion, allowing the operation to affect multiple rows in a directory.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after deleting.
- * This method can be called from multiple threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after deleting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
+ * <p>
+ * The implementation is responsible for parsing out a row ID at the end of
+ * the URI, if a specific row is being deleted. That is, the client would
+ * pass in <code>content://contacts/people/22</code> and the implementation
+ * is responsible for parsing the record number (22) when creating a SQL
+ * statement.
*
- * <p>The implementation is responsible for parsing out a row ID at the end
- * of the URI, if a specific row is being deleted. That is, the client would
- * pass in <code>content://contacts/people/22</code> and the implementation is
- * responsible for parsing the record number (22) when creating a SQL statement.
- *
- * @param uri The full URI to query, including a row ID (if a specific record is requested).
+ * @param uri The full URI to query, including a row ID (if a specific
+ * record is requested).
* @param selection An optional restriction to apply to rows when deleting.
* @return The number of rows affected.
* @throws SQLException
*/
- @Override
public abstract int delete(@NonNull Uri uri, @Nullable String selection,
@Nullable String[] selectionArgs);
/**
- * Implement this to handle requests to update one or more rows.
- * The implementation should update all rows matching the selection
- * to set the columns according to the provided values map.
- * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
- * after updating.
- * This method can be called from multiple threads, as described in
- * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * Implement this to handle requests to delete one or more rows. The
+ * implementation should apply the selection clause when performing
+ * deletion, allowing the operation to affect multiple rows in a directory.
+ * As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after deleting. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * and Threads</a>.
+ * <p>
+ * The implementation is responsible for parsing out a row ID at the end of
+ * the URI, if a specific row is being deleted. That is, the client would
+ * pass in <code>content://contacts/people/22</code> and the implementation
+ * is responsible for parsing the record number (22) when creating a SQL
+ * statement.
+ *
+ * @param uri The full URI to query, including a row ID (if a specific
+ * record is requested).
+ * @param extras A Bundle containing all additional information necessary
+ * for the delete. Values in the Bundle may include SQL style
+ * arguments.
+ * @return The number of rows affected.
+ * @throws SQLException
+ */
+ @Override
+ public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
+ extras = (extras != null) ? extras : Bundle.EMPTY;
+ return delete(uri,
+ extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION),
+ extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS));
+ }
+
+ /**
+ * Implement this to handle requests to update one or more rows. The
+ * implementation should update all rows matching the selection to set the
+ * columns according to the provided values map. As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after updating. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
*
- * @param uri The URI to query. This can potentially have a record ID if this
- * is an update request for a specific record.
+ * @param uri The URI to query. This can potentially have a record ID if
+ * this is an update request for a specific record.
* @param values A set of column_name/value pairs to update in the database.
* @param selection An optional filter to match rows to update.
* @return the number of rows affected.
*/
- @Override
public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
@Nullable String selection, @Nullable String[] selectionArgs);
/**
+ * Implement this to handle requests to update one or more rows. The
+ * implementation should update all rows matching the selection to set the
+ * columns according to the provided values map. As a courtesy, call
+ * {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver)
+ * notifyChange()} after updating. This method can be called from multiple
+ * threads, as described in <a href="
+ * {@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
+ * and Threads</a>.
+ *
+ * @param uri The URI to query. This can potentially have a record ID if
+ * this is an update request for a specific record.
+ * @param values A set of column_name/value pairs to update in the database.
+ * @param extras A Bundle containing all additional information necessary
+ * for the update. Values in the Bundle may include SQL style
+ * arguments.
+ * @return the number of rows affected.
+ */
+ @Override
+ public int update(@NonNull Uri uri, @Nullable ContentValues values,
+ @Nullable Bundle extras) {
+ extras = (extras != null) ? extras : Bundle.EMPTY;
+ return update(uri, values,
+ extras.getString(ContentResolver.QUERY_ARG_SQL_SELECTION),
+ extras.getStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS));
+ }
+
+ /**
* Override this to handle requests to open a file blob.
* The default implementation always throws {@link FileNotFoundException}.
* This method can be called from multiple threads, as described in
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index d2632e7..bb65aa0 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -286,7 +286,7 @@
/** See {@link ContentProvider#refresh} */
@Override
- public boolean refresh(Uri url, @Nullable Bundle args,
+ public boolean refresh(Uri url, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) throws RemoteException {
Preconditions.checkNotNull(url, "url");
@@ -298,7 +298,7 @@
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return mContentProvider.refresh(mPackageName, mFeatureId, url, args,
+ return mContentProvider.refresh(mPackageName, mFeatureId, url, extras,
remoteCancellationSignal);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -331,14 +331,20 @@
}
/** See {@link ContentProvider#insert ContentProvider.insert} */
- @Override
public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
throws RemoteException {
+ return insert(url, initialValues, null);
+ }
+
+ /** See {@link ContentProvider#insert ContentProvider.insert} */
+ @Override
+ public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues,
+ @Nullable Bundle extras) throws RemoteException {
Preconditions.checkNotNull(url, "url");
beforeRemote();
try {
- return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues);
+ return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -370,15 +376,19 @@
}
/** See {@link ContentProvider#delete ContentProvider.delete} */
- @Override
public int delete(@NonNull Uri url, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException {
+ return delete(url, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+ }
+
+ /** See {@link ContentProvider#delete ContentProvider.delete} */
+ @Override
+ public int delete(@NonNull Uri url, @Nullable Bundle extras) throws RemoteException {
Preconditions.checkNotNull(url, "url");
beforeRemote();
try {
- return mContentProvider.delete(mPackageName, mFeatureId, url, selection,
- selectionArgs);
+ return mContentProvider.delete(mPackageName, mFeatureId, url, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -390,15 +400,20 @@
}
/** See {@link ContentProvider#update ContentProvider.update} */
- @Override
public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
@Nullable String[] selectionArgs) throws RemoteException {
+ return update(url, values, ContentResolver.createSqlQueryBundle(selection, selectionArgs));
+ }
+
+ /** See {@link ContentProvider#update ContentProvider.update} */
+ @Override
+ public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable Bundle extras)
+ throws RemoteException {
Preconditions.checkNotNull(url, "url");
beforeRemote();
try {
- return mContentProvider.update(mPackageName, mFeatureId, url, values, selection,
- selectionArgs);
+ return mContentProvider.update(mPackageName, mFeatureId, url, values, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index f082690..dfa71f8 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -153,8 +153,9 @@
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
+ Bundle extras = data.readBundle();
- Uri out = insert(callingPkg, featureId, url, values);
+ Uri out = insert(callingPkg, featureId, url, values, extras);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -199,10 +200,9 @@
String callingPkg = data.readString();
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
+ Bundle extras = data.readBundle();
- int count = delete(callingPkg, featureId, url, selection, selectionArgs);
+ int count = delete(callingPkg, featureId, url, extras);
reply.writeNoException();
reply.writeInt(count);
@@ -216,11 +216,9 @@
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
- String selection = data.readString();
- String[] selectionArgs = data.readStringArray();
+ Bundle extras = data.readBundle();
- int count = update(callingPkg, featureId, url, values, selection,
- selectionArgs);
+ int count = update(callingPkg, featureId, url, values, extras);
reply.writeNoException();
reply.writeInt(count);
@@ -283,10 +281,10 @@
String authority = data.readString();
String method = data.readString();
String stringArg = data.readString();
- Bundle args = data.readBundle();
+ Bundle extras = data.readBundle();
Bundle responseBundle = call(callingPkg, featureId, authority, method,
- stringArg, args);
+ stringArg, extras);
reply.writeNoException();
reply.writeBundle(responseBundle);
@@ -370,11 +368,11 @@
String callingPkg = data.readString();
String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
- Bundle args = data.readBundle();
+ Bundle extras = data.readBundle();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- boolean out = refresh(callingPkg, featureId, url, args, signal);
+ boolean out = refresh(callingPkg, featureId, url, extras, signal);
reply.writeNoException();
reply.writeInt(out ? 0 : -1);
return true;
@@ -498,7 +496,7 @@
@Override
public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
- ContentValues values) throws RemoteException
+ ContentValues values, Bundle extras) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -509,6 +507,7 @@
data.writeString(featureId);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
@@ -573,8 +572,8 @@
}
@Override
- public int delete(String callingPkg, @Nullable String featureId, Uri url, String selection,
- String[] selectionArgs) throws RemoteException {
+ public int delete(String callingPkg, @Nullable String featureId, Uri url, Bundle extras)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
@@ -583,8 +582,7 @@
data.writeString(callingPkg);
data.writeString(featureId);
url.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
@@ -599,7 +597,7 @@
@Override
public int update(String callingPkg, @Nullable String featureId, Uri url,
- ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
+ ContentValues values, Bundle extras) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
@@ -609,8 +607,7 @@
data.writeString(featureId);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
- data.writeString(selection);
- data.writeStringArray(selectionArgs);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
@@ -682,7 +679,7 @@
@Override
public Bundle call(String callingPkg, @Nullable String featureId, String authority,
- String method, String request, Bundle args) throws RemoteException {
+ String method, String request, Bundle extras) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
@@ -693,7 +690,7 @@
data.writeString(authority);
data.writeString(method);
data.writeString(request);
- data.writeBundle(args);
+ data.writeBundle(extras);
mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
@@ -824,7 +821,7 @@
}
@Override
- public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
+ public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle extras,
ICancellationSignal signal) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -834,7 +831,7 @@
data.writeString(callingPkg);
data.writeString(featureId);
url.writeToParcel(data, 0);
- data.writeBundle(args);
+ data.writeBundle(extras);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
mRemote.transact(IContentProvider.REFRESH_TRANSACTION, data, reply, 0);
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 5c2de57..93f4287 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -357,11 +357,22 @@
ContentProviderResult[] backRefs, int numBackRefs)
throws OperationApplicationException {
final ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
- final Bundle extras = resolveExtrasBackReferences(backRefs, numBackRefs);
- final String[] selectionArgs = resolveSelectionArgsBackReferences(backRefs, numBackRefs);
+
+ // If the creator requested explicit selection or selectionArgs, it
+ // should take precedence over similar values they defined in extras
+ Bundle extras = resolveExtrasBackReferences(backRefs, numBackRefs);
+ if (mSelection != null) {
+ extras = (extras != null) ? extras : new Bundle();
+ extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, mSelection);
+ }
+ if (mSelectionArgs != null) {
+ extras = (extras != null) ? extras : new Bundle();
+ extras.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS,
+ resolveSelectionArgsBackReferences(backRefs, numBackRefs));
+ }
if (mType == TYPE_INSERT) {
- final Uri newUri = provider.insert(mUri, values);
+ final Uri newUri = provider.insert(mUri, values, extras);
if (newUri != null) {
return new ContentProviderResult(newUri);
} else {
@@ -375,9 +386,9 @@
final int numRows;
if (mType == TYPE_DELETE) {
- numRows = provider.delete(mUri, mSelection, selectionArgs);
+ numRows = provider.delete(mUri, extras);
} else if (mType == TYPE_UPDATE) {
- numRows = provider.update(mUri, values, mSelection, selectionArgs);
+ numRows = provider.update(mUri, values, extras);
} else if (mType == TYPE_ASSERT) {
// Assert that all rows match expected values
String[] projection = null;
@@ -389,7 +400,7 @@
}
projection = projectionList.toArray(new String[projectionList.size()]);
}
- final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null);
+ final Cursor cursor = provider.query(mUri, projection, extras, null);
try {
numRows = cursor.getCount();
if (projection != null) {
@@ -1013,6 +1024,10 @@
private void assertExtrasAllowed() {
switch (mType) {
+ case TYPE_INSERT:
+ case TYPE_UPDATE:
+ case TYPE_DELETE:
+ case TYPE_ASSERT:
case TYPE_CALL:
break;
default:
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 61c8db5d..d4280f8 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -304,31 +304,61 @@
*/
public static final String QUERY_ARG_SQL_SORT_ORDER = "android:query-arg-sql-sort-order";
- /** {@hide} */
+ /**
+ * Key for an SQL style {@code GROUP BY} string that may be present in the
+ * query Bundle argument passed to
+ * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
+ *
+ * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
+ * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
+ *
+ * @see #QUERY_ARG_GROUP_COLUMNS
+ */
public static final String QUERY_ARG_SQL_GROUP_BY = "android:query-arg-sql-group-by";
- /** {@hide} */
+
+ /**
+ * Key for an SQL style {@code HAVING} string that may be present in the
+ * query Bundle argument passed to
+ * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
+ *
+ * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
+ * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
+ */
public static final String QUERY_ARG_SQL_HAVING = "android:query-arg-sql-having";
- /** {@hide} */
+
+ /**
+ * Key for an SQL style {@code LIMIT} string that may be present in the
+ * query Bundle argument passed to
+ * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}.
+ *
+ * <p><b>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher are strongly
+ * encourage to use structured query arguments in lieu of opaque SQL query clauses.</b>
+ *
+ * @see #QUERY_ARG_LIMIT
+ * @see #QUERY_ARG_OFFSET
+ */
public static final String QUERY_ARG_SQL_LIMIT = "android:query-arg-sql-limit";
/**
- * Specifies the list of columns against which to sort results. When first column values
- * are identical, records are then sorted based on second column values, and so on.
- *
- * <p>Columns present in this list must also be included in the projection
- * supplied to {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
- *
- * <p>Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher:
- *
+ * Specifies the list of columns (stored as a {@code String[]}) against
+ * which to sort results. When first column values are identical, records
+ * are then sorted based on second column values, and so on.
+ * <p>
+ * Columns present in this list must also be included in the projection
+ * supplied to
+ * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
+ * <p>
+ * Apps targeting {@link android.os.Build.VERSION_CODES#O} or higher:
* <li>{@link ContentProvider} implementations: When preparing data in
- * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)}, if sort columns
- * is reflected in the returned Cursor, it is strongly recommended that
- * {@link #QUERY_ARG_SORT_COLUMNS} then be included in the array of honored arguments
- * reflected in {@link Cursor} extras {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
- *
- * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in the
- * arguments {@link Bundle}, the Content framework will attempt to synthesize
- * an QUERY_ARG_SQL* argument using the corresponding QUERY_ARG_SORT* values.
+ * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
+ * if sort columns is reflected in the returned Cursor, it is strongly
+ * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the
+ * array of honored arguments reflected in {@link Cursor} extras
+ * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
+ * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
+ * the arguments {@link Bundle}, the Content framework will attempt to
+ * synthesize an QUERY_ARG_SQL* argument using the corresponding
+ * QUERY_ARG_SORT* values.
*/
public static final String QUERY_ARG_SORT_COLUMNS = "android:query-arg-sort-columns";
@@ -402,6 +432,29 @@
public static final String QUERY_ARG_SORT_LOCALE = "android:query-arg-sort-locale";
/**
+ * Specifies the list of columns (stored as a {@code String[]}) against
+ * which to group results. When column values are identical, multiple
+ * records are collapsed together into a single record.
+ * <p>
+ * Columns present in this list must also be included in the projection
+ * supplied to
+ * {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}.
+ * <p>
+ * Apps targeting {@link android.os.Build.VERSION_CODES#R} or higher:
+ * <li>{@link ContentProvider} implementations: When preparing data in
+ * {@link ContentProvider#query(Uri, String[], Bundle, CancellationSignal)},
+ * if group columns is reflected in the returned Cursor, it is strongly
+ * recommended that {@link #QUERY_ARG_SORT_COLUMNS} then be included in the
+ * array of honored arguments reflected in {@link Cursor} extras
+ * {@link Bundle} under {@link #EXTRA_HONORED_ARGS}.
+ * <li>When querying a provider, where no QUERY_ARG_SQL* otherwise exists in
+ * the arguments {@link Bundle}, the Content framework will attempt to
+ * synthesize an QUERY_ARG_SQL* argument using the corresponding
+ * QUERY_ARG_SORT* values.
+ */
+ public static final String QUERY_ARG_GROUP_COLUMNS = "android:query-arg-group-columns";
+
+ /**
* Allows provider to report back to client which query keys are honored in a Cursor.
*
* <p>Key identifying a {@code String[]} containing all QUERY_ARG_SORT* arguments
@@ -415,6 +468,7 @@
* @see #QUERY_ARG_SORT_DIRECTION
* @see #QUERY_ARG_SORT_COLLATION
* @see #QUERY_ARG_SORT_LOCALE
+ * @see #QUERY_ARG_GROUP_COLUMNS
*/
public static final String EXTRA_HONORED_ARGS = "android.content.extra.HONORED_ARGS";
@@ -1127,28 +1181,31 @@
}
/**
- * This allows clients to request an explicit refresh of content identified by {@code uri}.
+ * This allows clients to request an explicit refresh of content identified
+ * by {@code uri}.
* <p>
- * Client code should only invoke this method when there is a strong indication (such as a user
- * initiated pull to refresh gesture) that the content is stale.
+ * Client code should only invoke this method when there is a strong
+ * indication (such as a user initiated pull to refresh gesture) that the
+ * content is stale.
* <p>
*
* @param url The Uri identifying the data to refresh.
- * @param args Additional options from the client. The definitions of these are specific to the
- * content provider being called.
- * @param cancellationSignal A signal to cancel the operation in progress, or {@code null} if
- * none. For example, if you called refresh on a particular uri, you should call
- * {@link CancellationSignal#throwIfCanceled()} to check whether the client has
- * canceled the refresh request.
+ * @param extras Additional options from the client. The definitions of
+ * these are specific to the content provider being called.
+ * @param cancellationSignal A signal to cancel the operation in progress,
+ * or {@code null} if none. For example, if you called refresh on
+ * a particular uri, you should call
+ * {@link CancellationSignal#throwIfCanceled()} to check whether
+ * the client has canceled the refresh request.
* @return true if the provider actually tried refreshing.
*/
@Override
- public final boolean refresh(@NonNull Uri url, @Nullable Bundle args,
+ public final boolean refresh(@NonNull Uri url, @Nullable Bundle extras,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(url, "url");
try {
- if (mWrapped != null) return mWrapped.refresh(url, args, cancellationSignal);
+ if (mWrapped != null) return mWrapped.refresh(url, extras, cancellationSignal);
} catch (RemoteException e) {
return false;
}
@@ -1165,7 +1222,7 @@
remoteCancellationSignal = provider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return provider.refresh(mPackageName, mFeatureId, url, args,
+ return provider.refresh(mPackageName, mFeatureId, url, extras,
remoteCancellationSignal);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -1856,13 +1913,30 @@
* @return the URL of the newly created row. May return <code>null</code> if the underlying
* content provider returns <code>null</code>, or if it crashes.
*/
- @Override
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
@Nullable ContentValues values) {
+ return insert(url, values, null);
+ }
+
+ /**
+ * Inserts a row into a table at the given URL.
+ *
+ * If the content provider supports transactions the insertion will be atomic.
+ *
+ * @param url The URL of the table to insert into.
+ * @param values The initial values for the newly inserted row. The key is the column name for
+ * the field. Passing an empty ContentValues will create an empty row.
+ * @param extras A Bundle containing all additional information necessary for the insert.
+ * @return the URL of the newly created row. May return <code>null</code> if the underlying
+ * content provider returns <code>null</code>, or if it crashes.
+ */
+ @Override
+ public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
+ @Nullable ContentValues values, @Nullable Bundle extras) {
Preconditions.checkNotNull(url, "url");
try {
- if (mWrapped != null) return mWrapped.insert(url, values);
+ if (mWrapped != null) return mWrapped.insert(url, values, extras);
} catch (RemoteException e) {
return null;
}
@@ -1873,7 +1947,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values);
+ Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
return createdRow;
@@ -1977,13 +2051,27 @@
(excluding the WHERE itself).
* @return The number of rows deleted.
*/
- @Override
public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,
@Nullable String[] selectionArgs) {
+ return delete(url, createSqlQueryBundle(where, selectionArgs));
+ }
+
+ /**
+ * Deletes row(s) specified by a content URI.
+ *
+ * If the content provider supports transactions, the deletion will be atomic.
+ *
+ * @param url The URL of the row to delete.
+ * @param extras A Bundle containing all additional information necessary for the delete.
+ * Values in the Bundle may include SQL style arguments.
+ * @return The number of rows deleted.
+ */
+ @Override
+ public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable Bundle extras) {
Preconditions.checkNotNull(url, "url");
try {
- if (mWrapped != null) return mWrapped.delete(url, where, selectionArgs);
+ if (mWrapped != null) return mWrapped.delete(url, extras);
} catch (RemoteException e) {
return 0;
}
@@ -1994,10 +2082,9 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, where,
- selectionArgs);
+ int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
+ maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
return rowsDeleted;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -2021,14 +2108,32 @@
* @return the number of rows updated.
* @throws NullPointerException if uri or values are null
*/
- @Override
public final int update(@RequiresPermission.Write @NonNull Uri uri,
@Nullable ContentValues values, @Nullable String where,
@Nullable String[] selectionArgs) {
+ return update(uri, values, createSqlQueryBundle(where, selectionArgs));
+ }
+
+ /**
+ * Update row(s) in a content URI.
+ *
+ * If the content provider supports transactions the update will be atomic.
+ *
+ * @param uri The URI to modify.
+ * @param values The new field values. The key is the column name for the field.
+ A null value will remove an existing field value.
+ * @param extras A Bundle containing all additional information necessary for the update.
+ * Values in the Bundle may include SQL style arguments.
+ * @return the number of rows updated.
+ * @throws NullPointerException if uri or values are null
+ */
+ @Override
+ public final int update(@RequiresPermission.Write @NonNull Uri uri,
+ @Nullable ContentValues values, @Nullable Bundle extras) {
Preconditions.checkNotNull(uri, "uri");
try {
- if (mWrapped != null) return mWrapped.update(uri, values, where, selectionArgs);
+ if (mWrapped != null) return mWrapped.update(uri, values, extras);
} catch (RemoteException e) {
return 0;
}
@@ -2039,10 +2144,9 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, where,
- selectionArgs);
+ int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
+ maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
return rowsUpdated;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -3589,6 +3693,15 @@
*/
public static @Nullable Bundle createSqlQueryBundle(
@Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ return createSqlQueryBundle(selection, selectionArgs, null);
+ }
+
+ /**
+ * @hide
+ */
+ public static @Nullable Bundle createSqlQueryBundle(
+ @Nullable String selection,
@Nullable String[] selectionArgs,
@Nullable String sortOrder) {
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index d2c97c4..1fb2958 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -48,10 +48,10 @@
+ "instead")
public default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
throws RemoteException {
- return insert(callingPkg, null, url, initialValues);
+ return insert(callingPkg, null, url, initialValues, null);
}
- public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues)
- throws RemoteException;
+ public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues,
+ Bundle extras) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
@@ -68,20 +68,22 @@
+ ".String[])} instead")
public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
throws RemoteException {
- return delete(callingPkg, null, url, selection, selectionArgs);
+ return delete(callingPkg, null, url,
+ ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
- public int delete(String callingPkg, String featureId, Uri url, String selection,
- String[] selectionArgs) throws RemoteException;
+ public int delete(String callingPkg, String featureId, Uri url, Bundle extras)
+ throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#update(android.net.Uri, android.content.ContentValues, java"
+ ".lang.String, java.lang.String[])} instead")
public default int update(String callingPkg, Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
- return update(callingPkg, null, url, values, selection, selectionArgs);
+ return update(callingPkg, null, url, values,
+ ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
public int update(String callingPkg, String featureId, Uri url, ContentValues values,
- String selection, String[] selectionArgs) throws RemoteException;
+ Bundle extras) throws RemoteException;
public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
String mode, ICancellationSignal signal, IBinder callerToken)
@@ -119,7 +121,7 @@
throws RemoteException;
public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
- @Nullable Bundle args, ICancellationSignal cancellationSignal) throws RemoteException;
+ @Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
// Data interchange.
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
diff --git a/core/java/android/content/LoggingContentInterface.java b/core/java/android/content/LoggingContentInterface.java
index 1df1c4f..3bd0832 100644
--- a/core/java/android/content/LoggingContentInterface.java
+++ b/core/java/android/content/LoggingContentInterface.java
@@ -178,11 +178,11 @@
}
@Override
- public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
- throws RemoteException {
- try (Logger l = new Logger("insert", uri, initialValues)) {
+ public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues,
+ @Nullable Bundle extras) throws RemoteException {
+ try (Logger l = new Logger("insert", uri, initialValues, extras)) {
try {
- return l.setResult(delegate.insert(uri, initialValues));
+ return l.setResult(delegate.insert(uri, initialValues, extras));
} catch (Exception res) {
l.setResult(res);
throw res;
@@ -204,11 +204,10 @@
}
@Override
- public int delete(@NonNull Uri uri, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException {
- try (Logger l = new Logger("delete", uri, selection, selectionArgs)) {
+ public int delete(@NonNull Uri uri, @Nullable Bundle extras) throws RemoteException {
+ try (Logger l = new Logger("delete", uri, extras)) {
try {
- return l.setResult(delegate.delete(uri, selection, selectionArgs));
+ return l.setResult(delegate.delete(uri, extras));
} catch (Exception res) {
l.setResult(res);
throw res;
@@ -217,11 +216,11 @@
}
@Override
- public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
- @Nullable String[] selectionArgs) throws RemoteException {
- try (Logger l = new Logger("update", uri, values, selection, selectionArgs)) {
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable Bundle extras)
+ throws RemoteException {
+ try (Logger l = new Logger("update", uri, values, extras)) {
try {
- return l.setResult(delegate.update(uri, values, selection, selectionArgs));
+ return l.setResult(delegate.update(uri, values, extras));
} catch (Exception res) {
l.setResult(res);
throw res;
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 1e88ce7..42d64d8 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.os.Parcel;
@@ -25,6 +26,8 @@
import android.os.UserManager;
import android.util.DebugUtils;
+import com.android.server.pm.UserTypeDetails;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -32,13 +35,13 @@
* Per-user information.
*
* <p>There are 3 base properties of users: {@link #FLAG_SYSTEM}, {@link #FLAG_FULL}, and
- * {@link #FLAG_MANAGED_PROFILE}. Every user must have one of the following combination of these
+ * {@link #FLAG_PROFILE}. Every user must have one of the following combination of these
* flags:
* <ul>
* <li>FLAG_SYSTEM (user {@link UserHandle#USER_SYSTEM} on a headless-user-0 device)</li>
* <li>FLAG_SYSTEM and FLAG_FULL (user {@link UserHandle#USER_SYSTEM} on a regular device)</li>
* <li>FLAG_FULL (non-profile secondary user)</li>
- * <li>FLAG_MANAGED_PROFILE (profile users)</li>
+ * <li>FLAG_PROFILE (profile users)</li>
* </ul>
* Users can have also have additional flags (such as FLAG_GUEST) as appropriate.
*
@@ -70,13 +73,17 @@
/**
* Indicates a guest user that may be transient.
+ * @deprecated Use {@link UserManager#USER_TYPE_FULL_GUEST} instead.
*/
+ @Deprecated
public static final int FLAG_GUEST = 0x00000004;
/**
* Indicates the user has restrictions in privileges, in addition to those for normal users.
* Exact meaning TBD. For instance, maybe they can't install apps or administer WiFi access pts.
+ * @deprecated Use {@link UserManager#USER_TYPE_FULL_RESTRICTED} instead.
*/
+ @Deprecated
public static final int FLAG_RESTRICTED = 0x00000008;
/**
@@ -87,7 +94,9 @@
/**
* Indicates that this user is a profile of another user, for example holding a users
* corporate data.
+ * @deprecated Use {@link UserManager#USER_TYPE_PROFILE_MANAGED} instead.
*/
+ @Deprecated
public static final int FLAG_MANAGED_PROFILE = 0x00000020;
/**
@@ -108,14 +117,16 @@
/**
* User is for demo purposes only and can be removed at any time.
+ * @deprecated Use {@link UserManager#USER_TYPE_FULL_DEMO} instead.
*/
+ @Deprecated
public static final int FLAG_DEMO = 0x00000200;
/**
* Indicates that this user is a non-profile human user.
*
* <p>When creating a new (non-system) user, this flag will always be forced true unless the
- * user is a {@link #FLAG_MANAGED_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
+ * user is a {@link #FLAG_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
* human user, it must also be flagged as FULL.
*/
public static final int FLAG_FULL = 0x00000400;
@@ -126,11 +137,10 @@
public static final int FLAG_SYSTEM = 0x00000800;
/**
- * Indicates that this user is some sort of profile. Right now, the only profile type is
- * {@link #FLAG_MANAGED_PROFILE}, but this can include other types of profiles too if any
- * are created in the future. This is therefore not a flag, but an OR of several flags.
+ * Indicates that this user is a profile human user, such as a managed profile.
+ * Mutually exclusive with {@link #FLAG_FULL}.
*/
- public static final int PROFILE_FLAGS_MASK = FLAG_MANAGED_PROFILE;
+ public static final int FLAG_PROFILE = 0x00001000;
/**
* @hide
@@ -147,7 +157,8 @@
FLAG_EPHEMERAL,
FLAG_DEMO,
FLAG_FULL,
- FLAG_SYSTEM
+ FLAG_SYSTEM,
+ FLAG_PROFILE
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserInfoFlag {
@@ -170,6 +181,13 @@
@UnsupportedAppUsage
public long lastLoggedInTime;
public String lastLoggedInFingerprint;
+
+ /**
+ * Type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}, corresponding to
+ * {@link UserTypeDetails#getName()}.
+ */
+ public String userType;
+
/**
* If this user is a parent user, it would be its own user id.
* If this user is a child user, it would be its parent user id.
@@ -178,7 +196,12 @@
@UnsupportedAppUsage
public int profileGroupId;
public int restrictedProfileParentId;
- /** Which profile badge color/label to use. */
+
+ /**
+ * Which badge color/label to use within a particular {@link UserTypeDetails}, i.e.
+ * the badgeIndex.
+ * This is an index for distinguishing different profiles with the same parent and user type.
+ */
public int profileBadge;
/** User is only partially created. */
@@ -199,21 +222,68 @@
*/
public boolean preCreated;
+ /**
+ * Creates a UserInfo whose user type is determined automatically by the flags according to
+ * {@link #getDefaultUserType}; can only be used for user types handled there.
+ */
@UnsupportedAppUsage
public UserInfo(int id, String name, int flags) {
this(id, name, null, flags);
}
+ /**
+ * Creates a UserInfo whose user type is determined automatically by the flags according to
+ * {@link #getDefaultUserType}; can only be used for user types handled there.
+ */
@UnsupportedAppUsage
public UserInfo(int id, String name, String iconPath, int flags) {
+ this(id, name, iconPath, flags, getDefaultUserType(flags));
+ }
+
+ public UserInfo(int id, String name, String iconPath, int flags, String userType) {
this.id = id;
this.name = name;
this.flags = flags;
+ this.userType = userType;
this.iconPath = iconPath;
this.profileGroupId = NO_PROFILE_GROUP_ID;
this.restrictedProfileParentId = NO_PROFILE_GROUP_ID;
}
+ /**
+ * Get the user type (such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}) that corresponds to
+ * the given {@link UserInfoFlag}s.
+
+ * <p>The userInfoFlag can contain GUEST, RESTRICTED, MANAGED_PROFILE, DEMO, or else be
+ * interpreted as a regular "secondary" user. It cannot contain more than one of these.
+ * It can contain other UserInfoFlag properties (like EPHEMERAL), which will be ignored here.
+ *
+ * @throws IllegalArgumentException if userInfoFlag is more than one type of user or if it
+ * is a SYSTEM user.
+ *
+ * @hide
+ */
+ public static @NonNull String getDefaultUserType(@UserInfoFlag int userInfoFlag) {
+ if ((userInfoFlag & FLAG_SYSTEM) != 0) {
+ throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
+ + Integer.toHexString(userInfoFlag) + " because it corresponds to a "
+ + "SYSTEM user type.");
+ }
+ final int supportedFlagTypes =
+ FLAG_GUEST | FLAG_RESTRICTED | FLAG_MANAGED_PROFILE | FLAG_DEMO;
+ switch (userInfoFlag & supportedFlagTypes) {
+ case 0 : return UserManager.USER_TYPE_FULL_SECONDARY;
+ case FLAG_GUEST: return UserManager.USER_TYPE_FULL_GUEST;
+ case FLAG_RESTRICTED: return UserManager.USER_TYPE_FULL_RESTRICTED;
+ case FLAG_MANAGED_PROFILE: return UserManager.USER_TYPE_PROFILE_MANAGED;
+ case FLAG_DEMO: return UserManager.USER_TYPE_FULL_DEMO;
+ default:
+ throw new IllegalArgumentException("Cannot getDefaultUserType for flags "
+ + Integer.toHexString(userInfoFlag) + " because it doesn't correspond to a "
+ + "valid user type.");
+ }
+ }
+
@UnsupportedAppUsage
public boolean isPrimary() {
return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
@@ -226,31 +296,21 @@
@UnsupportedAppUsage
public boolean isGuest() {
- return isGuest(flags);
- }
-
- /**
- * Checks if the flag denotes a guest user.
- */
- public static boolean isGuest(@UserInfoFlag int flags) {
- return (flags & FLAG_GUEST) == FLAG_GUEST;
+ return UserManager.isUserTypeGuest(userType);
}
@UnsupportedAppUsage
public boolean isRestricted() {
- return (flags & FLAG_RESTRICTED) == FLAG_RESTRICTED;
+ return UserManager.isUserTypeRestricted(userType);
+ }
+
+ public boolean isProfile() {
+ return (flags & FLAG_PROFILE) != 0;
}
@UnsupportedAppUsage
public boolean isManagedProfile() {
- return isManagedProfile(flags);
- }
-
- /**
- * Checks if the flag denotes a managed profile.
- */
- public static boolean isManagedProfile(@UserInfoFlag int flags) {
- return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
+ return UserManager.isUserTypeManagedProfile(userType);
}
@UnsupportedAppUsage
@@ -271,7 +331,7 @@
}
public boolean isDemo() {
- return (flags & FLAG_DEMO) == FLAG_DEMO;
+ return UserManager.isUserTypeDemo(userType);
}
public boolean isFull() {
@@ -304,7 +364,7 @@
// Don't support switching to an ephemeral user with removal in progress.
return false;
}
- return !isManagedProfile();
+ return !isProfile();
}
/**
@@ -316,9 +376,10 @@
return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
}
+ // TODO(b/142482943): Make this logic more specific and customizable. (canHaveProfile(userType))
/* @hide */
public boolean canHaveProfile() {
- if (isManagedProfile() || isGuest() || isRestricted()) {
+ if (isProfile() || isGuest() || isRestricted()) {
return false;
}
if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
@@ -336,6 +397,7 @@
iconPath = orig.iconPath;
id = orig.id;
flags = orig.flags;
+ userType = orig.userType;
serialNumber = orig.serialNumber;
creationTime = orig.creationTime;
lastLoggedInTime = orig.lastLoggedInTime;
@@ -353,6 +415,7 @@
return UserHandle.of(id);
}
+ // TODO(b/142482943): Probably include mUserType here, which means updating TestDevice, etc.
@Override
public String toString() {
// NOTE: do not change this string, it's used by 'pm list users', which in turn is
@@ -365,6 +428,7 @@
public String toFullString() {
return "UserInfo[id=" + id
+ ", name=" + name
+ + ", type=" + userType
+ ", flags=" + flagsToString(flags)
+ (preCreated ? " (pre-created)" : "")
+ (partial ? " (partial)" : "")
@@ -387,6 +451,7 @@
dest.writeString(name);
dest.writeString(iconPath);
dest.writeInt(flags);
+ dest.writeString(userType);
dest.writeInt(serialNumber);
dest.writeLong(creationTime);
dest.writeLong(lastLoggedInTime);
@@ -415,6 +480,7 @@
name = source.readString();
iconPath = source.readString();
flags = source.readInt();
+ userType = source.readString();
serialNumber = source.readInt();
creationTime = source.readLong();
lastLoggedInTime = source.readLong();
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index 21fcc63..a6a44be 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -79,7 +79,8 @@
/**
* Histogram counting how many times a pixel of a given value was displayed onscreen for the
* Value component of HSV if the device supports color sampling, if the device does not support
- * color sampling the value will be null.
+ * color sampling or {@link BrightnessConfiguration#shouldCollectColorSamples()} is false the
+ * value will be null.
*
* The buckets of the histogram are evenly weighted, the number of buckets is device specific.
* The units are in pixels * milliseconds, with 1 pixel millisecond being 1 pixel displayed
@@ -94,7 +95,8 @@
/**
* How many milliseconds of data are contained in the colorValueBuckets, if the device does
- * not support color sampling the value will be 0L.
+ * not support color sampling or {@link BrightnessConfiguration#shouldCollectColorSamples()} is
+ * false the value will be 0L.
*
* {@see #colorValueBuckets}
*/
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 4c2e297..139be8e 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -49,26 +49,31 @@
private static final String TAG_BRIGHTNESS_POINT = "brightness-point";
private static final String TAG_BRIGHTNESS_CORRECTIONS = "brightness-corrections";
private static final String TAG_BRIGHTNESS_CORRECTION = "brightness-correction";
+ private static final String TAG_BRIGHTNESS_PARAMS = "brightness-params";
private static final String ATTR_LUX = "lux";
private static final String ATTR_NITS = "nits";
private static final String ATTR_DESCRIPTION = "description";
private static final String ATTR_PACKAGE_NAME = "package-name";
private static final String ATTR_CATEGORY = "category";
+ private static final String ATTR_COLLECT_COLOR = "collect-color";
private final float[] mLux;
private final float[] mNits;
private final Map<String, BrightnessCorrection> mCorrectionsByPackageName;
private final Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
private final String mDescription;
+ private final boolean mShouldCollectColorSamples;
private BrightnessConfiguration(float[] lux, float[] nits,
Map<String, BrightnessCorrection> correctionsByPackageName,
- Map<Integer, BrightnessCorrection> correctionsByCategory, String description) {
+ Map<Integer, BrightnessCorrection> correctionsByCategory, String description,
+ boolean shouldCollectColorSamples) {
mLux = lux;
mNits = nits;
mCorrectionsByPackageName = correctionsByPackageName;
mCorrectionsByCategory = correctionsByCategory;
mDescription = description;
+ mShouldCollectColorSamples = shouldCollectColorSamples;
}
/**
@@ -119,6 +124,14 @@
return mDescription;
}
+ /**
+ * Returns whether color samples should be collected in
+ * {@link BrightnessChangeEvent#colorValueBuckets}.
+ */
+ public boolean shouldCollectColorSamples() {
+ return mShouldCollectColorSamples;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloatArray(mLux);
@@ -138,6 +151,7 @@
correction.writeToParcel(dest, flags);
}
dest.writeString(mDescription);
+ dest.writeBoolean(mShouldCollectColorSamples);
}
@Override
@@ -167,6 +181,7 @@
if (mDescription != null) {
sb.append(mDescription);
}
+ sb.append(", shouldCollectColorSamples = " + mShouldCollectColorSamples);
sb.append("'}");
return sb.toString();
}
@@ -181,6 +196,7 @@
if (mDescription != null) {
result = result * 31 + mDescription.hashCode();
}
+ result = result * 31 + Boolean.hashCode(mShouldCollectColorSamples);
return result;
}
@@ -196,7 +212,8 @@
return Arrays.equals(mLux, other.mLux) && Arrays.equals(mNits, other.mNits)
&& mCorrectionsByPackageName.equals(other.mCorrectionsByPackageName)
&& mCorrectionsByCategory.equals(other.mCorrectionsByCategory)
- && Objects.equals(mDescription, other.mDescription);
+ && Objects.equals(mDescription, other.mDescription)
+ && mShouldCollectColorSamples == other.mShouldCollectColorSamples;
}
public static final @android.annotation.NonNull Creator<BrightnessConfiguration> CREATOR =
@@ -224,6 +241,8 @@
final String description = in.readString();
builder.setDescription(description);
+ final boolean shouldCollectColorSamples = in.readBoolean();
+ builder.setShouldCollectColorSamples(shouldCollectColorSamples);
return builder.build();
}
@@ -252,6 +271,7 @@
serializer.endTag(null, TAG_BRIGHTNESS_POINT);
}
serializer.endTag(null, TAG_BRIGHTNESS_CURVE);
+
serializer.startTag(null, TAG_BRIGHTNESS_CORRECTIONS);
for (Map.Entry<String, BrightnessCorrection> entry :
mCorrectionsByPackageName.entrySet()) {
@@ -271,6 +291,12 @@
serializer.endTag(null, TAG_BRIGHTNESS_CORRECTION);
}
serializer.endTag(null, TAG_BRIGHTNESS_CORRECTIONS);
+
+ serializer.startTag(null, TAG_BRIGHTNESS_PARAMS);
+ if (mShouldCollectColorSamples) {
+ serializer.attribute(null, ATTR_COLLECT_COLOR, Boolean.toString(true));
+ }
+ serializer.endTag(null, TAG_BRIGHTNESS_PARAMS);
}
/**
@@ -293,6 +319,7 @@
List<Float> nitsList = new ArrayList<>();
Map<String, BrightnessCorrection> correctionsByPackageName = new HashMap<>();
Map<Integer, BrightnessCorrection> correctionsByCategory = new HashMap<>();
+ boolean shouldCollectColorSamples = false;
final int configDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, configDepth)) {
if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) {
@@ -307,8 +334,7 @@
luxList.add(lux);
nitsList.add(nits);
}
- }
- if (TAG_BRIGHTNESS_CORRECTIONS.equals(parser.getName())) {
+ } else if (TAG_BRIGHTNESS_CORRECTIONS.equals(parser.getName())) {
final int correctionsDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, correctionsDepth)) {
if (!TAG_BRIGHTNESS_CORRECTION.equals(parser.getName())) {
@@ -328,6 +354,9 @@
}
}
}
+ } else if (TAG_BRIGHTNESS_PARAMS.equals(parser.getName())) {
+ shouldCollectColorSamples =
+ Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_COLLECT_COLOR));
}
}
final int n = luxList.size();
@@ -350,6 +379,7 @@
final BrightnessCorrection correction = entry.getValue();
builder.addCorrectionByCategory(category, correction);
}
+ builder.setShouldCollectColorSamples(shouldCollectColorSamples);
return builder.build();
}
@@ -374,6 +404,7 @@
private Map<String, BrightnessCorrection> mCorrectionsByPackageName;
private Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
private String mDescription;
+ private boolean mShouldCollectColorSamples;
/**
* Constructs the builder with the control points for the brightness curve.
@@ -498,6 +529,19 @@
}
/**
+ * Control whether screen color samples should be returned in
+ * {@link BrightnessChangeEvent#colorValueBuckets} if supported by the device.
+ *
+ * @param shouldCollectColorSamples true if color samples should be collected.
+ * @return
+ */
+ @NonNull
+ public Builder setShouldCollectColorSamples(boolean shouldCollectColorSamples) {
+ mShouldCollectColorSamples = shouldCollectColorSamples;
+ return this;
+ }
+
+ /**
* Builds the {@link BrightnessConfiguration}.
*/
@NonNull
@@ -506,7 +550,7 @@
throw new IllegalStateException("A curve must be set!");
}
return new BrightnessConfiguration(mCurveLux, mCurveNits, mCorrectionsByPackageName,
- mCorrectionsByCategory, mDescription);
+ mCorrectionsByCategory, mDescription, mShouldCollectColorSamples);
}
private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 5bc9953..990c114 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -25,6 +25,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
@@ -152,6 +154,7 @@
* @return The {@link Builder} for chaining.
*/
public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
+ Preconditions.checkNotNull(dnsServers);
mDnsServers = dnsServers;
return this;
}
@@ -175,8 +178,10 @@
final StaticIpConfiguration config = new StaticIpConfiguration();
config.ipAddress = mIpAddress;
config.gateway = mGateway;
- for (InetAddress server : mDnsServers) {
- config.dnsServers.add(server);
+ if (mDnsServers != null) {
+ for (InetAddress server : mDnsServers) {
+ config.dnsServers.add(server);
+ }
}
config.domains = mDomains;
return config;
diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java
index 4e88149..aa0f622 100644
--- a/core/java/android/net/util/MultinetworkPolicyTracker.java
+++ b/core/java/android/net/util/MultinetworkPolicyTracker.java
@@ -94,7 +94,8 @@
}
};
- TelephonyManager.from(ctx).listen(new PhoneStateListener(handler.getLooper()) {
+ ctx.getSystemService(TelephonyManager.class).listen(
+ new PhoneStateListener(handler.getLooper()) {
@Override
public void onActiveDataSubscriptionIdChanged(int subId) {
mActiveSubId = subId;
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 400d981..89ccef6 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -161,7 +161,7 @@
try {
Application application = ActivityThread.currentApplication();
String callingPackage = application != null ? application.getPackageName() : null;
- return service.getSerialForPackage(callingPackage);
+ return service.getSerialForPackage(callingPackage, null);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/IDeviceIdentifiersPolicyService.aidl b/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
index 87d358f..d11aa0c 100644
--- a/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
+++ b/core/java/android/os/IDeviceIdentifiersPolicyService.aidl
@@ -21,5 +21,5 @@
*/
interface IDeviceIdentifiersPolicyService {
String getSerial();
- String getSerialForPackage(in String callingPackage);
-}
\ No newline at end of file
+ String getSerialForPackage(in String callingPackage, String callingFeatureId);
+}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index e8cc73f..40048d9 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -35,77 +35,84 @@
/*
* DO NOT MOVE - UserManager.h depends on the ordering of this function.
*/
- int getCredentialOwnerProfile(int userHandle);
- int getProfileParentId(int userHandle);
+ int getCredentialOwnerProfile(int userId);
+ int getProfileParentId(int userId);
/*
* END OF DO NOT MOVE
*/
- UserInfo createUser(in String name, int flags);
- UserInfo preCreateUser(int flags);
- UserInfo createProfileForUser(in String name, int flags, int userHandle,
+ UserInfo createUser(in String name, in String userType, int flags);
+ UserInfo preCreateUser(in String userType);
+ UserInfo createProfileForUser(in String name, in String userType, int flags, int userId,
in String[] disallowedPackages);
UserInfo createRestrictedProfile(String name, int parentUserHandle);
- void setUserEnabled(int userHandle);
+ void setUserEnabled(int userId);
void setUserAdmin(int userId);
- void evictCredentialEncryptionKey(int userHandle);
- boolean removeUser(int userHandle);
- boolean removeUserEvenWhenDisallowed(int userHandle);
- void setUserName(int userHandle, String name);
- void setUserIcon(int userHandle, in Bitmap icon);
- ParcelFileDescriptor getUserIcon(int userHandle);
+ void evictCredentialEncryptionKey(int userId);
+ boolean removeUser(int userId);
+ boolean removeUserEvenWhenDisallowed(int userId);
+ void setUserName(int userId, String name);
+ void setUserIcon(int userId, in Bitmap icon);
+ ParcelFileDescriptor getUserIcon(int userId);
UserInfo getPrimaryUser();
List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
- List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
+ List<UserInfo> getProfiles(int userId, boolean enabledOnly);
int[] getProfileIds(int userId, boolean enabledOnly);
- boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
- UserInfo getProfileParent(int userHandle);
- boolean isSameProfileGroup(int userHandle, int otherUserHandle);
+ boolean canAddMoreProfilesToUser(in String userType, int userId, boolean allowedToRemoveOne);
+ boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne);
+ UserInfo getProfileParent(int userId);
+ boolean isSameProfileGroup(int userId, int otherUserHandle);
+ String getUserTypeForUser(int userId);
@UnsupportedAppUsage
- UserInfo getUserInfo(int userHandle);
- String getUserAccount(int userHandle);
- void setUserAccount(int userHandle, String accountName);
- long getUserCreationTime(int userHandle);
+ UserInfo getUserInfo(int userId);
+ String getUserAccount(int userId);
+ void setUserAccount(int userId, String accountName);
+ long getUserCreationTime(int userId);
boolean isRestricted();
- boolean canHaveRestrictedProfile(int userHandle);
- int getUserSerialNumber(int userHandle);
+ boolean canHaveRestrictedProfile(int userId);
+ int getUserSerialNumber(int userId);
int getUserHandle(int userSerialNumber);
- int getUserRestrictionSource(String restrictionKey, int userHandle);
- List<UserManager.EnforcingUser> getUserRestrictionSources(String restrictionKey, int userHandle);
- Bundle getUserRestrictions(int userHandle);
- boolean hasBaseUserRestriction(String restrictionKey, int userHandle);
- boolean hasUserRestriction(in String restrictionKey, int userHandle);
+ int getUserRestrictionSource(String restrictionKey, int userId);
+ List<UserManager.EnforcingUser> getUserRestrictionSources(String restrictionKey, int userId);
+ Bundle getUserRestrictions(int userId);
+ boolean hasBaseUserRestriction(String restrictionKey, int userId);
+ boolean hasUserRestriction(in String restrictionKey, int userId);
boolean hasUserRestrictionOnAnyUser(in String restrictionKey);
boolean isSettingRestrictedForUser(in String setting, int userId, in String value, int callingUid);
void addUserRestrictionsListener(IUserRestrictionsListener listener);
- void setUserRestriction(String key, boolean value, int userHandle);
- void setApplicationRestrictions(in String packageName, in Bundle restrictions,
- int userHandle);
+ void setUserRestriction(String key, boolean value, int userId);
+ void setApplicationRestrictions(in String packageName, in Bundle restrictions, int userId);
Bundle getApplicationRestrictions(in String packageName);
- Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
+ Bundle getApplicationRestrictionsForUser(in String packageName, int userId);
void setDefaultGuestRestrictions(in Bundle restrictions);
Bundle getDefaultGuestRestrictions();
- boolean markGuestForDeletion(int userHandle);
- boolean isQuietModeEnabled(int userHandle);
- void setSeedAccountData(int userHandle, in String accountName,
+ boolean markGuestForDeletion(int userId);
+ boolean isQuietModeEnabled(int userId);
+ void setSeedAccountData(int userId, in String accountName,
in String accountType, in PersistableBundle accountOptions, boolean persist);
String getSeedAccountName();
String getSeedAccountType();
PersistableBundle getSeedAccountOptions();
void clearSeedAccountData();
boolean someUserHasSeedAccount(in String accountName, in String accountType);
+ boolean isProfile(int userId);
boolean isManagedProfile(int userId);
boolean isDemoUser(int userId);
boolean isPreCreated(int userId);
- UserInfo createProfileForUserEvenWhenDisallowed(in String name, int flags, int userHandle,
- in String[] disallowedPackages);
+ UserInfo createProfileForUserEvenWhenDisallowed(in String name, in String userType, int flags,
+ int userId, in String[] disallowedPackages);
boolean isUserUnlockingOrUnlocked(int userId);
- int getManagedProfileBadge(int userId);
+ int getUserIconBadgeResId(int userId);
+ int getUserBadgeResId(int userId);
+ int getUserBadgeNoBackgroundResId(int userId);
+ int getUserBadgeLabelResId(int userId);
+ int getUserBadgeColorResId(int userId);
+ boolean hasBadge(int userId);
boolean isUserUnlocked(int userId);
boolean isUserRunning(int userId);
- boolean isUserNameSet(int userHandle);
+ boolean isUserNameSet(int userId);
boolean hasRestrictedProfiles();
- boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
+ boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userId, in IntentSender target);
String getUserName();
long getUserStartRealtime();
long getUserUnlockRealtime();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index dd1f8c3..f18b4db 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -426,9 +426,15 @@
public static final int GO_TO_SLEEP_REASON_FORCE_SUSPEND = 8;
/**
+ * Go to sleep reason code: Going to sleep due to user inattentiveness.
* @hide
*/
- public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_FORCE_SUSPEND;
+ public static final int GO_TO_SLEEP_REASON_INATTENTIVE = 9;
+
+ /**
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_INATTENTIVE;
/**
* @hide
@@ -444,6 +450,7 @@
case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
+ case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive";
default: return Integer.toString(sleepReason);
}
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b096049..bb62eb2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -18,6 +18,8 @@
import android.Manifest;
import android.accounts.AccountManager;
+import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -76,6 +78,57 @@
private final Context mContext;
private Boolean mIsManagedProfileCached;
+ private Boolean mIsProfileCached;
+
+ /**
+ * User type representing a {@link UserHandle#USER_SYSTEM system} user that is a human user.
+ * This type of user cannot be created; it can only pre-exist on first boot.
+ * @hide
+ */
+ public static final String USER_TYPE_FULL_SYSTEM = "android.os.usertype.full.SYSTEM";
+
+ /**
+ * User type representing a regular non-profile non-{@link UserHandle#USER_SYSTEM system} human
+ * user.
+ * This is sometimes called an ordinary 'secondary user'.
+ * @hide
+ */
+ public static final String USER_TYPE_FULL_SECONDARY = "android.os.usertype.full.SECONDARY";
+
+ /**
+ * User type representing a guest user that may be transient.
+ * @hide
+ */
+ public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST";
+
+ /**
+ * User type representing a user for demo purposes only, which can be removed at any time.
+ * @hide
+ */
+ public static final String USER_TYPE_FULL_DEMO = "android.os.usertype.full.DEMO";
+
+ /**
+ * User type representing a "restricted profile" user, which is a full user that is subject to
+ * certain restrictions from a parent user. Note, however, that it is NOT technically a profile.
+ * @hide
+ */
+ public static final String USER_TYPE_FULL_RESTRICTED = "android.os.usertype.full.RESTRICTED";
+
+ /**
+ * User type representing a managed profile, which is a profile that is to be managed by a
+ * device policy controller (DPC).
+ * The intended purpose is for work profiles, which are managed by a corporate entity.
+ * @hide
+ */
+ public static final String USER_TYPE_PROFILE_MANAGED = "android.os.usertype.profile.MANAGED";
+
+ /**
+ * User type representing a {@link UserHandle#USER_SYSTEM system} user that is <b>not</b> a
+ * human user.
+ * This type of user cannot be created; it can only pre-exist on first boot.
+ * @hide
+ */
+ public static final String USER_TYPE_SYSTEM_HEADLESS = "android.os.usertype.system.HEADLESS";
/**
* @hide
@@ -1306,8 +1359,11 @@
mContext.getContentResolver(),
Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
boolean isSystemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
- boolean inCall = TelephonyManager.getDefault().getCallState()
- != TelephonyManager.CALL_STATE_IDLE;
+ boolean inCall = false;
+ TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+ if (telephonyManager != null) {
+ inCall = telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;
+ }
boolean isUserSwitchDisallowed = hasUserRestriction(DISALLOW_USER_SWITCH);
return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall
&& !isUserSwitchDisallowed;
@@ -1479,6 +1535,79 @@
}
/**
+ * Returns the calling user's user type.
+ *
+ * // TODO(b/142482943): Decide on the appropriate permission requirements.
+ *
+ * @return the name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
+ * @hide
+ */
+ public @NonNull String getUserType() {
+ try {
+ return mService.getUserTypeForUser(UserHandle.myUserId());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the given user's user type.
+ *
+ * // TODO(b/142482943): Decide on the appropriate permission requirements.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission, otherwise the caller
+ * must be in the same profile group of specified user.
+ *
+ * @param userHandle the user handle of the user whose type is being requested.
+ * @return the name of the user's user type, e.g. {@link UserManager#USER_TYPE_PROFILE_MANAGED},
+ * or {@code null} if there is no such user.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ public @Nullable String getUserTypeForUser(@NonNull UserHandle userHandle) {
+ try {
+ return mService.getUserTypeForUser(userHandle.getIdentifier());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the user type is a
+ * {@link UserManager#USER_TYPE_PROFILE_MANAGED managed profile}.
+ * @hide
+ */
+ public static boolean isUserTypeManagedProfile(String userType) {
+ return USER_TYPE_PROFILE_MANAGED.equals(userType);
+ }
+
+ /**
+ * Returns whether the user type is a {@link UserManager#USER_TYPE_FULL_GUEST guest user}.
+ * @hide
+ */
+ public static boolean isUserTypeGuest(String userType) {
+ return USER_TYPE_FULL_GUEST.equals(userType);
+ }
+
+ /**
+ * Returns whether the user type is a
+ * {@link UserManager#USER_TYPE_FULL_RESTRICTED restricted user}.
+ * @hide
+ */
+ public static boolean isUserTypeRestricted(String userType) {
+ return USER_TYPE_FULL_RESTRICTED.equals(userType);
+ }
+
+ /**
+ * Returns whether the user type is a {@link UserManager#USER_TYPE_FULL_DEMO demo user}.
+ * @hide
+ */
+ public static boolean isUserTypeDemo(String userType) {
+ return USER_TYPE_FULL_DEMO.equals(userType);
+ }
+
+ /**
* @hide
* @deprecated Use {@link #isRestrictedProfile()}
*/
@@ -1589,6 +1718,48 @@
}
/**
+ * Checks if the calling app is running in a profile.
+ *
+ * @return whether the caller is in a profile.
+ * @hide
+ */
+ public boolean isProfile() {
+ // No need for synchronization. Once it becomes non-null, it'll be non-null forever.
+ // Worst case we might end up calling the AIDL method multiple times but that's fine.
+ if (mIsProfileCached != null) {
+ return mIsProfileCached;
+ }
+ try {
+ mIsProfileCached = mService.isProfile(UserHandle.myUserId());
+ return mIsProfileCached;
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Checks if the specified user is a profile.
+ *
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission, otherwise the caller
+ * must be in the same profile group of specified user.
+ *
+ * @return whether the specified user is a profile.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ public boolean isProfile(@UserIdInt int userId) {
+ if (userId == UserHandle.myUserId()) {
+ return isProfile();
+ }
+ try {
+ return mService.isProfile(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ /**
* Checks if the calling app is running in a managed profile.
*
* @return whether the caller is in a managed profile.
@@ -1612,7 +1783,8 @@
/**
* Checks if the specified user is a managed profile.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission, otherwise the caller
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission, otherwise the caller
* must be in the same profile group of specified user.
*
* @return whether the specified user is a managed profile.
@@ -1632,23 +1804,6 @@
}
/**
- * Gets badge for a managed profile.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission, otherwise the caller
- * must be in the same profile group of specified user.
- *
- * @return which badge to use for the managed profile badge id will be less than
- * UserManagerService.getMaxManagedProfiles()
- * @hide
- */
- public int getManagedProfileBadge(@UserIdInt int userId) {
- try {
- return mService.getManagedProfileBadge(userId);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
* Checks if the calling app is running as an ephemeral user.
*
* @return whether the caller is an ephemeral user.
@@ -2120,23 +2275,44 @@
/**
* Creates a user with the specified name and options. For non-admin users, default user
+ * restrictions are going to be applied.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @param name the user's name
+ * @param flags UserInfo flags that identify the type of user and other properties.
+ * @see UserInfo
+ *
+ * @return the UserInfo object for the created user, or null if the user could not be created.
+ * @throws IllegalArgumentException if flags do not correspond to a valid user type.
+ * @deprecated Use {@link #createUser(String, String, int)} instead.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ @Deprecated
+ public @Nullable UserInfo createUser(@Nullable String name, @UserInfoFlag int flags) {
+ return createUser(name, UserInfo.getDefaultUserType(flags), flags);
+ }
+
+ /**
+ * Creates a user with the specified name and options. For non-admin users, default user
* restrictions will be applied.
*
* <p>Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
* @param name the user's name
- * @param flags UserInfo flags that identify the type of user and other properties.
+ * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_GUEST}.
+ * @param flags UserInfo flags that specify user properties.
* @see UserInfo
*
* @return the UserInfo object for the created user, or {@code null} if the user could not be
* created.
* @hide
*/
- @UnsupportedAppUsage
- public @Nullable UserInfo createUser(@Nullable String name, @UserInfoFlag int flags) {
+ public @Nullable UserInfo createUser(@Nullable String name, @NonNull String userType,
+ @UserInfoFlag int flags) {
UserInfo user = null;
try {
- user = mService.createUser(name, flags);
+ user = mService.createUser(name, userType, flags);
// TODO: Keep this in sync with
// UserManagerService.LocalService.createUserEvenWhenDisallowed
if (user != null && !user.isAdmin() && !user.isDemo()) {
@@ -2150,19 +2326,17 @@
}
/**
- * Pre-creates a user with the specified name and options. For non-admin users, default user
+ * Pre-creates a user of the specified type. For non-admin users, default user
* restrictions will be applied.
*
* <p>This method can be used by OEMs to "warm" up the user creation by pre-creating some users
* at the first boot, so they when the "real" user is created (for example,
- * by {@link #createUser(String, int)} or {@link #createGuest(Context, String)}), it takes
- * less time.
+ * by {@link #createUser(String, String, int)} or {@link #createGuest(Context, String)}), it
+ * takes less time.
*
* <p>Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
- * @param flags UserInfo flags that identify the type of user and other properties.
- * @see UserInfo
- *
+ * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_GUEST}.
* @return the UserInfo object for the created user, or {@code null} if the user could not be
* created.
*
@@ -2171,9 +2345,9 @@
*
* @hide
*/
- public @Nullable UserInfo preCreateUser(@UserInfoFlag int flags) {
+ public @Nullable UserInfo preCreateUser(@NonNull String userType) {
try {
- return mService.preCreateUser(flags);
+ return mService.preCreateUser(userType);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2188,7 +2362,7 @@
public UserInfo createGuest(Context context, String name) {
UserInfo guest = null;
try {
- guest = mService.createUser(name, UserInfo.FLAG_GUEST);
+ guest = mService.createUser(name, USER_TYPE_FULL_GUEST, 0);
if (guest != null) {
Settings.Secure.putStringForUser(context.getContentResolver(),
Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
@@ -2202,6 +2376,7 @@
/**
* Creates a user with the specified name and options as a profile of another user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * The type of profile must be specified using the given flags.
*
* @param name the user's name
* @param flags flags that identify the type of user and other properties.
@@ -2209,20 +2384,44 @@
*
* @return the {@link UserInfo} object for the created user, or null if the user
* could not be created.
+ * @throws IllegalArgumentException if flags do not correspond to a valid user type.
+ * @deprecated Use {@link #createProfileForUser(String, String, int, int)} instead.
* @hide
*/
@UnsupportedAppUsage
- public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId) {
- return createProfileForUser(name, flags, userId, null);
+ @Deprecated
+ public UserInfo createProfileForUser(String name, @UserInfoFlag int flags,
+ @UserIdInt int userId) {
+ return createProfileForUser(name, UserInfo.getDefaultUserType(flags), flags,
+ userId, null);
}
/**
- * Version of {@link #createProfileForUser(String, int, int)} that allows you to specify
+ * Creates a user with the specified name and options as a profile of another user.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @param name the user's name
+ * @param userType the type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
+ * @param flags UserInfo flags that specify user properties.
+ * @param userId new user will be a profile of this user.
+ *
+ * @return the {@link UserInfo} object for the created user, or null if the user
+ * could not be created.
+ * @hide
+ */
+ public UserInfo createProfileForUser(String name, @NonNull String userType,
+ @UserInfoFlag int flags, @UserIdInt int userId) {
+ return createProfileForUser(name, userType, flags, userId, null);
+ }
+
+ /**
+ * Version of {@link #createProfileForUser(String, String, int, int)} that allows you to specify
* any packages that should not be installed in the new profile by default, these packages can
* still be installed later by the user if needed.
*
* @param name the user's name
- * @param flags flags that identify the type of user and other properties.
+ * @param userType the type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
+ * @param flags UserInfo flags that specify user properties.
* @param userId new user will be a profile of this user.
* @param disallowedPackages packages that will not be installed in the profile being created.
*
@@ -2230,28 +2429,29 @@
* could not be created.
* @hide
*/
- public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId,
- String[] disallowedPackages) {
+ public UserInfo createProfileForUser(String name, @NonNull String userType,
+ @UserInfoFlag int flags, @UserIdInt int userId, String[] disallowedPackages) {
try {
- return mService.createProfileForUser(name, flags, userId, disallowedPackages);
+ return mService.createProfileForUser(name, userType, flags, userId, disallowedPackages);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
- * Similar to {@link #createProfileForUser(String, int, int, String[])}
+ * Similar to {@link #createProfileForUser(String, String, int, int, String[])}
* except bypassing the checking of {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
- * @see #createProfileForUser(String, int, int, String[])
+ * @see #createProfileForUser(String, String, int, int, String[])
* @hide
*/
- public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags,
- @UserIdInt int userId, String[] disallowedPackages) {
+ public UserInfo createProfileForUserEvenWhenDisallowed(String name,
+ @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId,
+ String[] disallowedPackages) {
try {
- return mService.createProfileForUserEvenWhenDisallowed(name, flags, userId,
- disallowedPackages);
+ return mService.createProfileForUserEvenWhenDisallowed(name, userType, flags,
+ userId, disallowedPackages);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2595,6 +2795,8 @@
* @hide
*/
public boolean canAddMoreUsers() {
+ // TODO(b/142482943): UMS has different logic, excluding Demo and Profile from counting. Why
+ // not here? The logic is inconsistent. See UMS.canAddMoreManagedProfiles
final List<UserInfo> users = getUsers(true);
final int totalUserCount = users.size();
int aliveUserCount = 0;
@@ -2625,6 +2827,22 @@
}
/**
+ * Checks whether it's possible to add more profiles of the given type to the given user.
+ *
+ * @param userType the type of user, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
+ * @return true if more profiles can be added, false if limit has been reached.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public boolean canAddMoreProfilesToUser(@NonNull String userType, @UserIdInt int userId) {
+ try {
+ return mService.canAddMoreProfilesToUser(userType, userId, false);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns list of the profiles of userId including userId itself.
* Note that this returns both enabled and not enabled profiles. See
* {@link #getEnabledProfiles(int)} if you need only the enabled ones.
@@ -2858,8 +3076,112 @@
}
/**
- * If the target user is a managed profile of the calling user or the caller
- * is itself a managed profile, then this returns a badged copy of the given
+ * Returns whether the given user has a badge (generally to put on profiles' icons).
+ *
+ * @param userId userId of the user in question
+ * @return true if the user's icons should display a badge; false otherwise.
+ *
+ * @see #getBadgedIconForUser more information about badging in general
+ * @hide
+ */
+ public boolean hasBadge(@UserIdInt int userId) {
+ if (!isProfile(userId)) {
+ // Since currently only profiles actually have badges, we can do this optimization.
+ return false;
+ }
+ try {
+ return mService.hasBadge(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the calling app's user has a badge (generally to put on profiles' icons).
+ *
+ * @return true if the user's icons should display a badge; false otherwise.
+ *
+ * @see #getBadgedIconForUser more information about badging in general
+ * @hide
+ */
+ public boolean hasBadge() {
+ return hasBadge(UserHandle.myUserId());
+ }
+
+ /**
+ * Returns the badge color for the given user (generally to color a profile's icon's badge).
+ *
+ * <p>To check whether a badge color is expected for the user, first call {@link #hasBadge}.
+ *
+ * @return the color (not the resource ID) to be used for the user's badge
+ * @throws Resources.NotFoundException if no valid badge color exists for this user
+ *
+ * @see #getBadgedIconForUser more information about badging in general
+ * @hide
+ */
+ public @ColorInt int getUserBadgeColor(@UserIdInt int userId) {
+ try {
+ final int resourceId = mService.getUserBadgeColorResId(userId);
+ return Resources.getSystem().getColor(resourceId, null);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the Resource ID of the user's icon badge.
+ *
+ * @return the Resource ID of the user's icon badge if it has one; otherwise
+ * {@link Resources#ID_NULL}.
+ *
+ * @see #getBadgedIconForUser more information about badging in general
+ * @hide
+ */
+ public @DrawableRes int getUserIconBadgeResId(@UserIdInt int userId) {
+ try {
+ return mService.getUserIconBadgeResId(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the Resource ID of the user's badge.
+ *
+ * @return the Resource ID of the user's badge if it has one; otherwise
+ * {@link Resources#ID_NULL}.
+ *
+ * @see #getBadgedIconForUser more information about badging in general
+ * @hide
+ */
+ public @DrawableRes int getUserBadgeResId(@UserIdInt int userId) {
+ try {
+ return mService.getUserBadgeResId(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the Resource ID of the user's badge without a background.
+ *
+ * @return the Resource ID of the user's no-background badge if it has one; otherwise
+ * {@link Resources#ID_NULL}.
+ *
+ * @see #getBadgedIconForUser more information about badging in general
+ * @hide
+ */
+ public @DrawableRes int getUserBadgeNoBackgroundResId(@UserIdInt int userId) {
+ try {
+ return mService.getUserBadgeNoBackgroundResId(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * If the target user is a profile of the calling user or the caller
+ * is itself a profile, then this returns a badged copy of the given
* icon to be able to distinguish it from the original icon. For badging an
* arbitrary drawable use {@link #getBadgedDrawableForUser(
* android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
@@ -2880,8 +3202,8 @@
}
/**
- * If the target user is a managed profile of the calling user or the caller
- * is itself a managed profile, then this returns a badged copy of the given
+ * If the target user is a profile of the calling user or the caller
+ * is itself a profile, then this returns a badged copy of the given
* drawable allowing the user to distinguish it from the original drawable.
* The caller can specify the location in the bounds of the drawable to be
* badged where the badge should be applied as well as the density of the
@@ -2911,11 +3233,15 @@
}
/**
- * If the target user is a managed profile of the calling user or the caller
- * is itself a managed profile, then this returns a copy of the label with
+ * If the target user is a profile of the calling user or the caller
+ * is itself a profile, then this returns a copy of the label with
* badging for accessibility services like talkback. E.g. passing in "Email"
* and it might return "Work Email" for Email in the work profile.
*
+ * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} or
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission, otherwise the caller
+ * must be in the same profile group of specified user.
+ *
* @param label The label to change.
* @param user The target user.
* @return A label that combines the original label and a badge as
@@ -2923,7 +3249,16 @@
* @removed
*/
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user) {
- return mContext.getPackageManager().getUserBadgedLabel(label, user);
+ final int userId = user.getIdentifier();
+ if (!hasBadge(userId)) {
+ return label;
+ }
+ try {
+ final int resourceId = mService.getUserBadgeLabelResId(userId);
+ return Resources.getSystem().getString(resourceId, label);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ac53f1b..3ac7deb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7707,6 +7707,20 @@
public static final String SLEEP_TIMEOUT = "sleep_timeout";
/**
+ * The timeout in milliseconds before the device goes to sleep due to user inattentiveness,
+ * even if the system is holding wakelocks. It should generally be longer than {@code
+ * config_attentiveWarningDuration}, as otherwise the device will show the attentive
+ * warning constantly. Small timeouts are discouraged, as they will cause the device to
+ * go to sleep quickly after waking up.
+ * <p>
+ * Use -1 to disable this timeout.
+ * </p>
+ *
+ * @hide
+ */
+ public static final String ATTENTIVE_TIMEOUT = "attentive_timeout";
+
+ /**
* Controls whether double tap to wake is enabled.
* @hide
*/
@@ -14085,6 +14099,77 @@
"android.settings.panel.action.VOLUME";
}
+ /**
+ * Activity Action: Show setting page to process the addition of Wi-Fi networks to the user's
+ * saved network list. The app should send a new intent with an extra that holds a maximum of
+ * five {@link android.net.wifi.WifiConfiguration} that specify credentials for the networks to
+ * be added to the user's database. The Intent should be sent via the {@link
+ * android.app.Activity#startActivityForResult(Intent, int)} API.
+ * <p>
+ * Note: The app sending the Intent to add the credentials doesn't get any ownership over the
+ * newly added network(s). For the Wi-Fi stack, these networks will look like the user
+ * manually added them from the Settings UI.
+ * <p>
+ * Input: The app should put parcelable array list to
+ * {@link android.net.wifi.WifiConfiguration} into the
+ * {@link #EXTRA_WIFI_CONFIGURATION_LIST} extra.
+ * <p>
+ * Output: After {@link android.app.Activity#startActivityForResult(Intent, int)}, the
+ * callback {@link android.app.Activity#onActivityResult(int, int, Intent)} will have a
+ * result code {@link android.app.Activity#RESULT_OK} to indicate user pressed the save
+ * button to save the networks or {@link android.app.Activity#RESULT_CANCELED} to indicate
+ * that the user rejected the request. Additionally, an integer array list, stored in
+ * {@link #EXTRA_WIFI_CONFIGURATION_RESULT_LIST}, will indicate the process result of
+ * each network.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_WIFI_ADD_NETWORKS =
+ "android.settings.WIFI_ADD_NETWORKS";
+
+ /**
+ * A bundle extra of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that indicates all the
+ * {@link android.net.wifi.WifiConfiguration} that would be saved.
+ */
+ public static final String EXTRA_WIFI_CONFIGURATION_LIST =
+ "android.provider.extra.WIFI_CONFIGURATION_LIST";
+
+ /**
+ * A bundle extra of the result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that
+ * indicates the action result of the saved {@link android.net.wifi.WifiConfiguration}. It's
+ * value of AddWifiResult interface, and will be 1:1 mapping to the element in {@link
+ * #EXTRA_WIFI_CONFIGURATION_LIST}.
+ */
+ public static final String EXTRA_WIFI_CONFIGURATION_RESULT_LIST =
+ "android.provider.extra.WIFI_CONFIGURATION_RESULT_LIST";
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"ADD_WIFI_RESULT_"}, value = {
+ ADD_WIFI_RESULT_SUCCESS,
+ ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED,
+ ADD_WIFI_RESULT_ALREADY_EXISTS
+ })
+ public @interface AddWifiResult {
+ }
+
+ /**
+ * A result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that saving or updating the
+ * corresponding Wi-Fi network was successful.
+ */
+ public static final int ADD_WIFI_RESULT_SUCCESS = 0;
+
+ /**
+ * A result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that saving the corresponding
+ * Wi-Fi network failed.
+ */
+ public static final int ADD_WIFI_RESULT_ADD_OR_UPDATE_FAILED = 1;
+
+ /**
+ * A result of {@link #ACTION_WIFI_ADD_NETWORKS} intent action that indicates the Wi-Fi network
+ * already exists.
+ */
+ public static final int ADD_WIFI_RESULT_ALREADY_EXISTS = 2;
+
private static final String[] PM_WRITE_SETTINGS = {
android.Manifest.permission.WRITE_SETTINGS
};
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 64d6124..a080091 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -15,7 +15,6 @@
*/
package android.telephony;
-import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Context;
@@ -23,8 +22,6 @@
import android.net.NetworkCapabilities;
import android.os.Binder;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.ApnType;
@@ -37,19 +34,12 @@
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
-import android.telephony.CallQuality;
-import android.telephony.CellInfo;
-import android.telephony.DisconnectCause;
-import android.telephony.PhoneCapability;
-import android.telephony.ServiceState;
-import android.telephony.SignalStrength;
-import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.util.Log;
-import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
+import com.android.internal.telephony.ITelephonyRegistry;
import java.util.HashMap;
import java.util.List;
@@ -120,7 +110,8 @@
};
mSubscriptionChangedListenerMap.put(listener, callback);
try {
- sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback);
+ sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+ mContext.getFeatureId(), callback);
} catch (RemoteException ex) {
// system server crash
}
@@ -179,7 +170,7 @@
mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
- callback);
+ mContext.getFeatureId(), callback);
} catch (RemoteException ex) {
// system server crash
}
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index df54209..993bbe8 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -663,11 +663,8 @@
private static void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s,
@Nullable Context context) {
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
- final TelephonyManager tm = (context == null)
- ? TelephonyManager.getDefault()
- : TelephonyManager.from(context);
Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
- tm.getSimCountryIso().toUpperCase(Locale.US),
+ TelephonyManager.getDefaultSimCountryIso().toUpperCase(Locale.US),
Leniency.POSSIBLE, Long.MAX_VALUE);
for (PhoneNumberMatch match : matches) {
LinkSpec spec = new LinkSpec();
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
index d90b65e..d86ebf3 100644
--- a/core/java/android/util/IconDrawableFactory.java
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -26,8 +26,6 @@
import android.os.UserHandle;
import android.os.UserManager;
-import com.android.internal.annotations.VisibleForTesting;
-
/**
* Utility class to load app drawables with appropriate badging.
*
@@ -78,10 +76,10 @@
com.android.internal.R.drawable.ic_instant_icon_badge_bolt,
badgeColor);
}
- if (mUm.isManagedProfile(userId)) {
+ if (mUm.hasBadge(userId)) {
icon = mLauncherIcons.getBadgedDrawable(icon,
- com.android.internal.R.drawable.ic_corp_icon_badge_case,
- getUserBadgeColor(mUm, userId));
+ mUm.getUserIconBadgeResId(userId),
+ mUm.getUserBadgeColor(userId));
}
return icon;
}
@@ -93,23 +91,6 @@
return mLauncherIcons.wrapIconDrawableWithShadow(icon);
}
- // Should have enough colors to cope with UserManagerService.getMaxManagedProfiles()
- @VisibleForTesting
- public static final int[] CORP_BADGE_COLORS = new int[] {
- com.android.internal.R.color.profile_badge_1,
- com.android.internal.R.color.profile_badge_2,
- com.android.internal.R.color.profile_badge_3
- };
-
- public static int getUserBadgeColor(UserManager um, @UserIdInt int userId) {
- int badge = um.getManagedProfileBadge(userId);
- if (badge < 0) {
- badge = 0;
- }
- int resourceId = CORP_BADGE_COLORS[badge % CORP_BADGE_COLORS.length];
- return Resources.getSystem().getColor(resourceId, null);
- }
-
@UnsupportedAppUsage
public static IconDrawableFactory newInstance(Context context) {
return new IconDrawableFactory(context, true);
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
index 8501eb5..e652e17 100644
--- a/core/java/android/util/LauncherIcons.java
+++ b/core/java/android/util/LauncherIcons.java
@@ -106,9 +106,11 @@
Resources overlayableRes =
ActivityThread.currentActivityThread().getApplication().getResources();
+ // ic_corp_icon_badge_shadow is not work-profile-specific.
Drawable badgeShadow = overlayableRes.getDrawable(
com.android.internal.R.drawable.ic_corp_icon_badge_shadow);
+ // ic_corp_icon_badge_color is not work-profile-specific.
Drawable badgeColor = overlayableRes.getDrawable(
com.android.internal.R.drawable.ic_corp_icon_badge_color)
.getConstantState().newDrawable().mutate();
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 36daa5c..a62ba63 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -415,6 +415,11 @@
private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";
private static final String REMOTE_COMMAND_DUMP = "DUMP";
private static final String REMOTE_COMMAND_DUMP_THEME = "DUMP_THEME";
+ /**
+ * Similar to REMOTE_COMMAND_DUMP but uses ViewHierarchyEncoder instead of flat text
+ * @hide
+ */
+ public static final String REMOTE_COMMAND_DUMP_ENCODED = "DUMP_ENCODED";
private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE";
private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
private static final String REMOTE_PROFILE = "PROFILE";
@@ -527,7 +532,6 @@
@UnsupportedAppUsage
static void dispatchCommand(View view, String command, String parameters,
OutputStream clientStream) throws IOException {
-
// Paranoid but safe...
view = view.getRootView();
@@ -535,6 +539,8 @@
dump(view, false, true, clientStream);
} else if (REMOTE_COMMAND_DUMP_THEME.equalsIgnoreCase(command)) {
dumpTheme(view, clientStream);
+ } else if (REMOTE_COMMAND_DUMP_ENCODED.equalsIgnoreCase(command)) {
+ dumpEncoded(view, clientStream);
} else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) {
captureLayers(view, new DataOutputStream(clientStream));
} else {
@@ -1198,6 +1204,18 @@
encoder.endStream();
}
+ private static void dumpEncoded(@NonNull final View view, @NonNull OutputStream out)
+ throws IOException {
+ ByteArrayOutputStream baOut = new ByteArrayOutputStream();
+
+ final ViewHierarchyEncoder encoder = new ViewHierarchyEncoder(baOut);
+ encoder.addProperty("window:left", view.mAttachInfo.mWindowLeft);
+ encoder.addProperty("window:top", view.mAttachInfo.mWindowTop);
+ view.encode(encoder);
+ encoder.endStream();
+ out.write(baOut.toByteArray());
+ }
+
/**
* Dumps the theme attributes from the given View.
* @hide
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index c11089b..49f77e1 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -194,7 +194,7 @@
private static Set<String> getSimCountries(Context context) {
Set<String> result = new HashSet<>();
- TelephonyManager tm = TelephonyManager.from(context);
+ TelephonyManager tm = context.getSystemService(TelephonyManager.class);
if (tm != null) {
String iso = tm.getSimCountryIso().toUpperCase(Locale.US);
diff --git a/core/java/com/android/internal/car/ICarStatsService.aidl b/core/java/com/android/internal/car/ICarStatsService.aidl
new file mode 100644
index 0000000..170b448
--- /dev/null
+++ b/core/java/com/android/internal/car/ICarStatsService.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.car;
+
+import android.os.StatsLogEventWrapper;
+
+/**
+ * Interface for pulling statsd atoms from automotive devices.
+ *
+ * @hide
+ */
+interface ICarStatsService {
+ /**
+ * Pull the specified atom. Results will be sent to statsd when complete.
+ */
+ StatsLogEventWrapper[] pullData(int atomId);
+}
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 5857642..045a680 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -133,7 +133,7 @@
boolean isChangeEnabledByUid(long changeId, int uid);
/**
- * Add overrides to compatibility changes.
+ * Add overrides to compatibility changes. Kills the app to allow the changes to take effect.
*
* @param overrides Parcelable containing the compat change overrides to be applied.
* @param packageName The package name of the app whose changes will be overridden.
@@ -142,7 +142,28 @@
void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
/**
- * Revert overrides to compatibility changes.
+ * Add overrides to compatibility changes. Doesn't kill the app, to be only used in tests.
+ *
+ * @param overrides Parcelable containing the compat change overrides to be applied.
+ * @param packageName The package name of the app whose changes will be overridden.
+ *
+ */
+ void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName);
+
+ /**
+ * Removes an override previously added via {@link #setOverrides(CompatibilityChangeConfig,
+ * String)}. This restores the default behaviour for the given change and app, once any app
+ * processes have been restarted.
+ * Kills the app to allow the changes to take effect.
+ *
+ * @param changeId The ID of the change that was overridden.
+ * @param packageName The app package name that was overridden.
+ * @return {@code true} if an override existed;
+ */
+ boolean clearOverride(long changeId, String packageName);
+
+ /**
+ * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
*
* @param packageName The package name of the app whose overrides will be cleared.
*
diff --git a/core/java/com/android/internal/package-info.java b/core/java/com/android/internal/package-info.java
new file mode 100644
index 0000000..8a226db
--- /dev/null
+++ b/core/java/com/android/internal/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * @hide
+ */
+package com.android.internal;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 73f549a..20706bb 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -188,4 +188,14 @@
* @param types the internal insets types of the bars are about to abort the transient state.
*/
void abortTransient(int displayId, in int[] types);
+
+ /**
+ * Show a warning that the device is about to go to sleep due to user inactivity.
+ */
+ void showInattentiveSleepWarning();
+
+ /**
+ * Dismiss the warning that the device is about to go to sleep due to user inactivity.
+ */
+ void dismissInattentiveSleepWarning();
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 3f08710..76235a4 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -113,4 +113,14 @@
void onBiometricError(int modality, int error, int vendorCode);
// Used to hide the authentication dialog, e.g. when the application cancels authentication
void hideAuthenticationDialog();
+
+ /**
+ * Show a warning that the device is about to go to sleep due to user inactivity.
+ */
+ void showInattentiveSleepWarning();
+
+ /**
+ * Dismiss the warning that the device is about to go to sleep due to user inactivity.
+ */
+ void dismissInattentiveSleepWarning();
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index d7a7af1..9ae0ba5 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -32,16 +32,22 @@
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
interface ITelephonyRegistry {
- void addOnSubscriptionsChangedListener(String pkg,
+ void addOnSubscriptionsChangedListener(String pkg, String featureId,
IOnSubscriptionsChangedListener callback);
- void addOnOpportunisticSubscriptionsChangedListener(String pkg,
+ void addOnOpportunisticSubscriptionsChangedListener(String pkg, String featureId,
IOnSubscriptionsChangedListener callback);
void removeOnSubscriptionsChangedListener(String pkg,
IOnSubscriptionsChangedListener callback);
+ /**
+ * @deprecated Use {@link #listenWithFeature(String, String, IPhoneStateListener, int,
+ * boolean) instead
+ */
@UnsupportedAppUsage
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
- void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events,
+ void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events,
boolean notifyNow);
+ void listenForSubscriber(in int subId, String pkg, String featureId,
+ IPhoneStateListener callback, int events, boolean notifyNow);
@UnsupportedAppUsage
void notifyCallStateForAllSubs(int state, String incomingNumber);
void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber);
diff --git a/core/java/com/android/server/pm/UserTypeDetails.java b/core/java/com/android/server/pm/UserTypeDetails.java
new file mode 100644
index 0000000..5fc3ba1
--- /dev/null
+++ b/core/java/com/android/server/pm/UserTypeDetails.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.ColorRes;
+import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+import android.content.pm.UserInfo;
+import android.content.pm.UserInfo.UserInfoFlag;
+import android.content.res.Resources;
+import android.os.UserManager;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Contains the details about a multiuser "user type", such as a
+ * {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
+ *
+ * Tests are located in UserManagerServiceUserTypeTest.java.
+ * @hide
+ */
+public final class UserTypeDetails {
+
+ /** Indicates that there is no limit to the number of users allowed. */
+ public static final int UNLIMITED_NUMBER_OF_USERS = -1;
+
+ /** Name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}. */
+ private final @NonNull String mName;
+
+ // TODO(b/142482943): Currently unused. Hook this up.
+ private final boolean mEnabled;
+
+ // TODO(b/142482943): Currently unused and not set. Hook this up.
+ private final int mLabel;
+
+ /**
+ * Maximum number of this user type allowed on the device.
+ * Use {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit.
+ */
+ private final int mMaxAllowed;
+
+ /**
+ * Maximum number of this user type allowed per parent (for user types, like profiles, that
+ * have parents).
+ * Use {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit.
+ */
+ // TODO(b/142482943): Should this also apply to restricted profiles?
+ private final int mMaxAllowedPerParent;
+
+ // TODO(b/143784345): Update doc when we clean up UserInfo.
+ /** The {@link UserInfo.UserInfoFlag} representing the base type of this user. */
+ private final @UserInfoFlag int mBaseType;
+
+ // TODO(b/143784345): Update doc/name when we clean up UserInfo.
+ /** The {@link UserInfo.UserInfoFlag}s that all users of this type will automatically have. */
+ private final @UserInfoFlag int mDefaultUserInfoPropertyFlags;
+
+ // TODO(b/142482943): Hook these up to something and set them for each type.
+ private final List<String> mDefaultRestrictions;
+
+
+ // Fields for profiles only, controlling the nature of their badges.
+ // All badge information should be set if {@link #hasBadge()} is true.
+
+ /** Resource ID of the badge put on icons. */
+ private @DrawableRes final int mIconBadge;
+ /** Resource ID of the badge. Should be set if mIconBadge is set. */
+ private @DrawableRes final int mBadgePlain;
+ /** Resource ID of the badge without a background. Should be set if mIconBadge is set. */
+ private @DrawableRes final int mBadgeNoBackground;
+
+ /**
+ * Resource ID ({@link StringRes}) of the of the labels to describe badged apps; should be the
+ * same format as com.android.internal.R.color.profile_badge_1. These are used for accessibility
+ * services.
+ *
+ * <p>This is an array because, in general, there may be multiple users of the same user type.
+ * In this case, the user is indexed according to its {@link UserInfo#profileBadge}.
+ *
+ * <p>Must be set if mIconBadge is set.
+ */
+ private final int[] mBadgeLabels;
+
+ /**
+ * Resource ID ({@link ColorRes}) of the colors badge put on icons.
+ * (The value is a resource ID referring to the color; it is not the color value itself).
+ *
+ * <p>This is an array because, in general, there may be multiple users of the same user type.
+ * In this case, the user is indexed according to its {@link UserInfo#profileBadge}.
+ *
+ * <p>Must be set if mIconBadge is set.
+ */
+ private final int[] mBadgeColors;
+
+ private UserTypeDetails(@NonNull String name, boolean enabled, int maxAllowed,
+ @UserInfoFlag int baseType, @UserInfoFlag int defaultUserInfoPropertyFlags, int label,
+ int maxAllowedPerParent,
+ int iconBadge, int badgePlain, int badgeNoBackground,
+ int[] badgeLabels, int[] badgeColors,
+ ArrayList<String> defaultRestrictions) {
+ this.mName = name;
+ this.mEnabled = enabled;
+ this.mMaxAllowed = maxAllowed;
+ this.mMaxAllowedPerParent = maxAllowedPerParent;
+ this.mBaseType = baseType;
+ this.mDefaultUserInfoPropertyFlags = defaultUserInfoPropertyFlags;
+ this.mDefaultRestrictions =
+ Collections.unmodifiableList(new ArrayList<>(defaultRestrictions));
+
+ this.mIconBadge = iconBadge;
+ this.mBadgePlain = badgePlain;
+ this.mBadgeNoBackground = badgeNoBackground;
+ this.mLabel = label;
+ this.mBadgeLabels = badgeLabels;
+ this.mBadgeColors = badgeColors;
+ }
+
+ /**
+ * Returns the name of the user type, such as {@link UserManager#USER_TYPE_PROFILE_MANAGED}.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ // TODO(b/142482943) Hook this up or delete it.
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ /**
+ * Returns the maximum number of this user type allowed on the device.
+ * <p>Returns {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit.
+ */
+ public int getMaxAllowed() {
+ return mMaxAllowed;
+ }
+
+ /**
+ * Returns the maximum number of this user type allowed per parent (for user types, like
+ * profiles, that have parents).
+ * <p>Returns {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit.
+ */
+ public int getMaxAllowedPerParent() {
+ return mMaxAllowedPerParent;
+ }
+
+ // TODO(b/143784345): Update comment when UserInfo is reorganized.
+ /** The {@link UserInfo.UserInfoFlag}s that all users of this type will automatically have. */
+ public int getDefaultUserInfoFlags() {
+ return mDefaultUserInfoPropertyFlags | mBaseType;
+ }
+
+ // TODO(b/142482943) Hook this up; it is currently unused.
+ public int getLabel() {
+ return mLabel;
+ }
+
+ /** Returns whether users of this user type should be badged. */
+ public boolean hasBadge() {
+ return mIconBadge != Resources.ID_NULL;
+ }
+
+ /** Resource ID of the badge put on icons. */
+ public @DrawableRes int getIconBadge() {
+ return mIconBadge;
+ }
+
+ /** Resource ID of the badge. Used for {@link UserManager#getUserBadgeResId(int)}. */
+ public @DrawableRes int getBadgePlain() {
+ return mBadgePlain;
+ }
+
+ /** Resource ID of the badge without a background. */
+ public @DrawableRes int getBadgeNoBackground() {
+ return mBadgeNoBackground;
+ }
+
+ /**
+ * Returns the Resource ID of the badgeIndexth badge label, where the badgeIndex is expected
+ * to be the {@link UserInfo#profileBadge} of the user.
+ * If badgeIndex exceeds the number of labels, returns the label for the highest index.
+ */
+ public @StringRes int getBadgeLabel(int badgeIndex) {
+ if (mBadgeLabels == null || mBadgeLabels.length == 0 || badgeIndex < 0) {
+ return Resources.ID_NULL;
+ }
+ return mBadgeLabels[Math.min(badgeIndex, mBadgeLabels.length - 1)];
+ }
+
+ /**
+ * Returns the Resource ID of the badgeIndexth badge color, where the badgeIndex is expected
+ * to be the {@link UserInfo#profileBadge} of the user.
+ * If badgeIndex exceeds the number of colors, returns the color for the highest index.
+ */
+ public @ColorRes int getBadgeColor(int badgeIndex) {
+ if (mBadgeColors == null || mBadgeColors.length == 0 || badgeIndex < 0) {
+ return Resources.ID_NULL;
+ }
+ return mBadgeColors[Math.min(badgeIndex, mBadgeColors.length - 1)];
+ }
+
+ public boolean isProfile() {
+ return (mBaseType & UserInfo.FLAG_PROFILE) != 0;
+ }
+
+ // TODO(b/142482943): Hook this up and don't return the original.
+ public List<String> getDefaultRestrictions() {
+ return mDefaultRestrictions;
+ }
+
+ /** Dumps details of the UserTypeDetails. Do not parse this. */
+ public void dump(PrintWriter pw) {
+ final String prefix = " ";
+ pw.print(prefix); pw.print("mName: "); pw.println(mName);
+ pw.print(prefix); pw.print("mBaseType: "); pw.println(UserInfo.flagsToString(mBaseType));
+ pw.print(prefix); pw.print("mEnabled: "); pw.println(mEnabled);
+ pw.print(prefix); pw.print("mMaxAllowed: "); pw.println(mMaxAllowed);
+ pw.print(prefix); pw.print("mMaxAllowedPerParent: "); pw.println(mMaxAllowedPerParent);
+ pw.print(prefix); pw.print("mDefaultUserInfoFlags: ");
+ pw.println(UserInfo.flagsToString(mDefaultUserInfoPropertyFlags));
+ pw.print(prefix); pw.print("mLabel: "); pw.println(mLabel);
+ pw.print(prefix); pw.print("mDefaultRestrictions: "); pw.println(mDefaultRestrictions);
+ pw.print(prefix); pw.print("mIconBadge: "); pw.println(mIconBadge);
+ pw.print(prefix); pw.print("mBadgePlain: "); pw.println(mBadgePlain);
+ pw.print(prefix); pw.print("mBadgeNoBackground: "); pw.println(mBadgeNoBackground);
+ pw.print(prefix); pw.print("mBadgeLabels.length: ");
+ pw.println(mBadgeLabels != null ? mBadgeLabels.length : "0(null)");
+ pw.print(prefix); pw.print("mBadgeColors.length: ");
+ pw.println(mBadgeColors != null ? mBadgeColors.length : "0(null)");
+ }
+
+ /** Builder for a {@link UserTypeDetails}; see that class for documentation. */
+ public static final class Builder {
+ // UserTypeDetails properties and their default values.
+ private String mName; // This MUST be explicitly set.
+ private int mBaseType; // This MUST be explicitly set.
+ private int mMaxAllowed = UNLIMITED_NUMBER_OF_USERS;
+ private int mMaxAllowedPerParent = UNLIMITED_NUMBER_OF_USERS;
+ private int mDefaultUserInfoPropertyFlags = 0;
+ private ArrayList<String> mDefaultRestrictions = new ArrayList<>();
+ private boolean mEnabled = true;
+ private int mLabel = Resources.ID_NULL;
+ private int[] mBadgeLabels = null;
+ private int[] mBadgeColors = null;
+ private int mIconBadge = Resources.ID_NULL;
+ private int mBadgePlain = Resources.ID_NULL;
+ private int mBadgeNoBackground = Resources.ID_NULL;
+
+ public Builder setName(String name) {
+ mName = name;
+ return this;
+ }
+
+ public Builder setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ return this;
+ }
+
+ public Builder setMaxAllowed(int maxAllowed) {
+ mMaxAllowed = maxAllowed;
+ return this;
+ }
+
+ public Builder setMaxAllowedPerParent(int maxAllowedPerParent) {
+ mMaxAllowedPerParent = maxAllowedPerParent;
+ return this;
+ }
+
+ public Builder setBaseType(@UserInfoFlag int baseType) {
+ mBaseType = baseType;
+ return this;
+ }
+
+ public Builder setDefaultUserInfoPropertyFlags(@UserInfoFlag int flags) {
+ mDefaultUserInfoPropertyFlags = flags;
+ return this;
+ }
+
+ public Builder setBadgeLabels(int ... badgeLabels) {
+ mBadgeLabels = badgeLabels;
+ return this;
+ }
+
+ public Builder setBadgeColors(int ... badgeColors) {
+ mBadgeColors = badgeColors;
+ return this;
+ }
+
+ public Builder setIconBadge(int badgeIcon) {
+ mIconBadge = badgeIcon;
+ return this;
+ }
+
+ public Builder setBadgePlain(int badgePlain) {
+ mBadgePlain = badgePlain;
+ return this;
+ }
+
+ public Builder setBadgeNoBackground(int badgeNoBackground) {
+ mBadgeNoBackground = badgeNoBackground;
+ return this;
+ }
+
+ public Builder setLabel(int label) {
+ mLabel = label;
+ return this;
+ }
+
+ public Builder setDefaultRestrictions(ArrayList<String> restrictions) {
+ mDefaultRestrictions = restrictions;
+ return this;
+ }
+
+ public UserTypeDetails createUserTypeDetails() {
+ Preconditions.checkArgument(mName != null,
+ "Cannot create a UserTypeDetails with no name.");
+ Preconditions.checkArgument(hasValidBaseType(),
+ "UserTypeDetails " + mName + " has invalid baseType: " + mBaseType);
+ Preconditions.checkArgument(hasValidPropertyFlags(),
+ "UserTypeDetails " + mName + " has invalid flags: "
+ + Integer.toHexString(mDefaultUserInfoPropertyFlags));
+ if (hasBadge()) {
+ Preconditions.checkArgument(mBadgeLabels != null && mBadgeLabels.length != 0,
+ "UserTypeDetails " + mName + " has badge but no badgeLabels.");
+ Preconditions.checkArgument(mBadgeColors != null && mBadgeColors.length != 0,
+ "UserTypeDetails " + mName + " has badge but no badgeColors.");
+ }
+
+ return new UserTypeDetails(mName, mEnabled, mMaxAllowed, mBaseType,
+ mDefaultUserInfoPropertyFlags, mLabel, mMaxAllowedPerParent,
+ mIconBadge, mBadgePlain, mBadgeNoBackground, mBadgeLabels, mBadgeColors,
+ mDefaultRestrictions);
+ }
+
+ private boolean hasBadge() {
+ return mIconBadge != Resources.ID_NULL;
+ }
+
+ // TODO(b/143784345): Refactor this when we clean up UserInfo.
+ private boolean hasValidBaseType() {
+ return mBaseType == UserInfo.FLAG_FULL
+ || mBaseType == UserInfo.FLAG_PROFILE
+ || mBaseType == UserInfo.FLAG_SYSTEM
+ || mBaseType == (UserInfo.FLAG_FULL | UserInfo.FLAG_SYSTEM);
+ }
+
+ // TODO(b/143784345): Refactor this when we clean up UserInfo.
+ private boolean hasValidPropertyFlags() {
+ final int forbiddenMask =
+ UserInfo.FLAG_PRIMARY |
+ UserInfo.FLAG_ADMIN |
+ UserInfo.FLAG_INITIALIZED |
+ UserInfo.FLAG_QUIET_MODE |
+ UserInfo.FLAG_FULL |
+ UserInfo.FLAG_SYSTEM |
+ UserInfo.FLAG_PROFILE;
+ return (mDefaultUserInfoPropertyFlags & forbiddenMask) == 0;
+ }
+ }
+
+ /**
+ * Returns whether the user type is a managed profile
+ * (i.e. {@link UserManager#USER_TYPE_PROFILE_MANAGED}).
+ */
+ public boolean isManagedProfile() {
+ return UserManager.isUserTypeManagedProfile(mName);
+ }
+}
diff --git a/core/java/com/android/server/pm/UserTypeFactory.java b/core/java/com/android/server/pm/UserTypeFactory.java
new file mode 100644
index 0000000..43bbab1
--- /dev/null
+++ b/core/java/com/android/server/pm/UserTypeFactory.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static android.content.pm.UserInfo.FLAG_DEMO;
+import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
+import static android.content.pm.UserInfo.FLAG_FULL;
+import static android.content.pm.UserInfo.FLAG_GUEST;
+import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
+import static android.content.pm.UserInfo.FLAG_PROFILE;
+import static android.content.pm.UserInfo.FLAG_RESTRICTED;
+import static android.content.pm.UserInfo.FLAG_SYSTEM;
+import static android.os.UserManager.USER_TYPE_FULL_DEMO;
+import static android.os.UserManager.USER_TYPE_FULL_GUEST;
+import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED;
+import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
+import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;
+
+import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS;
+
+import android.content.res.Resources;
+import android.os.UserManager;
+import android.util.ArrayMap;
+
+/**
+ * Class for creating all {@link UserTypeDetails} on the device.
+ *
+ * Tests are located in UserManagerServiceUserTypeTest.java.
+ * @hide
+ */
+public final class UserTypeFactory {
+
+ /** This is a utility class, so no instantiable constructor. */
+ private UserTypeFactory() {}
+
+ /**
+ * Obtains the user types (built-in and customized) for this device.
+ *
+ * @return mapping from the name of each user type to its {@link UserTypeDetails} object
+ */
+ public static ArrayMap<String, UserTypeDetails> getUserTypes() {
+ final ArrayMap<String, UserTypeDetails> map = new ArrayMap<>();
+ // TODO(b/142482943): Read an xml file for OEM customized types.
+ // Remember to disallow "android." namespace
+ // TODO(b/142482943): Read an xml file to get any overrides for the built-in types.
+ final int maxManagedProfiles = 1;
+ map.put(USER_TYPE_PROFILE_MANAGED,
+ getDefaultTypeProfileManaged().setMaxAllowedPerParent(maxManagedProfiles)
+ .createUserTypeDetails());
+ map.put(USER_TYPE_FULL_SYSTEM, getDefaultTypeSystemFull().createUserTypeDetails());
+ map.put(USER_TYPE_FULL_SECONDARY, getDefaultTypeFullSecondary().createUserTypeDetails());
+ map.put(USER_TYPE_FULL_GUEST, getDefaultTypeFullGuest().createUserTypeDetails());
+ map.put(USER_TYPE_FULL_DEMO, getDefaultTypeFullDemo().createUserTypeDetails());
+ map.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted().createUserTypeDetails());
+ map.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless().createUserTypeDetails());
+ return map;
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_MANAGED}
+ * configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeProfileManaged() {
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_PROFILE_MANAGED)
+ .setBaseType(FLAG_PROFILE)
+ .setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE)
+ .setMaxAllowedPerParent(1)
+ .setLabel(0)
+ .setIconBadge(com.android.internal.R.drawable.ic_corp_icon_badge_case)
+ .setBadgePlain(com.android.internal.R.drawable.ic_corp_badge_case)
+ .setBadgeNoBackground(com.android.internal.R.drawable.ic_corp_badge_no_background)
+ .setBadgeLabels(
+ com.android.internal.R.string.managed_profile_label_badge,
+ com.android.internal.R.string.managed_profile_label_badge_2,
+ com.android.internal.R.string.managed_profile_label_badge_3)
+ .setBadgeColors(
+ com.android.internal.R.color.profile_badge_1,
+ com.android.internal.R.color.profile_badge_2,
+ com.android.internal.R.color.profile_badge_3);
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SECONDARY}
+ * configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeFullSecondary() {
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_FULL_SECONDARY)
+ .setBaseType(FLAG_FULL)
+ .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS);
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_GUEST} configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeFullGuest() {
+ final boolean ephemeralGuests = Resources.getSystem()
+ .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
+ final int flags = FLAG_GUEST | (ephemeralGuests ? FLAG_EPHEMERAL : 0);
+
+ // TODO(b/142482943): Put UMS.initDefaultGuestRestrictions() here; then fetch them from here
+
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_FULL_GUEST)
+ .setBaseType(FLAG_FULL)
+ .setDefaultUserInfoPropertyFlags(flags)
+ .setMaxAllowed(1);
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_DEMO} configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeFullDemo() {
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_FULL_DEMO)
+ .setBaseType(FLAG_FULL)
+ .setDefaultUserInfoPropertyFlags(FLAG_DEMO)
+ .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS);
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_RESTRICTED}
+ * configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeFullRestricted() {
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_FULL_RESTRICTED)
+ .setBaseType(FLAG_FULL)
+ .setDefaultUserInfoPropertyFlags(FLAG_RESTRICTED)
+ .setMaxAllowed(UNLIMITED_NUMBER_OF_USERS);
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_FULL_SYSTEM} configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeSystemFull() {
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_FULL_SYSTEM)
+ .setBaseType(FLAG_SYSTEM | FLAG_FULL);
+ }
+
+ /**
+ * Returns the Builder for the default {@link UserManager#USER_TYPE_SYSTEM_HEADLESS}
+ * configuration.
+ */
+ private static UserTypeDetails.Builder getDefaultTypeSystemHeadless() {
+ return new UserTypeDetails.Builder()
+ .setName(USER_TYPE_SYSTEM_HEADLESS)
+ .setBaseType(FLAG_SYSTEM);
+ }
+}
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index 091e1c2..c039570 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -172,6 +172,8 @@
repeated SuspendBlockerProto suspend_blockers = 48;
optional WirelessChargerDetectorProto wireless_charger_detector = 49;
optional BatterySaverStateMachineProto battery_saver_state_machine = 50;
+ // Attentive timeout in ms. The timeout is disabled if it is set to -1.
+ optional sint32 attentive_timeout_ms = 51;
}
// A com.android.server.power.PowerManagerService.SuspendBlockerImpl object.
@@ -310,6 +312,12 @@
optional bool is_vr_mode_enabled = 35;
// True if Sidekick is controlling the display and we shouldn't change its power mode.
optional bool draw_wake_lock_override_from_sidekick = 36;
+ // The attentive timeout setting value in milliseconds. Default value is -1.
+ optional sint32 attentive_timeout_setting_ms = 37;
+ // The attentive timeout config value in milliseconds.
+ optional sint32 attentive_timeout_config_ms = 38;
+ // The attentive warning duration config value in milliseconds.
+ optional sint32 attentive_warning_duration_config_ms = 39;
}
message BatterySaverStateMachineProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9f77407..545538b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -142,7 +142,7 @@
<protected-broadcast android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.UUID" />
<protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" />
- <protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.ALIAS_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
<protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
<protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index 3ecb1dd..655d4dd 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -42,4 +42,8 @@
<!-- Allow SystemUI to show the shutdown dialog -->
<bool name="config_showSysuiShutdown">true</bool>
+
+ <!-- The time in milliseconds of prolonged user inactivity after which device goes to sleep,
+ even if wakelocks are held. On TVs, this defaults to 4 hours. -->
+ <integer name="config_attentiveTimeout">14400000</integer>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cb0b599..e6f038a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -959,6 +959,14 @@
The default is false. -->
<bool name="config_suspendWhenScreenOffDueToProximity">false</bool>
+ <!-- The time in milliseconds of prolonged user inactivity after which device goes to sleep,
+ even if wakelocks are held. -->
+ <integer name="config_attentiveTimeout">-1</integer>
+
+ <!-- How long to show a warning message to user before the device goes to sleep after prolonged
+ user inactivity. -->
+ <integer name="config_attentiveWarningDuration">30000</integer>
+
<!-- Control the behavior when the user long presses the power button.
0 - Nothing
1 - Global actions menu
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7854eed..42e62d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5238,13 +5238,6 @@
<!-- Application name displayed in notifications [CHAR LIMIT=60] -->
<string name="notification_app_name_settings">Settings</string>
- <!-- Title of the overlay warning the user to interact with the device or it will go into standby. [CHAR LIMIT=25] -->
- <string name="standby_warning_title">Standby</string>
- <!-- Message of the overlay warning the user to interact with the device or it will go into standby. [CHAR LIMIT=NONE] -->
- <string name="standby_warning_message" product="tv">The Android TV device will soon turn off; press a button to keep it on.</string>
- <!-- Message of the overlay warning the user to interact with the device or it will go into standby. [CHAR LIMIT=NONE] -->
- <string name="standby_warning_message" product="default">The device will soon turn off; press to keep it on.</string>
-
<!-- Active Permission - accessibility support -->
<!-- Content description of the camera icon in the notification. [CHAR LIMIT=NONE] -->
<string name="notification_appops_camera_active">Camera</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 28809da..e56bbf6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2117,6 +2117,8 @@
<java-symbol type="integer" name="config_minimumScreenOffTimeout" />
<java-symbol type="integer" name="config_maximumScreenDimDuration" />
<java-symbol type="fraction" name="config_maximumScreenDimRatio" />
+ <java-symbol type="integer" name="config_attentiveTimeout" />
+ <java-symbol type="integer" name="config_attentiveWarningDuration" />
<java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
<java-symbol type="string" name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" />
<java-symbol type="string" name="config_customVpnConfirmDialogComponent" />
diff --git a/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java b/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
index 22b2314..1bc46a7 100644
--- a/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
@@ -19,6 +19,7 @@
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import androidx.test.filters.LargeTest;
@@ -40,6 +41,6 @@
@Override
protected UserInfo createUser() throws RemoteException {
return mUm.createProfileForUser("Managed user",
- UserInfo.FLAG_MANAGED_PROFILE, UserHandle.myUserId());
+ UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, UserHandle.myUserId());
}
}
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 823fca5..85aa118 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -23,13 +23,23 @@
import android.os.Parcel;
import android.util.Pair;
+import android.util.Xml;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.util.FastXmlSerializer;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@SmallTest
@@ -104,11 +114,15 @@
});
}
-
@Test
public void testParceledConfigIsEquivalent() {
BrightnessConfiguration.Builder builder =
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
BrightnessConfiguration config = builder.build();
Parcel p = Parcel.obtain();
p.writeParcelable(config, 0 /*flags*/);
@@ -119,12 +133,49 @@
}
@Test
+ public void testWriteReadXml() throws IOException, XmlPullParserException {
+ BrightnessConfiguration.Builder builder =
+ new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ BrightnessConfiguration config = builder.build();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(baos, StandardCharsets.UTF_8.name());
+ out.startDocument(null, true);
+ config.saveToXml(out);
+ out.endDocument();
+ baos.flush();
+
+ ByteArrayInputStream input = new ByteArrayInputStream(baos.toByteArray());
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(input, StandardCharsets.UTF_8.name());
+ BrightnessConfiguration loadedConfig = BrightnessConfiguration.loadFromXml(parser);
+
+ assertEquals(config, loadedConfig);
+ }
+
+ @Test
public void testEquals() {
BrightnessConfiguration.Builder builder =
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
BrightnessConfiguration baseConfig = builder.build();
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
BrightnessConfiguration identicalConfig = builder.build();
assertEquals(baseConfig, identicalConfig);
assertEquals("hashCodes must be equal for identical configs",
@@ -133,14 +184,37 @@
float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
lux[lux.length - 1] = lux[lux.length - 1] * 2;
builder = new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
BrightnessConfiguration luxDifferConfig = builder.build();
assertNotEquals(baseConfig, luxDifferConfig);
float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
nits[nits.length - 1] = nits[nits.length - 1] * 2;
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
+ builder.setShouldCollectColorSamples(true);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
BrightnessConfiguration nitsDifferConfig = builder.build();
assertNotEquals(baseConfig, nitsDifferConfig);
+
+ builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.addCorrectionByCategory(3,
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ builder.addCorrectionByPackageName("a.package.name",
+ BrightnessCorrection.createScaleAndTranslateLog(1.0f, 2.0f));
+ BrightnessConfiguration colorCollectionDiffers = builder.build();
+ assertNotEquals(baseConfig, colorCollectionDiffers);
+
+ builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
+ builder.setShouldCollectColorSamples(true);
+ BrightnessConfiguration correctionsDiffer = builder.build();
+ assertNotEquals(baseConfig, correctionsDiffer);
}
private static void assertArrayEquals(float[] expected, float[] actual, String name) {
diff --git a/media/java/android/media/tv/OWNER b/media/java/android/media/tv/OWNER
deleted file mode 100644
index 64c0bb5..0000000
--- a/media/java/android/media/tv/OWNER
+++ /dev/null
@@ -1,5 +0,0 @@
-amyjojo@google.com
-nchalko@google.com
-shubang@google.com
-quxiangfang@google.com
-
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index 4a03b3c..64c0bb5 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -1,2 +1,5 @@
+amyjojo@google.com
nchalko@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml b/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
deleted file mode 100644
index 918abd9..0000000
--- a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/car_privacy_chip"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_margin="@dimen/ongoing_appops_chip_margin"
- android:layout_toStartOf="@+id/clock_container"
- android:focusable="true"
- android:gravity="center_vertical|end"
- android:orientation="horizontal"
- android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
- android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
- android:visibility="visible">
-
- <LinearLayout
- android:id="@+id/icons_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical|start"/>
-</com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index 7299ddf..ce0d31c 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -65,8 +65,6 @@
/>
</FrameLayout>
- <include layout="@layout/car_ongoing_privacy_chip"/>
-
<FrameLayout
android:id="@+id/clock_container"
android:layout_width="wrap_content"
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index e2da91b..ee79653 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -59,18 +59,6 @@
<dimen name="car_keyline_1">24dp</dimen>
<dimen name="car_keyline_2">96dp</dimen>
<dimen name="car_keyline_3">128dp</dimen>
- <dimen name="privacy_chip_icon_height">36dp</dimen>
- <dimen name="privacy_chip_icon_padding_left">0dp</dimen>
- <dimen name="privacy_chip_icon_padding_right">0dp</dimen>
- <dimen name="privacy_chip_icon_padding_top">0dp</dimen>
- <dimen name="privacy_chip_icon_padding_bottom">0dp</dimen>
-
- <dimen name="privacy_chip_text_padding_left">0dp</dimen>
- <dimen name="privacy_chip_text_padding_right">0dp</dimen>
- <dimen name="privacy_chip_text_padding_top">0dp</dimen>
- <dimen name="privacy_chip_text_padding_bottom">0dp</dimen>
-
- <dimen name="privacy_chip_icon_max_height">100dp</dimen>
<!-- Height of icons in Ongoing App Ops dialog. Both App Op icon and application icon -->
<dimen name="ongoing_appops_dialog_icon_height">48dp</dimen>
@@ -86,16 +74,6 @@
<dimen name="ongoing_appops_chip_bg_padding">4dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
<dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
- <!-- Start padding for the app icon displayed in the dialog -->
- <dimen name="privacy_dialog_app_icon_padding_start">40dp</dimen>
- <!-- End padding for the app opps icon displayed in the dialog -->
- <dimen name="privacy_dialog_app_ops_icon_padding_end">40dp</dimen>
- <!-- Top padding for the list of application displayed in the dialog -->
- <dimen name="privacy_dialog_app_list_padding_top">20dp</dimen>
- <!-- Top padding for the dialog container-->
- <dimen name="privacy_dialog_container_padding_top">10dp</dimen>
- <!-- Top padding for the dialog title-->
- <dimen name="privacy_dialog_title_padding_start">10dp</dimen>
<!-- Car volume dimens. -->
<dimen name="car_volume_item_icon_size">@dimen/car_primary_icon_size</dimen>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
deleted file mode 100644
index 88d641e..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.appops.AppOpItem;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.plugins.ActivityStarter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Layout defining the privacy chip that will be displayed in CarStatusRar with the information for
- * which applications are using AppOpps permission fpr camera, mic and location.
- */
-public class OngoingPrivacyChip extends LinearLayout implements View.OnClickListener {
-
- private Context mContext;
- private Handler mHandler;
-
- private LinearLayout mIconsContainer;
- private List<PrivacyItem> mPrivacyItems;
- private static AppOpsController sAppOpsController;
- private UserManager mUserManager;
- private int mCurrentUser;
- private List<Integer> mCurrentUserIds;
- private boolean mListening = false;
- PrivacyDialogBuilder mPrivacyDialogBuilder;
- private LinearLayout mPrivacyChip;
- private ActivityStarter mActivityStarter;
-
- protected static final int[] OPS = new int[]{
- AppOpsManager.OP_CAMERA,
- AppOpsManager.OP_RECORD_AUDIO,
- AppOpsManager.OP_COARSE_LOCATION,
- AppOpsManager.OP_FINE_LOCATION
- };
-
- public OngoingPrivacyChip(Context context) {
- super(context, null);
- init(context);
- }
-
- public OngoingPrivacyChip(Context context, AttributeSet attr) {
- super(context, attr);
- init(context);
- }
-
- public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle) {
- super(context, attr, defStyle);
- init(context);
- }
-
- public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle, int a) {
- super(context, attr, defStyle, a);
- init(context);
- }
-
- private void init(Context context) {
- mContext = context;
- mHandler = new Handler(Looper.getMainLooper());
- mPrivacyItems = new ArrayList<>();
- sAppOpsController = Dependency.get(AppOpsController.class);
- mUserManager = mContext.getSystemService(UserManager.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
- mCurrentUser = ActivityManager.getCurrentUser();
- mCurrentUserIds = mUserManager.getProfiles(mCurrentUser).stream().map(
- userInfo -> userInfo.id).collect(Collectors.toList());
-
- mPrivacyDialogBuilder = new PrivacyDialogBuilder(context, mPrivacyItems);
- }
-
- private AppOpsController.Callback mCallback = new AppOpsController.Callback() {
-
- @Override
- public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
- int userId = UserHandle.getUserId(uid);
- if (mCurrentUserIds.contains(userId)) {
- updatePrivacyList();
- }
- }
- };
-
- @Override
- public void onFinishInflate() {
- mIconsContainer = findViewById(R.id.icons_container);
- mPrivacyChip = (LinearLayout) findViewById(R.id.car_privacy_chip);
- if (mPrivacyChip != null) {
- mPrivacyChip.setOnClickListener(this);
- setListening(true);
- }
- }
-
- @Override
- public void onDetachedFromWindow() {
- if (mPrivacyChip != null) {
- setListening(false);
- }
- super.onDetachedFromWindow();
- }
-
- @Override
- public void onClick(View v) {
- updatePrivacyList();
- mHandler.post(() -> {
- mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
- });
- }
-
- private void setListening(boolean listen) {
- if (mListening == listen) {
- return;
- }
- mListening = listen;
- if (mListening) {
- sAppOpsController.addCallback(OPS, mCallback);
- updatePrivacyList();
- } else {
- sAppOpsController.removeCallback(OPS, mCallback);
- }
- }
-
- private void updatePrivacyList() {
- List<PrivacyItem> privacyItems = mCurrentUserIds.stream()
- .flatMap(item -> sAppOpsController.getActiveAppOpsForUser(item).stream())
- .filter(Objects::nonNull)
- .map(item -> toPrivacyItem(item))
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
- if (!privacyItems.equals(mPrivacyItems)) {
- mPrivacyItems = privacyItems;
- mPrivacyDialogBuilder = new PrivacyDialogBuilder(mContext, mPrivacyItems);
- mHandler.post(this::updateView);
- }
- }
-
- private PrivacyItem toPrivacyItem(AppOpItem appOpItem) {
- PrivacyType type;
- switch (appOpItem.getCode()) {
- case AppOpsManager.OP_CAMERA:
- type = PrivacyType.TYPE_CAMERA;
- break;
- case AppOpsManager.OP_COARSE_LOCATION:
- type = PrivacyType.TYPE_LOCATION;
- break;
- case AppOpsManager.OP_FINE_LOCATION:
- type = PrivacyType.TYPE_LOCATION;
- break;
- case AppOpsManager.OP_RECORD_AUDIO:
- type = PrivacyType.TYPE_MICROPHONE;
- break;
- default:
- return null;
- }
- PrivacyApplication app = new PrivacyApplication(appOpItem.getPackageName(), mContext);
- return new PrivacyItem(type, app, appOpItem.getTimeStarted());
- }
-
- // Should only be called if the mPrivacyDialogBuilder icons or app changed
- private void updateView() {
- if (mPrivacyItems.isEmpty()) {
- mPrivacyChip.setVisibility(GONE);
- return;
- }
- mPrivacyChip.setVisibility(VISIBLE);
- setIcons(mPrivacyDialogBuilder);
-
- requestLayout();
- }
-
- private void setIcons(PrivacyDialogBuilder dialogBuilder) {
- mIconsContainer.removeAllViews();
- dialogBuilder.generateIcons().forEach(item -> {
- int size = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_height);
- ImageView image = new ImageView(mContext);
- image.setImageDrawable(item);
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size);
-
- int leftPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_left);
- int topPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_top);
- int rightPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_right);
- int bottomPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_bottom);
- image.setLayoutParams(layoutParams);
- image.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
- mIconsContainer.addView(image);
- });
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
deleted file mode 100644
index a5d3bf7..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import java.util.Objects;
-
-/**
- * Class to hold the data for the applications that are using the AppOps permissions.
- */
-public class PrivacyApplication {
- private static final String TAG = "PrivacyApplication";
-
- private String mPackageName;
- private Drawable mIcon;
- private String mApplicationName;
-
- public PrivacyApplication(String packageName, Context context) {
- mPackageName = packageName;
- try {
- ApplicationInfo app = context.getPackageManager()
- .getApplicationInfoAsUser(packageName, 0,
- ActivityManager.getCurrentUser());
- mIcon = context.getPackageManager().getApplicationIcon(app);
- mApplicationName = context.getPackageManager().getApplicationLabel(app).toString();
- } catch (PackageManager.NameNotFoundException e) {
- mApplicationName = packageName;
- Log.e(TAG, "Failed to to find package name", e);
- }
- }
-
- /**
- * Gets the application name.
- */
- public Drawable getIcon() {
- return mIcon;
- }
-
- /**
- * Gets the application name.
- */
- public String getApplicationName() {
- return mApplicationName;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- PrivacyApplication that = (PrivacyApplication) o;
- return mPackageName.equals(that.mPackageName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mPackageName);
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
deleted file mode 100644
index 3b83e7c..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Helper class to build the {@link OngoingPrivacyDialog}
- */
-public class PrivacyDialogBuilder {
-
- private Map<PrivacyType, List<PrivacyItem>> mItemsByType;
- private PrivacyApplication mApplication;
- private Context mContext;
-
- public PrivacyDialogBuilder(Context context, List<PrivacyItem> itemsList) {
- mContext = context;
- mItemsByType = itemsList.stream().filter(Objects::nonNull).collect(
- Collectors.groupingBy(PrivacyItem::getPrivacyType));
- List<PrivacyApplication> apps = itemsList.stream().filter(Objects::nonNull).map(
- PrivacyItem::getPrivacyApplication).distinct().collect(Collectors.toList());
- mApplication = apps.size() == 1 ? apps.get(0) : null;
- }
-
- /**
- * Gets the icon id for all the {@link PrivacyItem} in the same order as of itemList.
- */
- public List<Drawable> generateIcons() {
- return mItemsByType.keySet().stream().map(item -> item.getIconId(mContext)).collect(
- Collectors.toList());
- }
-
- /**
- * Gets the application object.
- */
- public PrivacyApplication getApplication() {
- return mApplication;
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
deleted file mode 100644
index d3e123e..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import java.util.Objects;
-
-/**
- * Class for holding the data of each privacy item displayed in {@link OngoingPrivacyDialog}
- */
-public class PrivacyItem {
-
- private PrivacyType mPrivacyType;
- private PrivacyApplication mPrivacyApplication;
-
- public PrivacyItem(PrivacyType privacyType, PrivacyApplication privacyApplication,
- long timeStarted) {
- this.mPrivacyType = privacyType;
- this.mPrivacyApplication = privacyApplication;
- }
-
- /**
- * Gets the application object.
- */
- public PrivacyApplication getPrivacyApplication() {
- return mPrivacyApplication;
- }
-
- /**
- * Gets the privacy type for the application.
- */
- public PrivacyType getPrivacyType() {
- return mPrivacyType;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- PrivacyItem that = (PrivacyItem) o;
- return mPrivacyType == that.mPrivacyType
- && mPrivacyApplication.equals(that.mPrivacyApplication);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mPrivacyType, mPrivacyApplication);
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
deleted file mode 100644
index 8955c87..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import com.android.systemui.R;
-
-/**
- * Enum for storing data for camera, mic and location.
- */
-public enum PrivacyType {
- TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
- TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
- TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_white);
-
- private int mNameId;
- private int mIconId;
-
- PrivacyType(int nameId, int iconId) {
- mNameId = nameId;
- mIconId = iconId;
- }
-
- /**
- * Get the icon Id.
- */
- public Drawable getIconId(Context context) {
- return context.getResources().getDrawable(mIconId, null);
- }
-
- /**
- * Get the name Id.
- */
- public String getNameId(Context context) {
- return context.getResources().getString(mNameId);
- }
-}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 97b2cb5..3ff5cf4 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Middelmatig"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Vinnig"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Baie vinnig"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Verval"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Ontkoppel"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ontkoppel tans…"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 62d5dca..264d8de 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"መካከለኛ"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"ፈጣን"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"እጅግ በጣም ፈጣን"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ጊዜው አልፏል"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ተለያይቷል"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"በመለያየት ላይ..."</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c786e09..c230236 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"متوسطة"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"سريعة"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"سريعة جدًا"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"منتهية الصلاحية"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"غير متصل"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"جارٍ قطع الاتصال..."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 552fbb8..ab0ed29 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"মধ্যমীয়া"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"দ্ৰুত"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"অতি দ্ৰুত"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ম্যাদ উকলিছে"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"সংযোগ বিচ্ছিন্ন কৰা হ’ল"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"সংযোগ বিচ্ছিন্ন কৰি থকা হৈছে…"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 3af2e25..fe62d31 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Orta"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Sürətli"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Çox Sürətli"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vaxtı keçib"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Ayrıldı"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ayrılır..."</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 8a76242..1619584 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Srednja"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Brza"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Veoma brza"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Isteklo"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Veza je prekinuta"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prekidanje veze..."</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 5ed4495..0f2df49 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Сярэдняя"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Хуткая"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Вельмі хуткая"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Тэрмін скончыўся"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Адключана"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Адключэнне..."</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index f7a7153..a3be2812 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Средна"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Бърза"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Много бърза"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Изтекло"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Изкл."</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Изключва се..."</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index f4c677f..743de50 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"মাঝারি"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"দ্রুত"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"খুব দ্রুত"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"মেয়াদ শেষ হয়ে গেছে"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ডিসকানেক্ট করা হয়েছে"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"ডিসকানেক্ট হচ্ছে..."</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index fc653b7..75a4047 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Srednja brzina"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Brzo"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Veoma brzo"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Istekao"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Isključen"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prekidanje veze…"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index f79375e..8627cf3 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Mitjana"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Ràpida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Molt ràpida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducat"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconnectat"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"S\'està desconnectant..."</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 64400a4..6fef07a 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Střední"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rychlá"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Velmi rychlá"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Platnost vypršela"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Odpojeno"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Odpojování..."</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index de7a228..80ee95e 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Middel"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Hurtig"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Meget hurtig"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Udløbet"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> – <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Afbrudt"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Afbryder ..."</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index eafe9d0..7dee120 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Μέτρια"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Γρήγορη"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Πολύ γρήγορη"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Έληξε"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Αποσυνδέθηκε"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Αποσύνδεση..."</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 840f5ee..41c817e 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Muy rápida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vencido"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index c86eb34..897eaa3 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Muy rápida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducado"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index f59b96a..9b94222 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Keskmine"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Kiire"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Väga kiire"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Aegunud"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Ühendus katkestatud"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ühenduse katkestamine ..."</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 9648139..b0e4b26 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Tartekoa"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Bizkorra"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Oso bizkorra"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Iraungita"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Deskonektatuta"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Deskonektatzen…"</string>
@@ -455,7 +454,7 @@
<string name="cancel" msgid="5665114069455378395">"Utzi"</string>
<string name="okay" msgid="949938843324579502">"Ados"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
- <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu \"Ez molestatu\" modua"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
<string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Inoiz ez"</string>
<string name="zen_interruption_level_priority" msgid="5392140786447823299">"Lehentasuna dutenak soilik"</string>
<string name="zen_mode_and_condition" msgid="8877086090066332516">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3e8de97..7298826 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"متوسط"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"سریع"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"خیلی سریع"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"منقضیشده"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"اتصال قطع شد"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"در حال قطع اتصال..."</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 68ddf7d..6f58f03 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Kohtuullinen"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Nopea"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Hyvin nopea"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Vanhentunut"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Yhteys katkaistu"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Katkaistaan yhteyttä..."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ef4800c..a5526f3 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Moyenne"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Élevée"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Très rapide"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expiré"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> : <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Déconnecté"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Déconnexion…"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 256ea03a..eaab027 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Moi rápida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Caducou"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando..."</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ed50f4b..00fd024 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"મધ્યમ"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"ઝડપી"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ખૂબ ઝડપી"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"સમય સમાપ્ત થયો"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ડિસ્કનેક્ટ કર્યું"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"ડિસ્કનેક્ટ થઈ રહ્યું છે..."</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 550eaf8..96aec94 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"मध्यम"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"तेज़"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"अत्यधिक तेज़"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"समयसीमा खत्म हो गई"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"डिसकनेक्ट किया गया"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"डिस्कनेक्ट हो रहा है..."</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 18ea1de..6df46ca 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Srednje"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Brzo"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Vrlo brzo"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Isteklo"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Niste povezani"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Isključivanje…"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 7baa044..6b5b05e 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Közepes"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Gyors"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Nagyon gyors"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Lejárt"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Szétkapcsolva"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Szétkapcsolás..."</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a5b03ea..c4002b9 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Միջին"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Արագ"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Շատ արագ"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Սպառվել է"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Անջատված է"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Անջատվում է..."</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index dea51a8..753f225 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Sedang"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Cepat"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Sangat Cepat"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Sudah tidak berlaku"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Sambungan terputus"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutus sambungan..."</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 0a85d06..b1d40bf 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Miðlungshratt"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Hratt"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Mjög hratt"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Útrunninn"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Aftengt"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Aftengist…"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 980bdf9..7f2bd3e 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Media"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Veloce"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Molto veloce"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Scaduto"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Disconnesso"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Disconnessione..."</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 77fd156..bdd1bab 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"בינונית"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"מהירה"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"מהירה מאוד"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"התוקף פג"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"מנותק"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"מתנתק..."</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 1d6b3d5..a6192a4 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"普通"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"速い"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"非常に速い"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"期限切れ"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"切断"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"切断中..."</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index a69713a..a3633f6 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"საშუალო"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"სწრაფი"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ძალიან სწრაფი"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ვადაგასულია"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"კავშირი გაწყვეტილია"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"მიმდინარეობს გათიშვა…"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 380d648..0962e55 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Орташа"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Жылдам"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Өте жылдам"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Мерзімі өтті."</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Ажыратылған"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылуда…"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 478e036..45620e8 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"មធ្យម"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"លឿន"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"លឿនណាស់"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ផុតកំណត់"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"បានផ្ដាច់"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"កំពុងផ្ដាច់…"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 73aa998..1fc2e4a 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"ಮಧ್ಯಮ"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"ವೇಗ"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ತುಂಬಾ ವೇಗವಾಗಿದೆ"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ಅವಧಿ ಮುಕ್ತಾಯವಾಗಿದೆ"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗುತ್ತಿದೆ..."</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 3ecde32..8e7c697 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"보통"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"빠름"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"매우 빠름"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"만료됨"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"연결 끊김"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"연결을 끊는 중…"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index ca8992f..18a1468 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Орто"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Ылдам"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Абдан ылдам"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Мөөнөтү бүткөн"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Ажыратылган"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Ажыратылууда…"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index b8a9322..808d5a7 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"ປານກາງ"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"ໄວ"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ໄວຫຼາຍ"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ໝົດອາຍຸແລ້ວ"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ຕັດການເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"ກຳລັງຢຸດການເຊື່ອມຕໍ່..."</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 3d6dfbb..78d1b1b 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Vidutinis"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Greitas"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Labai greitas"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Baigėsi galiojimo laikas"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Atsijungęs (-usi)"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Atjungiama..."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index bf0c97d..0ae10aa 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Vidējs"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Ātrs"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Ļoti ātrs"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Beidzies derīguma termiņš"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Atvienots"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Notiek atvienošana..."</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 53b0d4c..9850ac5 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Средна"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Брза"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Многу брза"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Истечено"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Исклучено"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Се исклучува..."</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 66ff005..2692a30 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"ഇടത്തരം"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"വേഗത്തിൽ"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"വളരെ വേഗത്തിൽ"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"കാലഹരണപ്പെട്ടത്"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"വിച്ഛേദിച്ചു"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"വിച്ഛേദിക്കുന്നു..."</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 75633ab..966cdff 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"मध्यम"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"जलद"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"खूप जलद"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"मुदत संपली"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"डिस्कनेक्ट केले"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"डिस्कनेक्ट करत आहे..."</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index fad37fe..88d7c7d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Sederhana"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Laju"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Sangat Laju"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Tamat tempoh"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Diputuskan sambungan"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Memutuskan sambungan..."</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index fd626f6c..6dfd290 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"အတော်အသင့်"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"မြန်"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"အလွန်မြန်"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"သက်တမ်းကုန်သွားပါပြီ"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ချိတ်ဆက်မှုပြတ်တောက်သည်"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"အဆက်အသွယ်ဖြတ်တောက်သည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index baf3c64..760c409 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Middels"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rask"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Veldig rask"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Utløpt"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Frakoblet"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Kobler fra…"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 00a3022..77f87ff 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"मध्यम"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"छिटो"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"धेरै छिटो"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"म्याद सकियो"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"विच्छेदन गरियो"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"जडान हटाइँदै ..."</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 533b0f2..55f56d9 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Gemiddeld"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Snel"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Zeer snel"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Verlopen"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Verbinding verbroken"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Verbinding verbreken..."</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 4a2ab80..98c302d 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"ମଧ୍ୟମ"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"ଦ୍ରୁତ"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ଅତି ଦ୍ରୁତ"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ମିଆଦ ଶେଷ ହୋଇଯାଇଛି"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ବିଛିନ୍ନ ହେଲା"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"ବିଚ୍ଛିନ୍ନ କରୁଛି…"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 62da49b..525ad2e 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"ਔਸਤ"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"ਤੇਜ਼"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ਬਹੁਤ ਤੇਜ਼"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"ਮਿਆਦ ਮੁੱਕ ਗਈ"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ਡਿਸਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"ਡਿਸਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 027afc3..69ebc59 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Średnia"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Szybka"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Bardzo szybka"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Ważność wygasła"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Rozłączona"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Rozłączanie..."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 9259c03..62017f1 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 0961b27..8304768 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desligado"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"A desligar..."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 9259c03..62017f1 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Média"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rápida"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Muito rápida"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirado"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1fc1d35..50ea4a0 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Medie"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Rapidă"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Foarte rapidă"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Expirat"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Deconectat"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"În curs de deconectare..."</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index c3baea2..0582a0c 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Средняя"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Быстрая"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Очень быстрая"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Срок действия истек"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Нет подключения"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Отключение..."</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index f8d2d08..43a4978 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"මධ්යම"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"වේගවත්"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"ඉතා වේගවත්"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"කල් ඉකුත් විය"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"විසන්ධි වුණි"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"විසන්ධි වෙමින්…"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 0d576b4..3a3958f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Stredná"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Vysoká"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Veľmi vysoká"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Platnosť vypršala"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Odpojený"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prebieha odpájanie..."</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 7c62d52..068f221 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Srednje hitra"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Hitra"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Zelo hitra"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Poteklo"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Prekinjena povezava"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Prekinjanje povezave ..."</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 7a1bdb5..54d4637 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Mesatare"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"E shpejtë"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Shumë e shpejtë"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Skaduar"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Shkëputur"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Po shkëputet..."</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index e809ab9..ab081ae 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Средња"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Брза"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Веома брза"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Истекло"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Веза је прекинута"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Прекидање везе..."</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 52a82db..cab971f 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Medelsnabb"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Snabb"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Mycket snabb"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Har upphört att gälla"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Kopplas ifrån"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Kopplar ifrån…"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index c83388a..df71b82 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Wastani"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Haraka"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Haraka Sana"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Muda umeisha"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Haijaunganishwa"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Inatenganisha..."</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 856fd4f..084ec16 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"நடுத்தரம்"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"வேகம்"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"மிகவும் வேகமானது"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"காலாவதியாகிவிட்டது"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"தொடர்பு துண்டிக்கப்பட்டது"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"துண்டிக்கிறது..."</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index cc17247..cbcaf1a 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"మధ్యస్థం"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"వేగవంతం"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"చాలా వేగవంతం"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"గడువు ముగిసింది"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"డిస్కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"డిస్కనెక్ట్ చేస్తోంది..."</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 4feb0d6..fa8caa1 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"ปานกลาง"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"เร็ว"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"เร็วมาก"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"หมดอายุแล้ว"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"ตัดการเชื่อมต่อ"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"กำลังตัดการเชื่อมต่อ..."</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e6963b9..21fe58c 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Katamtaman"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Mabilis"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Napakabilis"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Nag-expire na"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Hindi nakakonekta"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Nadidiskonekta..."</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index bd457d3..4e7f38d 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Orta"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Hızlı"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Çok Hızlı"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Süresi sona erdi"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Bağlantı kesildi"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Bağlantı kesiliyor…"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 36a82ea..9807417 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Середня"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Швидка"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Дуже швидка"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Термін дії минув"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>: <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Роз’єднано"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Відключення..."</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 50dc72e..e17b0b0 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"متوسط"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"تیز"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"بہت تیز"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"میعاد ختم ہو گئی"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"منقطع"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"منقطع کیا جارہا ہے…"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 38edb6d0..ea51eba 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"O‘rtacha"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Tez"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Juda tez"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Muddati tugagan"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Uzildi"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Uzilyapti…"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index e0798aa..0b71a8c 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Trung bình"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Nhanh"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Rất nhanh"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Đã hết hạn"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Đã ngắt kết nối"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Đang ngắt kết nối…"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4303615..1805694 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"适中"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"快"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"很快"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"已失效"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"已断开连接"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"正在断开连接..."</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index f3b8653..1d217b5 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"適中"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"快"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"非常快"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"已過期"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"已中斷連線"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"正在中斷連線..."</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 53b54c4..ee68665 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"適中"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"快"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"非常快"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"已失效"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"已中斷連線"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"正在中斷連線…"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 249e73c..820aa77 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -61,8 +61,7 @@
<string name="speed_label_medium" msgid="9078405312828606976">"Okumaphakathi"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Sheshayo"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Kushesha kakhulu"</string>
- <!-- no translation found for wifi_passpoint_expired (6540867261754427561) -->
- <skip />
+ <string name="wifi_passpoint_expired" msgid="6540867261754427561">"Iphelelwe isikhathi"</string>
<string name="preference_summary_default_combination" msgid="2644094566845577901">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="7739366554710388701">"Ayixhunyiwe"</string>
<string name="bluetooth_disconnecting" msgid="7638892134401574338">"Inqamula uxhumano kwi-inthanethi..."</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a1ef831..80240af 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -609,6 +609,9 @@
<string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string>
<!-- UI debug setting: Trigger Bluetooth Audio Codec Selection: Sample Rate -->
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Trigger Bluetooth Audio Codec\u000ASelection: Sample Rate</string>
+ <!-- UI debug setting: Label for unsupported Bluetooth Audio Codec. [CHAR LIMIT=none] -->
+ <string name="bluetooth_select_a2dp_codec_type_help_info">Gray-out means not supported by phone
+ or headset</string>
<!-- UI debug setting: Trigger Bluetooth Audio Bits Per Sample Selection -->
<string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 2507a34..0095692 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -442,12 +442,12 @@
/**
* Get name from remote device
- * @return {@link BluetoothDevice#getAliasName()} if
- * {@link BluetoothDevice#getAliasName()} is not null otherwise return
+ * @return {@link BluetoothDevice#getAlias()} if
+ * {@link BluetoothDevice#getAlias()} is not null otherwise return
* {@link BluetoothDevice#getAddress()}
*/
public String getName() {
- final String aliasName = mDevice.getAliasName();
+ final String aliasName = mDevice.getAlias();
return TextUtils.isEmpty(aliasName) ? getAddress() : aliasName;
}
@@ -505,7 +505,7 @@
* @return true if device's alias name is not null nor empty, false otherwise
*/
public boolean hasHumanReadableName() {
- return !TextUtils.isEmpty(mDevice.getAliasName());
+ return !TextUtils.isEmpty(mDevice.getAlias());
}
/**
@@ -652,7 +652,7 @@
}
if (BluetoothUtils.D) {
- Log.e(TAG, "updating profiles for " + mDevice.getAliasName() + ", " + mDevice);
+ Log.e(TAG, "updating profiles for " + mDevice.getAlias() + ", " + mDevice);
BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString());
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 9f71033..cca9cfa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -168,7 +168,7 @@
return cachedDevice.getName();
}
- String name = device.getAliasName();
+ String name = device.getAlias();
if (name != null) {
return name;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 274696b..69487d5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -39,6 +39,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
+import android.os.UserManager;
import com.android.settingslib.R;
@@ -176,8 +177,8 @@
boolean isManaged = context.getSystemService(DevicePolicyManager.class)
.getProfileOwnerAsUser(userId) != null;
if (isManaged) {
- badge = getDrawableForDisplayDensity(
- context, com.android.internal.R.drawable.ic_corp_badge_case);
+ badge = getDrawableForDisplayDensity(context,
+ context.getSystemService(UserManager.class).getUserBadgeResId(userId));
}
}
return setBadge(badge);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index aef7fae..2c4f57f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -92,9 +92,9 @@
when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
when(mDevice3.getName()).thenReturn(DEVICE_NAME_3);
- when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
- when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
- when(mDevice3.getAliasName()).thenReturn(DEVICE_ALIAS_3);
+ when(mDevice1.getAlias()).thenReturn(DEVICE_ALIAS_1);
+ when(mDevice2.getAlias()).thenReturn(DEVICE_ALIAS_2);
+ when(mDevice3.getAlias()).thenReturn(DEVICE_ALIAS_3);
when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1);
when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
when(mDevice3.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
@@ -240,7 +240,7 @@
assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
final String newAliasName = "NewAliasName";
- when(mDevice1.getAliasName()).thenReturn(newAliasName);
+ when(mDevice1.getAlias()).thenReturn(newAliasName);
mCachedDeviceManager.onDeviceNameUpdated(mDevice1);
assertThat(cachedDevice1.getName()).isEqualTo(newAliasName);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 5c89a01..53ff1a1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -702,7 +702,7 @@
@Test
public void deviceName_testAliasNameAvailable() {
- when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS);
+ when(mDevice.getAlias()).thenReturn(DEVICE_ALIAS);
when(mDevice.getName()).thenReturn(DEVICE_NAME);
CachedBluetoothDevice cachedBluetoothDevice =
new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
@@ -725,7 +725,7 @@
@Test
public void deviceName_testRenameDevice() {
final String[] alias = {DEVICE_ALIAS};
- doAnswer(invocation -> alias[0]).when(mDevice).getAliasName();
+ doAnswer(invocation -> alias[0]).when(mDevice).getAlias();
doAnswer(invocation -> {
alias[0] = (String) invocation.getArguments()[0];
return true;
@@ -842,14 +842,14 @@
@Test
public void getName_aliasNameNotNull_returnAliasName() {
- when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+ when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_NAME);
}
@Test
public void getName_aliasNameIsNull_returnAddress() {
- when(mDevice.getAliasName()).thenReturn(null);
+ when(mDevice.getAlias()).thenReturn(null);
assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_ADDRESS);
}
@@ -857,7 +857,7 @@
@Test
public void setName_setDeviceNameIsNotNull() {
final String name = "test name";
- when(mDevice.getAliasName()).thenReturn(DEVICE_NAME);
+ when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
mCachedDevice.setName(name);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index 2b5466c..7be176a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -75,8 +75,8 @@
when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
- when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
- when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+ when(mDevice1.getAlias()).thenReturn(DEVICE_ALIAS_1);
+ when(mDevice2.getAlias()).thenReturn(DEVICE_ALIAS_2);
when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS);
when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS);
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 10d990a..289ac80 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -605,6 +605,7 @@
Settings.Secure.ASSIST_GESTURE_SETUP_COMPLETE,
Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
Settings.Secure.ASSIST_STRUCTURE_ENABLED,
+ Settings.Secure.ATTENTIVE_TIMEOUT,
Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION,
Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT,
Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE,
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NavigationEdgeBackPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NavigationEdgeBackPlugin.java
new file mode 100644
index 0000000..bd86407
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NavigationEdgeBackPlugin.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins;
+
+import android.graphics.Point;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/** Plugin to handle navigation edge gestures for Back. */
+@ProvidesInterface(
+ action = NavigationEdgeBackPlugin.ACTION,
+ version = NavigationEdgeBackPlugin.VERSION)
+public interface NavigationEdgeBackPlugin extends Plugin {
+ String ACTION = "com.android.systemui.action.PLUGIN_NAVIGATION_EDGE_BACK_ACTION";
+ int VERSION = 1;
+
+
+ /** Specifies if the UI should be rendered on the left side of the screen. */
+ void setIsLeftPanel(boolean isLeftPanel);
+
+ /** Sets the insets for the gesture handling area. */
+ void setInsets(int leftInset, int rightInset);
+
+ /** Sets the display size. */
+ void setDisplaySize(Point displaySize);
+
+ /** Sets the callback that should be invoked when a Back gesture is detected. */
+ void setBackCallback(BackCallback callback);
+
+ /** Sets the base LayoutParams for the UI. */
+ void setLayoutParams(WindowManager.LayoutParams layoutParams);
+
+ /** Updates the UI based on the motion events passed in device coordinates. */
+ void onMotionEvent(MotionEvent motionEvent);
+
+ /** Callback to let the system react to the detected back gestures. */
+ interface BackCallback {
+ /** Indicates that a Back gesture was recognized and the system should go back. */
+ void triggerBack();
+
+ /** Indicates that the gesture was cancelled and the system should not go back. */
+ void cancelBack();
+ }
+}
diff --git a/packages/SystemUI/res/layout-television/inattentive_sleep_warning.xml b/packages/SystemUI/res/layout-television/inattentive_sleep_warning.xml
new file mode 100644
index 0000000..eb21c43
--- /dev/null
+++ b/packages/SystemUI/res/layout-television/inattentive_sleep_warning.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/sleep_warning_dialog_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:theme="@android:style/Theme.DeviceDefault.Dialog"
+ android:focusable="true">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/black"
+ android:alpha="?android:backgroundDimAmount" />
+ <LinearLayout
+ android:layout_width="380dp"
+ android:layout_height="wrap_content"
+ android:background="@drawable/rounded_bg_full"
+ android:padding="16dp"
+ android:layout_margin="32dp"
+ android:layout_gravity="bottom|right"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inattentive_sleep_warning_title"
+ android:layout_marginBottom="8dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textAppearance="@android:style/TextAppearance.DeviceDefault.Large"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inattentive_sleep_warning_message"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@android:style/TextAppearance.DeviceDefault"/>
+ </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/inattentive_sleep_warning.xml b/packages/SystemUI/res/layout/inattentive_sleep_warning.xml
new file mode 100644
index 0000000..f1f9b1f
--- /dev/null
+++ b/packages/SystemUI/res/layout/inattentive_sleep_warning.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/sleep_warning_dialog_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:theme="@android:style/Theme.Material.Dialog"
+ android:focusable="true">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/black"
+ android:alpha="?android:backgroundDimAmount" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/rounded_bg_full"
+ android:layout_margin="8dp"
+ android:padding="16dp"
+ android:layout_gravity="top"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inattentive_sleep_warning_title"
+ android:layout_marginBottom="8dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textAppearance="@android:style/TextAppearance.Material.Large"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inattentive_sleep_warning_message"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@android:style/TextAppearance.Material"/>
+ </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index dff21cf..c3f410e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -281,6 +281,7 @@
<item>com.android.systemui.statusbar.phone.StatusBar</item>
<item>com.android.systemui.usb.StorageNotification</item>
<item>com.android.systemui.power.PowerUI</item>
+ <item>com.android.systemui.power.InattentiveSleepWarningController</item>
<item>com.android.systemui.media.RingtonePlayer</item>
<item>com.android.systemui.keyboard.KeyboardUI</item>
<item>com.android.systemui.pip.PipUI</item>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 19daa90..3138547 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2507,4 +2507,11 @@
<!-- Notification content text when switching to a default launcher that supports gesture navigation [CHAR LIMIT=NONE] -->
<string name="notification_content_gesture_nav_available">Go to Settings to update system navigation</string>
+ <!-- Title of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=25] -->
+ <string name="inattentive_sleep_warning_title">Standby</string>
+ <!-- Message of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=NONE] -->
+ <string name="inattentive_sleep_warning_message" product="tv">The Android TV device will soon turn off; press a button to keep it on.</string>
+ <!-- Message of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=NONE] -->
+ <string name="inattentive_sleep_warning_message" product="default">The device will soon turn off; press to keep it on.</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 3cf14d6..25986c5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -25,6 +25,7 @@
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.pip.PipUI;
+import com.android.systemui.power.InattentiveSleepWarningController;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
@@ -102,6 +103,13 @@
@ClassKey(PowerUI.class)
public abstract SystemUI bindPowerUI(PowerUI sysui);
+ /** Inject into InattentiveSleepWarningController. */
+ @Binds
+ @IntoMap
+ @ClassKey(InattentiveSleepWarningController.class)
+ public abstract SystemUI bindInattentiveSleepWarningController(
+ InattentiveSleepWarningController sysui);
+
/** Inject into Recents. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java
new file mode 100644
index 0000000..7169431
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.power;
+
+import android.content.Context;
+
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.CommandQueue;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Receives messages sent from {@link com.android.server.power.InattentiveSleepWarningController}
+ * and shows the appropriate inattentive sleep UI (e.g. {@link InattentiveSleepWarningView}).
+ */
+@Singleton
+public class InattentiveSleepWarningController extends SystemUI implements CommandQueue.Callbacks {
+ private final CommandQueue mCommandQueue;
+ private InattentiveSleepWarningView mOverlayView;
+
+ @Inject
+ public InattentiveSleepWarningController(Context context, CommandQueue commandQueue) {
+ super(context);
+ mCommandQueue = commandQueue;
+ }
+
+ @Override
+ public void start() {
+ mCommandQueue.addCallback(this);
+ }
+
+ @Override
+ public void showInattentiveSleepWarning() {
+ if (mOverlayView == null) {
+ mOverlayView = new InattentiveSleepWarningView(mContext);
+ }
+
+ mOverlayView.show();
+ }
+
+ @Override
+ public void dismissInattentiveSleepWarning() {
+ if (mOverlayView != null) {
+ mOverlayView.dismiss();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
new file mode 100644
index 0000000..8ccc679
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.power;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+/**
+ * View that shows a warning shortly before the device goes into sleep
+ * after prolonged user inactivity when bound to.
+ */
+public class InattentiveSleepWarningView extends FrameLayout {
+ private final IBinder mWindowToken = new Binder();
+ private final WindowManager mWindowManager;
+
+ InattentiveSleepWarningView(Context context) {
+ super(context);
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+
+ final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ layoutInflater.inflate(R.layout.inattentive_sleep_warning, this, true /* attachToRoot */);
+
+ setFocusable(true);
+ setOnKeyListener((v, keyCode, event) -> {
+ // overlay consumes key presses
+ return true;
+ });
+ }
+
+ /**
+ * Show the warning.
+ */
+ public void show() {
+ if (getParent() == null) {
+ mWindowManager.addView(this, getLayoutParams(mWindowToken));
+ }
+ }
+
+ /**
+ * Dismiss the warning.
+ */
+ public void dismiss() {
+ if (getParent() != null) {
+ mWindowManager.removeView(this);
+ }
+ }
+
+ /**
+ * @param windowToken token for the window
+ */
+ private WindowManager.LayoutParams getLayoutParams(IBinder windowToken) {
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ PixelFormat.TRANSLUCENT);
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ lp.setTitle("InattentiveSleepWarning");
+ lp.token = windowToken;
+ return lp;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 94a1cf0..d377f1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -319,7 +319,14 @@
} else{
mColumns = mCellWidth == 0 ? 1 :
Math.min(maxTiles, availableWidth / mCellWidth );
- mCellMarginHorizontal = (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+ // If we can only fit one column, use mCellMarginHorizontal to center it.
+ if (mColumns == 1) {
+ mCellMarginHorizontal = (availableWidth - mCellWidth) / 2;
+ } else {
+ mCellMarginHorizontal =
+ (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+ }
+
}
return mColumns != prevNumColumns;
}
@@ -357,6 +364,10 @@
@Override
protected int getColumnStart(int column) {
+ if (mColumns == 1) {
+ // Only one column/tile. Use the margin to center the tile.
+ return getPaddingStart() + mCellMarginHorizontal;
+ }
return getPaddingStart() + column * (mCellWidth + mCellMarginHorizontal);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 621f101..88b6fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -70,53 +70,55 @@
private static final int OP_SET_ICON = 1;
private static final int OP_REMOVE_ICON = 2;
- private static final int MSG_ICON = 1 << MSG_SHIFT;
- private static final int MSG_DISABLE = 2 << MSG_SHIFT;
- private static final int MSG_EXPAND_NOTIFICATIONS = 3 << MSG_SHIFT;
- private static final int MSG_COLLAPSE_PANELS = 4 << MSG_SHIFT;
- private static final int MSG_EXPAND_SETTINGS = 5 << MSG_SHIFT;
- private static final int MSG_SYSTEM_BAR_APPEARANCE_CHANGED = 6 << MSG_SHIFT;
- private static final int MSG_DISPLAY_READY = 7 << MSG_SHIFT;
- private static final int MSG_SHOW_IME_BUTTON = 8 << MSG_SHIFT;
- private static final int MSG_TOGGLE_RECENT_APPS = 9 << MSG_SHIFT;
- private static final int MSG_PRELOAD_RECENT_APPS = 10 << MSG_SHIFT;
- private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 11 << MSG_SHIFT;
- private static final int MSG_SET_WINDOW_STATE = 12 << MSG_SHIFT;
- private static final int MSG_SHOW_RECENT_APPS = 13 << MSG_SHIFT;
- private static final int MSG_HIDE_RECENT_APPS = 14 << MSG_SHIFT;
- private static final int MSG_SHOW_SCREEN_PIN_REQUEST = 18 << MSG_SHIFT;
- private static final int MSG_APP_TRANSITION_PENDING = 19 << MSG_SHIFT;
- private static final int MSG_APP_TRANSITION_CANCELLED = 20 << MSG_SHIFT;
- private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
- private static final int MSG_ASSIST_DISCLOSURE = 22 << MSG_SHIFT;
- private static final int MSG_START_ASSIST = 23 << MSG_SHIFT;
- private static final int MSG_CAMERA_LAUNCH_GESTURE = 24 << MSG_SHIFT;
- private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS = 25 << MSG_SHIFT;
- private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 26 << MSG_SHIFT;
- private static final int MSG_ADD_QS_TILE = 27 << MSG_SHIFT;
- private static final int MSG_REMOVE_QS_TILE = 28 << MSG_SHIFT;
- private static final int MSG_CLICK_QS_TILE = 29 << MSG_SHIFT;
- private static final int MSG_TOGGLE_APP_SPLIT_SCREEN = 30 << MSG_SHIFT;
- private static final int MSG_APP_TRANSITION_FINISHED = 31 << MSG_SHIFT;
- private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS = 32 << MSG_SHIFT;
- private static final int MSG_HANDLE_SYSTEM_KEY = 33 << MSG_SHIFT;
- private static final int MSG_SHOW_GLOBAL_ACTIONS = 34 << MSG_SHIFT;
- private static final int MSG_TOGGLE_PANEL = 35 << MSG_SHIFT;
- private static final int MSG_SHOW_SHUTDOWN_UI = 36 << MSG_SHIFT;
- private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR = 37 << MSG_SHIFT;
- private static final int MSG_ROTATION_PROPOSAL = 38 << MSG_SHIFT;
- private static final int MSG_BIOMETRIC_SHOW = 39 << MSG_SHIFT;
- private static final int MSG_BIOMETRIC_AUTHENTICATED = 40 << MSG_SHIFT;
- private static final int MSG_BIOMETRIC_HELP = 41 << MSG_SHIFT;
- private static final int MSG_BIOMETRIC_ERROR = 42 << MSG_SHIFT;
- private static final int MSG_BIOMETRIC_HIDE = 43 << MSG_SHIFT;
- private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
- private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
- private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
- private static final int MSG_RECENTS_ANIMATION_STATE_CHANGED = 47 << MSG_SHIFT;
- private static final int MSG_SHOW_TRANSIENT = 48 << MSG_SHIFT;
- private static final int MSG_ABORT_TRANSIENT = 49 << MSG_SHIFT;
- private static final int MSG_TOP_APP_WINDOW_CHANGED = 50 << MSG_SHIFT;
+ private static final int MSG_ICON = 1 << MSG_SHIFT;
+ private static final int MSG_DISABLE = 2 << MSG_SHIFT;
+ private static final int MSG_EXPAND_NOTIFICATIONS = 3 << MSG_SHIFT;
+ private static final int MSG_COLLAPSE_PANELS = 4 << MSG_SHIFT;
+ private static final int MSG_EXPAND_SETTINGS = 5 << MSG_SHIFT;
+ private static final int MSG_SYSTEM_BAR_APPEARANCE_CHANGED = 6 << MSG_SHIFT;
+ private static final int MSG_DISPLAY_READY = 7 << MSG_SHIFT;
+ private static final int MSG_SHOW_IME_BUTTON = 8 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_RECENT_APPS = 9 << MSG_SHIFT;
+ private static final int MSG_PRELOAD_RECENT_APPS = 10 << MSG_SHIFT;
+ private static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 11 << MSG_SHIFT;
+ private static final int MSG_SET_WINDOW_STATE = 12 << MSG_SHIFT;
+ private static final int MSG_SHOW_RECENT_APPS = 13 << MSG_SHIFT;
+ private static final int MSG_HIDE_RECENT_APPS = 14 << MSG_SHIFT;
+ private static final int MSG_SHOW_SCREEN_PIN_REQUEST = 18 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_PENDING = 19 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_CANCELLED = 20 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
+ private static final int MSG_ASSIST_DISCLOSURE = 22 << MSG_SHIFT;
+ private static final int MSG_START_ASSIST = 23 << MSG_SHIFT;
+ private static final int MSG_CAMERA_LAUNCH_GESTURE = 24 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS = 25 << MSG_SHIFT;
+ private static final int MSG_SHOW_PICTURE_IN_PICTURE_MENU = 26 << MSG_SHIFT;
+ private static final int MSG_ADD_QS_TILE = 27 << MSG_SHIFT;
+ private static final int MSG_REMOVE_QS_TILE = 28 << MSG_SHIFT;
+ private static final int MSG_CLICK_QS_TILE = 29 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_APP_SPLIT_SCREEN = 30 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_FINISHED = 31 << MSG_SHIFT;
+ private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS = 32 << MSG_SHIFT;
+ private static final int MSG_HANDLE_SYSTEM_KEY = 33 << MSG_SHIFT;
+ private static final int MSG_SHOW_GLOBAL_ACTIONS = 34 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_PANEL = 35 << MSG_SHIFT;
+ private static final int MSG_SHOW_SHUTDOWN_UI = 36 << MSG_SHIFT;
+ private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR = 37 << MSG_SHIFT;
+ private static final int MSG_ROTATION_PROPOSAL = 38 << MSG_SHIFT;
+ private static final int MSG_BIOMETRIC_SHOW = 39 << MSG_SHIFT;
+ private static final int MSG_BIOMETRIC_AUTHENTICATED = 40 << MSG_SHIFT;
+ private static final int MSG_BIOMETRIC_HELP = 41 << MSG_SHIFT;
+ private static final int MSG_BIOMETRIC_ERROR = 42 << MSG_SHIFT;
+ private static final int MSG_BIOMETRIC_HIDE = 43 << MSG_SHIFT;
+ private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
+ private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
+ private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
+ private static final int MSG_RECENTS_ANIMATION_STATE_CHANGED = 47 << MSG_SHIFT;
+ private static final int MSG_SHOW_TRANSIENT = 48 << MSG_SHIFT;
+ private static final int MSG_ABORT_TRANSIENT = 49 << MSG_SHIFT;
+ private static final int MSG_TOP_APP_WINDOW_CHANGED = 50 << MSG_SHIFT;
+ private static final int MSG_SHOW_INATTENTIVE_SLEEP_WARNING = 51 << MSG_SHIFT;
+ private static final int MSG_DISMISS_INATTENTIVE_SLEEP_WARNING = 52 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -294,6 +296,18 @@
*/
default void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
}
+
+ /**
+ * Called to notify System UI that a warning about the device going to sleep
+ * due to prolonged user inactivity should be shown.
+ */
+ default void showInattentiveSleepWarning() { }
+
+ /**
+ * Called to notify System UI that the warning about the device going to sleep
+ * due to prolonged user inactivity should be dismissed.
+ */
+ default void dismissInattentiveSleepWarning() { }
}
public CommandQueue(Context context) {
@@ -793,6 +807,22 @@
}
}
+ @Override
+ public void showInattentiveSleepWarning() {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SHOW_INATTENTIVE_SLEEP_WARNING)
+ .sendToTarget();
+ }
+ }
+
+ @Override
+ public void dismissInattentiveSleepWarning() {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_DISMISS_INATTENTIVE_SLEEP_WARNING)
+ .sendToTarget();
+ }
+ }
+
private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition,
boolean showImeSwitcher, boolean isMultiClientImeEnabled) {
if (displayId == INVALID_DISPLAY) return;
@@ -1138,6 +1168,16 @@
args.recycle();
break;
}
+ case MSG_SHOW_INATTENTIVE_SLEEP_WARNING:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showInattentiveSleepWarning();
+ }
+ break;
+ case MSG_DISMISS_INATTENTIVE_SLEEP_WARNING:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).dismissInattentiveSleepWarning();
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
index b21c65e..18574f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
@@ -71,7 +71,7 @@
ViewParent parent = view.getParent();
StatusBarNotification statusBarNotification =
- getRowForParent(parent).getStatusBarNotification();
+ getRowForParent(parent).getEntry().getSbn();
final Intent intent = new Intent()
.setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
.putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index ef40d98..0bfcdbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -44,7 +44,7 @@
private static final DataExtractor sIconExtractor = new DataExtractor() {
@Override
public Object extractData(ExpandableNotificationRow row) {
- return row.getStatusBarNotification().getNotification();
+ return row.getEntry().getSbn().getNotification();
}
};
private static final IconComparator sIconVisibilityComparator = new IconComparator() {
@@ -207,7 +207,7 @@
}
// in case no view is visible we make sure the time is visible
int timeVisibility = !hasVisibleText
- || mRow.getStatusBarNotification().getNotification().showsTime()
+ || mRow.getEntry().getSbn().getNotification().showsTime()
? View.VISIBLE : View.GONE;
time.setVisibility(timeVisibility);
View left = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index e10d27b..c556bc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -216,7 +216,7 @@
private StatusBarNotification getNotificationForParent(ViewParent parent) {
while (parent != null) {
if (parent instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) parent).getStatusBarNotification();
+ return ((ExpandableNotificationRow) parent).getEntry().getSbn();
}
parent = parent.getParent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index ef733a9..4204f68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -204,7 +204,7 @@
}
for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
- if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getStatusBarNotification())) {
+ if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getEntry().getSbn())) {
// we are only transferring this notification to its parent, don't generate an
// animation
mListContainer.setChildTransferInProgress(true);
@@ -339,7 +339,7 @@
for (ExpandableNotificationRow remove : toRemove) {
parent.removeChildNotification(remove);
if (mEntryManager.getActiveNotificationUnfiltered(
- remove.getStatusBarNotification().getKey()) == null) {
+ remove.getEntry().getSbn().getKey()) == null) {
// We only want to add an animation if the view is completely removed
// otherwise it's just a transfer
mListContainer.notifyGroupChildRemoved(remove,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
index fd2f720..b5c6641 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
@@ -55,7 +55,7 @@
mShadeController.wakeUpIfDozing(SystemClock.uptimeMillis(), v, "NOTIFICATION_CLICK");
final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
- final StatusBarNotification sbn = row.getStatusBarNotification();
+ final StatusBarNotification sbn = row.getEntry().getSbn();
if (sbn == null) {
Log.e(TAG, "NotificationClicker called on an unclickable notification,");
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index f0d07a7..9ac5b44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -198,7 +198,6 @@
private String mLoggingKey;
private NotificationGuts mGuts;
private NotificationEntry mEntry;
- private StatusBarNotification mStatusBarNotification;
private String mAppName;
/**
@@ -261,10 +260,10 @@
@Override
public void onClick(View v) {
if (!shouldShowPublic() && (!mIsLowPriority || isExpanded())
- && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+ && mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
mGroupExpansionChanging = true;
- final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
- boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+ final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+ boolean nowExpanded = mGroupManager.toggleGroupExpansion(mEntry.getSbn());
mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
nowExpanded);
@@ -441,7 +440,6 @@
*/
public void setEntry(@NonNull NotificationEntry entry) {
mEntry = entry;
- mStatusBarNotification = entry.getSbn();
cacheIsSystemNotification();
}
@@ -516,7 +514,7 @@
*/
public boolean getIsNonblockable() {
boolean isNonblockable = Dependency.get(NotificationBlockingHelperManager.class)
- .isNonblockable(mStatusBarNotification.getPackageName(),
+ .isNonblockable(mEntry.getSbn().getPackageName(),
mEntry.getChannel().getId());
// If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once
@@ -526,7 +524,7 @@
Log.d(TAG, "Retrieving isSystemNotification on main thread");
}
mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */);
- mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification);
+ mEntry.mIsSystemNotification = isSystemNotification(mContext, mEntry.getSbn());
}
isNonblockable |= mEntry.getChannel().isImportanceLockedByOEM();
@@ -547,11 +545,11 @@
for (NotificationContentView l : mLayouts) {
l.onNotificationUpdated(mEntry);
}
- mIsColorized = mStatusBarNotification.getNotification().isColorized();
+ mIsColorized = mEntry.getSbn().getNotification().isColorized();
mShowingPublicInitialized = false;
updateNotificationColor();
if (mMenuRow != null) {
- mMenuRow.onNotificationUpdated(mStatusBarNotification);
+ mMenuRow.onNotificationUpdated(mEntry.getSbn());
mMenuRow.setAppName(mAppName);
}
if (mIsSummaryWithChildren) {
@@ -583,7 +581,7 @@
/** Called when the notification's ranking was changed (but nothing else changed). */
public void onNotificationRankingUpdated() {
if (mMenuRow != null) {
- mMenuRow.onNotificationUpdated(mStatusBarNotification);
+ mMenuRow.onNotificationUpdated(mEntry.getSbn());
}
}
@@ -676,10 +674,6 @@
layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight);
}
- public StatusBarNotification getStatusBarNotification() {
- return mStatusBarNotification;
- }
-
public NotificationEntry getEntry() {
return mEntry;
}
@@ -807,7 +801,7 @@
* @return whether this notification is the only child in the group summary
*/
public boolean isOnlyChildInGroup() {
- return mGroupManager.isOnlyChildInGroup(getStatusBarNotification());
+ return mGroupManager.isOnlyChildInGroup(mEntry.getSbn());
}
public ExpandableNotificationRow getNotificationParent() {
@@ -1181,7 +1175,7 @@
}
if (mMenuRow.getMenuView() == null) {
- mMenuRow.createMenu(this, mStatusBarNotification);
+ mMenuRow.createMenu(this, mEntry.getSbn());
mMenuRow.setAppName(mAppName);
FrameLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
@@ -1222,7 +1216,7 @@
if (oldMenu != null) {
int menuIndex = indexOfChild(oldMenu);
removeView(oldMenu);
- mMenuRow.createMenu(ExpandableNotificationRow.this, mStatusBarNotification);
+ mMenuRow.createMenu(ExpandableNotificationRow.this, mEntry.getSbn());
mMenuRow.setAppName(mAppName);
addView(mMenuRow.getMenuView(), menuIndex);
}
@@ -1230,7 +1224,7 @@
l.initView();
l.reInflateViews();
}
- mStatusBarNotification.clearPackageContext();
+ mEntry.getSbn().clearPackageContext();
mNotificationInflater.clearCachesAndReInflate();
}
@@ -1290,7 +1284,7 @@
== Configuration.UI_MODE_NIGHT_YES;
mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
- getStatusBarNotification().getNotification().color,
+ mEntry.getSbn().getNotification().color,
getBackgroundColorWithoutTint(), nightMode);
}
@@ -1438,7 +1432,7 @@
public void performDismiss(boolean fromAccessibility) {
if (isOnlyChildInGroup()) {
NotificationEntry groupSummary =
- mGroupManager.getLogicalGroupSummary(getStatusBarNotification());
+ mGroupManager.getLogicalGroupSummary(mEntry.getSbn());
if (groupSummary.isClearable()) {
// If this is the only child in the group, dismiss the group, but don't try to show
// the blocking helper affordance!
@@ -2209,8 +2203,8 @@
getFalsingManager().setNotificationExpanded();
if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
&& !mChildrenContainer.showingAsLowPriority()) {
- final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
- mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
+ final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+ mGroupManager.setGroupExpanded(mEntry.getSbn(), userExpanded);
onExpansionChanged(true /* userAction */, wasExpanded);
return;
}
@@ -2356,7 +2350,7 @@
@Override
public boolean isGroupExpanded() {
- return mGroupManager.isGroupExpanded(mStatusBarNotification);
+ return mGroupManager.isGroupExpanded(mEntry.getSbn());
}
private void onChildrenCountChanged() {
@@ -2397,9 +2391,9 @@
for (int i = 0; i < numChildren; i++) {
final ExpandableNotificationRow childRow = childrenRows.get(i);
final NotificationChannel childChannel = childRow.getEntry().getChannel();
- final StatusBarNotification childSbn = childRow.getStatusBarNotification();
- if (childSbn.getUser().equals(mStatusBarNotification.getUser()) &&
- childSbn.getPackageName().equals(mStatusBarNotification.getPackageName())) {
+ final StatusBarNotification childSbn = childRow.getEntry().getSbn();
+ if (childSbn.getUser().equals(mEntry.getSbn().getUser())
+ && childSbn.getPackageName().equals(mEntry.getSbn().getPackageName())) {
channels.add(childChannel);
}
}
@@ -2593,7 +2587,7 @@
public void makeActionsVisibile() {
setUserExpanded(true, true);
if (isChildInGroup()) {
- mGroupManager.setGroupExpanded(mStatusBarNotification, true);
+ mGroupManager.setGroupExpanded(mEntry.getSbn(), true);
}
notifyHeightChanged(false /* needsAnimation */);
}
@@ -2890,7 +2884,7 @@
public void onExpandedByGesture(boolean userExpanded) {
int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER;
- if (mGroupManager.isSummaryOfGroup(getStatusBarNotification())) {
+ if (mGroupManager.isSummaryOfGroup(mEntry.getSbn())) {
event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER;
}
MetricsLogger.action(mContext, event, userExpanded);
@@ -2935,7 +2929,7 @@
private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
boolean nowExpanded = isExpanded();
if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
- nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
+ nowExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
}
if (nowExpanded != wasExpanded) {
updateShelfIconColor();
@@ -3224,7 +3218,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
super.dump(fd, pw, args);
- pw.println(" Notification: " + getStatusBarNotification().getKey());
+ pw.println(" Notification: " + mEntry.getKey());
pw.print(" visibility: " + getVisibility());
pw.print(", alpha: " + getAlpha());
pw.print(", translation: " + getTranslation());
@@ -3267,7 +3261,7 @@
@Override
protected Boolean doInBackground(Void... voids) {
- return isSystemNotification(mContext, mStatusBarNotification);
+ return isSystemNotification(mContext, mEntry.getSbn());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 37f63c9..7b758aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -166,7 +166,7 @@
}
private LogMaker getLogMaker() {
- return mBlockingHelperRow.getStatusBarNotification()
+ return mBlockingHelperRow.getEntry().getSbn()
.getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index a91a119..54dee8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -512,7 +512,7 @@
existingWrapper.onReinflated();
}
} catch (Exception e) {
- handleInflationError(runningInflations, e, row.getStatusBarNotification(), callback);
+ handleInflationError(runningInflations, e, row.getEntry().getSbn(), callback);
// Add a running inflation to make sure we don't trigger callbacks.
// Safe to do because only happens in tests.
runningInflations.put(inflationId, new CancellationSignal());
@@ -563,7 +563,7 @@
onViewApplied(newView);
} catch (Exception anotherException) {
runningInflations.remove(inflationId);
- handleInflationError(runningInflations, e, row.getStatusBarNotification(),
+ handleInflationError(runningInflations, e, row.getEntry().getSbn(),
callback);
}
}
@@ -838,7 +838,7 @@
private void handleError(Exception e) {
mRow.getEntry().onInflationTaskFinished();
- StatusBarNotification sbn = mRow.getStatusBarNotification();
+ StatusBarNotification sbn = mRow.getEntry().getSbn();
final String ident = sbn.getPackageName() + "/0x"
+ Integer.toHexString(sbn.getId());
Log.e(StatusBar.TAG, "couldn't inflate view for notification " + ident, e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index f67cd1b..77c0a46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -189,7 +189,7 @@
@VisibleForTesting
protected boolean bindGuts(final ExpandableNotificationRow row,
NotificationMenuRowPlugin.MenuItem item) {
- StatusBarNotification sbn = row.getStatusBarNotification();
+ StatusBarNotification sbn = row.getEntry().getSbn();
row.setGutsView(item);
row.setTag(sbn.getPackageName());
@@ -238,7 +238,7 @@
final ExpandableNotificationRow row,
NotificationSnooze notificationSnoozeView) {
NotificationGuts guts = row.getGuts();
- StatusBarNotification sbn = row.getStatusBarNotification();
+ StatusBarNotification sbn = row.getEntry().getSbn();
notificationSnoozeView.setSnoozeListener(mListContainer.getSwipeActionHelper());
notificationSnoozeView.setStatusBarNotification(sbn);
@@ -258,7 +258,7 @@
final ExpandableNotificationRow row,
AppOpsInfo appOpsInfoView) {
NotificationGuts guts = row.getGuts();
- StatusBarNotification sbn = row.getStatusBarNotification();
+ StatusBarNotification sbn = row.getEntry().getSbn();
UserHandle userHandle = sbn.getUser();
PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
userHandle.getIdentifier());
@@ -284,7 +284,7 @@
final ExpandableNotificationRow row,
NotificationInfo notificationInfoView) throws Exception {
NotificationGuts guts = row.getGuts();
- StatusBarNotification sbn = row.getStatusBarNotification();
+ StatusBarNotification sbn = row.getEntry().getSbn();
String packageName = sbn.getPackageName();
// Settings link is only valid for notifications that specify a non-system user
NotificationInfo.OnSettingsClickListener onSettingsClick = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
index 2da4d2c..7248bce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
@@ -39,7 +39,7 @@
@Override
public void onContentUpdated(ExpandableNotificationRow row) {
super.onContentUpdated(row);
- updateImageTag(row.getStatusBarNotification());
+ updateImageTag(row.getEntry().getSbn());
}
private void updateImageTag(StatusBarNotification notification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
index 4261df3..41f93cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -44,7 +44,7 @@
public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
- resolveViews(row.getStatusBarNotification());
+ resolveViews(row.getEntry().getSbn());
super.onContentUpdated(row);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 0b3871d..5e52c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -125,7 +125,7 @@
updateTransformedTypes();
addRemainingTransformTypes();
updateCropToPaddingForImageViews();
- Notification notification = row.getStatusBarNotification().getNotification();
+ Notification notification = row.getEntry().getSbn().getNotification();
mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
// The work profile image is always the same lets just set the icon tag for it not to
// animate
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 516d649..2a4b315 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -183,7 +183,7 @@
QuickQSPanel panel = ctrl.getStatusBarView().findViewById(
com.android.systemui.R.id.quick_qs_panel);
panel.getMediaPlayer().setMediaSession(token,
- mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+ mRow.getEntry().getSbn().getNotification().getSmallIcon(),
getNotificationHeader().getOriginalIconColor(),
mRow.getCurrentBackgroundTint(),
mActions,
@@ -191,11 +191,11 @@
QSPanel bigPanel = ctrl.getStatusBarView().findViewById(
com.android.systemui.R.id.quick_settings_panel);
bigPanel.addMediaSession(token,
- mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+ mRow.getEntry().getSbn().getNotification().getSmallIcon(),
getNotificationHeader().getOriginalIconColor(),
mRow.getCurrentBackgroundTint(),
mActions,
- mRow.getStatusBarNotification());
+ mRow.getEntry().getSbn());
}
boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 97d8443..90ea6e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -286,7 +286,7 @@
public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
// the transformation types and we need to have our values set by then.
- resolveTemplateViews(row.getStatusBarNotification());
+ resolveTemplateViews(row.getEntry().getSbn());
super.onContentUpdated(row);
if (row.getHeaderVisibleAmount() != DEFAULT_HEADER_VISIBLE_AMOUNT) {
setHeaderVisibleAmount(row.getHeaderVisibleAmount());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 45f7b3a..75ceb0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -299,7 +299,7 @@
public void recreateNotificationHeader(OnClickListener listener) {
mHeaderClickListener = listener;
- StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+ StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
notification.getNotification());
RemoteViews header = builder.makeNotificationHeader();
@@ -329,7 +329,7 @@
*/
private void recreateLowPriorityHeader(Notification.Builder builder) {
RemoteViews header;
- StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+ StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
if (mIsLowPriority) {
if (builder == null) {
builder = Notification.Builder.recoverBuilder(getContext(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 462fa59..43af3aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1454,8 +1454,8 @@
}
ExpandableNotificationRow row = topEntry.getRow();
if (row.isChildInGroup()) {
- final NotificationEntry groupSummary
- = mGroupManager.getGroupSummary(row.getStatusBarNotification());
+ final NotificationEntry groupSummary =
+ mGroupManager.getGroupSummary(row.getEntry().getSbn());
if (groupSummary != null) {
row = groupSummary.getRow();
}
@@ -2996,7 +2996,7 @@
private boolean isChildInGroup(View child) {
return child instanceof ExpandableNotificationRow
&& mGroupManager.isChildInGroupWithSummary(
- ((ExpandableNotificationRow) child).getStatusBarNotification());
+ ((ExpandableNotificationRow) child).getEntry().getSbn());
}
/**
@@ -3071,7 +3071,7 @@
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
NotificationEntry groupSummary =
- mGroupManager.getGroupSummary(row.getStatusBarNotification());
+ mGroupManager.getGroupSummary(row.getEntry().getSbn());
if (groupSummary != null && groupSummary.getRow() != row) {
return row.getVisibility() == View.INVISIBLE;
}
@@ -6134,7 +6134,7 @@
}
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
- mMetricsLogger.write(row.getStatusBarNotification().getLogMaker()
+ mMetricsLogger.write(row.getEntry().getSbn().getLogMaker()
.setCategory(MetricsEvent.ACTION_TOUCH_GEAR)
.setType(MetricsEvent.TYPE_ACTION)
);
@@ -6160,7 +6160,7 @@
public void onMenuShown(View row) {
if (row instanceof ExpandableNotificationRow) {
ExpandableNotificationRow notificationRow = (ExpandableNotificationRow) row;
- mMetricsLogger.write(notificationRow.getStatusBarNotification().getLogMaker()
+ mMetricsLogger.write(notificationRow.getEntry().getSbn().getLogMaker()
.setCategory(MetricsEvent.ACTION_REVEAL_GEAR)
.setType(MetricsEvent.TYPE_ACTION));
mHeadsUpManager.setMenuShown(notificationRow.getEntry(), true);
@@ -6256,7 +6256,7 @@
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
if (row.isHeadsUp()) {
mHeadsUpManager.addSwipedOutNotification(
- row.getStatusBarNotification().getKey());
+ row.getEntry().getSbn().getKey());
}
isBlockingHelperShown =
row.performDismissWithBlockingHelper(false /* fromAccessibility */);
@@ -6327,9 +6327,9 @@
if (animView instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
if (row.isPinned() && !canChildBeDismissed(row)
- && row.getStatusBarNotification().getNotification().fullScreenIntent
+ && row.getEntry().getSbn().getNotification().fullScreenIntent
== null) {
- mHeadsUpManager.removeNotification(row.getStatusBarNotification().getKey(),
+ mHeadsUpManager.removeNotification(row.getEntry().getSbn().getKey(),
true /* removeImmediately */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 1c8e832..8ee964f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -22,7 +22,6 @@
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
@@ -32,9 +31,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
-import android.util.MathUtils;
import android.util.StatsLog;
-import android.view.Gravity;
import android.view.ISystemGestureExclusionListener;
import android.view.InputChannel;
import android.view.InputDevice;
@@ -44,7 +41,6 @@
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -53,7 +49,10 @@
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.plugins.NavigationEdgeBackPlugin;
+import com.android.systemui.plugins.PluginListener;
import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.QuickStepContract;
import java.io.PrintWriter;
@@ -62,7 +61,8 @@
/**
* Utility class to handle edge swipes for back gesture
*/
-public class EdgeBackGestureHandler implements DisplayListener {
+public class EdgeBackGestureHandler implements DisplayListener,
+ PluginListener<NavigationEdgeBackPlugin> {
private static final String TAG = "EdgeBackGestureHandler";
private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
@@ -85,6 +85,7 @@
private final Context mContext;
private final OverviewProxyService mOverviewProxyService;
+ private PluginManager mPluginManager;
private final Point mDisplaySize = new Point();
private final int mDisplayId;
@@ -100,14 +101,6 @@
private final float mTouchSlop;
// Duration after which we consider the event as longpress.
private final int mLongPressTimeout;
- // The threshold where the touch needs to be at most, such that the arrow is displayed above the
- // finger, otherwise it will be below
- private final int mMinArrowPosition;
- // The amount by which the arrow is shifted to avoid the finger
- private final int mFingerOffset;
-
-
- private final int mNavBarHeight;
private final PointF mDownPoint = new PointF();
private boolean mThresholdCrossed = false;
@@ -123,24 +116,49 @@
private InputMonitor mInputMonitor;
private InputEventReceiver mInputEventReceiver;
- private final WindowManager mWm;
-
- private NavigationBarEdgePanel mEdgePanel;
- private WindowManager.LayoutParams mEdgePanelLp;
- private final Rect mSamplingRect = new Rect();
- private RegionSamplingHelper mRegionSamplingHelper;
+ private NavigationEdgeBackPlugin mEdgeBackPlugin;
private int mLeftInset;
private int mRightInset;
private int mSysUiFlags;
+ private final NavigationEdgeBackPlugin.BackCallback mBackCallback =
+ new NavigationEdgeBackPlugin.BackCallback() {
+ @Override
+ public void triggerBack() {
+ sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+ sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+
+ mOverviewProxyService.notifyBackAction(true, (int) mDownPoint.x,
+ (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
+ int backtype = (mInRejectedExclusion
+ ? StatsLog.BACK_GESTURE__TYPE__COMPLETED_REJECTED :
+ StatsLog.BACK_GESTURE__TYPE__COMPLETED);
+ StatsLog.write(StatsLog.BACK_GESTURE_REPORTED_REPORTED, backtype,
+ (int) mDownPoint.y, mIsOnLeftEdge
+ ? StatsLog.BACK_GESTURE__X_LOCATION__LEFT :
+ StatsLog.BACK_GESTURE__X_LOCATION__RIGHT);
+ }
+
+ @Override
+ public void cancelBack() {
+ mOverviewProxyService.notifyBackAction(false, (int) mDownPoint.x,
+ (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
+ int backtype = StatsLog.BACK_GESTURE__TYPE__INCOMPLETE;
+ StatsLog.write(StatsLog.BACK_GESTURE_REPORTED_REPORTED, backtype,
+ (int) mDownPoint.y, mIsOnLeftEdge
+ ? StatsLog.BACK_GESTURE__X_LOCATION__LEFT :
+ StatsLog.BACK_GESTURE__X_LOCATION__RIGHT);
+ }
+ };
+
public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
- SysUiState sysUiFlagContainer) {
+ SysUiState sysUiFlagContainer, PluginManager pluginManager) {
final Resources res = context.getResources();
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
- mWm = context.getSystemService(WindowManager.class);
mOverviewProxyService = overviewProxyService;
+ mPluginManager = pluginManager;
// Reduce the default touch slop to ensure that we can intercept the gesture
// before the app starts to react to it.
@@ -149,9 +167,6 @@
mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
ViewConfiguration.getLongPressTimeout());
- mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
- mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
- mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
updateCurrentUserResources(res);
sysUiFlagContainer.addCallback(sysUiFlags -> mSysUiFlags = sysUiFlags);
}
@@ -206,15 +221,14 @@
mIsEnabled = isEnabled;
disposeInputChannel();
- if (mEdgePanel != null) {
- mWm.removeView(mEdgePanel);
- mEdgePanel = null;
- mRegionSamplingHelper.stop();
- mRegionSamplingHelper = null;
+ if (mEdgeBackPlugin != null) {
+ mEdgeBackPlugin.onDestroy();
+ mEdgeBackPlugin = null;
}
if (!mIsEnabled) {
mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ mPluginManager.removePluginListener(this);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -244,41 +258,51 @@
mInputMonitor.getInputChannel(), Looper.getMainLooper());
// Add a nav bar panel window
- mEdgePanel = new NavigationBarEdgePanel(mContext);
- mEdgePanelLp = new WindowManager.LayoutParams(
- mContext.getResources()
- .getDimensionPixelSize(R.dimen.navigation_edge_panel_width),
- mContext.getResources()
- .getDimensionPixelSize(R.dimen.navigation_edge_panel_height),
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
- PixelFormat.TRANSLUCENT);
- mEdgePanelLp.privateFlags |=
- WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
- mEdgePanelLp.setTitle(TAG + mDisplayId);
- mEdgePanelLp.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
- mEdgePanelLp.windowAnimations = 0;
- mEdgePanel.setLayoutParams(mEdgePanelLp);
- mWm.addView(mEdgePanel, mEdgePanelLp);
- mRegionSamplingHelper = new RegionSamplingHelper(mEdgePanel,
- new RegionSamplingHelper.SamplingCallback() {
- @Override
- public void onRegionDarknessChanged(boolean isRegionDark) {
- mEdgePanel.setIsDark(!isRegionDark, true /* animate */);
- }
-
- @Override
- public Rect getSampledRegion(View sampledView) {
- return mSamplingRect;
- }
- });
- mRegionSamplingHelper.setWindowVisible(true);
+ setEdgeBackPlugin(new NavigationBarEdgePanel(mContext));
+ mPluginManager.addPluginListener(
+ this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
}
}
+ @Override
+ public void onPluginConnected(NavigationEdgeBackPlugin plugin, Context context) {
+ setEdgeBackPlugin(plugin);
+ }
+
+ @Override
+ public void onPluginDisconnected(NavigationEdgeBackPlugin plugin) {
+ setEdgeBackPlugin(new NavigationBarEdgePanel(mContext));
+ }
+
+ private void setEdgeBackPlugin(NavigationEdgeBackPlugin edgeBackPlugin) {
+ if (mEdgeBackPlugin != null) {
+ mEdgeBackPlugin.onDestroy();
+ }
+ mEdgeBackPlugin = edgeBackPlugin;
+ mEdgeBackPlugin.setBackCallback(mBackCallback);
+ mEdgeBackPlugin.setLayoutParams(createLayoutParams());
+ updateDisplaySize();
+ }
+
+ private WindowManager.LayoutParams createLayoutParams() {
+ Resources resources = mContext.getResources();
+ WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+ resources.getDimensionPixelSize(R.dimen.navigation_edge_panel_width),
+ resources.getDimensionPixelSize(R.dimen.navigation_edge_panel_height),
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ PixelFormat.TRANSLUCENT);
+ layoutParams.privateFlags |=
+ WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ layoutParams.setTitle(TAG + mContext.getDisplayId());
+ layoutParams.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
+ layoutParams.windowAnimations = 0;
+ return layoutParams;
+ }
+
private void onInputEvent(InputEvent ev) {
if (ev instanceof MotionEvent) {
onMotionEvent((MotionEvent) ev);
@@ -316,7 +340,7 @@
mInRejectedExclusion = false;
MotionEvent cancelEv = MotionEvent.obtain(ev);
cancelEv.setAction(MotionEvent.ACTION_CANCEL);
- mEdgePanel.handleTouch(cancelEv);
+ mEdgeBackPlugin.onMotionEvent(cancelEv);
cancelEv.recycle();
}
@@ -330,14 +354,8 @@
mAllowGesture = !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
&& isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
if (mAllowGesture) {
- mEdgePanelLp.gravity = mIsOnLeftEdge
- ? (Gravity.LEFT | Gravity.TOP)
- : (Gravity.RIGHT | Gravity.TOP);
- mEdgePanel.setIsLeftPanel(mIsOnLeftEdge);
- mEdgePanel.handleTouch(ev);
- updateEdgePanelPosition(ev.getY());
- mWm.updateViewLayout(mEdgePanel, mEdgePanelLp);
- mRegionSamplingHelper.start(mSamplingRect);
+ mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
+ mEdgeBackPlugin.onMotionEvent(ev);
mDownPoint.set(ev.getX(), ev.getY());
mThresholdCrossed = false;
@@ -369,53 +387,10 @@
}
// forward touch
- mEdgePanel.handleTouch(ev);
-
- boolean isUp = action == MotionEvent.ACTION_UP;
- if (isUp) {
- boolean performAction = mEdgePanel.shouldTriggerBack();
- if (performAction) {
- // Perform back
- sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
- sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
- }
- mOverviewProxyService.notifyBackAction(performAction, (int) mDownPoint.x,
- (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
- int backtype = performAction ? (mInRejectedExclusion
- ? StatsLog.BACK_GESTURE__TYPE__COMPLETED_REJECTED :
- StatsLog.BACK_GESTURE__TYPE__COMPLETED) :
- StatsLog.BACK_GESTURE__TYPE__INCOMPLETE;
- StatsLog.write(StatsLog.BACK_GESTURE_REPORTED_REPORTED, backtype,
- (int) mDownPoint.y, mIsOnLeftEdge
- ? StatsLog.BACK_GESTURE__X_LOCATION__LEFT :
- StatsLog.BACK_GESTURE__X_LOCATION__RIGHT);
- }
- if (isUp || action == MotionEvent.ACTION_CANCEL) {
- mRegionSamplingHelper.stop();
- } else {
- updateSamplingRect();
- mRegionSamplingHelper.updateSamplingRect();
- }
+ mEdgeBackPlugin.onMotionEvent(ev);
}
}
- private void updateEdgePanelPosition(float touchY) {
- float position = touchY - mFingerOffset;
- position = Math.max(position, mMinArrowPosition);
- position = (position - mEdgePanelLp.height / 2.0f);
- mEdgePanelLp.y = MathUtils.constrain((int) position, 0, mDisplaySize.y);
- updateSamplingRect();
- }
-
- private void updateSamplingRect() {
- int top = mEdgePanelLp.y;
- int left = mIsOnLeftEdge ? mLeftInset : mDisplaySize.x - mRightInset - mEdgePanelLp.width;
- int right = left + mEdgePanelLp.width;
- int bottom = top + mEdgePanelLp.height;
- mSamplingRect.set(left, top, right, bottom);
- mEdgePanel.adjustRectToBoundingBox(mSamplingRect);
- }
-
@Override
public void onDisplayAdded(int displayId) { }
@@ -433,6 +408,9 @@
mContext.getSystemService(DisplayManager.class)
.getDisplay(mDisplayId)
.getRealSize(mDisplaySize);
+ if (mEdgeBackPlugin != null) {
+ mEdgeBackPlugin.setDisplaySize(mDisplaySize);
+ }
}
private void sendEvent(int action, int code) {
@@ -454,6 +432,9 @@
public void setInsets(int leftInset, int rightInset) {
mLeftInset = leftInset;
mRightInset = rightInset;
+ if (mEdgeBackPlugin != null) {
+ mEdgeBackPlugin.setInsets(leftInset, rightInset);
+ }
}
public void dump(PrintWriter pw) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index 7f31f3d..ac06d9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -132,7 +132,7 @@
if (mPickedChild != null && mTouchingHeadsUpView) {
// We may swallow this click if the heads up just came in.
if (mHeadsUpManager.shouldSwallowClick(
- mPickedChild.getStatusBarNotification().getKey())) {
+ mPickedChild.getEntry().getSbn().getKey())) {
endMotion();
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index 4f223c3..2357309 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -19,34 +19,40 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Canvas;;
+import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
import android.os.VibrationEffect;
-import android.util.DisplayMetrics;
import android.util.MathUtils;
import android.view.ContextThemeWrapper;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
-import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.VibratorHelper;
-
import androidx.core.graphics.ColorUtils;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
-public class NavigationBarEdgePanel extends View {
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.NavigationEdgeBackPlugin;
+import com.android.systemui.statusbar.VibratorHelper;
+
+public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPlugin {
+
+ private static final String TAG = "NavigationBarEdgePanel";
private static final long COLOR_ANIMATION_DURATION_MS = 120;
private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 80;
@@ -114,6 +120,7 @@
private static final Interpolator RUBBER_BAND_INTERPOLATOR_APPEAR
= new PathInterpolator(1.0f / RUBBER_BAND_AMOUNT_APPEAR, 1.0f, 1.0f, 1.0f);
+ private final WindowManager mWindowManager;
private final VibratorHelper mVibratorHelper;
/**
@@ -134,9 +141,14 @@
* The minimum delta needed in movement for the arrow to change direction / stop triggering back
*/
private final float mMinDeltaForSwitch;
+ // The closest to y = 0 that the arrow will be displayed.
+ private int mMinArrowPosition;
+ // The amount the arrow is shifted to avoid the finger.
+ private int mFingerOffset;
private final float mSwipeThreshold;
private final Path mArrowPath = new Path();
+ private final Point mDisplaySize = new Point();
private final SpringAnimation mAngleAnimation;
private final SpringAnimation mTranslationAnimation;
@@ -158,6 +170,11 @@
private int mArrowColorDark;
private int mProtectionColor;
private int mArrowColor;
+ private RegionSamplingHelper mRegionSamplingHelper;
+ private final Rect mSamplingRect = new Rect();
+ private WindowManager.LayoutParams mLayoutParams;
+ private int mLeftInset;
+ private int mRightInset;
/**
* True if the panel is currently on the left of the screen
@@ -242,10 +259,12 @@
return object.getVerticalTranslation();
}
};
+ private BackCallback mBackCallback;
public NavigationBarEdgePanel(Context context) {
super(context);
+ mWindowManager = context.getSystemService(WindowManager.class);
mVibratorHelper = Dependency.get(VibratorHelper.class);
mDensity = context.getResources().getDisplayMetrics().density;
@@ -263,13 +282,10 @@
mArrowColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
mArrowColorAnimator.setDuration(COLOR_ANIMATION_DURATION_MS);
- mArrowColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- int newColor = ColorUtils.blendARGB(mArrowStartColor, mArrowColor,
- animation.getAnimatedFraction());
- setCurrentArrowColor(newColor);
- }
+ mArrowColorAnimator.addUpdateListener(animation -> {
+ int newColor = ColorUtils.blendARGB(
+ mArrowStartColor, mArrowColor, animation.getAnimatedFraction());
+ setCurrentArrowColor(newColor);
});
mArrowDisappearAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
@@ -317,6 +333,27 @@
mSwipeThreshold = context.getResources()
.getDimension(R.dimen.navigation_edge_action_drag_threshold);
setVisibility(GONE);
+
+ mRegionSamplingHelper = new RegionSamplingHelper(this,
+ new RegionSamplingHelper.SamplingCallback() {
+ @Override
+ public void onRegionDarknessChanged(boolean isRegionDark) {
+ setIsDark(!isRegionDark, true /* animate */);
+ }
+
+ @Override
+ public Rect getSampledRegion(View sampledView) {
+ return mSamplingRect;
+ }
+ });
+ mRegionSamplingHelper.setWindowVisible(true);
+ }
+
+ @Override
+ public void onDestroy() {
+ mWindowManager.removeView(this);
+ mRegionSamplingHelper.stop();
+ mRegionSamplingHelper = null;
}
@Override
@@ -324,30 +361,51 @@
return false;
}
- public boolean shouldTriggerBack() {
- return mTriggerBack;
- }
-
- public void setIsDark(boolean isDark, boolean animate) {
+ private void setIsDark(boolean isDark, boolean animate) {
mIsDark = isDark;
updateIsDark(animate);
}
- public void setShowProtection(boolean showProtection) {
+ private void setShowProtection(boolean showProtection) {
mShowProtection = showProtection;
invalidate();
}
+ @Override
public void setIsLeftPanel(boolean isLeftPanel) {
mIsLeftPanel = isLeftPanel;
+ mLayoutParams.gravity = mIsLeftPanel
+ ? (Gravity.LEFT | Gravity.TOP)
+ : (Gravity.RIGHT | Gravity.TOP);
+ }
+
+ @Override
+ public void setInsets(int leftInset, int rightInset) {
+ mLeftInset = leftInset;
+ mRightInset = rightInset;
+ }
+
+ @Override
+ public void setDisplaySize(Point displaySize) {
+ mDisplaySize.set(displaySize.x, displaySize.y);
+ mScreenSize = Math.min(mDisplaySize.x, mDisplaySize.y);
+ }
+
+ @Override
+ public void setBackCallback(BackCallback callback) {
+ mBackCallback = callback;
+ }
+
+ @Override
+ public void setLayoutParams(WindowManager.LayoutParams layoutParams) {
+ mLayoutParams = layoutParams;
+ mWindowManager.addView(this, mLayoutParams);
}
/**
- * Adjust the rect to conform the the actual visible bounding box of the arrow.
- *
- * @param samplingRect the existing bounding box in screen coordinates, to be modified
+ * Adjusts the sampling rect to conform to the actual visible bounding box of the arrow.
*/
- public void adjustRectToBoundingBox(Rect samplingRect) {
+ private void adjustSamplingRectToBoundingBox() {
float translation = mDesiredTranslation;
if (!mTriggerBack) {
// Let's take the resting position and bounds as the sampling rect, since we are not
@@ -361,7 +419,7 @@
}
}
float left = translation - mArrowThickness / 2.0f;
- left = mIsLeftPanel ? left : samplingRect.width() - left;
+ left = mIsLeftPanel ? left : mSamplingRect.width() - left;
// Let's calculate the position of the end based on the angle
float width = getStaticArrowWidth();
@@ -371,49 +429,49 @@
}
float top = (getHeight() * 0.5f) + mDesiredVerticalTranslation - height / 2.0f;
- samplingRect.offset((int) left, (int) top);
- samplingRect.set(samplingRect.left, samplingRect.top,
- (int) (samplingRect.left + width),
- (int) (samplingRect.top + height));
+ mSamplingRect.offset((int) left, (int) top);
+ mSamplingRect.set(mSamplingRect.left, mSamplingRect.top,
+ (int) (mSamplingRect.left + width),
+ (int) (mSamplingRect.top + height));
+ mRegionSamplingHelper.updateSamplingRect();
}
- /**
- * Updates the UI based on the motion events passed in device co-ordinates
- */
- public void handleTouch(MotionEvent event) {
+ @Override
+ public void onMotionEvent(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN : {
+ case MotionEvent.ACTION_DOWN:
mDragSlopPassed = false;
resetOnDown();
mStartX = event.getX();
mStartY = event.getY();
setVisibility(VISIBLE);
+ updatePosition(event.getY());
+ mRegionSamplingHelper.start(mSamplingRect);
+ mWindowManager.updateViewLayout(this, mLayoutParams);
break;
- }
- case MotionEvent.ACTION_MOVE: {
+ case MotionEvent.ACTION_MOVE:
handleMoveEvent(event);
break;
- }
- // Fall through
case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL: {
if (mTriggerBack) {
triggerBack();
} else {
- if (mTranslationAnimation.isRunning()) {
- mTranslationAnimation.addEndListener(mSetGoneEndListener);
- } else {
- setVisibility(GONE);
- }
+ cancelBack();
}
+ mRegionSamplingHelper.stop();
mVelocityTracker.recycle();
mVelocityTracker = null;
break;
- }
+ case MotionEvent.ACTION_CANCEL:
+ cancelBack();
+ mRegionSamplingHelper.stop();
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ break;
}
}
@@ -452,10 +510,10 @@
}
private void loadDimens() {
- mArrowPaddingEnd = getContext().getResources().getDimensionPixelSize(
- R.dimen.navigation_edge_panel_padding);
- DisplayMetrics metrics = getResources().getDisplayMetrics();
- mScreenSize = Math.min(metrics.widthPixels, metrics.heightPixels);
+ Resources res = getResources();
+ mArrowPaddingEnd = res.getDimensionPixelSize(R.dimen.navigation_edge_panel_padding);
+ mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
+ mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
}
private void updateArrowDirection() {
@@ -531,6 +589,11 @@
}
private void triggerBack() {
+ mBackCallback.triggerBack();
+
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
mVelocityTracker.computeCurrentVelocity(1000);
// Only do the extra translation if we're not already flinging
boolean isSlow = Math.abs(mVelocityTracker.getXVelocity()) < 500;
@@ -573,7 +636,16 @@
} else {
translationEnd.run();
}
+ }
+ private void cancelBack() {
+ mBackCallback.cancelBack();
+
+ if (mTranslationAnimation.isRunning()) {
+ mTranslationAnimation.addEndListener(mSetGoneEndListener);
+ } else {
+ setVisibility(GONE);
+ }
}
private void resetOnDown() {
@@ -680,6 +752,24 @@
float verticalTranslation = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
* maxYOffset * Math.signum(yOffset);
setDesiredVerticalTransition(verticalTranslation, true /* animated */);
+ updateSamplingRect();
+ }
+
+ private void updatePosition(float touchY) {
+ float position = touchY - mFingerOffset;
+ position = Math.max(position, mMinArrowPosition);
+ position -= mLayoutParams.height / 2.0f;
+ mLayoutParams.y = MathUtils.constrain((int) position, 0, mDisplaySize.y);
+ updateSamplingRect();
+ }
+
+ private void updateSamplingRect() {
+ int top = mLayoutParams.y;
+ int left = mIsLeftPanel ? mLeftInset : mDisplaySize.x - mRightInset - mLayoutParams.width;
+ int right = left + mLayoutParams.width;
+ int bottom = top + mLayoutParams.height;
+ mSamplingRect.set(left, top, right, bottom);
+ adjustSamplingRectToBoundingBox();
}
private void setDesiredVerticalTransition(float verticalTranslation, boolean animated) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d3c7940..5a1b20d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -72,6 +72,7 @@
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsOnboarding;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -96,6 +97,7 @@
private final RegionSamplingHelper mRegionSamplingHelper;
private final int mNavColorSampleMargin;
private final SysUiState mSysUiFlagContainer;
+ private final PluginManager mPluginManager;
View mCurrentView = null;
private View mVertical;
@@ -272,6 +274,7 @@
boolean isGesturalMode = isGesturalMode(mNavBarMode);
mSysUiFlagContainer = Dependency.get(SysUiState.class);
+ mPluginManager = Dependency.get(PluginManager.class);
// Set up the context group of buttons
mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
@@ -315,8 +318,8 @@
mNavColorSampleMargin = getResources()
.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
- mEdgeBackGestureHandler =
- new EdgeBackGestureHandler(context, mOverviewProxyService, mSysUiFlagContainer);
+ mEdgeBackGestureHandler = new EdgeBackGestureHandler(
+ context, mOverviewProxyService, mSysUiFlagContainer, mPluginManager);
mRegionSamplingHelper = new RegionSamplingHelper(this,
new RegionSamplingHelper.SamplingCallback() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 8ebf574..35407c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -986,7 +986,7 @@
}
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
boolean suppressedSummary = mGroupManager != null
- && mGroupManager.isSummaryOfSuppressedGroup(row.getStatusBarNotification());
+ && mGroupManager.isSummaryOfSuppressedGroup(row.getEntry().getSbn());
if (suppressedSummary) {
continue;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index b5a7847..322b23f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -175,7 +175,7 @@
} else {
if (row.isChildInGroup() && !row.areChildrenExpanded()) {
// The group isn't expanded, let's make sure it's visible!
- mGroupManager.toggleGroupExpansion(row.getStatusBarNotification());
+ mGroupManager.toggleGroupExpansion(row.getEntry().getSbn());
}
row.setUserExpanded(true);
row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index c1328ec..6d6a1fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -188,6 +188,7 @@
boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
+ boolean expandingBelowNotch = mExpandingBelowNotch;
if (isUp || isCancel) {
mExpandingBelowNotch = false;
}
@@ -236,8 +237,9 @@
// regular view bounds.
if (isDown && ev.getY() >= mView.getBottom()) {
mExpandingBelowNotch = true;
+ expandingBelowNotch = true;
}
- if (mExpandingBelowNotch) {
+ if (expandingBelowNotch) {
return mStatusBarView.dispatchTouchEvent(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 7587c8c..6331a2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -111,8 +111,8 @@
if (mWifiManager != null) {
if (mListening) {
if (mCallbacks.size() == 1) {
- mWifiManager.registerSoftApCallback(this,
- new HandlerExecutor(mMainHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mMainHandler),
+ this);
} else {
// mWifiManager#registerSoftApCallback triggers a call to
// onConnectedClientsChanged on the Main Handler. In order to always update
@@ -146,7 +146,7 @@
if (mListening || !listening) return;
mListening = true;
if (mCallbacks.size() >= 1) {
- mWifiManager.registerSoftApCallback(this, new HandlerExecutor(mMainHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mMainHandler), this);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 99c94ac..46a8dad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -117,7 +117,7 @@
private NotificationEntry createEntry() throws Exception {
ExpandableNotificationRow row = mHelper.createRow();
NotificationEntry entry = new NotificationEntryBuilder()
- .setSbn(row.getStatusBarNotification())
+ .setSbn(row.getEntry().getSbn())
.build();
entry.setRow(row);
return entry;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
index 7326cd4..a25af84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
@@ -34,7 +34,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
-import android.util.Log;
import androidx.test.filters.SmallTest;
@@ -121,7 +120,7 @@
addNotif(6, PACKAGE_1).setRank(0);
dispatchBuild();
- // The final output is sorted based on rank
+ // The final output is sorted based first by rank and then by when
verifyBuiltList(
notif(6),
notif(5),
@@ -204,7 +203,7 @@
addGroupSummary(6, PACKAGE_1, GROUP_1).setRank(3);
dispatchBuild();
- // THEN the notifs are grouped together
+ // THEN the children are sorted by rank and when
verifyBuiltList(
group(
summary(6),
@@ -503,10 +502,6 @@
addNotif(5, PACKAGE_3);
dispatchBuild();
- for (NotificationEntry entry : mEntrySet) {
- Log.d("pizza", "entry: " + entry.getKey() + " " + entry);
- }
-
// THEN both promoters are called on each child, except for children that a previous
// promoter has already promoted
verify(promoter1).shouldPromoteToTopLevel(mEntrySet.get(1));
@@ -840,6 +835,9 @@
notif(0)
);
assertNull(group.getParent());
+
+ // but its previous parent indicates that it was added in the previous iteration
+ assertEquals(GroupEntry.ROOT_ENTRY, group.getPreviousParent());
}
@Test(expected = IllegalStateException.class)
@@ -860,14 +858,14 @@
@Test(expected = IllegalStateException.class)
public void testOutOfOrderPrompterInvalidationThrows() {
- // GIVEN a NotifFilter that gets invalidated during the grouping stage
+ // GIVEN a NotifPromoter that gets invalidated during the sorting stage
NotifPromoter promoter = new IdPromoter(47);
OnBeforeSortListener listener =
(list) -> promoter.invalidateList();
mListBuilder.addPromoter(promoter);
mListBuilder.addOnBeforeSortListener(listener);
- // WHEN we try to run the pipeline and the filter is invalidated
+ // WHEN we try to run the pipeline and the promoter is invalidated
addNotif(0, PACKAGE_1);
dispatchBuild();
@@ -876,14 +874,14 @@
@Test(expected = IllegalStateException.class)
public void testOutOfOrderComparatorInvalidationThrows() {
- // GIVEN a NotifFilter that gets invalidated during the grouping stage
+ // GIVEN a NotifComparator that gets invalidated during the finalizing stage
NotifComparator comparator = new HypeComparator(PACKAGE_5);
OnBeforeRenderListListener listener =
(list) -> comparator.invalidateList();
mListBuilder.setComparators(Collections.singletonList(comparator));
mListBuilder.addOnBeforeRenderListListener(listener);
- // WHEN we try to run the pipeline and the filter is invalidated
+ // WHEN we try to run the pipeline and the comparator is invalidated
addNotif(0, PACKAGE_1);
dispatchBuild();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 71c2e11..ba28879 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -139,7 +139,7 @@
@Test
public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
mRow.getPrivateLayout().removeAllViews();
- mRow.getStatusBarNotification().getNotification().contentView
+ mRow.getEntry().getSbn().getNotification().contentView
= new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
true /* expectingException */, mNotificationInflater);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 0b123fc..749dae5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -320,7 +320,7 @@
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
when(row.getIsNonblockable()).thenReturn(false);
- StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+ StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -352,7 +352,7 @@
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
when(row.getIsNonblockable()).thenReturn(false);
- StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+ StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -386,7 +386,7 @@
.build();
row.getEntry().setIsHighPriority(true);
when(row.getIsNonblockable()).thenReturn(false);
- StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+ StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -418,7 +418,7 @@
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
when(row.getIsNonblockable()).thenReturn(false);
- StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+ StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
@@ -452,7 +452,7 @@
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
when(row.getIsNonblockable()).thenReturn(false);
- StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+ StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
@@ -530,7 +530,7 @@
private NotificationMenuRowPlugin.MenuItem createTestMenuItem(ExpandableNotificationRow row) {
NotificationMenuRowPlugin menuRow = new NotificationMenuRow(mContext);
- menuRow.createMenu(row, row.getStatusBarNotification());
+ menuRow.createMenu(row, row.getEntry().getSbn());
NotificationMenuRowPlugin.MenuItem menuItem = menuRow.getLongpressMenuItem(mContext);
assertNotNull(menuItem);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 5b624bc..d20a37a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -448,12 +448,12 @@
mock(ExpandableNotificationRow.LongPressListener.class));
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
- when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker(
+ when(row.getEntry().getSbn().getLogMaker()).thenReturn(new LogMaker(
MetricsProto.MetricsEvent.VIEW_UNKNOWN));
mStackScroller.mMenuEventListener.onMenuClicked(row, 0, 0, mock(
NotificationMenuRowPlugin.MenuItem.class));
- verify(row.getStatusBarNotification()).getLogMaker(); // This writes most of the log data
+ verify(row.getEntry().getSbn()).getLogMaker(); // This writes most of the log data
verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_TOUCH_GEAR,
MetricsProto.MetricsEvent.TYPE_ACTION));
}
@@ -463,11 +463,11 @@
public void testOnMenuShownLogging() { ;
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
- when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker(
+ when(row.getEntry().getSbn().getLogMaker()).thenReturn(new LogMaker(
MetricsProto.MetricsEvent.VIEW_UNKNOWN));
mStackScroller.mMenuEventListener.onMenuShown(row);
- verify(row.getStatusBarNotification()).getLogMaker(); // This writes most of the log data
+ verify(row.getEntry().getSbn()).getLogMaker(); // This writes most of the log data
verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_REVEAL_GEAR,
MetricsProto.MetricsEvent.TYPE_ACTION));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
index a49ae35..3ad1e39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
@@ -87,7 +87,6 @@
ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
entry.setRow(row);
when(row.getEntry()).thenReturn(entry);
- when(row.getStatusBarNotification()).thenReturn(entry.getSbn());
when(row.isInflationFlagSet(anyInt())).thenReturn(true);
return entry;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 24a5d93..07be0d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -141,13 +141,13 @@
// Create standard notification with contentIntent
mNotificationRow = mNotificationTestHelper.createRow();
- StatusBarNotification sbn = mNotificationRow.getStatusBarNotification();
+ StatusBarNotification sbn = mNotificationRow.getEntry().getSbn();
sbn.getNotification().contentIntent = mContentIntent;
sbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
// Create bubble notification row with contentIntent
mBubbleNotificationRow = mNotificationTestHelper.createBubble();
- StatusBarNotification bubbleSbn = mBubbleNotificationRow.getStatusBarNotification();
+ StatusBarNotification bubbleSbn = mBubbleNotificationRow.getEntry().getSbn();
bubbleSbn.getNotification().contentIntent = mContentIntent;
bubbleSbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
@@ -194,7 +194,7 @@
public void testOnNotificationClicked_keyGuardShowing()
throws PendingIntent.CanceledException, RemoteException {
// Given
- StatusBarNotification sbn = mNotificationRow.getStatusBarNotification();
+ StatusBarNotification sbn = mNotificationRow.getEntry().getSbn();
sbn.getNotification().contentIntent = mContentIntent;
sbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
@@ -228,7 +228,7 @@
@Test
public void testOnNotificationClicked_bubble_noContentIntent_noKeyGuard()
throws RemoteException {
- StatusBarNotification sbn = mBubbleNotificationRow.getStatusBarNotification();
+ StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
// Given
sbn.getNotification().contentIntent = null;
@@ -257,7 +257,7 @@
@Test
public void testOnNotificationClicked_bubble_noContentIntent_keyGuardShowing()
throws RemoteException {
- StatusBarNotification sbn = mBubbleNotificationRow.getStatusBarNotification();
+ StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
// Given
sbn.getNotification().contentIntent = null;
@@ -287,7 +287,7 @@
@Test
public void testOnNotificationClicked_bubble_withContentIntent_keyGuardShowing()
throws RemoteException {
- StatusBarNotification sbn = mBubbleNotificationRow.getStatusBarNotification();
+ StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
// Given
sbn.getNotification().contentIntent = mContentIntent;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
index 0d1e1bd..811e6a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -70,11 +70,11 @@
mContext.addMockSystemService(WifiManager.class, mWifiManager);
doAnswer((InvocationOnMock invocation) -> {
- ((WifiManager.SoftApCallback) invocation.getArgument(0))
+ ((WifiManager.SoftApCallback) invocation.getArgument(1))
.onConnectedClientsChanged(new ArrayList<>());
return null;
- }).when(mWifiManager).registerSoftApCallback(any(WifiManager.SoftApCallback.class),
- any(Executor.class));
+ }).when(mWifiManager).registerSoftApCallback(any(Executor.class),
+ any(WifiManager.SoftApCallback.class));
mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper()));
mController.handleSetListening(true);
@@ -85,7 +85,7 @@
mController.addCallback(mCallback1);
mController.addCallback(mCallback2);
- verify(mWifiManager, times(1)).registerSoftApCallback(eq(mController), any());
+ verify(mWifiManager, times(1)).registerSoftApCallback(any(), eq(mController));
}
@Test
diff --git a/services/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java
index e5f8b49..9a7cb3f 100644
--- a/services/core/java/android/os/UserManagerInternal.java
+++ b/services/core/java/android/os/UserManagerInternal.java
@@ -143,8 +143,8 @@
* <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
* createAndManageUser is called by the device owner.
*/
- public abstract UserInfo createUserEvenWhenDisallowed(String name, int flags,
- String[] disallowedPackages);
+ public abstract UserInfo createUserEvenWhenDisallowed(String name, String userType,
+ int flags, String[] disallowedPackages);
/**
* Same as {@link UserManager#removeUser(int userId)}, but bypasses the check for
@@ -202,8 +202,7 @@
/**
* Checks if the {@code callingUserId} and {@code targetUserId} are same or in same group
- * and that the {@code callingUserId} is not a managed profile and
- * {@code targetUserId} is enabled.
+ * and that the {@code callingUserId} is not a profile and {@code targetUserId} is enabled.
*
* @return TRUE if the {@code callingUserId} can access {@code targetUserId}. FALSE
* otherwise
@@ -215,8 +214,7 @@
String debugMsg, boolean throwSecurityException);
/**
- * If {@code userId} is of a managed profile, return the parent user ID. Otherwise return
- * itself.
+ * If {@code userId} is of a profile, return the parent user ID. Otherwise return itself.
*/
public abstract int getProfileParentId(int userId);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index f8b0072..dc61261 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -20,6 +20,7 @@
import static java.util.Arrays.copyOf;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
@@ -112,6 +113,7 @@
Context context;
String callingPackage;
+ String callingFeatureId;
IBinder binder;
@@ -145,7 +147,7 @@
boolean canReadCallLog() {
try {
return TelephonyPermissions.checkReadCallLog(
- context, subId, callerPid, callerUid, callingPackage);
+ context, subId, callerPid, callerUid, callingPackage, callingFeatureId);
} catch (SecurityException e) {
return false;
}
@@ -578,7 +580,7 @@
}
@Override
- public void addOnSubscriptionsChangedListener(String callingPackage,
+ public void addOnSubscriptionsChangedListener(String callingPackage, String callingFeatureId,
IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
@@ -600,6 +602,7 @@
r.context = mContext;
r.onSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
@@ -632,7 +635,7 @@
@Override
public void addOnOpportunisticSubscriptionsChangedListener(String callingPackage,
- IOnSubscriptionsChangedListener callback) {
+ String callingFeatureId, IOnSubscriptionsChangedListener callback) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (VDBG) {
@@ -653,6 +656,7 @@
r.context = mContext;
r.onOpportunisticSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
r.events = 0;
@@ -728,21 +732,28 @@
}
}
+ @Deprecated
@Override
- public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
+ public void listen(String callingPackage, IPhoneStateListener callback, int events,
boolean notifyNow) {
- listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
- events, notifyNow);
+ listenWithFeature(callingPackage, null, callback, events, notifyNow);
}
@Override
- public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback,
- int events, boolean notifyNow) {
- listen(pkgForDebug, callback, events, notifyNow, subId);
+ public void listenWithFeature(String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow) {
+ listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage,
+ callingFeatureId, callback, events, notifyNow);
}
- private void listen(String callingPackage, IPhoneStateListener callback, int events,
- boolean notifyNow, int subId) {
+ @Override
+ public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow) {
+ listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId);
+ }
+
+ private void listen(String callingPackage, @Nullable String callingFeatureId,
+ IPhoneStateListener callback, int events, boolean notifyNow, int subId) {
int callerUserId = UserHandle.getCallingUserId();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
String str = "listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
@@ -757,7 +768,8 @@
// Checks permission and throws SecurityException for disallowed operations. For pre-M
// apps whose runtime permission has been revoked, we return immediately to skip sending
// events to the app without crashing it.
- if (!checkListenerPermission(events, subId, callingPackage, "listen")) {
+ if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
+ "listen")) {
return;
}
@@ -774,6 +786,7 @@
r.context = mContext;
r.callback = callback;
r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
r.callerUid = Binder.getCallingUid();
r.callerPid = Binder.getCallingPid();
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
@@ -2374,8 +2387,8 @@
== PackageManager.PERMISSION_GRANTED;
}
- private boolean checkListenerPermission(
- int events, int subId, String callingPackage, String message) {
+ private boolean checkListenerPermission(int events, int subId, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
new LocationAccessPolicy.LocationPermissionQuery.Builder()
.setCallingPackage(callingPackage)
@@ -2410,7 +2423,7 @@
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
- mContext, subId, callingPackage, message)) {
+ mContext, subId, callingPackage, callingFeatureId, message)) {
return false;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4bb29f0..3dc745b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -346,7 +346,6 @@
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
import com.android.server.appop.AppOpsService;
-import com.android.server.compat.CompatConfig;
import com.android.server.compat.PlatformCompat;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.firewall.IntentFirewall;
@@ -5032,8 +5031,9 @@
bindApplicationTimeMillis = SystemClock.elapsedRealtime();
mAtmInternal.preBindApplication(app.getWindowProcessController());
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
- long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
+ long[] disabledCompatChanges = {};
if (mPlatformCompat != null) {
+ disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
mPlatformCompat.resetReporting(app.info);
}
if (app.isolatedEntryPoint != null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 1f56176..908ec6b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -37,11 +37,13 @@
import android.app.IUidObserver;
import android.app.KeyguardManager;
import android.app.ProfilerInfo;
+import android.app.UserSwitchObserver;
import android.app.WaitResult;
import android.app.usage.AppStandbyInfo;
import android.app.usage.ConfigurationStats;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageStatsManager;
+import android.compat.Compatibility;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Context;
@@ -80,15 +82,17 @@
import android.os.UserManager;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.DisplayMetrics;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.util.HexDump;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
-import com.android.server.compat.CompatConfig;
+import com.android.server.compat.PlatformCompat;
import java.io.BufferedReader;
import java.io.File;
@@ -1729,6 +1733,30 @@
return 0;
}
+ private void switchUserAndWaitForComplete(int userId) throws RemoteException {
+ // Register switch observer.
+ final CountDownLatch switchLatch = new CountDownLatch(1);
+ mInterface.registerUserSwitchObserver(
+ new UserSwitchObserver() {
+ @Override
+ public void onUserSwitchComplete(int newUserId) {
+ if (userId == newUserId) {
+ switchLatch.countDown();
+ }
+ }
+ }, ActivityManagerShellCommand.class.getName());
+
+ // Switch.
+ mInterface.switchUser(userId);
+
+ // Wait.
+ try {
+ switchLatch.await(USER_OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ getErrPrintWriter().println("Thread interrupted unexpectedly.");
+ }
+ }
+
int runSwitchUser(PrintWriter pw) throws RemoteException {
UserManager userManager = mInternal.mContext.getSystemService(UserManager.class);
final int userSwitchable = userManager.getUserSwitchability();
@@ -1736,8 +1764,23 @@
getErrPrintWriter().println("Error: " + userSwitchable);
return -1;
}
- String user = getNextArgRequired();
- mInterface.switchUser(Integer.parseInt(user));
+ boolean wait = false;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ if ("-w".equals(opt)) {
+ wait = true;
+ } else {
+ getErrPrintWriter().println("Error: unknown option: " + opt);
+ return -1;
+ }
+ }
+
+ int userId = Integer.parseInt(getNextArgRequired());
+ if (wait) {
+ switchUserAndWaitForComplete(userId);
+ } else {
+ mInterface.switchUser(userId);
+ }
return 0;
}
@@ -2862,56 +2905,49 @@
return 0;
}
- private void killPackage(String packageName, PrintWriter pw) throws RemoteException {
- int uid = mPm.getPackageUid(packageName, 0, mUserId);
- if (uid < 0) {
- // uid is negative if the package wasn't found.
- pw.println("Didn't find package " + packageName + " on device.");
- } else {
- pw.println("Killing package " + packageName + " (UID " + uid + ").");
- final long origId = Binder.clearCallingIdentity();
- mInterface.killUid(UserHandle.getAppId(uid),
- UserHandle.USER_ALL, "killPackage");
- Binder.restoreCallingIdentity(origId);
- }
- }
-
private int runCompat(PrintWriter pw) throws RemoteException {
- final CompatConfig config = CompatConfig.get();
+ final PlatformCompat platformCompat = (PlatformCompat)
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
String toggleValue = getNextArgRequired();
long changeId;
String changeIdString = getNextArgRequired();
try {
changeId = Long.parseLong(changeIdString);
} catch (NumberFormatException e) {
- changeId = config.lookupChangeId(changeIdString);
+ changeId = platformCompat.lookupChangeId(changeIdString);
}
if (changeId == -1) {
pw.println("Unknown or invalid change: '" + changeIdString + "'.");
+ return -1;
}
String packageName = getNextArgRequired();
+ if (!platformCompat.isKnownChangeId(changeId)) {
+ pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
+ + " could have no effect.");
+ }
+ ArraySet<Long> enabled = new ArraySet<>();
+ ArraySet<Long> disabled = new ArraySet<>();
switch (toggleValue) {
case "enable":
- if (!config.addOverride(changeId, packageName, true)) {
- pw.println("Warning! Change " + changeId + " is not known yet. Enabling it"
- + " could have no effect.");
- }
+ enabled.add(changeId);
pw.println("Enabled change " + changeId + " for " + packageName + ".");
- killPackage(packageName, pw);
+ CompatibilityChangeConfig overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
return 0;
case "disable":
- if (!config.addOverride(changeId, packageName, false)) {
- pw.println("Warning! Change " + changeId + " is not known yet. Disabling it"
- + " could have no effect.");
- }
+ disabled.add(changeId);
pw.println("Disabled change " + changeId + " for " + packageName + ".");
- killPackage(packageName, pw);
+ overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
return 0;
case "reset":
- if (config.removeOverride(changeId, packageName)) {
+ if (platformCompat.clearOverride(changeId, packageName)) {
pw.println("Reset change " + changeId + " for " + packageName
+ " to default value.");
- killPackage(packageName, pw);
} else {
pw.println("No override exists for changeId " + changeId + ".");
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 4361676..31ceb38 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -384,7 +384,7 @@
// We need to delay unlocking managed profiles until the parent user
// is also unlocked.
- if (mInjector.getUserManager().isManagedProfile(userId)) {
+ if (mInjector.getUserManager().isProfile(userId)) {
final UserInfo parent = mInjector.getUserManager().getProfileParent(userId);
if (parent != null
&& isUserRunning(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) {
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index d6ec22b..490cce3 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -43,13 +43,14 @@
import java.util.Set;
import javax.xml.datatype.DatatypeConfigurationException;
+
/**
* This class maintains state relating to platform compatibility changes.
*
* <p>It stores the default configuration for each change, and any per-package overrides that have
* been configured.
*/
-public final class CompatConfig {
+final class CompatConfig {
private static final String TAG = "CompatConfig";
@@ -61,13 +62,13 @@
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
@VisibleForTesting
- public CompatConfig() {
+ CompatConfig() {
}
/**
* @return The static instance of this class to be used within the system server.
*/
- public static CompatConfig get() {
+ static CompatConfig get() {
return sInstance;
}
@@ -77,7 +78,7 @@
*
* @param change The change to add. Any change with the same ID will be overwritten.
*/
- public void addChange(CompatChange change) {
+ void addChange(CompatChange change) {
synchronized (mChanges) {
mChanges.put(change.getId(), change);
}
@@ -89,10 +90,10 @@
*
* @param app The app in question
* @return A sorted long array of change IDs. We use a primitive array to minimize memory
- * footprint: Every app process will store this array statically so we aim to reduce
- * overhead as much as possible.
+ * footprint: Every app process will store this array statically so we aim to reduce
+ * overhead as much as possible.
*/
- public long[] getDisabledChanges(ApplicationInfo app) {
+ long[] getDisabledChanges(ApplicationInfo app) {
LongArray disabled = new LongArray();
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
@@ -113,7 +114,7 @@
* @param name Name of the change to look up
* @return The change ID, or {@code -1} if no change with that name exists.
*/
- public long lookupChangeId(String name) {
+ long lookupChangeId(String name) {
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
if (TextUtils.equals(mChanges.valueAt(i).getName(), name)) {
@@ -128,11 +129,11 @@
* Find if a given change is enabled for a given application.
*
* @param changeId The ID of the change in question
- * @param app App to check for
+ * @param app App to check for
* @return {@code true} if the change is enabled for this app. Also returns {@code true} if the
- * change ID is not known, as unknown changes are enabled by default.
+ * change ID is not known, as unknown changes are enabled by default.
*/
- public boolean isChangeEnabled(long changeId, ApplicationInfo app) {
+ boolean isChangeEnabled(long changeId, ApplicationInfo app) {
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c == null) {
@@ -150,14 +151,15 @@
*
* <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
*
- * @param changeId The ID of the change to be overridden. Note, this call will succeed even if
- * this change is not known; it will only have any effect if any code in the
- * platform is gated on the ID given.
+ * @param changeId The ID of the change to be overridden. Note, this call will succeed even
+ * if
+ * this change is not known; it will only have any effect if any code in the
+ * platform is gated on the ID given.
* @param packageName The app package name to override the change for.
- * @param enabled If the change should be enabled or disabled.
+ * @param enabled If the change should be enabled or disabled.
* @return {@code true} if the change existed before adding the override.
*/
- public boolean addOverride(long changeId, String packageName, boolean enabled) {
+ boolean addOverride(long changeId, String packageName, boolean enabled) {
boolean alreadyKnown = true;
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
@@ -172,15 +174,27 @@
}
/**
+ * Check whether the change is known to the compat config.
+ *
+ * @return {@code true} if the change is known.
+ */
+ boolean isKnownChangeId(long changeId) {
+ synchronized (mChanges) {
+ CompatChange c = mChanges.get(changeId);
+ return c != null;
+ }
+ }
+
+ /**
* Removes an override previously added via {@link #addOverride(long, String, boolean)}. This
* restores the default behaviour for the given change and app, once any app processes have been
* restarted.
*
- * @param changeId The ID of the change that was overridden.
+ * @param changeId The ID of the change that was overridden.
* @param packageName The app package name that was overridden.
* @return {@code true} if an override existed;
*/
- public boolean removeOverride(long changeId, String packageName) {
+ boolean removeOverride(long changeId, String packageName) {
boolean overrideExists = false;
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
@@ -191,22 +205,22 @@
}
return overrideExists;
}
+
/**
* Overrides the enabled state for a given change and app. This method is intended to be used
* *only* for debugging purposes.
*
* <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
*
- * @param overrides list of overrides to default changes config.
+ * @param overrides list of overrides to default changes config.
* @param packageName app for which the overrides will be applied.
*/
- public void addOverrides(
- CompatibilityChangeConfig overrides, String packageName) {
+ void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
synchronized (mChanges) {
- for (Long changeId: overrides.enabledChanges()) {
+ for (Long changeId : overrides.enabledChanges()) {
addOverride(changeId, packageName, true);
}
- for (Long changeId: overrides.disabledChanges()) {
+ for (Long changeId : overrides.disabledChanges()) {
addOverride(changeId, packageName, false);
}
}
@@ -221,7 +235,7 @@
*
* @param packageName The package for which the overrides should be purged.
*/
- public void removePackageOverrides(String packageName) {
+ void removePackageOverrides(String packageName) {
synchronized (mChanges) {
for (int i = 0; i < mChanges.size(); ++i) {
mChanges.valueAt(i).removePackageOverride(packageName);
@@ -230,11 +244,11 @@
}
/**
- * Dumps the current list of compatibility config information.
- *
- * @param pw The {@link PrintWriter} instance to which the information will be dumped.
- */
- public void dumpConfig(PrintWriter pw) {
+ * Dumps the current list of compatibility config information.
+ *
+ * @param pw The {@link PrintWriter} instance to which the information will be dumped.
+ */
+ void dumpConfig(PrintWriter pw) {
synchronized (mChanges) {
if (mChanges.size() == 0) {
pw.println("No compat overrides.");
@@ -252,10 +266,10 @@
*
* @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped.
* @return A {@link CompatibilityChangeConfig} which contains the compat config info for the
- * given app.
+ * given app.
*/
- public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
+ CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
Set<Long> enabled = new HashSet<>();
Set<Long> disabled = new HashSet<>();
synchronized (mChanges) {
@@ -276,15 +290,15 @@
*
* @return An array of {@link CompatibilityChangeInfo} with the current changes.
*/
- public CompatibilityChangeInfo[] dumpChanges() {
+ CompatibilityChangeInfo[] dumpChanges() {
synchronized (mChanges) {
CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()];
for (int i = 0; i < mChanges.size(); ++i) {
CompatChange change = mChanges.valueAt(i);
changeInfos[i] = new CompatibilityChangeInfo(change.getId(),
- change.getName(),
- change.getEnableAfterTargetSdk(),
- change.getDisabled());
+ change.getName(),
+ change.getEnableAfterTargetSdk(),
+ change.getDisabled());
}
return changeInfos;
}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 75e2d22..709f3f8 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,9 +16,13 @@
package com.android.server.compat;
+import android.app.ActivityManager;
+import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.util.StatsLog;
@@ -106,12 +110,26 @@
@Override
public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
CompatConfig.get().addOverrides(overrides, packageName);
+ killPackage(packageName);
+ }
+
+ @Override
+ public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
+ CompatConfig.get().addOverrides(overrides, packageName);
}
@Override
public void clearOverrides(String packageName) {
CompatConfig config = CompatConfig.get();
config.removePackageOverrides(packageName);
+ killPackage(packageName);
+ }
+
+ @Override
+ public boolean clearOverride(long changeId, String packageName) {
+ boolean existed = CompatConfig.get().removeOverride(changeId, packageName);
+ killPackage(packageName);
+ return existed;
}
@Override
@@ -124,6 +142,39 @@
return CompatConfig.get().dumpChanges();
}
+ /**
+ * Check whether the change is known to the compat config.
+ * @param changeId
+ * @return {@code true} if the change is known.
+ */
+ public boolean isKnownChangeId(long changeId) {
+ return CompatConfig.get().isKnownChangeId(changeId);
+
+ }
+
+ /**
+ * Retrieves the set of disabled changes for a given app. Any change ID not in the returned
+ * array is by default enabled for the app.
+ *
+ * @param appInfo The app in question
+ * @return A sorted long array of change IDs. We use a primitive array to minimize memory
+ * footprint: Every app process will store this array statically so we aim to reduce
+ * overhead as much as possible.
+ */
+ public long[] getDisabledChanges(ApplicationInfo appInfo) {
+ return CompatConfig.get().getDisabledChanges(appInfo);
+ }
+
+ /**
+ * Look up a change ID by name.
+ *
+ * @param name Name of the change to look up
+ * @return The change ID, or {@code -1} if no change with that name exists.
+ */
+ public long lookupChangeId(String name) {
+ return CompatConfig.get().lookupChangeId(name);
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
@@ -151,4 +202,34 @@
private void reportChange(long changeId, int uid, int state) {
mChangeReporter.reportChange(uid, changeId, state);
}
+
+ private void killPackage(String packageName) {
+ int uid = -1;
+ try {
+ uid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.w(TAG, "Didn't find package " + packageName + " on device.", e);
+ return;
+ }
+
+ Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ").");
+ killUid(UserHandle.getAppId(uid),
+ UserHandle.USER_ALL, "PlatformCompat overrides");
+ }
+
+ private void killUid(int appId, int userId, String reason) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ IActivityManager am = ActivityManager.getService();
+ if (am != null) {
+ try {
+ am.killUid(appId, userId, reason);
+ } catch (RemoteException e) {
+ /* ignore - same process */
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b3804c4..acedc36 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -286,8 +286,8 @@
private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening();
- TelephonyManager.from(mContext).listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+ mContext.getSystemService(TelephonyManager.class).listen(
+ mPhoneStateListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_STATE);
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 126beef..eea1980 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -34,6 +34,7 @@
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
+import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -125,6 +126,7 @@
private static final int MSG_BRIGHTNESS_CHANGED = 1;
private static final int MSG_STOP_SENSOR_LISTENER = 2;
private static final int MSG_START_SENSOR_LISTENER = 3;
+ private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -158,6 +160,7 @@
private boolean mColorSamplingEnabled;
private int mNoFramesToSample;
private float mFrameRate;
+ private BrightnessConfiguration mBrightnessConfiguration;
// End of block of members that should only be accessed on the mBgHandler thread.
private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
@@ -202,6 +205,14 @@
mBgHandler.obtainMessage(MSG_BACKGROUND_START, (Float) initialBrightness).sendToTarget();
}
+ /**
+ * Update tracker with new brightness configuration.
+ */
+ public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) {
+ mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED,
+ brightnessConfiguration).sendToTarget();
+ }
+
private void backgroundStart(float initialBrightness) {
readEvents();
readAmbientBrightnessStats();
@@ -759,7 +770,9 @@
private void enableColorSampling() {
if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
|| !mInjector.isInteractive(mContext)
- || mColorSamplingEnabled) {
+ || mColorSamplingEnabled
+ || mBrightnessConfiguration == null
+ || !mBrightnessConfiguration.shouldCollectColorSamples()) {
return;
}
@@ -977,6 +990,18 @@
stopSensorListener();
disableColorSampling();
break;
+ case MSG_BRIGHTNESS_CONFIG_CHANGED:
+ mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
+ boolean shouldCollectColorSamples =
+ mBrightnessConfiguration != null
+ && mBrightnessConfiguration.shouldCollectColorSamples();
+ if (shouldCollectColorSamples && !mColorSamplingEnabled) {
+ enableColorSampling();
+ } else if (!shouldCollectColorSamples && mColorSamplingEnabled) {
+ disableColorSampling();
+ }
+ break;
+
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 5804fc8..e42545e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -931,6 +931,10 @@
autoBrightnessAdjustmentChanged, mPowerRequest.policy);
}
+ if (mBrightnessTracker != null) {
+ mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+ }
+
// Apply auto-brightness.
boolean slowChange = false;
if (brightness < 0) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8d2fc17..637bcae 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -301,6 +301,7 @@
// Timeout when holding wakelocks for downloading PSDS data.
private static final long DOWNLOAD_PSDS_DATA_TIMEOUT_MS = 60 * 1000;
+ private static final long WAKELOCK_TIMEOUT_MILLIS = 30 * 1000;
private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL,
MAX_RETRY_INTERVAL);
@@ -901,13 +902,8 @@
if (mDownloadPsdsWakeLock.isHeld()) {
// This wakelock may have time-out, if a timeout was specified.
// Catch (and ignore) any timeout exceptions.
- try {
- mDownloadPsdsWakeLock.release();
- if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()");
- } catch (Exception e) {
- Log.i(TAG, "Wakelock timeout & release race exception in "
- + "handleDownloadPsdsData()", e);
- }
+ mDownloadPsdsWakeLock.release();
+ if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()");
} else {
Log.e(TAG, "WakeLock expired before release in "
+ "handleDownloadPsdsData()");
@@ -2009,7 +2005,7 @@
// hold a wake lock until this message is delivered
// note that this assumes the message will not be removed from the queue before
// it is handled (otherwise the wake lock would be leaked).
- mWakeLock.acquire();
+ mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
if (DEBUG) {
Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
+ ", " + obj + ")");
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
index 2e72fbd..93227bd 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -321,7 +321,11 @@
private void handleUpdateNetworkState(Network network, boolean isConnected,
NetworkCapabilities capabilities) {
- boolean networkAvailable = isConnected && TelephonyManager.getDefault().getDataEnabled();
+ boolean networkAvailable = false;
+ TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+ if (telephonyManager != null) {
+ networkAvailable = isConnected && telephonyManager.getDataEnabled();
+ }
NetworkAttributes networkAttributes = updateTrackedNetworksState(isConnected, network,
capabilities);
String apn = networkAttributes.mApn;
diff --git a/services/core/java/com/android/server/location/NtpTimeHelper.java b/services/core/java/com/android/server/location/NtpTimeHelper.java
index 296b500..67841ac 100644
--- a/services/core/java/com/android/server/location/NtpTimeHelper.java
+++ b/services/core/java/com/android/server/location/NtpTimeHelper.java
@@ -181,11 +181,7 @@
mHandler.postDelayed(this::retrieveAndInjectNtpTime, delay);
}
}
- try {
- // release wake lock held by task
- mWakeLock.release();
- } catch (Exception e) {
- // This happens when the WakeLock is already released.
- }
+ // release wake lock held by task
+ mWakeLock.release();
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 41806ca..08c9426 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -337,7 +337,7 @@
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
- wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
+ wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class),
new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(),
new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir());
service.registerLocalService();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5b39fb6..ec53157 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7724,7 +7724,7 @@
}
private void listenForCallState() {
- TelephonyManager.from(getContext()).listen(new PhoneStateListener() {
+ getContext().getSystemService(TelephonyManager.class).listen(new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
if (mCallState == state) return;
diff --git a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
index 9c1ac34..947405e 100644
--- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
+++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@@ -56,16 +56,17 @@
// for any device / profile owner checks. The majority of requests for the serial number
// should use the getSerialForPackage method with the calling package specified.
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
- /* callingPackage */ null, "getSerial")) {
+ /* callingPackage */ null, null, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
@Override
- public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
+ public @Nullable String getSerialForPackage(String callingPackage,
+ String callingFeatureId) throws RemoteException {
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
- callingPackage, "getSerial")) {
+ callingPackage, callingFeatureId, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index bb5b04a..ec11a97 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -29,27 +29,24 @@
import android.content.pm.PackageParser;
import android.content.pm.ProviderInfo;
import android.net.Uri;
-import android.os.Build;
import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.Trace;
-import android.permission.IPermissionManager;
+import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseSetArray;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.server.FgThread;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -60,7 +57,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class AppsFilter {
- private static final String TAG = PackageManagerService.TAG;
+ private static final String TAG = "AppsFilter";
// Logs all filtering instead of enforcing
private static final boolean DEBUG_ALLOW_ALL = false;
@@ -69,52 +66,46 @@
private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL;
/**
- * This contains a list of packages that are implicitly queryable because another app explicitly
+ * This contains a list of app UIDs that are implicitly queryable because another app explicitly
* interacted with it. For example, if application A starts a service in application B,
* application B is implicitly allowed to query for application A; regardless of any manifest
* entries.
*/
- private final SparseArray<HashMap<String, Set<String>>> mImplicitlyQueryable =
- new SparseArray<>();
+ private final SparseSetArray<Integer> mImplicitlyQueryable = new SparseSetArray<>();
/**
- * A mapping from the set of packages that query other packages via package name to the
+ * A mapping from the set of App IDs that query other App IDs via package name to the
* list of packages that they can see.
*/
- private final HashMap<String, Set<String>> mQueriesViaPackage = new HashMap<>();
+ private final SparseSetArray<Integer> mQueriesViaPackage = new SparseSetArray<>();
/**
- * A mapping from the set of packages that query others via intent to the list
+ * A mapping from the set of App IDs that query others via intent to the list
* of packages that the intents resolve to.
*/
- private final HashMap<String, Set<String>> mQueriesViaIntent = new HashMap<>();
+ private final SparseSetArray<Integer> mQueriesViaIntent = new SparseSetArray<>();
/**
- * A set of packages that are always queryable by any package, regardless of their manifest
+ * A set of App IDs that are always queryable by any package, regardless of their manifest
* content.
*/
- private final HashSet<String> mForceQueryable;
+ private final ArraySet<Integer> mForceQueryable = new ArraySet<>();
+
/**
- * A set of packages that are always queryable by any package, regardless of their manifest
- * content.
+ * The set of package names provided by the device that should be force queryable regardless of
+ * their manifest contents.
*/
- private final Set<String> mForceQueryableByDevice;
+ private final String[] mForceQueryableByDevicePackageNames;
/** True if all system apps should be made queryable by default. */
private final boolean mSystemAppsQueryable;
- private final IPermissionManager mPermissionManager;
-
private final FeatureConfig mFeatureConfig;
- AppsFilter(FeatureConfig featureConfig, IPermissionManager permissionManager,
- String[] forceQueryableWhitelist, boolean systemAppsQueryable) {
+ AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
+ boolean systemAppsQueryable) {
mFeatureConfig = featureConfig;
- final HashSet<String> forceQueryableByDeviceSet = new HashSet<>();
- Collections.addAll(forceQueryableByDeviceSet, forceQueryableWhitelist);
- this.mForceQueryableByDevice = Collections.unmodifiableSet(forceQueryableByDeviceSet);
- this.mForceQueryable = new HashSet<>();
- mPermissionManager = permissionManager;
+ mForceQueryableByDevicePackageNames = forceQueryableWhitelist;
mSystemAppsQueryable = systemAppsQueryable;
}
@@ -127,7 +118,6 @@
/** @return true if the feature is enabled for the given package. */
boolean packageIsEnabled(PackageParser.Package pkg);
-
}
private static class FeatureConfigImpl implements FeatureConfig {
@@ -174,7 +164,6 @@
}
}
-
public static AppsFilter create(PackageManagerService.Injector injector) {
final boolean forceSystemAppsQueryable =
injector.getContext().getResources()
@@ -192,15 +181,12 @@
forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
}
}
- IPermissionManager permissionmgr =
- (IPermissionManager) ServiceManager.getService("permissionmgr");
-
- return new AppsFilter(featureConfig, permissionmgr, forcedQueryablePackageNames,
+ return new AppsFilter(featureConfig, forcedQueryablePackageNames,
forceSystemAppsQueryable);
}
/** Returns true if the querying package may query for the potential target package */
- private static boolean canQuery(PackageParser.Package querying,
+ private static boolean canQueryViaIntent(PackageParser.Package querying,
PackageParser.Package potentialTarget) {
if (querying.mQueriesIntents == null) {
return false;
@@ -274,22 +260,14 @@
* Grants access based on an interaction between a calling and target package, granting
* visibility of the caller from the target.
*
- * @param callingPackage the package initiating the interaction
- * @param targetPackage the package being interacted with and thus gaining visibility of the
- * initiating package.
- * @param userId the user in which this interaction was taking place
+ * @param callingUid the uid initiating the interaction
+ * @param targetUid the uid being interacted with and thus gaining visibility of the
+ * initiating uid.
*/
- public void grantImplicitAccess(
- String callingPackage, String targetPackage, int userId) {
- HashMap<String, Set<String>> currentUser = mImplicitlyQueryable.get(userId);
- if (currentUser == null) {
- currentUser = new HashMap<>();
- mImplicitlyQueryable.put(userId, currentUser);
+ public void grantImplicitAccess(int callingUid, int targetUid) {
+ if (mImplicitlyQueryable.add(targetUid, callingUid) && DEBUG_LOGGING) {
+ Slog.wtf(TAG, "implicit access granted: " + callingUid + " -> " + targetUid);
}
- if (!currentUser.containsKey(targetPackage)) {
- currentUser.put(targetPackage, new HashSet<>());
- }
- currentUser.get(targetPackage).add(callingPackage);
}
public void onSystemReady() {
@@ -299,50 +277,57 @@
/**
* Adds a package that should be considered when filtering visibility between apps.
*
- * @param newPkg the new package being added
- * @param existing all other packages currently on the device.
+ * @param newPkgSetting the new setting being added
+ * @param existingSettings all other settings currently on the device.
*/
- public void addPackage(PackageParser.Package newPkg,
- Map<String, PackageParser.Package> existing) {
+ public void addPackage(PackageSetting newPkgSetting,
+ ArrayMap<String, PackageSetting> existingSettings) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
try {
- // let's re-evaluate the ability of already added packages to see this new package
- if (newPkg.mForceQueryable
- || (mSystemAppsQueryable && (newPkg.isSystem()
- || newPkg.isUpdatedSystemApp()))) {
- mForceQueryable.add(newPkg.packageName);
- } else {
- for (String packageName : mQueriesViaIntent.keySet()) {
- if (packageName == newPkg.packageName) {
- continue;
+ final PackageParser.Package newPkg = newPkgSetting.pkg;
+ if (newPkg == null) {
+ // nothing to add
+ return;
+ }
+
+ final boolean newIsForceQueryable =
+ mForceQueryable.contains(newPkgSetting.appId)
+ /* shared user that is already force queryable */
+ || newPkg.mForceQueryable
+ || (newPkgSetting.isSystem() && (mSystemAppsQueryable
+ || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
+ newPkg.packageName)));
+ if (newIsForceQueryable) {
+ mForceQueryable.add(newPkgSetting.appId);
+ }
+
+ for (int i = existingSettings.size() - 1; i >= 0; i--) {
+ final PackageSetting existingSetting = existingSettings.valueAt(i);
+ if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) {
+ continue;
+ }
+ final PackageParser.Package existingPkg = existingSetting.pkg;
+ // let's evaluate the ability of already added packages to see this new package
+ if (!newIsForceQueryable) {
+ if (canQueryViaIntent(existingPkg, newPkg)) {
+ mQueriesViaIntent.add(existingSetting.appId, newPkgSetting.appId);
}
- final PackageParser.Package existingPackage = existing.get(packageName);
- if (canQuery(existingPackage, newPkg)) {
- mQueriesViaIntent.get(packageName).add(newPkg.packageName);
+ if (existingPkg.mQueriesPackages != null
+ && existingPkg.mQueriesPackages.contains(newPkg.packageName)) {
+ mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
+ }
+ }
+ // now we'll evaluate our new package's ability to see existing packages
+ if (!mForceQueryable.contains(existingSetting.appId)) {
+ if (canQueryViaIntent(newPkg, existingPkg)) {
+ mQueriesViaIntent.add(newPkgSetting.appId, existingSetting.appId);
+ }
+ if (newPkg.mQueriesPackages != null
+ && newPkg.mQueriesPackages.contains(existingPkg.packageName)) {
+ mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
}
}
}
- // if the new package declares them, let's evaluate its ability to see existing packages
- mQueriesViaIntent.put(newPkg.packageName, new HashSet<>());
- for (PackageParser.Package existingPackage : existing.values()) {
- if (existingPackage.packageName == newPkg.packageName) {
- continue;
- }
- if (existingPackage.mForceQueryable
- || (mSystemAppsQueryable
- && (newPkg.isSystem() || newPkg.isUpdatedSystemApp()))) {
- continue;
- }
- if (canQuery(newPkg, existingPackage)) {
- mQueriesViaIntent.get(newPkg.packageName).add(existingPackage.packageName);
- }
- }
- final HashSet<String> queriesPackages = new HashSet<>(
- newPkg.mQueriesPackages == null ? 0 : newPkg.mQueriesPackages.size());
- if (newPkg.mQueriesPackages != null) {
- queriesPackages.addAll(newPkg.mQueriesPackages);
- }
- mQueriesViaPackage.put(newPkg.packageName, queriesPackages);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -351,24 +336,41 @@
/**
* Removes a package for consideration when filtering visibility between apps.
*
- * @param packageName the name of the package being removed.
+ * @param setting the setting of the package being removed.
+ * @param allUsers array of all current users on device.
*/
- public void removePackage(String packageName) {
- mForceQueryable.remove(packageName);
+ public void removePackage(PackageSetting setting, int[] allUsers,
+ ArrayMap<String, PackageSetting> existingSettings) {
+ mForceQueryable.remove(setting.appId);
- for (int i = 0; i < mImplicitlyQueryable.size(); i++) {
- mImplicitlyQueryable.valueAt(i).remove(packageName);
- for (Set<String> initiators : mImplicitlyQueryable.valueAt(i).values()) {
- initiators.remove(packageName);
+ for (int u = 0; u < allUsers.length; u++) {
+ final int userId = allUsers[u];
+ final int removingUid = UserHandle.getUid(userId, setting.appId);
+ mImplicitlyQueryable.remove(removingUid);
+ for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
+ mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
}
}
- mQueriesViaIntent.remove(packageName);
- for (Set<String> declarators : mQueriesViaIntent.values()) {
- declarators.remove(packageName);
+ mQueriesViaIntent.remove(setting.appId);
+ for (int i = mQueriesViaIntent.size() - 1; i >= 0; i--) {
+ mQueriesViaIntent.remove(mQueriesViaIntent.keyAt(i), setting.appId);
+ }
+ mQueriesViaPackage.remove(setting.appId);
+ for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
+ mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
}
- mQueriesViaPackage.remove(packageName);
+ // re-add other shared user members to re-establish visibility between them and other
+ // packages
+ if (setting.sharedUser != null) {
+ for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
+ if (setting.sharedUser.packages.valueAt(i) == setting) {
+ continue;
+ }
+ addPackage(setting.sharedUser.packages.valueAt(i), existingSettings);
+ }
+ }
}
/**
@@ -385,6 +387,25 @@
PackageSetting targetPkgSetting, int userId) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
try {
+ if (!shouldFilterApplicationInternal(callingUid, callingSetting,
+ targetPkgSetting,
+ userId)) {
+ return false;
+ }
+ if (DEBUG_LOGGING) {
+ log(callingSetting, targetPkgSetting,
+ DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED", new RuntimeException());
+ }
+ return !DEBUG_ALLOW_ALL;
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ private boolean shouldFilterApplicationInternal(int callingUid,
+ SettingBase callingSetting, PackageSetting targetPkgSetting, int userId) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
+ try {
final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
if (!featureEnabled) {
if (DEBUG_LOGGING) {
@@ -402,85 +423,37 @@
Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
return true;
}
- PackageSetting callingPkgSetting = null;
+ final PackageSetting callingPkgSetting;
+ final ArraySet<PackageSetting> callingSharedPkgSettings;
if (callingSetting instanceof PackageSetting) {
callingPkgSetting = (PackageSetting) callingSetting;
- if (!shouldFilterApplicationInternal(callingPkgSetting, targetPkgSetting,
- userId)) {
+ callingSharedPkgSettings = null;
+ } else {
+ callingPkgSetting = null;
+ callingSharedPkgSettings = ((SharedUserSetting) callingSetting).packages;
+ }
+
+ if (callingPkgSetting != null) {
+ if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
+ if (DEBUG_LOGGING) {
+ log(callingSetting, targetPkgSetting, "DISABLED");
+ }
return false;
}
- } else if (callingSetting instanceof SharedUserSetting) {
- final ArraySet<PackageSetting> packageSettings =
- ((SharedUserSetting) callingSetting).packages;
- if (packageSettings != null && packageSettings.size() > 0) {
- for (int i = 0, max = packageSettings.size(); i < max; i++) {
- final PackageSetting packageSetting = packageSettings.valueAt(i);
- if (!shouldFilterApplicationInternal(packageSetting, targetPkgSetting,
- userId)) {
- return false;
+ } else {
+ for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
+ if (!mFeatureConfig.packageIsEnabled(callingSharedPkgSettings.valueAt(i).pkg)) {
+ if (DEBUG_LOGGING) {
+ log(callingSetting, targetPkgSetting, "DISABLED");
}
- if (callingPkgSetting == null && packageSetting.pkg != null) {
- callingPkgSetting = packageSetting;
- }
- }
- if (callingPkgSetting == null) {
- Slog.wtf(TAG, callingSetting + " does not have any non-null packages!");
- return true;
- }
- } else {
- Slog.wtf(TAG, callingSetting + " has no packages!");
- return true;
- }
- }
-
- if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting,
- DEBUG_ALLOW_ALL ? "ALLOWED" : "BLOCKED");
- }
- return !DEBUG_ALLOW_ALL;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
-
- private boolean shouldFilterApplicationInternal(
- PackageSetting callingPkgSetting, PackageSetting targetPkgSetting, int userId) {
- return shouldFilterApplicationInternal(callingPkgSetting, targetPkgSetting, userId,
- true /*expandSharedUser*/);
- }
-
- /**
- * @param expandSharedUser true if all members of the shared user a target may belong to should
- * be considered
- */
- private boolean shouldFilterApplicationInternal(
- PackageSetting callingPkgSetting, PackageSetting targetPkgSetting, int userId,
- boolean expandSharedUser) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
- try {
- // special case shared user targets
- if (expandSharedUser && targetPkgSetting.sharedUser != null) {
- for (PackageSetting sharedMemberSetting : targetPkgSetting.sharedUser.packages) {
- if (!shouldFilterApplicationInternal(
- callingPkgSetting, sharedMemberSetting, userId,
- false /*expandSharedUser*/)) {
return false;
}
}
- return true;
}
- final String callingName = callingPkgSetting.pkg.packageName;
- final PackageParser.Package targetPkg = targetPkgSetting.pkg;
-
- if (!mFeatureConfig.packageIsEnabled(callingPkgSetting.pkg)) {
- if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "DISABLED");
- }
- return false;
- }
// This package isn't technically installed and won't be written to settings, so we can
// treat it as filtered until it's available again.
+ final PackageParser.Package targetPkg = targetPkgSetting.pkg;
if (targetPkg == null) {
if (DEBUG_LOGGING) {
Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null");
@@ -488,149 +461,180 @@
return true;
}
final String targetName = targetPkg.packageName;
- if (callingPkgSetting.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.R) {
+ final int callingAppId;
+ if (callingPkgSetting != null) {
+ callingAppId = callingPkgSetting.appId;
+ } else {
+ callingAppId = callingSharedPkgSettings.valueAt(0).appId; // all should be the same
+ }
+ final int targetAppId = targetPkgSetting.appId;
+ if (callingAppId == targetAppId) {
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "caller pre-R");
+ log(callingSetting, targetPkgSetting, "same app id");
}
return false;
}
- if (callingPkgSetting.appId == targetPkgSetting.appId) {
+
+ if (callingSetting.getPermissionsState().hasPermission(
+ Manifest.permission.QUERY_ALL_PACKAGES, UserHandle.getUserId(callingUid))) {
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "same app id");
+ log(callingSetting, targetPkgSetting, "has query-all permission");
}
return false;
}
- if (isImplicitlyQueryableSystemApp(targetPkgSetting)) {
+ if (mForceQueryable.contains(targetAppId)) {
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "implicitly queryable sys");
+ log(callingSetting, targetPkgSetting, "force queryable");
}
return false;
}
- if (targetPkg.mForceQueryable) {
- if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "manifest forceQueryable");
- }
- return false;
- }
- if (mForceQueryable.contains(targetName)) {
- if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "whitelist forceQueryable");
- }
- return false;
- }
- if (mQueriesViaPackage.containsKey(callingName)
- && mQueriesViaPackage.get(callingName).contains(
- targetName)) {
+ if (mQueriesViaPackage.contains(callingAppId, targetAppId)) {
// the calling package has explicitly declared the target package; allow
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "queries package");
+ log(callingSetting, targetPkgSetting, "queries package");
}
return false;
- } else if (mQueriesViaIntent.containsKey(callingName)
- && mQueriesViaIntent.get(callingName).contains(targetName)) {
+ } else if (mQueriesViaIntent.contains(callingAppId, targetAppId)) {
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "queries intent");
+ log(callingSetting, targetPkgSetting, "queries intent");
}
return false;
}
- if (mImplicitlyQueryable.get(userId) != null
- && mImplicitlyQueryable.get(userId).containsKey(callingName)
- && mImplicitlyQueryable.get(userId).get(callingName).contains(targetName)) {
+
+ final int targetUid = UserHandle.getUid(userId, targetAppId);
+ if (mImplicitlyQueryable.contains(callingUid, targetUid)) {
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "implicitly queryable for user");
+ log(callingSetting, targetPkgSetting, "implicitly queryable for user");
}
return false;
}
- final ArrayList<PackageParser.Instrumentation> inst =
- callingPkgSetting.pkg.instrumentation;
- if (inst.size() > 0) {
- for (int i = 0, max = inst.size(); i < max; i++) {
- if (inst.get(i).info.targetPackage == targetName) {
- if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "instrumentation");
- }
+ if (callingPkgSetting != null) {
+ if (callingPkgInstruments(callingPkgSetting, targetPkgSetting, targetName)) {
+ return false;
+ }
+ } else {
+ for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
+ if (callingPkgInstruments(callingSharedPkgSettings.valueAt(i),
+ targetPkgSetting, targetName)) {
return false;
}
}
}
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.checkPermission");
- try {
- if (mPermissionManager.checkPermission(
- Manifest.permission.QUERY_ALL_PACKAGES, callingName, userId)
- == PackageManager.PERMISSION_GRANTED) {
- if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "permission");
- }
- return false;
- }
- } catch (RemoteException e) {
- return true;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
return true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
- private static void log(PackageSetting callingPkgSetting, PackageSetting targetPkgSetting,
- String description) {
- Slog.wtf(TAG,
- "interaction: " + callingPkgSetting.name + " -> " + targetPkgSetting.name + " "
- + description);
+ private static boolean callingPkgInstruments(PackageSetting callingPkgSetting,
+ PackageSetting targetPkgSetting,
+ String targetName) {
+ final ArrayList<PackageParser.Instrumentation> inst = callingPkgSetting.pkg.instrumentation;
+ for (int i = inst.size() - 1; i >= 0; i--) {
+ if (inst.get(i).info.targetPackage == targetName) {
+ if (DEBUG_LOGGING) {
+ log(callingPkgSetting, targetPkgSetting, "instrumentation");
+ }
+ return true;
+ }
+ }
+ return false;
}
- private boolean isImplicitlyQueryableSystemApp(PackageSetting targetPkgSetting) {
- return targetPkgSetting.isSystem() && (mSystemAppsQueryable
- || mForceQueryableByDevice.contains(targetPkgSetting.pkg.packageName));
+ private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
+ String description) {
+ log(callingPkgSetting, targetPkgSetting, description, null);
+ }
+
+ private static void log(SettingBase callingPkgSetting, PackageSetting targetPkgSetting,
+ String description, Throwable throwable) {
+ Slog.wtf(TAG,
+ "interaction: " + callingPkgSetting.toString()
+ + " -> " + targetPkgSetting.name + " "
+ + description, throwable);
}
public void dumpQueries(
- PrintWriter pw, @Nullable String filteringPackageName, DumpState dumpState,
+ PrintWriter pw, PackageManagerService pms, @Nullable Integer filteringAppId,
+ DumpState dumpState,
int[] users) {
+ final SparseArray<String> cache = new SparseArray<>();
+ ToString<Integer> expandPackages = input -> {
+ String cachedValue = cache.get(input);
+ if (cachedValue == null) {
+ final String[] packagesForUid = pms.getPackagesForUid(input);
+ if (packagesForUid == null) {
+ cachedValue = "[unknown app id " + input + "]";
+ } else {
+ cachedValue = packagesForUid.length == 1 ? packagesForUid[0]
+ : "[" + TextUtils.join(",", packagesForUid) + "]";
+ }
+ cache.put(input, cachedValue);
+ }
+ return cachedValue;
+ };
pw.println();
pw.println("Queries:");
dumpState.onTitlePrinted();
+ if (!mFeatureConfig.isGloballyEnabled()) {
+ pw.println(" DISABLED");
+ if (!DEBUG_LOGGING) {
+ return;
+ }
+ }
pw.println(" system apps queryable: " + mSystemAppsQueryable);
- dumpPackageSet(pw, filteringPackageName, mForceQueryableByDevice, "System whitelist", " ");
- dumpPackageSet(pw, filteringPackageName, mForceQueryable, "forceQueryable", " ");
+ dumpPackageSet(pw, filteringAppId, mForceQueryable, "forceQueryable", " ", expandPackages);
pw.println(" queries via package name:");
- dumpQueriesMap(pw, filteringPackageName, mQueriesViaPackage, " ");
+ dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages);
pw.println(" queries via intent:");
- dumpQueriesMap(pw, filteringPackageName, mQueriesViaIntent, " ");
+ dumpQueriesMap(pw, filteringAppId, mQueriesViaIntent, " ", expandPackages);
pw.println(" queryable via interaction:");
for (int user : users) {
pw.append(" User ").append(Integer.toString(user)).println(":");
- final HashMap<String, Set<String>> queryMapForUser = mImplicitlyQueryable.get(user);
- if (queryMapForUser != null) {
- dumpQueriesMap(pw, filteringPackageName, queryMapForUser, " ");
- }
+ dumpQueriesMap(pw,
+ filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
+ mImplicitlyQueryable, " ", expandPackages);
}
}
- private static void dumpQueriesMap(PrintWriter pw, @Nullable String filteringPackageName,
- HashMap<String, Set<String>> queriesMap, String spacing) {
- for (String callingPkg : queriesMap.keySet()) {
- if (Objects.equals(callingPkg, filteringPackageName)) {
- // don't filter target package names if the calling is filteringPackageName
- dumpPackageSet(pw, null /*filteringPackageName*/, queriesMap.get(callingPkg),
- callingPkg, spacing);
+ private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
+ SparseSetArray<Integer> queriesMap, String spacing,
+ @Nullable ToString<Integer> toString) {
+ for (int i = 0; i < queriesMap.size(); i++) {
+ Integer callingId = queriesMap.keyAt(i);
+ if (Objects.equals(callingId, filteringId)) {
+ // don't filter target package names if the calling is filteringId
+ dumpPackageSet(
+ pw, null /*filteringId*/, queriesMap.get(callingId),
+ toString == null
+ ? callingId.toString()
+ : toString.toString(callingId),
+ spacing, toString);
} else {
- dumpPackageSet(pw, filteringPackageName, queriesMap.get(callingPkg), callingPkg,
- spacing);
+ dumpPackageSet(
+ pw, filteringId, queriesMap.get(callingId),
+ toString == null
+ ? callingId.toString()
+ : toString.toString(callingId),
+ spacing, toString);
}
}
}
- private static void dumpPackageSet(PrintWriter pw, @Nullable String filteringPackageName,
- Set<String> targetPkgSet, String subTitle, String spacing) {
+ private interface ToString<T> {
+ String toString(T input);
+ }
+
+ private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId,
+ Set<T> targetPkgSet, String subTitle, String spacing,
+ @Nullable ToString<T> toString) {
if (targetPkgSet != null && targetPkgSet.size() > 0
- && (filteringPackageName == null || targetPkgSet.contains(filteringPackageName))) {
+ && (filteringId == null || targetPkgSet.contains(filteringId))) {
pw.append(spacing).append(subTitle).println(":");
- for (String pkgName : targetPkgSet) {
- if (filteringPackageName == null || Objects.equals(filteringPackageName, pkgName)) {
- pw.append(spacing).append(" ").println(pkgName);
+ for (T item : targetPkgSet) {
+ if (filteringId == null || Objects.equals(filteringId, item)) {
+ pw.append(spacing).append(" ")
+ .println(toString == null ? item : toString.toString(item));
}
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 2b6c347..bd95667 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -304,7 +304,7 @@
long ident = injectClearCallingIdentity();
try {
final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
- if (callingUserInfo != null && callingUserInfo.isManagedProfile()) {
+ if (callingUserInfo != null && callingUserInfo.isProfile()) {
Slog.w(TAG, message + " for another profile "
+ targetUserId + " from " + callingUserId + " not allowed");
return false;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fe82f7c..fa98c96 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11701,7 +11701,7 @@
ksms.addScannedPackageLPw(pkg);
mComponentResolver.addAllComponents(pkg, chatty);
- mAppsFilter.addPackage(pkg, mPackages);
+ mAppsFilter.addPackage(pkgSetting, mSettings.mPackages);
// Don't allow ephemeral applications to define new permissions groups.
if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
@@ -11889,31 +11889,10 @@
}
}
- void removeInstalledPackageLI(PackageParser.Package pkg, boolean chatty) {
- if (DEBUG_INSTALL) {
- if (chatty)
- Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
- }
-
- // writer
- synchronized (mLock) {
- // Remove the parent package
- mPackages.remove(pkg.applicationInfo.packageName);
- cleanPackageDataStructuresLILPw(pkg, chatty);
-
- // Remove the child packages
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- PackageParser.Package childPkg = pkg.childPackages.get(i);
- mPackages.remove(childPkg.applicationInfo.packageName);
- cleanPackageDataStructuresLILPw(childPkg, chatty);
- }
- }
- }
-
void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
mComponentResolver.removeAllComponents(pkg, chatty);
- mAppsFilter.removePackage(pkg.packageName);
+ mAppsFilter.removePackage((PackageSetting) pkg.mExtras,
+ mInjector.getUserManagerInternal().getUserIds(), mSettings.mPackages);
mPermissionManager.removeAllPermissions(pkg, chatty);
final int instrumentationSize = pkg.instrumentation.size();
@@ -20861,7 +20840,11 @@
}
if (dumpState.isDumping(DumpState.DUMP_QUERIES)) {
- mAppsFilter.dumpQueries(pw, packageName, dumpState, mUserManager.getUserIds());
+ final PackageSetting setting = mSettings.getPackageLPr(packageName);
+ Integer filteringAppId = setting == null ? null : setting.appId;
+ mAppsFilter.dumpQueries(
+ pw, this, filteringAppId, dumpState,
+ mUserManager.getUserIds());
}
if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
@@ -23195,8 +23178,9 @@
int callingUid, int targetAppId) {
synchronized (mLock) {
final PackageParser.Package callingPackage = getPackage(callingUid);
+ final int targetUid = UserHandle.getUid(userId, targetAppId);
final PackageParser.Package targetPackage =
- getPackage(UserHandle.getUid(userId, targetAppId));
+ getPackage(targetUid);
if (callingPackage == null || targetPackage == null) {
return;
}
@@ -23207,8 +23191,7 @@
mInstantAppRegistry.grantInstantAccessLPw(userId, intent,
UserHandle.getAppId(callingUid), targetAppId);
} else {
- mAppsFilter.grantImplicitAccess(
- callingPackage.packageName, targetPackage.packageName, userId);
+ mAppsFilter.grantImplicitAccess(callingUid, targetUid);
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 525d357..232374c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2453,27 +2453,40 @@
String name;
int userId = -1;
int flags = 0;
+ String userType = null;
String opt;
boolean preCreateOnly = false;
while ((opt = getNextOption()) != null) {
+ String newUserType = null;
if ("--profileOf".equals(opt)) {
userId = UserHandle.parseUserArg(getNextArgRequired());
} else if ("--managed".equals(opt)) {
- flags |= UserInfo.FLAG_MANAGED_PROFILE;
+ newUserType = UserManager.USER_TYPE_PROFILE_MANAGED;
} else if ("--restricted".equals(opt)) {
- flags |= UserInfo.FLAG_RESTRICTED;
+ newUserType = UserManager.USER_TYPE_FULL_RESTRICTED;
+ } else if ("--guest".equals(opt)) {
+ newUserType = UserManager.USER_TYPE_FULL_GUEST;
+ } else if ("--demo".equals(opt)) {
+ newUserType = UserManager.USER_TYPE_FULL_DEMO;
} else if ("--ephemeral".equals(opt)) {
flags |= UserInfo.FLAG_EPHEMERAL;
- } else if ("--guest".equals(opt)) {
- flags |= UserInfo.FLAG_GUEST;
- } else if ("--demo".equals(opt)) {
- flags |= UserInfo.FLAG_DEMO;
} else if ("--pre-create-only".equals(opt)) {
preCreateOnly = true;
+ } else if ("--user-type".equals(opt)) {
+ newUserType = getNextArgRequired();
} else {
getErrPrintWriter().println("Error: unknown option " + opt);
return 1;
}
+ // Ensure only one user-type was specified.
+ if (newUserType != null) {
+ if (userType != null && !userType.equals(newUserType)) {
+ getErrPrintWriter().println("Error: more than one user type was specified ("
+ + userType + " and " + newUserType + ")");
+ return 1;
+ }
+ userType = newUserType;
+ }
}
String arg = getNextArg();
if (arg == null && !preCreateOnly) {
@@ -2490,16 +2503,20 @@
ServiceManager.getService(Context.USER_SERVICE));
IAccountManager accm = IAccountManager.Stub.asInterface(
ServiceManager.getService(Context.ACCOUNT_SERVICE));
- if ((flags & UserInfo.FLAG_RESTRICTED) != 0) {
+ if (userType == null) {
+ userType = UserInfo.getDefaultUserType(flags);
+ }
+ if (UserManager.isUserTypeRestricted(userType)) {
// In non-split user mode, userId can only be SYSTEM
int parentUserId = userId >= 0 ? userId : UserHandle.USER_SYSTEM;
info = um.createRestrictedProfile(name, parentUserId);
accm.addSharedAccountsFromParentUser(parentUserId, userId,
(Process.myUid() == Process.ROOT_UID) ? "root" : "com.android.shell");
} else if (userId < 0) {
- info = preCreateOnly ? um.preCreateUser(flags) : um.createUser(name, flags);
+ info = preCreateOnly ?
+ um.preCreateUser(userType) : um.createUser(name, userType, flags);
} else {
- info = um.createProfileForUser(name, flags, userId, null);
+ info = um.createProfileForUser(name, userType, flags, userId, null);
}
if (info != null) {
@@ -3421,9 +3438,15 @@
pw.println(" Lists the current users.");
pw.println("");
pw.println(" create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral]");
- pw.println(" [--guest] [--pre-create-only] USER_NAME");
+ pw.println(" [--guest] [--pre-create-only] [--user-type USER_TYPE] USER_NAME");
pw.println(" Create a new user with the given USER_NAME, printing the new user identifier");
pw.println(" of the user.");
+ // TODO(b/142482943): Consider fetching the list of user types from UMS.
+ pw.println(" USER_TYPE is the name of a user type, e.g. android.os.usertype.profile.MANAGED.");
+ pw.println(" If not specified, the default user type is android.os.usertype.full.SECONDARY.");
+ pw.println(" --managed is shorthand for '--user-type android.os.usertype.profile.MANAGED'.");
+ pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'.");
+ pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'.");
pw.println("");
pw.println(" remove-user USER_ID");
pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5c9b9c9..8ddfad9 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -20,8 +20,11 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import android.Manifest;
+import android.annotation.ColorRes;
+import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -77,6 +80,7 @@
import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
import android.stats.devicepolicy.DevicePolicyEnums;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IntArray;
@@ -152,6 +156,7 @@
private static final String TAG_NAME = "name";
private static final String TAG_ACCOUNT = "account";
private static final String ATTR_FLAGS = "flags";
+ private static final String ATTR_TYPE = "type";
private static final String ATTR_ICON_PATH = "icon";
private static final String ATTR_ID = "id";
private static final String ATTR_CREATION_TIME = "created";
@@ -220,15 +225,10 @@
@VisibleForTesting
static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;
- private static final int USER_VERSION = 8;
+ private static final int USER_VERSION = 9;
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
- // Maximum number of managed profiles permitted per user is 1. This cannot be increased
- // without first making sure that the rest of the framework is prepared for it.
- @VisibleForTesting
- static final int MAX_MANAGED_PROFILES = 1;
-
static final int WRITE_USER_MSG = 1;
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
@@ -304,6 +304,12 @@
private final SparseArray<UserData> mUsers = new SparseArray<>();
/**
+ * Map of user type names to their corresponding {@link UserTypeDetails}.
+ * Should not be modified after UserManagerService constructor finishes.
+ */
+ private final ArrayMap<String, UserTypeDetails> mUserTypes;
+
+ /**
* User restrictions set via UserManager. This doesn't include restrictions set by
* device owner / profile owners. Only non-empty restriction bundles are stored.
*
@@ -543,6 +549,7 @@
mPackagesLock = packagesLock;
mHandler = new MainHandler();
mUserDataPreparer = userDataPreparer;
+ mUserTypes = UserTypeFactory.getUserTypes();
synchronized (mPackagesLock) {
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
@@ -700,22 +707,37 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mUsersLock) {
- return getProfilesLU(userId, enabledOnly, returnFullInfo);
+ return getProfilesLU(userId, /* userType */ null, enabledOnly, returnFullInfo);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
+ // TODO(b/142482943): Will probably need a getProfiles(userType). But permissions may vary.
+
@Override
public int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
+ return getProfileIds(userId, null, enabledOnly);
+ }
+
+ // TODO(b/142482943): Probably @Override and make this accessible in UserManager.
+ /**
+ * Returns all the users of type userType that are in the same profile group as userId
+ * (including userId itself, if it is of the appropriate user type).
+ *
+ * <p>If userType is non-{@code null}, only returns users that are of type userType.
+ * If enabledOnly, only returns users that are not {@link UserInfo#FLAG_DISABLED}.
+ */
+ public int[] getProfileIds(@UserIdInt int userId, @Nullable String userType,
+ boolean enabledOnly) {
if (userId != UserHandle.getCallingUserId()) {
checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
}
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mUsersLock) {
- return getProfileIdsLU(userId, enabledOnly).toArray();
+ return getProfileIdsLU(userId, userType, enabledOnly).toArray();
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -724,9 +746,9 @@
/** Assume permissions already checked and caller's identity cleared */
@GuardedBy("mUsersLock")
- private List<UserInfo> getProfilesLU(@UserIdInt int userId, boolean enabledOnly,
- boolean fullInfo) {
- IntArray profileIds = getProfileIdsLU(userId, enabledOnly);
+ private List<UserInfo> getProfilesLU(@UserIdInt int userId, @Nullable String userType,
+ boolean enabledOnly, boolean fullInfo) {
+ IntArray profileIds = getProfileIdsLU(userId, userType, enabledOnly);
ArrayList<UserInfo> users = new ArrayList<>(profileIds.size());
for (int i = 0; i < profileIds.size(); i++) {
int profileId = profileIds.get(i);
@@ -746,9 +768,12 @@
/**
* Assume permissions already checked and caller's identity cleared
+ * <p>If userType is {@code null}, returns all profiles for user; else, only returns
+ * profiles of that type.
*/
@GuardedBy("mUsersLock")
- private IntArray getProfileIdsLU(@UserIdInt int userId, boolean enabledOnly) {
+ private IntArray getProfileIdsLU(@UserIdInt int userId, @Nullable String userType,
+ boolean enabledOnly) {
UserInfo user = getUserInfoLU(userId);
IntArray result = new IntArray(mUsers.size());
if (user == null) {
@@ -770,6 +795,9 @@
if (profile.partial) {
continue;
}
+ if (userType != null && !userType.equals(profile.userType)) {
+ continue;
+ }
result.add(profile.id);
}
return result;
@@ -1116,6 +1144,45 @@
}
}
+ /**
+ * Returns the user type, e.g. {@link UserManager#USER_TYPE_FULL_GUEST}, of the given userId,
+ * or null if the user doesn't exist.
+ */
+ @Override
+ public @Nullable String getUserTypeForUser(@UserIdInt int userId) {
+ // TODO(b/142482943): Decide on the appropriate permission requirements.
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserTypeForUser");
+ return getUserTypeNoChecks(userId);
+ }
+
+ /**
+ * Returns the user type of the given userId, or null if the user doesn't exist.
+ * <p>No permissions checks are made (but userId checks may be made).
+ */
+ private @Nullable String getUserTypeNoChecks(@UserIdInt int userId) {
+ synchronized (mUsersLock) {
+ final UserInfo userInfo = getUserInfoLU(userId);
+ return userInfo != null ? userInfo.userType : null;
+ }
+ }
+
+ /**
+ * Returns the UserTypeDetails of the given userId's user type, or null if the no such user.
+ * <p>No permissions checks are made (but userId checks may be made).
+ */
+ private @Nullable UserTypeDetails getUserTypeDetailsNoChecks(@UserIdInt int userId) {
+ final String typeStr = getUserTypeNoChecks(userId);
+ return typeStr != null ? mUserTypes.get(typeStr) : null;
+ }
+
+ /**
+ * Returns the UserTypeDetails of the given userInfo's user type (or null for a null userInfo).
+ */
+ private @Nullable UserTypeDetails getUserTypeDetails(@Nullable UserInfo userInfo) {
+ final String typeStr = userInfo != null ? userInfo.userType : null;
+ return typeStr != null ? mUserTypes.get(typeStr) : null;
+ }
+
@Override
public UserInfo getUserInfo(@UserIdInt int userId) {
checkManageOrCreateUsersPermission("query user");
@@ -1139,11 +1206,78 @@
}
@Override
- public int getManagedProfileBadge(@UserIdInt int userId) {
- checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getManagedProfileBadge");
+ public boolean hasBadge(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "hasBadge");
+ final UserTypeDetails userTypeDetails = getUserTypeDetailsNoChecks(userId);
+ return userTypeDetails != null && userTypeDetails.hasBadge();
+ }
+
+ @Override
+ public @StringRes int getUserBadgeLabelResId(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserBadgeLabelResId");
+ final UserInfo userInfo = getUserInfoNoChecks(userId);
+ final UserTypeDetails userTypeDetails = getUserTypeDetails(userInfo);
+ if (userInfo == null || userTypeDetails == null || !userTypeDetails.hasBadge()) {
+ Slog.e(LOG_TAG, "Requested badge label for non-badged user " + userId);
+ return Resources.ID_NULL;
+ }
+ final int badgeIndex = userInfo.profileBadge;
+ return userTypeDetails.getBadgeLabel(badgeIndex);
+ }
+
+ @Override
+ public @ColorRes int getUserBadgeColorResId(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserBadgeColorResId");
+ final UserInfo userInfo = getUserInfoNoChecks(userId);
+ final UserTypeDetails userTypeDetails = getUserTypeDetails(userInfo);
+ if (userInfo == null || userTypeDetails == null || !userTypeDetails.hasBadge()) {
+ Slog.e(LOG_TAG, "Requested badge color for non-badged user " + userId);
+ return Resources.ID_NULL;
+ }
+ final int badgeIndex = userInfo.profileBadge;
+ return userTypeDetails.getBadgeColor(badgeIndex);
+ }
+
+ @Override
+ public @DrawableRes int getUserIconBadgeResId(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserIconBadgeResId");
+ final UserTypeDetails userTypeDetails = getUserTypeDetailsNoChecks(userId);
+ if (userTypeDetails == null || !userTypeDetails.hasBadge()) {
+ Slog.e(LOG_TAG, "Requested icon badge for non-badged user " + userId);
+ return Resources.ID_NULL;
+ }
+ return userTypeDetails.getIconBadge();
+ }
+
+ @Override
+ public @DrawableRes int getUserBadgeResId(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserBadgeResId");
+ final UserTypeDetails userTypeDetails = getUserTypeDetailsNoChecks(userId);
+ if (userTypeDetails == null || !userTypeDetails.hasBadge()) {
+ Slog.e(LOG_TAG, "Requested badge for non-badged user " + userId);
+ return Resources.ID_NULL;
+ }
+ return userTypeDetails.getBadgePlain();
+ }
+
+ @Override
+ public @DrawableRes int getUserBadgeNoBackgroundResId(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId,
+ "getUserBadgeNoBackgroundResId");
+ final UserTypeDetails userTypeDetails = getUserTypeDetailsNoChecks(userId);
+ if (userTypeDetails == null || !userTypeDetails.hasBadge()) {
+ Slog.e(LOG_TAG, "Requested badge (no background) for non-badged user " + userId);
+ return Resources.ID_NULL;
+ }
+ return userTypeDetails.getBadgeNoBackground();
+ }
+
+ @Override
+ public boolean isProfile(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isProfile");
synchronized (mUsersLock) {
UserInfo userInfo = getUserInfoLU(userId);
- return userInfo != null ? userInfo.profileBadge : 0;
+ return userInfo != null && userInfo.isProfile();
}
}
@@ -1896,33 +2030,93 @@
return count >= UserManager.getMaxSupportedUsers();
}
+ /**
+ * Returns whether more users of the given type can be added (based on how many users of that
+ * type already exist).
+ *
+ * <p>For checking whether more profiles can be added to a particular parent use
+ * {@link #canAddMoreProfilesToUser}.
+ */
+ private boolean canAddMoreUsersOfType(UserTypeDetails userTypeDetails) {
+ final int max = userTypeDetails.getMaxAllowed();
+ if (max == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) {
+ return true; // Indicates that there is no max.
+ }
+ return getNumberOfUsersOfType(userTypeDetails.getName()) < max;
+ }
+
+ /**
+ * Gets the number of users of the given user type.
+ * Does not include users that are about to die.
+ */
+ private int getNumberOfUsersOfType(String userType) {
+ int count = 0;
+ synchronized (mUsersLock) {
+ final int size = mUsers.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo user = mUsers.valueAt(i).info;
+ if (user.userType.equals(userType)
+ && !user.guestToRemove
+ && !mRemovingUserIds.get(user.id)
+ && !user.preCreated) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
@Override
public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) {
- checkManageUsersPermission("check if more managed profiles can be added.");
- if (ActivityManager.isLowRamDeviceStatic()) {
+ return canAddMoreProfilesToUser(UserManager.USER_TYPE_PROFILE_MANAGED, userId,
+ allowedToRemoveOne);
+ }
+
+ /** Returns whether more profiles of the given type can be added to the given parent userId. */
+ @Override
+ public boolean canAddMoreProfilesToUser(String userType, @UserIdInt int userId,
+ boolean allowedToRemoveOne) {
+ checkManageUsersPermission("check if more profiles can be added.");
+ final UserTypeDetails type = mUserTypes.get(userType);
+ if (type == null) {
return false;
}
- if (!mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_MANAGED_USERS)) {
- return false;
+ // Managed profiles have their own specific rules.
+ final boolean isManagedProfile = type.isManagedProfile();
+ if (isManagedProfile) {
+ if (ActivityManager.isLowRamDeviceStatic()) {
+ return false;
+ }
+ if (!mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_MANAGED_USERS)) {
+ return false;
+ }
}
- // Limit number of managed profiles that can be created
- final int managedProfilesCount = getProfiles(userId, false).size() - 1;
- final int profilesRemovedCount = managedProfilesCount > 0 && allowedToRemoveOne ? 1 : 0;
- if (managedProfilesCount - profilesRemovedCount >= getMaxManagedProfiles()) {
- return false;
- }
- synchronized(mUsersLock) {
+ synchronized (mUsersLock) {
+ // Check if the parent exists and its type is even allowed to have a profile.
UserInfo userInfo = getUserInfoLU(userId);
if (userInfo == null || !userInfo.canHaveProfile()) {
return false;
}
- int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU()
- - profilesRemovedCount;
- // We allow creating a managed profile in the special case where there is only one user.
- return usersCountAfterRemoving == 1
- || usersCountAfterRemoving < UserManager.getMaxSupportedUsers();
+
+ // Limit the number of profiles that can be created
+ final int maxUsersOfType = getMaxUsersOfTypePerParent(type);
+ if (maxUsersOfType != UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) {
+ final int userTypeCount = getProfileIds(userId, userType, false).length;
+ final int profilesRemovedCount = userTypeCount > 0 && allowedToRemoveOne ? 1 : 0;
+ if (userTypeCount - profilesRemovedCount >= maxUsersOfType) {
+ return false;
+ }
+ // Allow creating a managed profile in the special case where there is only one user
+ if (isManagedProfile) {
+ int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU()
+ - profilesRemovedCount;
+ return usersCountAfterRemoving == 1
+ || usersCountAfterRemoving < UserManager.getMaxSupportedUsers();
+ }
+ }
}
+ return true;
}
@GuardedBy("mUsersLock")
@@ -2207,9 +2401,18 @@
*/
@GuardedBy({"mRestrictionsLock", "mPackagesLock"})
private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
+ upgradeIfNecessaryLP(oldGlobalUserRestrictions, mUserVersion);
+ }
+
+ /**
+ * Version of {@link #upgradeIfNecessaryLP(Bundle)} that takes in the userVersion for testing
+ * purposes. For non-tests, use {@link #upgradeIfNecessaryLP(Bundle)}.
+ */
+ @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
+ @VisibleForTesting
+ void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions, int userVersion) {
Set<Integer> userIdsToWrite = new ArraySet<>();
final int originalVersion = mUserVersion;
- int userVersion = mUserVersion;
if (userVersion < 1) {
// Assign a proper name for the owner, if not initialized correctly before
UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
@@ -2298,6 +2501,44 @@
userVersion = 8;
}
+ if (userVersion < 9) {
+ // Convert from UserInfo flags to UserTypes. Apply FLAG_PROFILE to FLAG_MANAGED_PROFILE.
+ synchronized (mUsersLock) {
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserData userData = mUsers.valueAt(i);
+ final int flags = userData.info.flags;
+ if ((flags & UserInfo.FLAG_SYSTEM) != 0) {
+ if ((flags & UserInfo.FLAG_FULL) != 0) {
+ userData.info.userType = UserManager.USER_TYPE_FULL_SYSTEM;
+ } else {
+ userData.info.userType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
+ }
+ } else {
+ try {
+ userData.info.userType = UserInfo.getDefaultUserType(flags);
+ } catch (IllegalArgumentException e) {
+ // TODO(b/142482943): What should we do here? Delete user? Crashloop?
+ throw new IllegalStateException("Cannot upgrade user with flags "
+ + Integer.toHexString(flags) + " because it doesn't correspond "
+ + "to a valid user type.", e);
+ }
+ }
+ // OEMs are responsible for their own custom upgrade logic here.
+
+ final UserTypeDetails userTypeDetails = mUserTypes.get(userData.info.userType);
+ if (userTypeDetails == null) {
+ throw new IllegalStateException(
+ "Cannot upgrade user with flags " + Integer.toHexString(flags)
+ + " because " + userData.info.userType + " isn't defined"
+ + " on this device!");
+ }
+ userData.info.flags |= userTypeDetails.getDefaultUserInfoFlags();
+ userIdsToWrite.add(userData.info.id);
+ }
+ }
+ userVersion = 9;
+ }
+
if (userVersion < USER_VERSION) {
Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
+ USER_VERSION);
@@ -2320,12 +2561,11 @@
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
| UserInfo.FLAG_PRIMARY;
- // In headless system user mode, headless system user is not a full user.
- if (!UserManager.isHeadlessSystemUserMode()) {
- flags |= UserInfo.FLAG_FULL;
- }
// Create the system user
- UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
+ String systemUserType = UserManager.isHeadlessSystemUserMode() ?
+ UserManager.USER_TYPE_SYSTEM_HEADLESS : UserManager.USER_TYPE_FULL_SYSTEM;
+ flags |= mUserTypes.get(systemUserType).getDefaultUserInfoFlags();
+ UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags, systemUserType);
UserData userData = putUserInfo(system);
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
@@ -2410,6 +2650,7 @@
serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
+ serializer.attribute(null, ATTR_TYPE, userInfo.userType);
serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
Long.toString(userInfo.lastLoggedInTime));
@@ -2570,6 +2811,7 @@
UserData readUserLP(int id, InputStream is) throws IOException,
XmlPullParserException {
int flags = 0;
+ String userType = null;
int serialNumber = id;
String name = null;
String account = null;
@@ -2613,6 +2855,8 @@
}
serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
flags = readIntAttribute(parser, ATTR_FLAGS, 0);
+ userType = parser.getAttributeValue(null, ATTR_TYPE);
+ userType = userType != null ? userType.intern() : null;
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
@@ -2678,7 +2922,7 @@
}
// Create the UserInfo object that gets passed around
- UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
+ UserInfo userInfo = new UserInfo(id, name, iconPath, flags, userType);
userInfo.serialNumber = serialNumber;
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
@@ -2745,108 +2989,135 @@
}
}
+ /**
+ * Creates a profile user. Used for actual profiles, like
+ * {@link UserManager#USER_TYPE_PROFILE_MANAGED}, as well as for
+ * {@link UserManager#USER_TYPE_FULL_RESTRICTED}.
+ */
@Override
- public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId,
- String[] disallowedPackages) {
+ public UserInfo createProfileForUser(String name, @NonNull String userType,
+ @UserInfoFlag int flags, @UserIdInt int userId, @Nullable String[] disallowedPackages) {
checkManageOrCreateUsersPermission(flags);
- return createUserInternal(name, flags, userId, disallowedPackages);
+ return createUserInternal(name, userType, flags, userId, disallowedPackages);
+ }
+
+ /** @see #createProfileForUser */
+ @Override
+ public UserInfo createProfileForUserEvenWhenDisallowed(String name, @NonNull String userType,
+ @UserInfoFlag int flags, @UserIdInt int userId, @Nullable String[] disallowedPackages) {
+ checkManageOrCreateUsersPermission(flags);
+ return createUserInternalUnchecked(name, userType, flags, userId,
+ /* preCreate= */ false, disallowedPackages);
}
@Override
- public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags,
- @UserIdInt int userId, String[] disallowedPackages) {
+ public UserInfo createUser(String name, @NonNull String userType, @UserInfoFlag int flags) {
checkManageOrCreateUsersPermission(flags);
- return createUserInternalUnchecked(name, flags, userId, /* preCreate= */ false,
- disallowedPackages);
+ return createUserInternal(name, userType, flags, UserHandle.USER_NULL,
+ /* disallowedPackages= */ null);
}
@Override
- public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) {
- checkManageOrCreateUsersPermission("Only the system can remove users");
- return removeUserUnchecked(userId);
- }
+ public UserInfo preCreateUser(String userType) {
+ final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
+ final int flags = userTypeDetails != null ? userTypeDetails.getDefaultUserInfoFlags() : 0;
- @Override
- public UserInfo createUser(String name, int flags) {
- checkManageOrCreateUsersPermission(flags);
- return createUserInternal(name, flags, UserHandle.USER_NULL);
- }
-
- @Override
- public UserInfo preCreateUser(int flags) {
checkManageOrCreateUsersPermission(flags);
- Preconditions.checkArgument(!UserInfo.isManagedProfile(flags),
- "cannot pre-create managed profiles");
+ Preconditions.checkArgument(isUserTypeEligibleForPreCreation(userTypeDetails),
+ "cannot pre-create user of type " + userType);
+ Slog.i(LOG_TAG, "Pre-creating user of type " + userType);
- Slog.i(LOG_TAG, "Pre-creating user with flags " + UserInfo.flagsToString(flags));
-
- return createUserInternalUnchecked(/* name= */ null, flags,
+ return createUserInternalUnchecked(/* name= */ null, userType, flags,
/* parentId= */ UserHandle.USER_NULL, /* preCreate= */ true,
/* disallowedPackages= */ null);
}
- private UserInfo createUserInternal(@Nullable String name, @UserInfoFlag int flags,
- @UserIdInt int parentId) {
- return createUserInternal(name, flags, parentId, null);
- }
-
- private UserInfo createUserInternal(@Nullable String name, @UserInfoFlag int flags,
- @UserIdInt int parentId, @Nullable String[] disallowedPackages) {
- String restriction = ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0)
+ private UserInfo createUserInternal(@Nullable String name, @NonNull String userType,
+ @UserInfoFlag int flags, @UserIdInt int parentId,
+ @Nullable String[] disallowedPackages) {
+ String restriction = (UserManager.isUserTypeManagedProfile(userType))
? UserManager.DISALLOW_ADD_MANAGED_PROFILE
: UserManager.DISALLOW_ADD_USER;
if (hasUserRestriction(restriction, UserHandle.getCallingUserId())) {
Log.w(LOG_TAG, "Cannot add user. " + restriction + " is enabled.");
return null;
}
- return createUserInternalUnchecked(name, flags, parentId, /* preCreate= */ false,
- disallowedPackages);
+ return createUserInternalUnchecked(name, userType, flags, parentId,
+ /* preCreate= */ false, disallowedPackages);
}
- private UserInfo createUserInternalUnchecked(@Nullable String name, @UserInfoFlag int flags,
- @UserIdInt int parentId, boolean preCreate,
- @Nullable String[] disallowedPackages) {
+ private UserInfo createUserInternalUnchecked(@Nullable String name,
+ @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId,
+ boolean preCreate, @Nullable String[] disallowedPackages) {
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
t.traceBegin("createUser-" + flags);
try {
- return createUserInternalUncheckedNoTracing(name, flags, parentId, preCreate,
- disallowedPackages, t);
+ return createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
+ preCreate, disallowedPackages, t);
} finally {
t.traceEnd();
}
}
private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name,
- @UserInfoFlag int flags, @UserIdInt int parentId, boolean preCreate,
- @Nullable String[] disallowedPackages, @NonNull TimingsTraceAndSlog t) {
+ @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId,
+ boolean preCreate, @Nullable String[] disallowedPackages,
+ @NonNull TimingsTraceAndSlog t) {
+
+ final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
+ if (userTypeDetails == null) {
+ Slog.e(LOG_TAG, "Cannot create user of invalid user type: " + userType);
+ return null;
+ }
+ userType = userType.intern(); // Now that we know it's valid, we can intern it.
+ flags |= userTypeDetails.getDefaultUserInfoFlags();
+ if (!checkUserTypeConsistency(flags)) {
+ Slog.e(LOG_TAG, "Cannot add user. Flags (" + Integer.toHexString(flags)
+ + ") and userTypeDetails (" + userType + ") are inconsistent.");
+ return null;
+ }
+ if ((flags & UserInfo.FLAG_SYSTEM) != 0) {
+ Slog.e(LOG_TAG, "Cannot add user. Flags (" + Integer.toHexString(flags)
+ + ") indicated SYSTEM user, which cannot be created.");
+ return null;
+ }
+ synchronized (mUsersLock) {
+ if (mForceEphemeralUsers) {
+ flags |= UserInfo.FLAG_EPHEMERAL;
+ }
+ }
// First try to use a pre-created user (if available).
- // NOTE: currently we don't support pre-created managed profiles
- if (!preCreate && (parentId < 0 && !UserInfo.isManagedProfile(flags))) {
+ // TODO(b/142482943): Move this to its own function later.
+ if (!preCreate
+ && (parentId < 0 && isUserTypeEligibleForPreCreation(userTypeDetails))) {
final UserData preCreatedUserData;
synchronized (mUsersLock) {
- preCreatedUserData = getPreCreatedUserLU(flags);
+ preCreatedUserData = getPreCreatedUserLU(userType);
}
if (preCreatedUserData != null) {
final UserInfo preCreatedUser = preCreatedUserData.info;
- Log.i(LOG_TAG, "Reusing pre-created user " + preCreatedUser.id + " for flags + "
- + UserInfo.flagsToString(flags));
- if (DBG) {
- Log.d(LOG_TAG, "pre-created user flags: "
- + UserInfo.flagsToString(preCreatedUser.flags)
- + " new-user flags: " + UserInfo.flagsToString(flags));
+ final int newFlags = preCreatedUser.flags | flags;
+ if (!checkUserTypeConsistency(newFlags)) {
+ Slog.wtf(LOG_TAG, "Cannot reuse pre-created user " + preCreatedUser.id
+ + " of type " + userType + " because flags are inconsistent. "
+ + "Flags (" + Integer.toHexString(flags) + "); preCreatedUserFlags ( "
+ + Integer.toHexString(preCreatedUser.flags) + ").");
+ } else {
+ Log.i(LOG_TAG, "Reusing pre-created user " + preCreatedUser.id + " of type "
+ + userType + " and bestowing on it flags "
+ + UserInfo.flagsToString(flags));
+ preCreatedUser.name = name;
+ preCreatedUser.flags = newFlags;
+ preCreatedUser.preCreated = false;
+ preCreatedUser.creationTime = getCreationTime();
+
+ dispatchUserAddedIntent(preCreatedUser);
+ writeUserLP(preCreatedUserData);
+ writeUserListLP();
+ return preCreatedUser;
}
- preCreatedUser.name = name;
- preCreatedUser.preCreated = false;
- preCreatedUser.creationTime = getCreationTime();
-
- dispatchUserAddedIntent(preCreatedUser);
-
- writeUserLP(preCreatedUserData);
- writeUserListLP();
-
- return preCreatedUser;
}
}
@@ -2857,10 +3128,11 @@
return null;
}
- final boolean isGuest = UserInfo.isGuest(flags);
- final boolean isManagedProfile = UserInfo.isManagedProfile(flags);
- final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
- final boolean isDemo = (flags & UserInfo.FLAG_DEMO) != 0;
+ final boolean isProfile = userTypeDetails.isProfile();
+ final boolean isGuest = UserManager.isUserTypeGuest(userType);
+ final boolean isRestricted = UserManager.isUserTypeRestricted(userType);
+ final boolean isDemo = UserManager.isUserTypeDemo(userType);
+
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo;
UserData userData;
@@ -2874,21 +3146,23 @@
}
if (parent == null) return null;
}
- if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
- Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
+ if (!preCreate && !canAddMoreUsersOfType(userTypeDetails)) {
+ Log.e(LOG_TAG, "Cannot add more users of type " + userType
+ + ". Maximum number of that type already exists.");
return null;
}
- if (!isGuest && !isManagedProfile && !isDemo && isUserLimitReached()) {
- // If we're not adding a guest/demo user or a managed profile,
- // and the limit has been reached, cannot add a user.
+ // TODO(b/142482943): Perhaps let the following code apply to restricted users too.
+ if (isProfile && !canAddMoreProfilesToUser(userType, parentId, false)) {
+ Log.e(LOG_TAG, "Cannot add more profiles of type " + userType
+ + " for user " + parentId);
+ return null;
+ }
+ if (!isGuest && !isProfile && !isDemo && isUserLimitReached()) {
+ // If we're not adding a guest/demo user or a profile and the 'user limit' has
+ // been reached, cannot add a user.
Log.e(LOG_TAG, "Cannot add user. Maximum user limit is reached.");
return null;
}
- // If we're adding a guest and there already exists one, bail.
- if (isGuest && !preCreate && findCurrentGuestUser() != null) {
- Log.e(LOG_TAG, "Cannot add guest user. Guest user already exists.");
- return null;
- }
// In legacy mode, restricted profile's parent can only be the owner user
if (isRestricted && !UserManager.isSplitSystemUser()
&& (parentId != UserHandle.USER_SYSTEM)) {
@@ -2908,30 +3182,23 @@
}
}
- if (!isManagedProfile) {
- // New users cannot be system, and it's not a profile, so per-force it's FULL.
- flags |= UserInfo.FLAG_FULL;
- }
-
userId = getNextAvailableId();
Environment.getUserSystemDirectory(userId).mkdirs();
- boolean ephemeralGuests = areGuestUsersEphemeral();
synchronized (mUsersLock) {
- // Add ephemeral flag to guests/users if required. Also inherit it from parent.
- if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
- || (parent != null && parent.info.isEphemeral())) {
+ // Inherit ephemeral flag from parent.
+ if (parent != null && parent.info.isEphemeral()) {
flags |= UserInfo.FLAG_EPHEMERAL;
}
- userInfo = new UserInfo(userId, name, null, flags);
+ userInfo = new UserInfo(userId, name, null, flags, userType);
userInfo.serialNumber = mNextSerialNumber++;
userInfo.creationTime = getCreationTime();
userInfo.partial = true;
userInfo.preCreated = preCreate;
userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
- if (isManagedProfile && parentId != UserHandle.USER_NULL) {
- userInfo.profileBadge = getFreeProfileBadgeLU(parentId);
+ if (userTypeDetails.hasBadge() && parentId != UserHandle.USER_NULL) {
+ userInfo.profileBadge = getFreeProfileBadgeLU(parentId, userType);
}
userData = new UserData();
userData.info = userInfo;
@@ -2940,7 +3207,7 @@
writeUserLP(userData);
writeUserListLP();
if (parent != null) {
- if (isManagedProfile) {
+ if (isProfile) {
if (parent.info.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
parent.info.profileGroupId = parent.info.id;
writeUserLP(parent);
@@ -2966,7 +3233,7 @@
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
t.traceEnd();
- final Set<String> installablePackages =
+ final Set<String> installablePackages = // TODO(b/142482943): use userType
mSystemPackageInstaller.getInstallablePackagesForUserType(flags);
t.traceBegin("PM.createNewUser");
mPm.createNewUser(userId, installablePackages, disallowedPackages);
@@ -2978,6 +3245,7 @@
}
updateUserIds();
Bundle restrictions = new Bundle();
+ // TODO(b/142482943): Generalize this using UserTypeDetails default restrictions.
if (isGuest) {
synchronized (mGuestRestrictions) {
restrictions.putAll(mGuestRestrictions);
@@ -3026,6 +3294,22 @@
return userInfo;
}
+ /** Checks that the flags do not contain mutually exclusive types/properties. */
+ static boolean checkUserTypeConsistency(@UserInfoFlag int flags) {
+ // Mask to check that flags don't refer to multiple user types.
+ final int userTypeFlagMask = UserInfo.FLAG_GUEST | UserInfo.FLAG_DEMO
+ | UserInfo.FLAG_RESTRICTED | UserInfo.FLAG_PROFILE;
+ return isAtMostOneFlag(flags & userTypeFlagMask)
+ && isAtMostOneFlag(flags & (UserInfo.FLAG_PROFILE | UserInfo.FLAG_FULL))
+ && isAtMostOneFlag(flags & (UserInfo.FLAG_PROFILE | UserInfo.FLAG_SYSTEM));
+ }
+
+ /** Returns whether the given flags contains at most one 1. */
+ private static boolean isAtMostOneFlag(int flags) {
+ return (flags & (flags - 1)) == 0;
+ // If !=0, this means that flags is not a power of 2, and therefore is multiple types.
+ }
+
/** Install/uninstall system packages for all users based on their user-type, as applicable. */
boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
return mSystemPackageInstaller.installWhitelistedSystemPackages(isFirstBoot, isUpgrade);
@@ -3045,39 +3329,23 @@
: (userInfo.isDemo() ? TRON_DEMO_CREATED : TRON_USER_CREATED), 1);
}
- private boolean areGuestUsersEphemeral() {
- return Resources.getSystem()
- .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
- }
-
/**
- * Gets a pre-created user for the given flag.
+ * Gets a pre-created user for the given user type.
*
* <p>Should be used only during user creation, so the pre-created user can be used (instead of
* creating and initializing a new user from scratch).
*/
// TODO(b/143092698): add unit test
@GuardedBy("mUsersLock")
- private @Nullable UserData getPreCreatedUserLU(@UserInfoFlag int flags) {
- if (DBG) {
- Slog.d(LOG_TAG, "getPreCreatedUser(): initialFlags= " + UserInfo.flagsToString(flags));
- }
- flags |= UserInfo.FLAG_FULL;
- if (UserInfo.isGuest(flags) && areGuestUsersEphemeral()) {
- flags |= UserInfo.FLAG_EPHEMERAL;
- }
- if (DBG) {
- Slog.d(LOG_TAG, "getPreCreatedUser(): targetFlags= " + UserInfo.flagsToString(flags));
- }
+ private @Nullable UserData getPreCreatedUserLU(String userType) {
+ if (DBG) Slog.d(LOG_TAG, "getPreCreatedUser(): userType= " + userType);
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
final UserData user = mUsers.valueAt(i);
if (DBG) Slog.d(LOG_TAG, i + ":" + user.info.toFullString());
- if (user.info.preCreated
- && (user.info.flags & ~UserInfo.FLAG_INITIALIZED) == flags) {
+ if (user.info.preCreated && user.info.userType.equals(userType)) {
if (!user.info.isInitialized()) {
- Slog.w(LOG_TAG, "found pre-created user for flags "
- + "" + UserInfo.flagsToString(flags)
+ Slog.w(LOG_TAG, "found pre-created user of type " + userType
+ ", but it's not initialized yet: " + user.info.toFullString());
continue;
}
@@ -3087,6 +3355,18 @@
return null;
}
+ /**
+ * Returns whether a user with the given userTypeDetails is eligible to be
+ * {@link UserInfo#preCreated}.
+ */
+ private static boolean isUserTypeEligibleForPreCreation(UserTypeDetails userTypeDetails) {
+ if (userTypeDetails == null) {
+ return false;
+ }
+ return !userTypeDetails.isProfile()
+ && !userTypeDetails.getName().equals(UserManager.USER_TYPE_FULL_RESTRICTED);
+ }
+
@VisibleForTesting
UserData putUserInfo(UserInfo userInfo) {
final UserData userData = new UserData();
@@ -3111,7 +3391,7 @@
public UserInfo createRestrictedProfile(String name, int parentUserId) {
checkManageOrCreateUsersPermission("setupRestrictedProfile");
final UserInfo user = createProfileForUser(
- name, UserInfo.FLAG_RESTRICTED, parentUserId, null);
+ name, UserManager.USER_TYPE_FULL_RESTRICTED, 0, parentUserId, null);
if (user == null) {
return null;
}
@@ -3217,6 +3497,12 @@
return removeUserUnchecked(userId);
}
+ @Override
+ public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) {
+ checkManageOrCreateUsersPermission("Only the system can remove users");
+ return removeUserUnchecked(userId);
+ }
+
private boolean removeUserUnchecked(@UserIdInt int userId) {
long ident = Binder.clearCallingIdentity();
try {
@@ -3264,6 +3550,7 @@
Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user.", e);
}
+ // TODO(b/142482943): Send some sort of broadcast for profiles even if non-managed?
if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
&& userData.info.isManagedProfile()) {
// Send broadcast to notify system that the user removed was a
@@ -4035,6 +4322,7 @@
pw.print(" <pre-created>");
}
pw.println();
+ pw.print(" Type: "); pw.println(userInfo.userType);
pw.print(" Flags: "); pw.print(userInfo.flags); pw.print(" (");
pw.print(UserInfo.flagsToString(userInfo.flags)); pw.println(")");
pw.print(" State: ");
@@ -4119,11 +4407,20 @@
pw.print(" Max users: " + UserManager.getMaxSupportedUsers());
pw.println(" (limit reached: " + isUserLimitReached() + ")");
pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers());
- pw.println(" All guests ephemeral: " + areGuestUsersEphemeral());
+ pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_guestUserEphemeral));
pw.println(" Is split-system user: " + UserManager.isSplitSystemUser());
pw.println(" Is headless-system mode: " + UserManager.isHeadlessSystemUserMode());
pw.println(" User version: " + mUserVersion);
+ // Dump UserTypes
+ pw.println();
+ pw.println(" User types (" + mUserTypes.size() + " types):");
+ for (int i = 0; i < mUserTypes.size(); i++) {
+ pw.println(" " + mUserTypes.keyAt(i) + ": ");
+ mUserTypes.valueAt(i).dump(pw);
+ }
+
// Dump package whitelist
pw.println();
mSystemPackageInstaller.dump(pw);
@@ -4322,10 +4619,10 @@
}
@Override
- public UserInfo createUserEvenWhenDisallowed(String name, int flags,
- String[] disallowedPackages) {
- UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL,
- /* preCreated= */ false, disallowedPackages);
+ public UserInfo createUserEvenWhenDisallowed(String name, @NonNull String userType,
+ @UserInfoFlag int flags, String[] disallowedPackages) {
+ UserInfo user = createUserInternalUnchecked(name, userType, flags,
+ UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages);
// Keep this in sync with UserManager.createUser
if (user != null && !user.isAdmin() && !user.isDemo()) {
setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
@@ -4410,7 +4707,7 @@
}
synchronized (mUsersLock) {
UserInfo callingUserInfo = getUserInfoLU(callingUserId);
- if (callingUserInfo == null || callingUserInfo.isManagedProfile()) {
+ if (callingUserInfo == null || callingUserInfo.isProfile()) {
if (throwSecurityException) {
throw new SecurityException(
debugMsg + " for another profile "
@@ -4529,36 +4826,53 @@
(DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : ""));
}
+ /** @see #getMaxUsersOfTypePerParent(UserTypeDetails) */
@VisibleForTesting
- static int getMaxManagedProfiles() {
- // Allow overriding max managed profiles on debuggable builds for testing
- // of multiple profiles.
- if (!Build.IS_DEBUGGABLE) {
- return MAX_MANAGED_PROFILES;
- } else {
- return SystemProperties.getInt("persist.sys.max_profiles",
- MAX_MANAGED_PROFILES);
+ int getMaxUsersOfTypePerParent(String userType) {
+ final UserTypeDetails type = mUserTypes.get(userType);
+ if (type == null) {
+ return 0;
}
+ return getMaxUsersOfTypePerParent(type);
+ }
+
+ /**
+ * Returns the maximum number of users allowed for the given userTypeDetails per parent user.
+ * This is applicable for user types that are {@link UserTypeDetails#isProfile()}.
+ * If there is no maximum, {@link UserTypeDetails#UNLIMITED_NUMBER_OF_USERS} is returned.
+ */
+ private static int getMaxUsersOfTypePerParent(UserTypeDetails userTypeDetails) {
+ final int defaultMax = userTypeDetails.getMaxAllowedPerParent();
+ if (!Build.IS_DEBUGGABLE) {
+ return defaultMax;
+ } else {
+ if (userTypeDetails.isManagedProfile()) {
+ return SystemProperties.getInt("persist.sys.max_profiles", defaultMax);
+ }
+ }
+ return defaultMax;
}
@GuardedBy("mUsersLock")
@VisibleForTesting
- int getFreeProfileBadgeLU(int parentUserId) {
- int maxManagedProfiles = getMaxManagedProfiles();
- boolean[] usedBadges = new boolean[maxManagedProfiles];
+ int getFreeProfileBadgeLU(int parentUserId, String userType) {
+ Set<Integer> usedBadges = new ArraySet<>();
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i).info;
// Check which badge indexes are already used by this profile group.
- if (ui.isManagedProfile()
+ if (ui.userType.equals(userType)
&& ui.profileGroupId == parentUserId
- && !mRemovingUserIds.get(ui.id)
- && ui.profileBadge < maxManagedProfiles) {
- usedBadges[ui.profileBadge] = true;
+ && !mRemovingUserIds.get(ui.id)) {
+ usedBadges.add(ui.profileBadge);
}
}
- for (int i = 0; i < maxManagedProfiles; i++) {
- if (!usedBadges[i]) {
+ int maxUsersOfType = getMaxUsersOfTypePerParent(userType);
+ if (maxUsersOfType == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS) {
+ maxUsersOfType = Integer.MAX_VALUE;
+ }
+ for (int i = 0; i < maxUsersOfType; i++) {
+ if (!usedBadges.contains(i)) {
return i;
}
}
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 4654cca..95197b0 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -411,12 +411,13 @@
}
// Regardless of the whitelists/blacklists, ensure mandatory packages.
result.put("android",
- UserInfo.FLAG_SYSTEM | UserInfo.FLAG_FULL | UserInfo.PROFILE_FLAGS_MASK);
+ UserInfo.FLAG_SYSTEM | UserInfo.FLAG_FULL | UserInfo.FLAG_PROFILE);
return result;
}
/** Converts a user types, as used in SystemConfig, to a UserInfo flag. */
private static int getFlagsFromUserTypes(Iterable<String> userTypes) {
+ // TODO(b/142482943): Update all this for the new UserTypes.
int flags = 0;
for (String type : userTypes) {
switch (type) {
@@ -442,7 +443,7 @@
flags |= UserInfo.FLAG_SYSTEM;
break;
case "PROFILE":
- flags |= UserInfo.PROFILE_FLAGS_MASK;
+ flags |= UserInfo.FLAG_PROFILE;
break;
default:
Slog.w(TAG, "SystemConfig contained an invalid user type: " + type);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
index 505a0e2..b68d541 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -23,6 +23,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
@@ -30,7 +31,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import com.android.internal.annotations.GuardedBy;
/**
* This class encapsulates the permissions for a package or a shared user.
@@ -708,7 +708,11 @@
}
private static final class PermissionData {
+
+ private final Object mLock = new Object();
+
private final BasePermission mPerm;
+ @GuardedBy("mLock")
private SparseArray<PermissionState> mUserStates = new SparseArray<>();
public PermissionData(BasePermission perm) {
@@ -717,11 +721,14 @@
public PermissionData(PermissionData other) {
this(other.mPerm);
- final int otherStateCount = other.mUserStates.size();
- for (int i = 0; i < otherStateCount; i++) {
- final int otherUserId = other.mUserStates.keyAt(i);
- PermissionState otherState = other.mUserStates.valueAt(i);
- mUserStates.put(otherUserId, new PermissionState(otherState));
+
+ synchronized (mLock) {
+ final int otherStateCount = other.mUserStates.size();
+ for (int i = 0; i < otherStateCount; i++) {
+ final int otherUserId = other.mUserStates.keyAt(i);
+ PermissionState otherState = other.mUserStates.valueAt(i);
+ mUserStates.put(otherUserId, new PermissionState(otherState));
+ }
}
}
@@ -730,71 +737,83 @@
}
public boolean isGranted(int userId) {
- if (isInstallPermission()) {
- userId = UserHandle.USER_ALL;
- }
+ synchronized (mLock) {
+ if (isInstallPermission()) {
+ userId = UserHandle.USER_ALL;
+ }
- PermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- return false;
- }
+ PermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ return false;
+ }
- return userState.mGranted;
+ return userState.mGranted;
+ }
}
public boolean grant(int userId) {
- if (!isCompatibleUserId(userId)) {
- return false;
+ synchronized (mLock) {
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ if (isGranted(userId)) {
+ return false;
+ }
+
+ PermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new PermissionState(mPerm.getName());
+ mUserStates.put(userId, userState);
+ }
+
+ userState.mGranted = true;
+
+ return true;
}
-
- if (isGranted(userId)) {
- return false;
- }
-
- PermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- userState = new PermissionState(mPerm.getName());
- mUserStates.put(userId, userState);
- }
-
- userState.mGranted = true;
-
- return true;
}
public boolean revoke(int userId) {
- if (!isCompatibleUserId(userId)) {
- return false;
+ synchronized (mLock) {
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ if (!isGranted(userId)) {
+ return false;
+ }
+
+ PermissionState userState = mUserStates.get(userId);
+ userState.mGranted = false;
+
+ if (userState.isDefault()) {
+ mUserStates.remove(userId);
+ }
+
+ return true;
}
-
- if (!isGranted(userId)) {
- return false;
- }
-
- PermissionState userState = mUserStates.get(userId);
- userState.mGranted = false;
-
- if (userState.isDefault()) {
- mUserStates.remove(userId);
- }
-
- return true;
}
public PermissionState getPermissionState(int userId) {
- return mUserStates.get(userId);
+ synchronized (mLock) {
+ return mUserStates.get(userId);
+ }
}
public int getFlags(int userId) {
- PermissionState userState = mUserStates.get(userId);
- if (userState != null) {
- return userState.mFlags;
+ synchronized (mLock) {
+ PermissionState userState = mUserStates.get(userId);
+ if (userState != null) {
+ return userState.mFlags;
+ }
+ return 0;
}
- return 0;
}
public boolean isDefault() {
- return mUserStates.size() <= 0;
+ synchronized (mLock) {
+ return mUserStates.size() <= 0;
+ }
}
public static boolean isInstallPermissionKey(int userId) {
@@ -802,32 +821,34 @@
}
public boolean updateFlags(int userId, int flagMask, int flagValues) {
- if (isInstallPermission()) {
- userId = UserHandle.USER_ALL;
- }
+ synchronized (mLock) {
+ if (isInstallPermission()) {
+ userId = UserHandle.USER_ALL;
+ }
- if (!isCompatibleUserId(userId)) {
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ final int newFlags = flagValues & flagMask;
+
+ PermissionState userState = mUserStates.get(userId);
+ if (userState != null) {
+ final int oldFlags = userState.mFlags;
+ userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
+ if (userState.isDefault()) {
+ mUserStates.remove(userId);
+ }
+ return userState.mFlags != oldFlags;
+ } else if (newFlags != 0) {
+ userState = new PermissionState(mPerm.getName());
+ userState.mFlags = newFlags;
+ mUserStates.put(userId, userState);
+ return true;
+ }
+
return false;
}
-
- final int newFlags = flagValues & flagMask;
-
- PermissionState userState = mUserStates.get(userId);
- if (userState != null) {
- final int oldFlags = userState.mFlags;
- userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
- if (userState.isDefault()) {
- mUserStates.remove(userId);
- }
- return userState.mFlags != oldFlags;
- } else if (newFlags != 0) {
- userState = new PermissionState(mPerm.getName());
- userState.mFlags = newFlags;
- mUserStates.put(userId, userState);
- return true;
- }
-
- return false;
}
private boolean isCompatibleUserId(int userId) {
diff --git a/services/core/java/com/android/server/power/InattentiveSleepWarningController.java b/services/core/java/com/android/server/power/InattentiveSleepWarningController.java
new file mode 100644
index 0000000..db8a63f
--- /dev/null
+++ b/services/core/java/com/android/server/power/InattentiveSleepWarningController.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.IStatusBarService;
+
+/**
+ * Communicates with System UI to show/hide the inattentive sleep warning overlay.
+ */
+@VisibleForTesting
+public class InattentiveSleepWarningController {
+ private static final String TAG = "InattentiveSleepWarning";
+
+ private final Handler mHandler = new Handler();
+
+ private boolean mIsShown;
+ private IStatusBarService mStatusBarService;
+
+ InattentiveSleepWarningController() {
+ }
+
+ /**
+ * Returns true if the warning is currently being displayed, false otherwise.
+ */
+ @GuardedBy("PowerManagerService.mLock")
+ public boolean isShown() {
+ return mIsShown;
+ }
+
+ /**
+ * Show the warning.
+ */
+ @GuardedBy("PowerManagerService.mLock")
+ public void show() {
+ if (isShown()) {
+ return;
+ }
+
+ mHandler.post(this::showInternal);
+ mIsShown = true;
+ }
+
+ private void showInternal() {
+ try {
+ getStatusBar().showInattentiveSleepWarning();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to show inattentive sleep warning", e);
+ mIsShown = false;
+ }
+ }
+
+ /**
+ * Dismiss the warning.
+ */
+ @GuardedBy("PowerManagerService.mLock")
+ public void dismiss() {
+ if (!isShown()) {
+ return;
+ }
+
+ mHandler.post(this::dismissInternal);
+ mIsShown = false;
+ }
+
+ private void dismissInternal() {
+ try {
+ getStatusBar().dismissInattentiveSleepWarning();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to dismiss inattentive sleep warning", e);
+ }
+ }
+
+ private IStatusBarService getStatusBar() {
+ if (mStatusBarService == null) {
+ mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ }
+
+ return mStatusBarService;
+ }
+}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b67d9b2..7fc9fdc0 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -536,6 +536,7 @@
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
return WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
+ case PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE:
return WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
default:
return WindowManagerPolicy.OFF_BECAUSE_OF_USER;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index befe4e9..00e0f71 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -128,6 +128,8 @@
private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
// Message: Polling to look for long held wake locks.
private static final int MSG_CHECK_FOR_LONG_WAKELOCKS = 4;
+ // Message: Sent when an attentive timeout occurs to update the power state.
+ private static final int MSG_ATTENTIVE_TIMEOUT = 5;
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -157,6 +159,8 @@
private static final int DIRTY_QUIESCENT = 1 << 12;
// Dirty bit: VR Mode enabled changed
private static final int DIRTY_VR_MODE_CHANGED = 1 << 13;
+ // Dirty bit: attentive timer may have timed out
+ private static final int DIRTY_ATTENTIVE = 1 << 14;
// Summarizes the state of all active wakelocks.
private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -249,6 +253,8 @@
private DreamManagerInternal mDreamManager;
private Light mAttentionLight;
+ private InattentiveSleepWarningController mInattentiveSleepWarningOverlayController;
+
private final Object mLock = LockGuard.installNewLock(LockGuard.INDEX_POWER);
// A bitfield that indicates what parts of the power state have
@@ -381,6 +387,9 @@
// True if the device should suspend when the screen is off due to proximity.
private boolean mSuspendWhenScreenOffDueToProximityConfig;
+ // Default value for attentive timeout.
+ private int mAttentiveTimeoutConfig;
+
// True if dreams are supported on this device.
private boolean mDreamsSupportedConfig;
@@ -441,9 +450,16 @@
// The screen off timeout setting value in milliseconds.
private long mScreenOffTimeoutSetting;
+ // Default for attentive warning duration.
+ private long mAttentiveWarningDurationConfig;
+
// The sleep timeout setting value in milliseconds.
private long mSleepTimeoutSetting;
+ // How long to show a warning message to user before the device goes to sleep
+ // after long user inactivity, even if wakelocks are held.
+ private long mAttentiveTimeoutSetting;
+
// The maximum allowable screen off timeout according to the device
// administration policy. Overrides other settings.
private long mMaximumScreenOffTimeoutFromDeviceAdmin = Long.MAX_VALUE;
@@ -735,6 +751,10 @@
AmbientDisplayConfiguration createAmbientDisplayConfiguration(Context context) {
return new AmbientDisplayConfiguration(context);
}
+
+ InattentiveSleepWarningController createInattentiveSleepWarningController() {
+ return new InattentiveSleepWarningController();
+ }
}
final Constants mConstants;
@@ -779,6 +799,9 @@
mBatterySaverStateMachine = new BatterySaverStateMachine(
mLock, mContext, mBatterySaverController);
+ mInattentiveSleepWarningOverlayController =
+ mInjector.createInattentiveSleepWarningController();
+
synchronized (mLock) {
mWakeLockSuspendBlocker =
mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");
@@ -902,6 +925,9 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SLEEP_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.ATTENTIVE_TIMEOUT),
+ false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
false, mSettingsObserver, UserHandle.USER_ALL);
@@ -966,6 +992,10 @@
com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug);
mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean(
com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
+ mAttentiveTimeoutConfig = resources.getInteger(
+ com.android.internal.R.integer.config_attentiveTimeout);
+ mAttentiveWarningDurationConfig = resources.getInteger(
+ com.android.internal.R.integer.config_attentiveWarningDuration);
mDreamsSupportedConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsSupported);
mDreamsEnabledByDefaultConfig = resources.getBoolean(
@@ -1015,6 +1045,9 @@
mSleepTimeoutSetting = Settings.Secure.getIntForUser(resolver,
Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT,
UserHandle.USER_CURRENT);
+ mAttentiveTimeoutSetting = Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.ATTENTIVE_TIMEOUT, mAttentiveTimeoutConfig,
+ UserHandle.USER_CURRENT);
mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
@@ -1700,6 +1733,7 @@
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
+ updateAttentiveStateLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
@@ -2042,8 +2076,10 @@
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
- final long sleepTimeout = getSleepTimeoutLocked();
- final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
+ final long attentiveTimeout = getAttentiveTimeoutLocked();
+ final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
+ final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
+ attentiveTimeout);
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
@@ -2134,6 +2170,12 @@
mHandler.sendMessageAtTime(msg, timeMs);
}
+ private void scheduleAttentiveTimeout(long timeMs) {
+ final Message msg = mHandler.obtainMessage(MSG_ATTENTIVE_TIMEOUT);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, timeMs);
+ }
+
/**
* Finds the next profile timeout time or returns -1 if there are no profiles to be locked.
*/
@@ -2150,6 +2192,69 @@
return nextTimeout;
}
+ private void updateAttentiveStateLocked(long now, int dirty) {
+ long attentiveTimeout = getAttentiveTimeoutLocked();
+ long goToSleepTime = mLastUserActivityTime + attentiveTimeout;
+ long showWarningTime = goToSleepTime - mAttentiveWarningDurationConfig;
+
+ boolean warningDismissed = maybeHideInattentiveSleepWarningLocked(now, showWarningTime);
+
+ if (attentiveTimeout >= 0 && (warningDismissed
+ || (dirty & (DIRTY_ATTENTIVE | DIRTY_STAY_ON | DIRTY_SCREEN_BRIGHTNESS_BOOST
+ | DIRTY_PROXIMITY_POSITIVE | DIRTY_WAKEFULNESS | DIRTY_BOOT_COMPLETED
+ | DIRTY_SETTINGS)) != 0)) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "Updating attentive state");
+ }
+
+ mHandler.removeMessages(MSG_ATTENTIVE_TIMEOUT);
+
+ if (isBeingKeptFromShowingInattentiveSleepWarningLocked()) {
+ return;
+ }
+
+ long nextTimeout = -1;
+
+ if (now < showWarningTime) {
+ nextTimeout = showWarningTime;
+ } else if (now < goToSleepTime) {
+ if (DEBUG) {
+ long timeToSleep = goToSleepTime - now;
+ Slog.d(TAG, "Going to sleep in " + timeToSleep
+ + "ms if there is no user activity");
+ }
+ mInattentiveSleepWarningOverlayController.show();
+ nextTimeout = goToSleepTime;
+ } else {
+ if (DEBUG && mWakefulness != WAKEFULNESS_ASLEEP) {
+ Slog.i(TAG, "Going to sleep now due to long user inactivity");
+ }
+ }
+
+ if (nextTimeout >= 0) {
+ scheduleAttentiveTimeout(nextTimeout);
+ }
+ }
+ }
+
+ private boolean maybeHideInattentiveSleepWarningLocked(long now, long showWarningTime) {
+ long attentiveTimeout = getAttentiveTimeoutLocked();
+
+ if (mInattentiveSleepWarningOverlayController.isShown() && (attentiveTimeout < 0
+ || isBeingKeptFromShowingInattentiveSleepWarningLocked()
+ || now < showWarningTime)) {
+ mInattentiveSleepWarningOverlayController.dismiss();
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean isAttentiveTimeoutExpired(long now) {
+ long attentiveTimeout = getAttentiveTimeoutLocked();
+ return attentiveTimeout >= 0 && now > mLastUserActivityTime + attentiveTimeout;
+ }
+
/**
* Called when a user activity timeout has occurred.
* Simply indicates that something about user activity has changed so that the new
@@ -2169,15 +2274,38 @@
}
}
- private long getSleepTimeoutLocked() {
- final long timeout = mSleepTimeoutSetting;
+ private void handleAttentiveTimeout() { // runs on handler thread
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "handleAttentiveTimeout");
+ }
+
+ mDirty |= DIRTY_ATTENTIVE;
+ updatePowerStateLocked();
+ }
+ }
+
+ private long getAttentiveTimeoutLocked() {
+ long timeout = mAttentiveTimeoutSetting;
if (timeout <= 0) {
return -1;
}
+
+ return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
+ }
+
+ private long getSleepTimeoutLocked(long attentiveTimeout) {
+ long timeout = mSleepTimeoutSetting;
+ if (timeout <= 0) {
+ return -1;
+ }
+ if (attentiveTimeout >= 0) {
+ timeout = Math.min(timeout, attentiveTimeout);
+ }
return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
}
- private long getScreenOffTimeoutLocked(long sleepTimeout) {
+ private long getScreenOffTimeoutLocked(long sleepTimeout, long attentiveTimeout) {
long timeout = mScreenOffTimeoutSetting;
if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
@@ -2188,6 +2316,9 @@
if (sleepTimeout >= 0) {
timeout = Math.min(timeout, sleepTimeout);
}
+ if (attentiveTimeout >= 0) {
+ timeout = Math.min(timeout, attentiveTimeout);
+ }
return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
}
@@ -2209,13 +2340,16 @@
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
- | DIRTY_DOCK_STATE)) != 0) {
+ | DIRTY_DOCK_STATE | DIRTY_ATTENTIVE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
final long time = SystemClock.uptimeMillis();
- if (shouldNapAtBedTimeLocked()) {
+ if (isAttentiveTimeoutExpired(time)) {
+ changed = goToSleepNoUpdateLocked(time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
+ } else if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
} else {
changed = goToSleepNoUpdateLocked(time,
@@ -2242,7 +2376,16 @@
* to being fully awake or else go to sleep for good.
*/
private boolean isItBedTimeYetLocked() {
- return mBootCompleted && !isBeingKeptAwakeLocked();
+ if (!mBootCompleted) {
+ return false;
+ }
+
+ long now = SystemClock.uptimeMillis();
+ if (isAttentiveTimeoutExpired(now)) {
+ return !isBeingKeptFromInattentiveSleepLocked();
+ } else {
+ return !isBeingKeptAwakeLocked();
+ }
}
/**
@@ -2263,11 +2406,29 @@
}
/**
+ * Returns true if the device is prevented from going into inattentive sleep by the stay on
+ * while powered setting. We also keep the device awake when the proximity sensor returns a
+ * positive result so that the device does not lock while in a phone call. This function only
+ * controls whether the device will go to sleep which is independent of whether it will be
+ * allowed to suspend.
+ */
+ private boolean isBeingKeptFromInattentiveSleepLocked() {
+ return mStayOn || mScreenBrightnessBoostInProgress || mProximityPositive
+ || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
+ | USER_ACTIVITY_SCREEN_DIM)) != 0;
+ }
+
+ private boolean isBeingKeptFromShowingInattentiveSleepWarningLocked() {
+ return mStayOn || mScreenBrightnessBoostInProgress || mProximityPositive || !mBootCompleted;
+ }
+
+ /**
* Determines whether to post a message to the sandman to update the dream state.
*/
private void updateDreamLocked(int dirty, boolean displayBecameReady) {
if ((dirty & (DIRTY_WAKEFULNESS
| DIRTY_USER_ACTIVITY
+ | DIRTY_ATTENTIVE
| DIRTY_WAKE_LOCKS
| DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS
@@ -2350,6 +2511,7 @@
}
// Determine whether the dream should continue.
+ long now = SystemClock.uptimeMillis();
if (wakefulness == WAKEFULNESS_DREAMING) {
if (isDreaming && canDreamLocked()) {
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
@@ -2371,11 +2533,15 @@
// Dream has ended or will be stopped. Update the power state.
if (isItBedTimeYetLocked()) {
- goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
+ int flags = 0;
+ if (isAttentiveTimeoutExpired(now)) {
+ flags |= PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE;
+ }
+ goToSleepNoUpdateLocked(now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags,
+ Process.SYSTEM_UID);
updatePowerStateLocked();
} else {
- wakeUpNoUpdateLocked(SystemClock.uptimeMillis(),
+ wakeUpNoUpdateLocked(now,
PowerManager.WAKE_REASON_UNKNOWN,
"android.server.power:DREAM_FINISHED", Process.SYSTEM_UID,
mContext.getOpPackageName(), Process.SYSTEM_UID);
@@ -2387,7 +2553,7 @@
}
// Doze has ended or will be stopped. Update the power state.
- reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
+ reallyGoToSleepNoUpdateLocked(now, Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
@@ -3474,6 +3640,9 @@
pw.println(" mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig);
pw.println(" mMaximumScreenDimDurationConfig=" + mMaximumScreenDimDurationConfig);
pw.println(" mMaximumScreenDimRatioConfig=" + mMaximumScreenDimRatioConfig);
+ pw.println(" mAttentiveTimeoutConfig=" + mAttentiveTimeoutConfig);
+ pw.println(" mAttentiveTimeoutSetting=" + mAttentiveTimeoutSetting);
+ pw.println(" mAttentiveWarningDurationConfig=" + mAttentiveWarningDurationConfig);
pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
pw.println(" mSleepTimeoutSetting=" + mSleepTimeoutSetting);
pw.println(" mMaximumScreenOffTimeoutFromDeviceAdmin="
@@ -3501,10 +3670,12 @@
pw.println(" mForegroundProfile=" + mForegroundProfile);
pw.println(" mUserId=" + mUserId);
- final long sleepTimeout = getSleepTimeoutLocked();
- final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
+ final long attentiveTimeout = getAttentiveTimeoutLocked();
+ final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
+ final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout, attentiveTimeout);
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
pw.println();
+ pw.println("Attentive timeout: " + attentiveTimeout + " ms");
pw.println("Sleep timeout: " + sleepTimeout + " ms");
pw.println("Screen off timeout: " + screenOffTimeout + " ms");
pw.println("Screen dim duration: " + screenDimDuration + " ms");
@@ -3772,6 +3943,16 @@
PowerServiceSettingsAndConfigurationDumpProto.SLEEP_TIMEOUT_SETTING_MS,
mSleepTimeoutSetting);
proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ATTENTIVE_TIMEOUT_SETTING_MS,
+ mAttentiveTimeoutSetting);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto.ATTENTIVE_TIMEOUT_CONFIG_MS,
+ mAttentiveTimeoutConfig);
+ proto.write(
+ PowerServiceSettingsAndConfigurationDumpProto
+ .ATTENTIVE_WARNING_DURATION_CONFIG_MS,
+ mAttentiveWarningDurationConfig);
+ proto.write(
PowerServiceSettingsAndConfigurationDumpProto
.MAXIMUM_SCREEN_OFF_TIMEOUT_FROM_DEVICE_ADMIN_MS,
// Clamp to int32
@@ -3853,9 +4034,11 @@
mIsVrModeEnabled);
proto.end(settingsAndConfigurationToken);
- final long sleepTimeout = getSleepTimeoutLocked();
- final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
+ final long attentiveTimeout = getAttentiveTimeoutLocked();
+ final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
+ final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout, attentiveTimeout);
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+ proto.write(PowerManagerServiceDumpProto.ATTENTIVE_TIMEOUT_MS, attentiveTimeout);
proto.write(PowerManagerServiceDumpProto.SLEEP_TIMEOUT_MS, sleepTimeout);
proto.write(PowerManagerServiceDumpProto.SCREEN_OFF_TIMEOUT_MS, screenOffTimeout);
proto.write(PowerManagerServiceDumpProto.SCREEN_DIM_DURATION_MS, screenDimDuration);
@@ -4009,6 +4192,9 @@
case MSG_CHECK_FOR_LONG_WAKELOCKS:
checkForLongWakeLocks();
break;
+ case MSG_ATTENTIVE_TIMEOUT:
+ handleAttentiveTimeout();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 25c41f5..c256b84 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -1375,6 +1375,28 @@
this, in, out, err, args, callback, resultReceiver);
}
+ @Override
+ public void showInattentiveSleepWarning() {
+ enforceStatusBarService();
+ if (mBar != null) {
+ try {
+ mBar.showInattentiveSleepWarning();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void dismissInattentiveSleepWarning() {
+ enforceStatusBarService();
+ if (mBar != null) {
+ try {
+ mBar.dismissInattentiveSleepWarning();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
public String[] getStatusBarIcons() {
return mContext.getResources().getStringArray(R.array.config_statusBarIcons);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 91c909d..a91998a 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -539,6 +539,7 @@
mRootActivityContainer = mService.mRootActivityContainer;
mHandler = new ActivityStackHandler(supervisor.mLooper);
mWindowManager = mService.mWindowManager;
+ mRemoteToken = new RemoteToken(this);
mCurrentUser = mService.mAmInternal.getCurrentUserId();
// Set display id before setting activity and window type to make sure it won't affect
// stacks on a wrong display.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3ef848c..79c76b9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3243,7 +3243,7 @@
private void sanitizeAndApplyConfigChange(ConfigurationContainer container,
WindowContainerTransaction.Change change) {
- if (!(container instanceof Task)) {
+ if (!(container instanceof Task || container instanceof ActivityStack)) {
throw new RuntimeException("Invalid token in task transaction");
}
// The "client"-facing API should prevent bad changes; however, just in case, sanitize
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 5a21016..06cce52 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1250,6 +1250,7 @@
stack.getBounds(info.bounds);
info.displayId = displayId;
info.stackId = stack.mStackId;
+ info.stackToken = stack.mRemoteToken;
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index f7b802d..a867a5d4 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -133,14 +133,15 @@
@Override
public void onInputEvent(InputEvent event) {
- if (!(event instanceof MotionEvent)
- || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
- return;
- }
- final MotionEvent motionEvent = (MotionEvent) event;
boolean handled = false;
-
try {
+ // All returns need to be in the try block to make sure the finishInputEvent is
+ // called correctly.
+ if (!(event instanceof MotionEvent)
+ || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
+ return;
+ }
+ final MotionEvent motionEvent = (MotionEvent) event;
if (mDragEnded) {
// The drag has ended but the clean-up message has not been processed by
// window manager. Drop events that occur after this until window manager
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 8e955cf..2218366 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -20,19 +20,27 @@
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.util.DisplayMetrics;
+import android.util.Pair;
import android.view.Display;
import android.view.IWindowManager;
import android.view.Surface;
+import android.view.ViewDebug;
+import com.android.internal.os.ByteTransferPipe;
import com.android.server.protolog.ProtoLogImpl;
+import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
/**
* ShellCommands for WindowManagerService.
@@ -81,6 +89,8 @@
return runSetDisplayUserRotation(pw);
case "set-fix-to-user-rotation":
return runSetFixToUserRotation(pw);
+ case "dump-visible-window-views":
+ return runDumpVisibleWindowViews(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -341,6 +351,50 @@
return 0;
}
+ private int runDumpVisibleWindowViews(PrintWriter pw) {
+ ParcelFileDescriptor outFile = openFileForSystem(getNextArgRequired(), "w");
+ try (ZipOutputStream out = new ZipOutputStream(
+ new ParcelFileDescriptor.AutoCloseOutputStream(outFile))) {
+ ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
+ synchronized (mInternal.mGlobalLock) {
+ // Request dump from all windows parallelly before writing to disk.
+ mInternal.mRoot.forAllWindows(w -> {
+ if (w.isVisible()) {
+ ByteTransferPipe pipe = null;
+ try {
+ pipe = new ByteTransferPipe();
+ w.mClient.executeCommand(ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null,
+ pipe.getWriteFd());
+ requestList.add(Pair.create(w.getName(), pipe));
+ } catch (IOException | RemoteException e) {
+ // Skip this window
+ pw.println("Error for window " + w.getName() + " : " + e.getMessage());
+ if (pipe != null) {
+ pipe.kill();
+ }
+ }
+ }
+ }, false /* traverseTopToBottom */);
+ }
+ for (Pair<String, ByteTransferPipe> entry : requestList) {
+ byte[] data;
+ try {
+ data = entry.second.get();
+ } catch (IOException e) {
+ // Ignore this window
+ pw.println(
+ "Error for window " + entry.first + " : " + e.getMessage());
+ continue;
+ }
+ out.putNextEntry(new ZipEntry(entry.first));
+ out.write(data);
+ }
+ } catch (IOException e) {
+ pw.println("Error fetching dump " + e.getMessage());
+ }
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -360,6 +414,8 @@
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
pw.println(" Set user rotation mode and user rotation.");
+ pw.println(" dump-visible-window-views out-file");
+ pw.println(" Dumps the encoded view hierarchies of visible windows");
pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
pw.println(" Enable or disable rotating display for app requested orientation.");
if (!IS_USER) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9dac03f..99f484e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1945,7 +1945,7 @@
}
TelephonyManager getTelephonyManager() {
- return TelephonyManager.from(mContext);
+ return mContext.getSystemService(TelephonyManager.class);
}
TrustManager getTrustManager() {
@@ -9724,13 +9724,9 @@
}
}
- int userInfoFlags = 0;
- if (ephemeral) {
- userInfoFlags |= UserInfo.FLAG_EPHEMERAL;
- }
- if (demo) {
- userInfoFlags |= UserInfo.FLAG_DEMO;
- }
+ int userInfoFlags = ephemeral ? UserInfo.FLAG_EPHEMERAL : 0;
+ String userType = demo ? UserManager.USER_TYPE_FULL_DEMO
+ : UserManager.USER_TYPE_FULL_SECONDARY;
String[] disallowedPackages = null;
if (!leaveAllSystemAppsEnabled) {
disallowedPackages = mOverlayPackagesProvider.getNonRequiredApps(admin,
@@ -9738,7 +9734,7 @@
new String[0]);
}
UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
- userInfoFlags, disallowedPackages);
+ userType, userInfoFlags, disallowedPackages);
if (userInfo != null) {
user = userInfo.getUserHandle();
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 9c97305..45de451 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -33,6 +33,8 @@
import static com.android.server.DeviceIdleController.LIGHT_STATE_PRE_IDLE;
import static com.android.server.DeviceIdleController.LIGHT_STATE_WAITING_FOR_NETWORK;
import static com.android.server.DeviceIdleController.MSG_REPORT_STATIONARY_STATUS;
+import static com.android.server.DeviceIdleController.MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR;
+import static com.android.server.DeviceIdleController.MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR;
import static com.android.server.DeviceIdleController.STATE_ACTIVE;
import static com.android.server.DeviceIdleController.STATE_IDLE;
import static com.android.server.DeviceIdleController.STATE_IDLE_MAINTENANCE;
@@ -180,7 +182,9 @@
mHandler = controller.new MyHandler(getContext().getMainLooper());
spyOn(mHandler);
doNothing().when(mHandler).handleMessage(argThat((message) ->
- message.what != MSG_REPORT_STATIONARY_STATUS));
+ message.what != MSG_REPORT_STATIONARY_STATUS
+ && message.what != MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
+ && message.what != MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR));
doAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
@@ -189,7 +193,9 @@
return true;
}
}).when(mHandler).sendMessageDelayed(
- argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS),
+ argThat((message) -> message.what == MSG_REPORT_STATIONARY_STATUS
+ || message.what == MSG_UPDATE_PRE_IDLE_TIMEOUT_FACTOR
+ || message.what == MSG_RESET_PRE_IDLE_TIMEOUT_FACTOR),
anyLong());
}
@@ -1734,13 +1740,11 @@
}
//TODO(b/123045185): Mocked Handler of DeviceIdleController to make message loop
//workable in this test class
- mDeviceIdleController.updatePreIdleFactor();
float expectedfactor = mDeviceIdleController.getPreIdleTimeoutByMode(mode);
float curfactor = mDeviceIdleController.getPreIdleTimeoutFactor();
assertEquals("Pre idle time factor of mode [" + mode + "].",
expectedfactor, curfactor, delta);
mDeviceIdleController.resetPreIdleTimeoutMode();
- mDeviceIdleController.updatePreIdleFactor();
checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_INACTIVE);
checkNextAlarmTimeWithNewPreIdleFactor(expectedfactor, STATE_IDLE_PENDING);
@@ -2088,14 +2092,11 @@
mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK, ret);
}
if (ret == mDeviceIdleController.SET_IDLE_FACTOR_RESULT_OK) {
- mDeviceIdleController.updatePreIdleFactor();
long newAlarm = mDeviceIdleController.getNextAlarmTime();
long newDelay = (long) ((alarm - now) * factor);
assertTrue("setPreIdleTimeoutFactor: " + factor,
Math.abs(newDelay - (newAlarm - now)) < errorTolerance);
mDeviceIdleController.resetPreIdleTimeoutMode();
- mDeviceIdleController.updatePreIdleFactor();
- mDeviceIdleController.maybeDoImmediateMaintenance();
newAlarm = mDeviceIdleController.getNextAlarmTime();
assertTrue("resetPreIdleTimeoutMode from: " + factor,
Math.abs(newAlarm - alarm) < errorTolerance);
@@ -2106,19 +2107,14 @@
assertTrue("setPreIdleTimeoutFactor: " + factor + " before step to idle",
Math.abs(newDelay - (newAlarm - now)) < errorTolerance);
mDeviceIdleController.resetPreIdleTimeoutMode();
- mDeviceIdleController.updatePreIdleFactor();
- mDeviceIdleController.maybeDoImmediateMaintenance();
}
} else {
mDeviceIdleController.setPreIdleTimeoutFactor(factor);
- mDeviceIdleController.updatePreIdleFactor();
long newAlarm = mDeviceIdleController.getNextAlarmTime();
assertTrue("setPreIdleTimeoutFactor: " + factor
+ " shounld not change next alarm" ,
(newAlarm == alarm));
mDeviceIdleController.resetPreIdleTimeoutMode();
- mDeviceIdleController.updatePreIdleFactor();
- mDeviceIdleController.maybeDoImmediateMaintenance();
}
}
@@ -2138,18 +2134,15 @@
long alarm = mDeviceIdleController.getNextAlarmTime();
mDeviceIdleController.setIdleStartTimeForTest(
now - (long) (mConstants.IDLE_TIMEOUT * 0.6));
- mDeviceIdleController.maybeDoImmediateMaintenance();
long newAlarm = mDeviceIdleController.getNextAlarmTime();
assertTrue("maintenance not reschedule IDLE_TIMEOUT * 0.6",
newAlarm == alarm);
mDeviceIdleController.setIdleStartTimeForTest(
now - (long) (mConstants.IDLE_TIMEOUT * 1.2));
- mDeviceIdleController.maybeDoImmediateMaintenance();
newAlarm = mDeviceIdleController.getNextAlarmTime();
assertTrue("maintenance not reschedule IDLE_TIMEOUT * 1.2",
(newAlarm - now) < minuteInMillis);
mDeviceIdleController.resetPreIdleTimeoutMode();
- mDeviceIdleController.updatePreIdleFactor();
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 7081d2e..1d04c83 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -37,6 +37,7 @@
import android.hardware.SensorEventListener;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
+import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
@@ -78,6 +79,7 @@
@RunWith(AndroidJUnit4.class)
public class BrightnessTrackerTest {
private static final float DEFAULT_INITIAL_BRIGHTNESS = 2.5f;
+ private static final boolean DEFAULT_COLOR_SAMPLING_ENABLED = true;
private static final float FLOAT_DELTA = 0.01f;
private BrightnessTracker mTracker;
@@ -151,6 +153,40 @@
}
@Test
+ public void testModifyBrightnessConfiguration() {
+ mInjector.mInteractive = true;
+ // Start with tracker not listening for color samples.
+ startTracker(mTracker, DEFAULT_INITIAL_BRIGHTNESS, /* collectColorSamples= */ false);
+ assertFalse(mInjector.mColorSamplingEnabled);
+
+ // Update brightness config to enabled color sampling.
+ mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
+ /* collectColorSamples= */ true));
+ mInjector.waitForHandler();
+ assertTrue(mInjector.mColorSamplingEnabled);
+
+ // Update brightness config to disable color sampling.
+ mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
+ /* collectColorSamples= */ false));
+ mInjector.waitForHandler();
+ assertFalse(mInjector.mColorSamplingEnabled);
+
+ // Pretend screen is off, update config to turn on color sampling.
+ mInjector.sendScreenChange(/*screen on */ false);
+ mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
+ /* collectColorSamples= */ true));
+ mInjector.waitForHandler();
+ assertFalse(mInjector.mColorSamplingEnabled);
+
+ // Pretend screen is on.
+ mInjector.sendScreenChange(/*screen on */ true);
+ assertTrue(mInjector.mColorSamplingEnabled);
+
+ mTracker.stop();
+ assertFalse(mInjector.mColorSamplingEnabled);
+ }
+
+ @Test
public void testNoColorSampling_WrongPixelFormat() {
mInjector.mDefaultSamplingAttributes =
new DisplayedContentSamplingAttributes(
@@ -278,7 +314,7 @@
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3333);
- startTracker(mTracker, initialBrightness);
+ startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
batteryChangeEvent(30, 60));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
@@ -311,7 +347,7 @@
@Test
public void testIgnoreAutomaticBrightnessChange() {
final int initialBrightness = 30;
- startTracker(mTracker, initialBrightness);
+ startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
@@ -750,11 +786,13 @@
}
private void startTracker(BrightnessTracker tracker) {
- startTracker(tracker, DEFAULT_INITIAL_BRIGHTNESS);
+ startTracker(tracker, DEFAULT_INITIAL_BRIGHTNESS, DEFAULT_COLOR_SAMPLING_ENABLED);
}
- private void startTracker(BrightnessTracker tracker, float initialBrightness) {
+ private void startTracker(BrightnessTracker tracker, float initialBrightness,
+ boolean collectColorSamples) {
tracker.start(initialBrightness);
+ tracker.setBrightnessConfiguration(buildBrightnessConfiguration(collectColorSamples));
mInjector.waitForHandler();
}
@@ -772,6 +810,14 @@
mInjector.waitForHandler();
}
+ private BrightnessConfiguration buildBrightnessConfiguration(boolean collectColorSamples) {
+ BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+ /* lux = */ new float[] {0f, 10f, 100f},
+ /* nits = */ new float[] {1f, 90f, 100f});
+ builder.setShouldCollectColorSamples(collectColorSamples);
+ return builder.build();
+ }
+
private static final class Idle implements MessageQueue.IdleHandler {
private boolean mIdle;
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 819091c..f6fb6e2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -20,20 +20,17 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.Nullable;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.os.Build;
import android.os.Process;
-import android.permission.IPermissionManager;
import android.util.ArrayMap;
import org.junit.Before;
@@ -43,20 +40,16 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Map;
-
@RunWith(JUnit4.class)
public class AppsFilterTest {
private static final int DUMMY_CALLING_UID = 10345;
-
- @Mock
- IPermissionManager mPermissionManagerMock;
+ private static final int DUMMY_TARGET_UID = 10556;
@Mock
AppsFilter.FeatureConfig mFeatureConfigMock;
- private Map<String, PackageParser.Package> mExisting = new ArrayMap<>();
+ private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>();
private static PackageBuilder pkg(String packageName) {
return new PackageBuilder(packageName)
@@ -72,9 +65,10 @@
}
private static PackageBuilder pkg(String packageName, IntentFilter... filters) {
+ final ActivityInfo activityInfo = new ActivityInfo();
final PackageBuilder packageBuilder = pkg(packageName).addActivity(
pkg -> new PackageParser.ParseComponentArgs(pkg, new String[1], 0, 0, 0, 0, 0, 0,
- new String[]{packageName}, 0, 0, 0), new ActivityInfo());
+ new String[]{packageName}, 0, 0, 0), activityInfo);
for (IntentFilter filter : filters) {
packageBuilder.addActivityIntentInfo(0 /* index */, activity -> {
final PackageParser.ActivityIntentInfo info =
@@ -83,7 +77,7 @@
filter.actionsIterator().forEachRemaining(info::addAction);
}
if (filter.countCategories() > 0) {
- filter.actionsIterator().forEachRemaining(info::addAction);
+ filter.actionsIterator().forEachRemaining(info::addCategory);
}
if (filter.countDataAuthorities() > 0) {
filter.authoritiesIterator().forEachRemaining(info::addDataAuthority);
@@ -91,6 +85,7 @@
if (filter.countDataSchemes() > 0) {
filter.schemesIterator().forEachRemaining(info::addDataScheme);
}
+ activityInfo.exported = true;
return info;
});
}
@@ -102,9 +97,6 @@
mExisting = new ArrayMap<>();
MockitoAnnotations.initMocks(this);
- when(mPermissionManagerMock
- .checkPermission(anyString(), anyString(), anyInt()))
- .thenReturn(PackageManager.PERMISSION_DENIED);
when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true);
when(mFeatureConfigMock.packageIsEnabled(any(PackageParser.Package.class)))
.thenReturn(true);
@@ -113,7 +105,7 @@
@Test
public void testSystemReadyPropogates() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock, new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
appsFilter.onSystemReady();
verify(mFeatureConfigMock).onSystemReady();
}
@@ -121,12 +113,12 @@
@Test
public void testQueriesAction_FilterMatches() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock, new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package", new IntentFilter("TEST_ACTION"))).build();
+ pkg("com.some.package", new IntentFilter("TEST_ACTION")), DUMMY_TARGET_UID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", new Intent("TEST_ACTION"))).build();
+ pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -134,12 +126,12 @@
@Test
public void testQueriesAction_NoMatchingAction_Filters() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock, new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package")).build();
+ pkg("com.some.package"), DUMMY_TARGET_UID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", new Intent("TEST_ACTION"))).build();
+ pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -147,13 +139,17 @@
@Test
public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
- PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package",
- new Intent("TEST_ACTION")).setApplicationInfoTargetSdkVersion(
- Build.VERSION_CODES.P)).build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID);
+ PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.some.other.package",
+ new Intent("TEST_ACTION"))
+ .setApplicationInfoTargetSdkVersion(Build.VERSION_CODES.P),
+ DUMMY_CALLING_UID);
+
+ when(mFeatureConfigMock.packageIsEnabled(calling.pkg)).thenReturn(false);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -161,12 +157,12 @@
@Test
public void testNoQueries_Filters() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package")).build();
+ pkg("com.some.other.package"), DUMMY_CALLING_UID);
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -174,14 +170,12 @@
@Test
public void testForceQueryable_DoesntFilter() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target =
- simulateAddPackage(appsFilter, pkg("com.some.package").setForceQueryable(true))
- .build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_UID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package")).build();
+ pkg("com.some.other.package"), DUMMY_CALLING_UID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -189,14 +183,13 @@
@Test
public void testForceQueryableByDevice_SystemCaller_DoesntFilter() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{"com.some.package"}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"))
- .setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
- .build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID,
+ setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package")).build();
+ pkg("com.some.other.package"), DUMMY_CALLING_UID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -204,12 +197,12 @@
@Test
public void testForceQueryableByDevice_NonSystemCaller_Filters() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{"com.some.package"}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package")).build();
+ pkg("com.some.other.package"), DUMMY_CALLING_UID);
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -218,14 +211,14 @@
@Test
public void testSystemQueryable_DoesntFilter() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, true /* system force queryable */);
+ new AppsFilter(mFeatureConfigMock, new String[]{},
+ true /* system force queryable */);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"))
- .setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
- .build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID,
+ setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package")).build();
+ pkg("com.some.other.package"), DUMMY_CALLING_UID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -233,12 +226,12 @@
@Test
public void testQueriesPackage_DoesntFilter() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", "com.some.package")).build();
+ pkg("com.some.other.package", "com.some.package"), DUMMY_CALLING_UID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -248,12 +241,12 @@
when(mFeatureConfigMock.packageIsEnabled(any(PackageParser.Package.class)))
.thenReturn(false);
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
- PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package")).build();
+ PackageSetting target = simulateAddPackage(
+ appsFilter, pkg("com.some.package"), DUMMY_TARGET_UID);
+ PackageSetting calling = simulateAddPackage(
+ appsFilter, pkg("com.some.other.package"), DUMMY_CALLING_UID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
@@ -261,10 +254,10 @@
@Test
public void testSystemUid_DoesntFilter() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID);
assertFalse(appsFilter.shouldFilterApplication(0, null, target, 0));
assertFalse(appsFilter.shouldFilterApplication(
@@ -274,10 +267,10 @@
@Test
public void testNonSystemUid_NoCallingSetting_Filters() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
- PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package")).build();
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package"), DUMMY_TARGET_UID);
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, null, target, 0));
}
@@ -285,8 +278,7 @@
@Test
public void testNoTargetPackage_filters() {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, mPermissionManagerMock,
- new String[]{}, false);
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false);
PackageSetting target = new PackageSettingBuilder()
.setName("com.some.package")
@@ -295,22 +287,36 @@
.setPVersionCode(1L)
.build();
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", new Intent("TEST_ACTION"))).build();
+ pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
- private PackageSettingBuilder simulateAddPackage(AppsFilter filter,
- PackageBuilder newPkgBuilder) {
+ private interface WithSettingBuilder {
+ PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
+ }
+
+ private PackageSetting simulateAddPackage(AppsFilter filter,
+ PackageBuilder newPkgBuilder, int appId) {
+ return simulateAddPackage(filter, newPkgBuilder, appId, null);
+ }
+
+ private PackageSetting simulateAddPackage(AppsFilter filter,
+ PackageBuilder newPkgBuilder, int appId, @Nullable WithSettingBuilder action) {
PackageParser.Package newPkg = newPkgBuilder.build();
- filter.addPackage(newPkg, mExisting);
- mExisting.put(newPkg.packageName, newPkg);
- return new PackageSettingBuilder()
+
+ final PackageSettingBuilder settingBuilder = new PackageSettingBuilder()
.setPackage(newPkg)
+ .setAppId(appId)
.setName(newPkg.packageName)
.setCodePath("/")
.setResourcePath("/")
.setPVersionCode(1L);
+ final PackageSetting setting =
+ (action == null ? settingBuilder : action.withBuilder(settingBuilder)).build();
+ filter.addPackage(setting, mExisting);
+ mExisting.put(newPkg.packageName, setting);
+ return setting;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 06c6314..8d476f6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -43,6 +43,7 @@
private String mVolumeUuid;
private SparseArray<PackageUserState> mUserStates = new SparseArray<>();
private PackageParser.Package mPkg;
+ private int mAppId;
public PackageSettingBuilder setPackage(PackageParser.Package pkg) {
this.mPkg = pkg;
@@ -54,6 +55,11 @@
return this;
}
+ public PackageSettingBuilder setAppId(int appId) {
+ this.mAppId = appId;
+ return this;
+ }
+
public PackageSettingBuilder setRealName(String realName) {
this.mRealName = realName;
return this;
@@ -152,6 +158,7 @@
mChildPackageNames, mSharedUserId, mUsesStaticLibraries,
mUsesStaticLibrariesVersions);
packageSetting.pkg = mPkg;
+ packageSetting.appId = mAppId;
packageSetting.volumeUuid = this.mVolumeUuid;
for (int i = 0; i < mUserStates.size(); i++) {
packageSetting.setUserState(mUserStates.keyAt(i), mUserStates.valueAt(i));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
index d6f7e37..7916bd3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
@@ -71,7 +71,7 @@
throws IOException, RemoteException, InterruptedException {
for (int i = 0; i < NUM_ITERATIONS_STOP_USER; i++) {
final UserInfo userInfo = mUserManager.createProfileForUser("TestUser",
- UserInfo.FLAG_MANAGED_PROFILE, mActivityManager.getCurrentUser());
+ UserManager.USER_TYPE_PROFILE_MANAGED, 0, mActivityManager.getCurrentUser());
assertNotNull(userInfo);
try {
assertTrue(
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
index 8dd8967..e375aef 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
@@ -16,15 +16,15 @@
package com.android.server.pm;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import android.app.ApplicationPackageManager;
import android.content.pm.UserInfo;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManagerInternal;
-import android.util.IconDrawableFactory;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -71,6 +71,7 @@
removeUsers();
}
+ /** Tests UMS.getProfileIds() when no specific userType is specified. */
@Test
public void testGetProfiles() {
// Pretend we have a secondary user with a profile.
@@ -93,38 +94,73 @@
|| users.get(1).id == profile.id);
}
+ /** Tests UMS.getProfileIds() when a specific userType is specified. */
+ @Test
+ public void testGetProfileIds_specifyType() {
+ // Pretend we have a secondary user with a profile.
+ UserInfo secondaryUser = addUser();
+ UserInfo profile = addProfile(secondaryUser);
+
+ // TODO: When there are multiple profiles types, ensure correct output for mixed types.
+ final String userType1 = USER_TYPE_PROFILE_MANAGED;
+
+ // System user should still have no userType1 profile so getProfileIds should be empty.
+ int[] users = mUserManagerService.getProfileIds(UserHandle.USER_SYSTEM, userType1, false);
+ assertEquals("System user should have no managed profiles", 0, users.length);
+
+ // Secondary user should have one userType1 profile, so return just that.
+ users = mUserManagerService.getProfileIds(secondaryUser.id, userType1, false);
+ assertEquals("Wrong number of profiles", 1, users.length);
+ assertEquals("Wrong profile id", profile.id, users[0]);
+
+ // The profile itself is a userType1 profile, so it should return just itself.
+ users = mUserManagerService.getProfileIds(profile.id, userType1, false);
+ assertEquals("Wrong number of profiles", 1, users.length);
+ assertEquals("Wrong profile id", profile.id, users[0]);
+ }
+
@Test
public void testProfileBadge() {
// First profile for system user should get badge 0
assertEquals("First profile isn't given badge index 0", 0,
- mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM));
+ mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
+ USER_TYPE_PROFILE_MANAGED));
// Pretend we have a secondary user.
UserInfo secondaryUser = addUser();
// Check first profile badge for secondary user is also 0.
assertEquals("First profile for secondary user isn't given badge index 0", 0,
- mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id));
+ mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id,
+ USER_TYPE_PROFILE_MANAGED));
// Shouldn't impact the badge for profile in system user
assertEquals("First profile isn't given badge index 0 with secondary user", 0,
- mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM));
+ mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
+ USER_TYPE_PROFILE_MANAGED));
// Pretend a secondary user has a profile.
addProfile(secondaryUser);
// Shouldn't have impacted the badge for the system user
assertEquals("First profile isn't given badge index 0 in secondary user", 0,
- mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM));
+ mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
+ USER_TYPE_PROFILE_MANAGED));
}
@Test
public void testProfileBadgeUnique() {
List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
UserInfo system = users.get(0);
+ int max = mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED);
+ if (max < 0) {
+ // Indicates no max. Instead of infinite, we'll just do 10.
+ max = 10;
+ }
// Badges should get allocated 0 -> max
- for (int i = 0; i < UserManagerService.getMaxManagedProfiles(); ++i) {
- int nextBadge = mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM);
+ for (int i = 0; i < max; ++i) {
+ int nextBadge = mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
+ USER_TYPE_PROFILE_MANAGED);
assertEquals("Wrong badge allocated", i, nextBadge);
UserInfo profile = addProfile(system);
profile.profileBadge = nextBadge;
@@ -140,30 +176,23 @@
mUserManagerService.addRemovingUserIdLocked(profile.id);
// We should reuse the badge from the profile being removed.
assertEquals("Badge index not reused while removing a user", 0,
- mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id));
+ mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id,
+ USER_TYPE_PROFILE_MANAGED));
// Edge case of reuse that only applies if we ever support 3 managed profiles
// We should prioritise using lower badge indexes
- if (UserManagerService.getMaxManagedProfiles() > 2) {
+ int max = mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED);
+ if (max < 0 || max > 2) {
UserInfo profileBadgeOne = addProfile(secondaryUser);
profileBadgeOne.profileBadge = 1;
// 0 and 2 are free, we should reuse 0 rather than 2.
assertEquals("Lower index not used", 0,
- mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id));
+ mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id,
+ USER_TYPE_PROFILE_MANAGED));
}
}
@Test
- public void testNumberOfBadges() {
- assertTrue("Max profiles greater than number of badges",
- UserManagerService.MAX_MANAGED_PROFILES
- <= IconDrawableFactory.CORP_BADGE_COLORS.length);
- assertEquals("Num colors doesn't match number of badge labels",
- IconDrawableFactory.CORP_BADGE_COLORS.length,
- ApplicationPackageManager.CORP_BADGE_LABEL_RES_ID.length);
- }
-
- @Test
public void testCanAddMoreManagedProfiles_removeProfile() {
// if device is low-ram or doesn't support managed profiles for some other reason, just
// skip the test
@@ -171,6 +200,10 @@
false /* disallow remove */)) {
return;
}
+ if (mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED) < 0) {
+ // Indicates no limit, so we cannot run this test;
+ return;
+ }
// GIVEN we've reached the limit of managed profiles possible on the system user
while (mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
@@ -192,6 +225,10 @@
false /* disallow remove */)) {
return;
}
+ if (mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED) < 0) {
+ // Indicates no limit, so we cannot run this test;
+ return;
+ }
// GIVEN we've reached the limit of managed profiles possible on the system user
// GIVEN that the profiles are not enabled yet
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index 6d5b994..1e760cc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -16,11 +16,29 @@
package com.android.server.pm;
+import static android.content.pm.UserInfo.FLAG_DEMO;
+import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
+import static android.content.pm.UserInfo.FLAG_FULL;
+import static android.content.pm.UserInfo.FLAG_GUEST;
+import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
+import static android.content.pm.UserInfo.FLAG_PROFILE;
+import static android.content.pm.UserInfo.FLAG_RESTRICTED;
+import static android.content.pm.UserInfo.FLAG_SYSTEM;
+import static android.os.UserManager.USER_TYPE_FULL_DEMO;
+import static android.os.UserManager.USER_TYPE_FULL_GUEST;
+import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED;
+import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
+import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.annotation.UserIdInt;
import android.content.pm.UserInfo;
+import android.content.pm.UserInfo.UserInfoFlag;
import android.os.Looper;
import android.os.Parcel;
import android.os.UserHandle;
@@ -121,8 +139,61 @@
assertEquals("A Name", mUserManagerService.getUserInfo(TEST_ID).name);
}
+ /** Test UMS.getUserTypeForUser(). */
+ @Test
+ public void testGetUserTypeForUser() throws Exception {
+ final String typeSys = mUserManagerService.getUserTypeForUser(UserHandle.USER_SYSTEM);
+ assertTrue("System user was of invalid type " + typeSys,
+ typeSys.equals(USER_TYPE_SYSTEM_HEADLESS) || typeSys.equals(USER_TYPE_FULL_SYSTEM));
+
+ final int testId = 100;
+ final String typeName = "A type";
+ UserInfo userInfo = createUser(testId, 0, typeName);
+ mUserManagerService.putUserInfo(userInfo);
+ assertEquals(typeName, mUserManagerService.getUserTypeForUser(testId));
+ }
+
+ /** Tests upgradeIfNecessaryLP (but without locking) for upgrading from version 8 to 9+. */
+ @Test
+ public void testUpgradeIfNecessaryLP_9() {
+ final int versionToTest = 9;
+
+ mUserManagerService.putUserInfo(createUser(100, FLAG_MANAGED_PROFILE, null));
+ mUserManagerService.putUserInfo(createUser(101,
+ FLAG_GUEST | FLAG_EPHEMERAL | FLAG_FULL, null));
+ mUserManagerService.putUserInfo(createUser(102, FLAG_RESTRICTED | FLAG_FULL, null));
+ mUserManagerService.putUserInfo(createUser(103, FLAG_FULL, null));
+ mUserManagerService.putUserInfo(createUser(104, FLAG_SYSTEM, null));
+ mUserManagerService.putUserInfo(createUser(105, FLAG_SYSTEM | FLAG_FULL, null));
+ mUserManagerService.putUserInfo(createUser(106, FLAG_DEMO | FLAG_FULL, null));
+
+ mUserManagerService.upgradeIfNecessaryLP(null, versionToTest - 1);
+
+ assertEquals(USER_TYPE_PROFILE_MANAGED, mUserManagerService.getUserTypeForUser(100));
+ assertTrue((mUserManagerService.getUserInfo(100).flags & FLAG_PROFILE) != 0);
+
+ assertEquals(USER_TYPE_FULL_GUEST, mUserManagerService.getUserTypeForUser(101));
+
+ assertEquals(USER_TYPE_FULL_RESTRICTED, mUserManagerService.getUserTypeForUser(102));
+ assertTrue((mUserManagerService.getUserInfo(102).flags & FLAG_PROFILE) == 0);
+
+ assertEquals(USER_TYPE_FULL_SECONDARY, mUserManagerService.getUserTypeForUser(103));
+ assertTrue((mUserManagerService.getUserInfo(103).flags & FLAG_PROFILE) == 0);
+
+ assertEquals(USER_TYPE_SYSTEM_HEADLESS, mUserManagerService.getUserTypeForUser(104));
+
+ assertEquals(USER_TYPE_FULL_SYSTEM, mUserManagerService.getUserTypeForUser(105));
+
+ assertEquals(USER_TYPE_FULL_DEMO, mUserManagerService.getUserTypeForUser(106));
+ }
+
+ /** Creates a UserInfo with the given flags and userType. */
+ private UserInfo createUser(@UserIdInt int userId, @UserInfoFlag int flags, String userType) {
+ return new UserInfo(userId, "A Name", "A path", flags, userType);
+ }
+
private UserInfo createUser() {
- UserInfo user = new UserInfo(/*id*/ 21, "A Name", "A path", /*flags*/ 0x0ff0ff);
+ UserInfo user = new UserInfo(/*id*/ 21, "A Name", "A path", /*flags*/ 0x0ff0ff, "A type");
user.serialNumber = 5;
user.creationTime = 4L << 32;
user.lastLoggedInTime = 5L << 32;
@@ -141,6 +212,7 @@
assertEquals("Name not preserved", one.name, two.name);
assertEquals("Icon path not preserved", one.iconPath, two.iconPath);
assertEquals("Flags not preserved", one.flags, two.flags);
+ assertEquals("UserType not preserved", one.userType, two.userType);
assertEquals("profile group not preserved", one.profileGroupId,
two.profileGroupId);
assertEquals("restricted profile parent not preseved", one.restrictedProfileParentId,
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
new file mode 100644
index 0000000..7aadd87
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static android.content.pm.UserInfo.FLAG_DEMO;
+import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
+import static android.content.pm.UserInfo.FLAG_FULL;
+import static android.content.pm.UserInfo.FLAG_GUEST;
+import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
+import static android.content.pm.UserInfo.FLAG_PROFILE;
+import static android.content.pm.UserInfo.FLAG_RESTRICTED;
+import static android.content.pm.UserInfo.FLAG_SYSTEM;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.testng.Assert.assertThrows;
+
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.os.UserManager;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Tests for {@link UserTypeDetails} and {@link UserTypeFactory}.
+ *
+ * <p>Run with: atest UserManagerServiceUserTypeTest
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class UserManagerServiceUserTypeTest {
+
+ @Test
+ public void testUserTypeBuilder_createUserType() {
+ UserTypeDetails type = new UserTypeDetails.Builder()
+ .setName("a.name")
+ .setEnabled(true)
+ .setMaxAllowed(21)
+ .setBaseType(FLAG_FULL)
+ .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL)
+ .setBadgeLabels(23, 24, 25)
+ .setBadgeColors(26, 27)
+ .setIconBadge(28)
+ .setBadgePlain(29)
+ .setBadgeNoBackground(30)
+ .setLabel(31)
+ .setMaxAllowedPerParent(32)
+ .setDefaultRestrictions(new ArrayList<>(Arrays.asList("r1", "r2")))
+ .createUserTypeDetails();
+
+ assertEquals("a.name", type.getName());
+ assertTrue(type.isEnabled());
+ assertEquals(21, type.getMaxAllowed());
+ assertEquals(FLAG_FULL | FLAG_EPHEMERAL, type.getDefaultUserInfoFlags());
+ assertEquals(28, type.getIconBadge());
+ assertEquals(29, type.getBadgePlain());
+ assertEquals(30, type.getBadgeNoBackground());
+ assertEquals(31, type.getLabel());
+ assertEquals(32, type.getMaxAllowedPerParent());
+ assertEquals(new ArrayList<>(Arrays.asList("r1", "r2")), type.getDefaultRestrictions());
+
+
+ assertEquals(23, type.getBadgeLabel(0));
+ assertEquals(24, type.getBadgeLabel(1));
+ assertEquals(25, type.getBadgeLabel(2));
+ assertEquals(25, type.getBadgeLabel(3));
+ assertEquals(25, type.getBadgeLabel(4));
+ assertEquals(Resources.ID_NULL, type.getBadgeLabel(-1));
+
+ assertEquals(26, type.getBadgeColor(0));
+ assertEquals(27, type.getBadgeColor(1));
+ assertEquals(27, type.getBadgeColor(2));
+ assertEquals(27, type.getBadgeColor(3));
+ assertEquals(Resources.ID_NULL, type.getBadgeColor(-100));
+
+ assertTrue(type.hasBadge());
+ }
+
+ @Test
+ public void testUserTypeBuilder_defaults() {
+ UserTypeDetails type = new UserTypeDetails.Builder()
+ .setName("name") // Required (no default allowed)
+ .setBaseType(FLAG_FULL) // Required (no default allowed)
+ .createUserTypeDetails();
+
+ assertTrue(type.isEnabled());
+ assertEquals(UserTypeDetails.UNLIMITED_NUMBER_OF_USERS, type.getMaxAllowed());
+ assertEquals(UserTypeDetails.UNLIMITED_NUMBER_OF_USERS, type.getMaxAllowedPerParent());
+ assertEquals(FLAG_FULL, type.getDefaultUserInfoFlags());
+ assertEquals(Resources.ID_NULL, type.getIconBadge());
+ assertEquals(Resources.ID_NULL, type.getBadgePlain());
+ assertEquals(Resources.ID_NULL, type.getBadgeNoBackground());
+ assertEquals(Resources.ID_NULL, type.getBadgeLabel(0));
+ assertEquals(Resources.ID_NULL, type.getBadgeColor(0));
+ assertEquals(Resources.ID_NULL, type.getLabel());
+ assertTrue(type.getDefaultRestrictions().isEmpty());
+
+ assertFalse(type.hasBadge());
+ }
+
+ @Test
+ public void testUserTypeBuilder_nameIsRequired() {
+ assertThrows(IllegalArgumentException.class,
+ () -> new UserTypeDetails.Builder()
+ .setMaxAllowed(21)
+ .setBaseType(FLAG_FULL)
+ .createUserTypeDetails());
+ }
+
+ @Test
+ public void testUserTypeBuilder_baseTypeIsRequired() {
+ assertThrows(IllegalArgumentException.class,
+ () -> new UserTypeDetails.Builder()
+ .setName("name")
+ .createUserTypeDetails());
+ }
+
+ @Test
+ public void testUserTypeBuilder_colorIsRequiredIfBadged() {
+ assertThrows(IllegalArgumentException.class,
+ () -> getMinimalBuilder()
+ .setIconBadge(1)
+ .setBadgeLabels(2)
+ .createUserTypeDetails());
+ }
+
+ @Test
+ public void testUserTypeBuilder_badgeLabelIsRequiredIfBadged() {
+ assertThrows(IllegalArgumentException.class,
+ () -> getMinimalBuilder()
+ .setIconBadge(1)
+ .setBadgeColors(2)
+ .createUserTypeDetails());
+ }
+
+ @Test
+ public void testCheckUserTypeConsistency() {
+ assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_GUEST));
+ assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_GUEST | FLAG_EPHEMERAL));
+ assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE));
+
+ assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_DEMO | FLAG_RESTRICTED));
+ assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE | FLAG_SYSTEM));
+ assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE | FLAG_FULL));
+ }
+
+ @Test
+ public void testGetDefaultUserType() {
+ // Simple example.
+ assertEquals(UserManager.USER_TYPE_FULL_RESTRICTED,
+ UserInfo.getDefaultUserType(FLAG_RESTRICTED));
+
+ // Type plus a non-type flag.
+ assertEquals(UserManager.USER_TYPE_FULL_GUEST,
+ UserInfo.getDefaultUserType(FLAG_GUEST | FLAG_EPHEMERAL));
+
+ // Two types, which is illegal.
+ assertThrows(IllegalArgumentException.class,
+ () -> UserInfo.getDefaultUserType(FLAG_MANAGED_PROFILE | FLAG_GUEST));
+
+ // No type, which defaults to {@link UserManager#USER_TYPE_FULL_SECONDARY}.
+ assertEquals(UserManager.USER_TYPE_FULL_SECONDARY,
+ UserInfo.getDefaultUserType(FLAG_EPHEMERAL));
+ }
+
+ /** Returns a minimal {@link UserTypeDetails.Builder} that can legitimately be created. */
+ private UserTypeDetails.Builder getMinimalBuilder() {
+ return new UserTypeDetails.Builder().setName("name").setBaseType(FLAG_FULL);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index e9edba5..d071927 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -16,6 +16,7 @@
package com.android.server.pm;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -23,6 +24,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -196,6 +198,62 @@
}
}
+ /** Tests creating a FULL user via specifying userType. */
+ @MediumTest
+ public void testCreateUserViaTypes() throws Exception {
+ createUserWithTypeAndCheckFlags(UserManager.USER_TYPE_FULL_GUEST,
+ UserInfo.FLAG_GUEST | UserInfo.FLAG_FULL);
+
+ createUserWithTypeAndCheckFlags(UserManager.USER_TYPE_FULL_DEMO,
+ UserInfo.FLAG_DEMO | UserInfo.FLAG_FULL);
+
+ createUserWithTypeAndCheckFlags(UserManager.USER_TYPE_FULL_SECONDARY,
+ UserInfo.FLAG_FULL);
+ }
+
+ /** Tests creating a FULL user via specifying user flags. */
+ @MediumTest
+ public void testCreateUserViaFlags() throws Exception {
+ createUserWithFlagsAndCheckType(UserInfo.FLAG_GUEST, UserManager.USER_TYPE_FULL_GUEST,
+ UserInfo.FLAG_FULL);
+
+ createUserWithFlagsAndCheckType(0, UserManager.USER_TYPE_FULL_SECONDARY,
+ UserInfo.FLAG_FULL);
+
+ createUserWithFlagsAndCheckType(UserInfo.FLAG_FULL, UserManager.USER_TYPE_FULL_SECONDARY,
+ 0);
+
+ createUserWithFlagsAndCheckType(UserInfo.FLAG_DEMO, UserManager.USER_TYPE_FULL_DEMO,
+ UserInfo.FLAG_FULL);
+ }
+
+ /** Creates a user of the given user type and checks that the result has the requiredFlags. */
+ private void createUserWithTypeAndCheckFlags(String userType,
+ @UserIdInt int requiredFlags) {
+ final UserInfo userInfo = createUser("Name", userType, 0);
+ assertEquals("Wrong user type", userType, userInfo.userType);
+ assertEquals(
+ "Flags " + userInfo.flags + " did not contain expected " + requiredFlags,
+ requiredFlags, userInfo.flags & requiredFlags);
+ removeUser(userInfo.id);
+ }
+
+ /**
+ * Creates a user of the given flags and checks that the result is of the expectedUserType type
+ * and that it has the expected flags (including both flags and any additionalRequiredFlags).
+ */
+ private void createUserWithFlagsAndCheckType(@UserIdInt int flags, String expectedUserType,
+ @UserIdInt int additionalRequiredFlags) {
+ final UserInfo userInfo = createUser("Name", flags);
+ assertEquals("Wrong user type", expectedUserType, userInfo.userType);
+ additionalRequiredFlags |= flags;
+ assertEquals(
+ "Flags " + userInfo.flags + " did not contain expected " + additionalRequiredFlags,
+ additionalRequiredFlags, userInfo.flags & additionalRequiredFlags);
+ removeUser(userInfo.id);
+ }
+
+
@MediumTest
public void testAddGuest() throws Exception {
UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
@@ -234,7 +292,7 @@
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo = createProfileForUser("Profile",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
assertNotNull(userInfo);
assertNull(mUserManager.getProfileParent(primaryUserId));
UserInfo parentProfileInfo = mUserManager.getProfileParent(userInfo.id);
@@ -244,17 +302,61 @@
assertNull(mUserManager.getProfileParent(primaryUserId));
}
+ /** Test that UserManager returns the correct badge information for a managed profile. */
+ @MediumTest
+ public void testProfileTypeInformation() throws Exception {
+ final UserTypeDetails userTypeDetails =
+ UserTypeFactory.getUserTypes().get(UserManager.USER_TYPE_PROFILE_MANAGED);
+ assertNotNull("No " + UserManager.USER_TYPE_PROFILE_MANAGED + " type on device",
+ userTypeDetails);
+ assertEquals(UserManager.USER_TYPE_PROFILE_MANAGED, userTypeDetails.getName());
+
+ final int primaryUserId = mUserManager.getPrimaryUser().id;
+ UserInfo userInfo = createProfileForUser("Managed",
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
+ assertNotNull(userInfo);
+ final int userId = userInfo.id;
+ final UserHandle userHandle = new UserHandle(userId);
+
+ assertEquals(userTypeDetails.hasBadge(),
+ mUserManager.hasBadge(userId));
+ assertEquals(userTypeDetails.getIconBadge(),
+ mUserManager.getUserIconBadgeResId(userId));
+ assertEquals(userTypeDetails.getBadgePlain(),
+ mUserManager.getUserBadgeResId(userId));
+ assertEquals(userTypeDetails.getBadgeNoBackground(),
+ mUserManager.getUserBadgeNoBackgroundResId(userId));
+ assertEquals(userTypeDetails.isProfile(),
+ mUserManager.isProfile(userId));
+ assertEquals(userTypeDetails.getName(),
+ mUserManager.getUserTypeForUser(userHandle));
+
+ final int badgeIndex = userInfo.profileBadge;
+ assertEquals(
+ Resources.getSystem().getColor(userTypeDetails.getBadgeColor(badgeIndex), null),
+ mUserManager.getUserBadgeColor(userId));
+ assertEquals(
+ Resources.getSystem().getString(userTypeDetails.getBadgeLabel(badgeIndex), "Test"),
+ mUserManager.getBadgedLabelForUser("Test", userHandle));
+ }
+
// Make sure only one managed profile can be created
@MediumTest
public void testAddManagedProfile() throws Exception {
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo1 = createProfileForUser("Managed 1",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
UserInfo userInfo2 = createProfileForUser("Managed 2",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
assertNotNull(userInfo1);
assertNull(userInfo2);
+
+ assertEquals(userInfo1.userType, UserManager.USER_TYPE_PROFILE_MANAGED);
+ int requiredFlags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE;
+ assertEquals("Wrong flags " + userInfo1.flags, requiredFlags,
+ userInfo1.flags & requiredFlags);
+
// Verify that current user is not a managed profile
assertFalse(mUserManager.isManagedProfile());
}
@@ -264,7 +366,7 @@
public void testAddManagedProfile_withDisallowedPackages() throws Exception {
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo1 = createProfileForUser("Managed1",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
// Verify that the packagesToVerify are installed by default.
for (String pkg : PACKAGES) {
assertTrue("Package should be installed in managed profile: " + pkg,
@@ -273,7 +375,7 @@
removeUser(userInfo1.id);
UserInfo userInfo2 = createProfileForUser("Managed2",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId, PACKAGES);
// Verify that the packagesToVerify are not installed by default.
for (String pkg : PACKAGES) {
assertFalse("Package should not be installed in managed profile when disallowed: "
@@ -287,7 +389,7 @@
public void testAddManagedProfile_disallowedPackagesInstalledLater() throws Exception {
final int primaryUserId = mUserManager.getPrimaryUser().id;
UserInfo userInfo = createProfileForUser("Managed",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId, PACKAGES);
// Verify that the packagesToVerify are not installed by default.
for (String pkg : PACKAGES) {
assertFalse("Package should not be installed in managed profile when disallowed: "
@@ -326,7 +428,7 @@
primaryUserHandle);
try {
UserInfo userInfo = createProfileForUser("Managed",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
assertNull(userInfo);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
@@ -343,7 +445,7 @@
primaryUserHandle);
try {
UserInfo userInfo = createProfileEvenWhenDisallowedForUser("Managed",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
assertNotNull(userInfo);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
@@ -359,7 +461,7 @@
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
try {
UserInfo userInfo = createProfileForUser("Managed",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
assertNotNull(userInfo);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
@@ -396,7 +498,7 @@
final int primaryUserId = mUserManager.getPrimaryUser().id;
final long startTime = System.currentTimeMillis();
UserInfo profile = createProfileForUser("Managed 1",
- UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+ UserManager.USER_TYPE_PROFILE_MANAGED, primaryUserId);
final long endTime = System.currentTimeMillis();
assertNotNull(profile);
if (System.currentTimeMillis() > EPOCH_PLUS_30_YEARS) {
@@ -663,24 +765,32 @@
return user;
}
- private UserInfo createProfileForUser(String name, int flags, int userHandle) {
- return createProfileForUser(name, flags, userHandle, null);
+ private UserInfo createUser(String name, String userType, int flags) {
+ UserInfo user = mUserManager.createUser(name, userType, flags);
+ if (user != null) {
+ usersToRemove.add(user.id);
+ }
+ return user;
}
- private UserInfo createProfileForUser(String name, int flags, int userHandle,
+ private UserInfo createProfileForUser(String name, String userType, int userHandle) {
+ return createProfileForUser(name, userType, userHandle, null);
+ }
+
+ private UserInfo createProfileForUser(String name, String userType, int userHandle,
String[] disallowedPackages) {
UserInfo profile = mUserManager.createProfileForUser(
- name, flags, userHandle, disallowedPackages);
+ name, userType, 0, userHandle, disallowedPackages);
if (profile != null) {
usersToRemove.add(profile.id);
}
return profile;
}
- private UserInfo createProfileEvenWhenDisallowedForUser(String name, int flags,
+ private UserInfo createProfileEvenWhenDisallowedForUser(String name, String userType,
int userHandle) {
UserInfo profile = mUserManager.createProfileForUserEvenWhenDisallowed(
- name, flags, userHandle, null);
+ name, userType, 0, userHandle, null);
if (profile != null) {
usersToRemove.add(profile.id);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index f0b0328..f492932 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -147,7 +147,7 @@
final ArrayMap<String, Integer> expectedOutput = getNewPackageToWhitelistedFlagsMap();
expectedOutput.put("com.android.package1",
- UserInfo.PROFILE_FLAGS_MASK | FLAG_SYSTEM | FLAG_GUEST);
+ UserInfo.FLAG_PROFILE | FLAG_SYSTEM | FLAG_GUEST);
expectedOutput.put("com.android.package2",
UserInfo.FLAG_MANAGED_PROFILE);
@@ -376,9 +376,9 @@
/** Sets the whitelist mode to the desired value via adb's setprop. */
private void setUserTypePackageWhitelistMode(int mode) {
- UiDevice mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
try {
- String result = mUiDevice.executeShellCommand(String.format("setprop %s %d",
+ String result = uiDevice.executeShellCommand(String.format("setprop %s %d",
PACKAGE_WHITELIST_MODE_PROP, mode));
assertFalse("Failed to set sysprop " + PACKAGE_WHITELIST_MODE_PROP + ": " + result,
result != null && result.contains("Failed"));
@@ -390,7 +390,7 @@
private ArrayMap<String, Integer> getNewPackageToWhitelistedFlagsMap() {
final ArrayMap<String, Integer> pkgFlagMap = new ArrayMap<>();
// "android" is always treated as whitelisted, regardless of the xml file.
- pkgFlagMap.put("android", FLAG_SYSTEM | UserInfo.FLAG_FULL | UserInfo.PROFILE_FLAGS_MASK);
+ pkgFlagMap.put("android", FLAG_SYSTEM | UserInfo.FLAG_FULL | UserInfo.FLAG_PROFILE);
return pkgFlagMap;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserTests.java b/services/tests/servicestests/src/com/android/server/pm/UserTests.java
new file mode 100644
index 0000000..525382d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ UserDataPreparerTest.class,
+ UserLifecycleStressTest.class,
+ UserManagerServiceCreateProfileTest.class,
+ UserManagerServiceIdRecyclingTest.class,
+ UserManagerServiceTest.class,
+ UserManagerServiceUserInfoTest.class,
+ UserManagerServiceUserTypeTest.class,
+ UserManagerTest.class,
+ UserRestrictionsUtilsTest.class,
+ UserSystemPackageInstallerTest.class,
+})
+public class UserTests {
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 88de250..592f4ec 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -33,9 +33,11 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -62,11 +64,13 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
+import android.test.mock.MockContentResolver;
import android.view.Display;
import androidx.test.InstrumentationRegistry;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.lights.LightsManager;
@@ -109,6 +113,9 @@
@Mock private WirelessChargerDetector mWirelessChargerDetectorMock;
@Mock private AmbientDisplayConfiguration mAmbientDisplayConfigurationMock;
+ @Mock
+ private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
+
private PowerManagerService mService;
private PowerSaveState mPowerSaveState;
private DisplayPowerRequest mDisplayPowerRequest;
@@ -149,6 +156,9 @@
when(mBatterySaverPolicyMock.getBatterySaverPolicy(
eq(PowerManager.ServiceType.SCREEN_BRIGHTNESS)))
.thenReturn(mPowerSaveState);
+ when(mBatteryManagerInternalMock.isPowered(anyInt())).thenReturn(false);
+ when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(false);
+ when(mDisplayManagerInternalMock.requestPowerState(any(), anyBoolean())).thenReturn(true);
mDisplayPowerRequest = new DisplayPowerRequest();
addLocalServiceMock(LightsManager.class, mLightsManagerMock);
@@ -161,7 +171,12 @@
mResourcesSpy = spy(mContextSpy.getResources());
when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
- when(mDisplayManagerInternalMock.requestPowerState(any(), anyBoolean())).thenReturn(true);
+ MockContentResolver cr = new MockContentResolver(mContextSpy);
+ cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ when(mContextSpy.getContentResolver()).thenReturn(cr);
+
+ Settings.Global.putInt(mContextSpy.getContentResolver(),
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
}
private PowerManagerService createService() {
@@ -198,6 +213,11 @@
AmbientDisplayConfiguration createAmbientDisplayConfiguration(Context context) {
return mAmbientDisplayConfigurationMock;
}
+
+ @Override
+ InattentiveSleepWarningController createInattentiveSleepWarningController() {
+ return mInattentiveSleepWarningControllerMock;
+ }
});
return mService;
}
@@ -208,8 +228,12 @@
LocalServices.removeServiceForTest(DisplayManagerInternal.class);
LocalServices.removeServiceForTest(BatteryManagerInternal.class);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+
Settings.Global.putInt(
mContextSpy.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0);
+ setAttentiveTimeout(-1);
+ Settings.Global.putInt(mContextSpy.getContentResolver(),
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
}
/**
@@ -263,12 +287,30 @@
private void setPluggedIn(boolean isPluggedIn) {
// Set the callback to return the new state
- when(mBatteryManagerInternalMock.isPowered(BatteryManager.BATTERY_PLUGGED_ANY))
+ when(mBatteryManagerInternalMock.isPowered(anyInt()))
.thenReturn(isPluggedIn);
// Trigger PowerManager to reread the plug-in state
mBatteryReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_BATTERY_CHANGED));
}
+ private void setAttentiveTimeout(int attentiveTimeoutMillis) {
+ Settings.Secure.putInt(
+ mContextSpy.getContentResolver(), Settings.Secure.ATTENTIVE_TIMEOUT,
+ attentiveTimeoutMillis);
+ }
+
+ private void setAttentiveWarningDuration(int attentiveWarningDurationMillis) {
+ when(mResourcesSpy.getInteger(
+ com.android.internal.R.integer.config_attentiveWarningDuration))
+ .thenReturn(attentiveWarningDurationMillis);
+ }
+
+ private void setMinimumScreenOffTimeoutConfig(int minimumScreenOffTimeoutConfigMillis) {
+ when(mResourcesSpy.getInteger(
+ com.android.internal.R.integer.config_minimumScreenOffTimeout))
+ .thenReturn(minimumScreenOffTimeoutConfigMillis);
+ }
+
@Test
public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
createService();
@@ -615,4 +657,97 @@
.setDozeOverrideFromDreamManager(Display.STATE_ON, PowerManager.BRIGHTNESS_DEFAULT);
assertTrue(isAcquired[0]);
}
+
+ @Test
+ public void testInattentiveSleep_hideWarningIfStayOnIsEnabledAndPluggedIn() throws Exception {
+ setAttentiveTimeout(15000);
+ Settings.Global.putInt(mContextSpy.getContentResolver(),
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
+
+ createService();
+ startSystem();
+
+ verify(mInattentiveSleepWarningControllerMock, times(1)).show();
+ verify(mInattentiveSleepWarningControllerMock, never()).dismiss();
+ when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);
+
+ setPluggedIn(true);
+ verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss();
+ }
+
+ @Test
+ public void testInattentive_userActivityDismissesWarning() throws Exception {
+ setMinimumScreenOffTimeoutConfig(5);
+ setAttentiveWarningDuration(30);
+ setAttentiveTimeout(100);
+
+ createService();
+ startSystem();
+
+ mService.getBinderServiceInstance().userActivity(SystemClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
+ verify(mInattentiveSleepWarningControllerMock, never()).show();
+
+ SystemClock.sleep(70);
+ verify(mInattentiveSleepWarningControllerMock, times(1)).show();
+ verify(mInattentiveSleepWarningControllerMock, never()).dismiss();
+ when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);
+
+ mService.getBinderServiceInstance().userActivity(SystemClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
+ verify(mInattentiveSleepWarningControllerMock, times(1)).dismiss();
+ }
+
+ @Test
+ public void testInattentiveSleep_warningHiddenAfterWakingUp() throws Exception {
+ setMinimumScreenOffTimeoutConfig(5);
+ setAttentiveWarningDuration(20);
+ setAttentiveTimeout(30);
+
+ createService();
+ startSystem();
+ SystemClock.sleep(10);
+ verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).show();
+ when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);
+ SystemClock.sleep(30);
+ forceAwake();
+ verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss();
+ }
+
+ @Test
+ public void testInattentiveSleep_noWarningShownIfInattentiveSleepDisabled() throws Exception {
+ setAttentiveTimeout(-1);
+ createService();
+ startSystem();
+ verify(mInattentiveSleepWarningControllerMock, never()).show();
+ }
+
+ @Test
+ public void testInattentiveSleep_goesToSleepAfterTimeout() throws Exception {
+ setMinimumScreenOffTimeoutConfig(5);
+ setAttentiveTimeout(5);
+ createService();
+ startSystem();
+ SystemClock.sleep(8);
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
+ }
+
+ @Test
+ public void testInattentiveSleep_goesToSleepWithWakeLock() throws Exception {
+ final String pkg = mContextSpy.getOpPackageName();
+ final Binder token = new Binder();
+ final String tag = "sleep_testWithWakeLock";
+
+ setMinimumScreenOffTimeoutConfig(5);
+ setAttentiveTimeout(10);
+ createService();
+ startSystem();
+
+ mService.getBinderServiceInstance().acquireWakeLock(token,
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
+ null /* workSource */, null /* historyTag */);
+
+ SystemClock.sleep(11);
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 39aa51a..a23e2f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -24,6 +25,7 @@
import static org.junit.Assert.assertTrue;
import android.app.Activity;
+import android.app.ActivityManager;
import android.graphics.Rect;
import android.view.WindowContainerTransaction;
@@ -76,5 +78,20 @@
mService.applyContainerTransaction(t);
assertEquals(newBounds, task.getBounds());
}
+
+ @Test
+ public void testStackTransaction() {
+ removeGlobalMinSizeRestriction();
+ final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ ActivityManager.StackInfo info =
+ mService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
+ WindowContainerTransaction t = new WindowContainerTransaction();
+ assertEquals(stack.mRemoteToken, info.stackToken);
+ Rect newBounds = new Rect(10, 10, 100, 100);
+ t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
+ mService.applyContainerTransaction(t);
+ assertEquals(newBounds, stack.getBounds());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index e0ffb0d..4f2d5d2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -61,6 +61,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.util.SparseBooleanArray;
@@ -92,7 +93,9 @@
private static final int TEST_USER_1_ID = 10;
private static final int TEST_QUIET_USER_ID = 20;
private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
- private static final UserInfo QUIET_USER_INFO = new UserInfo();
+ private static final UserInfo QUIET_PROFILE_USER_INFO = new UserInfo(TEST_QUIET_USER_ID,
+ "quiet_profile", null /* iconPath */, UserInfo.FLAG_QUIET_MODE,
+ UserManager.USER_TYPE_PROFILE_MANAGED);
private static final int INVALID_STACK_ID = 999;
private ActivityDisplay mDisplay;
@@ -125,7 +128,6 @@
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mCallbacksRecorder = new CallbacksRecorder();
mRecentTasks.registerCallback(mCallbacksRecorder);
- QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
mTasks = new ArrayList<>();
mTasks.add(createTaskBuilder(".Task1").build());
@@ -1220,7 +1222,7 @@
case TEST_USER_1_ID:
return DEFAULT_USER_INFO;
case TEST_QUIET_USER_ID:
- return QUIET_USER_INFO;
+ return QUIET_PROFILE_USER_INFO;
}
return null;
}
diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp
index 3f20273..f42c755 100644
--- a/startop/apps/test/Android.bp
+++ b/startop/apps/test/Android.bp
@@ -17,6 +17,7 @@
android_app {
name: "startop_test_app",
srcs: [
+ "src/ApplicationBenchmarks.java",
"src/ComplexLayoutInflationActivity.java",
"src/CPUIntensiveBenchmarkActivity.java",
"src/CPUIntensiveBenchmarks.java",
@@ -25,8 +26,8 @@
"src/InitCheckOverheadBenchmarkActivity.java",
"src/InitCheckOverheadBenchmarks.java",
"src/LayoutInflationActivity.java",
- "src/NonInteractiveSystemServerBenchmarkActivity.java",
- "src/SystemServerBenchmarkActivity.java",
+ "src/NonInteractiveMicrobenchmarkActivity.java",
+ "src/InteractiveMicrobenchmarkActivity.java",
"src/SystemServerBenchmarks.java",
"src/TextViewInflationActivity.java",
],
diff --git a/startop/apps/test/AndroidManifest.xml b/startop/apps/test/AndroidManifest.xml
index 235aa0d..adaab61 100644
--- a/startop/apps/test/AndroidManifest.xml
+++ b/startop/apps/test/AndroidManifest.xml
@@ -97,8 +97,8 @@
</activity>
<activity
- android:label="SystemServer Benchmark"
- android:name=".SystemServerBenchmarkActivity"
+ android:label="Interactive Microbenchmarks"
+ android:name=".InteractiveMicrobenchmarkActivity"
android:exported="true" >
<intent-filter>
@@ -109,8 +109,8 @@
</activity>
<activity
- android:label="Non-interactive SystemServer Benchmark"
- android:name=".NonInteractiveSystemServerBenchmarkActivity"
+ android:label="Non-interactive Microbenchmarks"
+ android:name=".NonInteractiveMicrobenchmarkActivity"
android:exported="true" />
</application>
diff --git a/startop/apps/test/src/ApplicationBenchmarks.java b/startop/apps/test/src/ApplicationBenchmarks.java
new file mode 100644
index 0000000..7d71916
--- /dev/null
+++ b/startop/apps/test/src/ApplicationBenchmarks.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.startop.test;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+
+final class ApplicationBenchmarks {
+
+ public static final void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) {
+ LayoutInflater inflater = LayoutInflater.from(parent);
+
+ benchmarks.addBenchmark("Complex Layout", () -> {
+ inflater.inflate(R.layout.activity_main, null);
+ });
+
+ benchmarks.addBenchmark("TextView List Layout", () -> {
+ inflater.inflate(R.layout.textview_list, null);
+ });
+
+ benchmarks.addBenchmark("FrameLayout List Layout", () -> {
+ inflater.inflate(R.layout.framelayout_list, null);
+ });
+ }
+}
diff --git a/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java b/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java
index 2ec5308..db3234a 100644
--- a/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java
+++ b/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java
@@ -18,7 +18,7 @@
import android.os.Bundle;
-public class CPUIntensiveBenchmarkActivity extends SystemServerBenchmarkActivity {
+public class CPUIntensiveBenchmarkActivity extends InteractiveMicrobenchmarkActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.system_server_benchmark_page);
diff --git a/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java b/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java
index 3e0e3b1..92d8638 100644
--- a/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java
+++ b/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java
@@ -18,7 +18,7 @@
import android.os.Bundle;
-public class InitCheckOverheadBenchmarkActivity extends SystemServerBenchmarkActivity {
+public class InitCheckOverheadBenchmarkActivity extends InteractiveMicrobenchmarkActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.system_server_benchmark_page);
diff --git a/startop/apps/test/src/SystemServerBenchmarkActivity.java b/startop/apps/test/src/InteractiveMicrobenchmarkActivity.java
similarity index 66%
rename from startop/apps/test/src/SystemServerBenchmarkActivity.java
rename to startop/apps/test/src/InteractiveMicrobenchmarkActivity.java
index 6be8df3..c3839c1 100644
--- a/startop/apps/test/src/SystemServerBenchmarkActivity.java
+++ b/startop/apps/test/src/InteractiveMicrobenchmarkActivity.java
@@ -18,12 +18,13 @@
import android.app.Activity;
import android.content.Context;
+import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.TextView;
-public class SystemServerBenchmarkActivity extends Activity implements BenchmarkRunner {
+public class InteractiveMicrobenchmarkActivity extends Activity implements BenchmarkRunner {
protected GridLayout mBenchmarkList;
protected void onCreate(Bundle savedInstanceState) {
@@ -32,10 +33,34 @@
mBenchmarkList = findViewById(R.id.benchmark_list);
+ addBenchmark("Empty", () -> {
+ });
+ addHeader("Application Benchmarks");
+ ApplicationBenchmarks.initializeBenchmarks(this, this);
+ addHeader("CPU Intensive Benchmarks");
+ CPUIntensiveBenchmarks.initializeBenchmarks(this, this);
+ addHeader("Init Check Overhead Benchmarks");
+ InitCheckOverheadBenchmarks.initializeBenchmarks(this, this);
+ addHeader("System Server Benchmarks");
SystemServerBenchmarks.initializeBenchmarks(this, this);
}
/**
+ * Add a heading for a group of related benchmarks
+ *
+ * @param name The name of this group of benchmarks
+ */
+ public void addHeader(CharSequence name) {
+ Context context = mBenchmarkList.getContext();
+ TextView header = new TextView(context);
+ header.setText(name);
+ header.setTypeface(header.getTypeface(), Typeface.BOLD);
+ GridLayout.LayoutParams params = new GridLayout.LayoutParams();
+ params.columnSpec = GridLayout.spec(0, 3);
+ mBenchmarkList.addView(header, params);
+ }
+
+ /**
* Adds a benchmark to the set to run.
*
* @param name A short name that shows up in the UI or benchmark results
diff --git a/startop/apps/test/src/NonInteractiveSystemServerBenchmarkActivity.java b/startop/apps/test/src/NonInteractiveMicrobenchmarkActivity.java
similarity index 96%
rename from startop/apps/test/src/NonInteractiveSystemServerBenchmarkActivity.java
rename to startop/apps/test/src/NonInteractiveMicrobenchmarkActivity.java
index a2dc2cf..0162ac6 100644
--- a/startop/apps/test/src/NonInteractiveSystemServerBenchmarkActivity.java
+++ b/startop/apps/test/src/NonInteractiveMicrobenchmarkActivity.java
@@ -36,7 +36,7 @@
import android.widget.GridLayout;
import android.widget.TextView;
-public class NonInteractiveSystemServerBenchmarkActivity extends Activity {
+public class NonInteractiveMicrobenchmarkActivity extends Activity {
ArrayList<CharSequence> benchmarkNames = new ArrayList();
ArrayList<Runnable> benchmarkThunks = new ArrayList();
diff --git a/startop/apps/test/src/SystemServerBenchmarks.java b/startop/apps/test/src/SystemServerBenchmarks.java
index 25b43f4..8114bc2 100644
--- a/startop/apps/test/src/SystemServerBenchmarks.java
+++ b/startop/apps/test/src/SystemServerBenchmarks.java
@@ -57,9 +57,6 @@
static void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) {
final String packageName = parent.getPackageName();
- benchmarks.addBenchmark("Empty", () -> {
- });
-
PackageManager pm = parent.getPackageManager();
benchmarks.addBenchmark("getInstalledApplications", () -> {
pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a315e6d..2cdf21d 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3797,7 +3797,8 @@
+ " ICarrierConfigLoader is null");
return null;
}
- return loader.getConfigForSubId(subId, mContext.getOpPackageName());
+ return loader.getConfigForSubIdWithFeature(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
Rlog.e(TAG, "Error getting config for subId " + subId + ": "
+ ex.toString());
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 1309b4d..89c4e90 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -514,7 +514,6 @@
throw new IllegalArgumentException("Invalid message body");
}
- final Context context = ActivityThread.currentApplication().getApplicationContext();
// We will only show the SMS disambiguation dialog in the case that the message is being
// persisted. This is for two reasons:
// 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
@@ -623,7 +622,6 @@
final int finalPriority = priority;
final int finalValidity = validityPeriod;
- final Context context = ActivityThread.currentApplication().getApplicationContext();
// We will only show the SMS disambiguation dialog in the case that the message is being
// persisted. This is for two reasons:
// 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
@@ -927,7 +925,6 @@
}
if (parts.size() > 1) {
- final Context context = ActivityThread.currentApplication().getApplicationContext();
// We will only show the SMS disambiguation dialog in the case that the message is being
// persisted. This is for two reasons:
// 1) Messages that are not persisted are sent by carrier/OEM apps for a specific
@@ -1168,7 +1165,6 @@
if (parts.size() > 1) {
final int finalPriority = priority;
final int finalValidity = validityPeriod;
- final Context context = ActivityThread.currentApplication().getApplicationContext();
if (persistMessage) {
resolveSubscriptionForOperation(new SubscriptionResolverResult() {
@Override
@@ -1325,7 +1321,6 @@
throw new IllegalArgumentException("Invalid message data");
}
- final Context context = ActivityThread.currentApplication().getApplicationContext();
resolveSubscriptionForOperation(new SubscriptionResolverResult() {
@Override
public void onSuccess(int subId) {
@@ -2659,7 +2654,7 @@
ISms iccISms = getISmsServiceOrThrow();
if (iccISms != null) {
return iccISms.checkSmsShortCodeDestination(getSubscriptionId(),
- ActivityThread.currentPackageName(), destAddress, countryIso);
+ ActivityThread.currentPackageName(), null, destAddress, countryIso);
}
} catch (RemoteException e) {
Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e);
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index f527bc3..9eff809 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -654,6 +654,7 @@
* Return whether the subscription's group is disabled.
* @hide
*/
+ @SystemApi
public boolean isGroupDisabled() {
return mIsGroupDisabled;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 1770671..3d63e4a 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1154,7 +1154,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName());
+ subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1182,7 +1183,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName());
+ result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1216,7 +1218,7 @@
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1239,7 +1241,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAllSubInfoList(mContext.getOpPackageName());
+ result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1283,18 +1286,39 @@
}
/**
- * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly
- * is true, it will filter out the hidden subscriptions.
+ * Get both hidden and visible SubscriptionInfo(s) of the currently active SIM(s).
+ * The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex}
+ * then by {@link SubscriptionInfo#getSubscriptionId}.
*
- * @hide
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
+ * to the calling app are returned.
+ *
+ * @return Sorted list of the currently available {@link SubscriptionInfo}
+ * records on the device.
+ * This is similar to {@link #getActiveSubscriptionInfoList} except that it will return
+ * both active and hidden SubscriptionInfos.
+ *
*/
- public List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) {
+ public @Nullable List<SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList() {
+ return getActiveSubscriptionInfoList(/* userVisibleonly */false);
+ }
+
+ /**
+ * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly
+ * is true, it will filter out the hidden subscriptions.
+ *
+ * @hide
+ */
+ public @Nullable List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) {
List<SubscriptionInfo> activeList = null;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName());
+ activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1344,7 +1368,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName());
+ result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1461,7 +1486,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getAllSubInfoCount(mContext.getOpPackageName());
+ result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -1489,7 +1515,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getActiveSubInfoCount(mContext.getOpPackageName());
+ result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -2227,7 +2254,7 @@
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
resultValue = iSub.getSubscriptionProperty(subId, propKey,
- context.getOpPackageName());
+ context.getOpPackageName(), context.getFeatureId());
}
} catch (RemoteException ex) {
// ignore it
@@ -2350,7 +2377,8 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- return iSub.isActiveSubId(subId, mContext.getOpPackageName());
+ return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
}
@@ -2715,13 +2743,14 @@
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() {
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextFeature = mContext != null ? mContext.getFeatureId() : null;
List<SubscriptionInfo> subInfoList = null;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfoList = iSub.getOpportunisticSubscriptions(pkgForDebug);
+ subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
}
} catch (RemoteException ex) {
// ignore it
@@ -2959,7 +2988,8 @@
@RequiresPermission(Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) {
Preconditions.checkNotNull(groupUuid, "groupUuid can't be null");
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String contextFeature = mContext != null ? mContext.getFeatureId() : null;
if (VDBG) {
logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid);
}
@@ -2968,7 +2998,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- result = iSub.getSubscriptionsInGroup(groupUuid, pkgForDebug);
+ result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
} else {
if (!isSystemProcess()) {
throw new IllegalStateException("telephony service is null.");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 864bf03..64b5aa5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1689,7 +1689,8 @@
if (telephony == null) return null;
try {
- return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName());
+ return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1730,7 +1731,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getDeviceId(mContext.getOpPackageName());
+ return telephony.getDeviceIdWithFeature(mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1774,7 +1776,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName());
+ return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1832,7 +1835,7 @@
if (telephony == null) return null;
try {
- return telephony.getImeiForSlot(slotIndex, getOpPackageName());
+ return telephony.getImeiForSlot(slotIndex, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1926,7 +1929,7 @@
if (telephony == null) return null;
try {
- String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName());
+ String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName(), getFeatureId());
if (TextUtils.isEmpty(meid)) {
Log.d(TAG, "getMeid: return null because MEID is not available");
return null;
@@ -2027,7 +2030,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName());
+ String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Rlog.v(TAG, "Nai = " + nai);
}
@@ -2578,7 +2582,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return "";
return telephony.getNetworkCountryIsoForPhone(getPhoneId(),
- null /* no permission check */);
+ null /* no permission check */, null);
} catch (RemoteException ex) {
return "";
}
@@ -2618,7 +2622,8 @@
ITelephony telephony = getITelephony();
if (telephony == null) return "";
- return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName());
+ return telephony.getNetworkCountryIsoForPhone(slotIndex, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return "";
}
@@ -2722,7 +2727,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2786,7 +2792,8 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -2822,7 +2829,8 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName());
+ return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -3566,13 +3574,36 @@
}
/**
+ * Returns the ISO-3166 country code equivalent for the SIM provider's country code
+ * of the default subscription
+ * <p>
+ * The ISO-3166 country code is provided in lowercase 2 character format.
+ * @return the lowercase 2 character ISO-3166 country code, or empty string is not available.
+ * <p>
+ * Note: This API is introduced to unblock mainlining work as the following APIs in
+ * Linkify.java invokes getSimCountryIso() without a context. TODO(Bug 144576376): remove
+ * this API once the following APIs are redesigned to access telephonymanager with a context.
+ *
+ * {@link Linkify#addLinks(@NonNull Spannable text, @LinkifyMask int mask)}
+ * {@link Linkify#addLinks(@NonNull Spannable text, @LinkifyMask int mask,
+ @Nullable Function<String, URLSpan> urlSpanFactory)}
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public static String getDefaultSimCountryIso() {
+ return getSimCountryIso(SubscriptionManager.getDefaultSubscriptionId());
+ }
+
+ /**
* Returns the ISO country code equivalent for the SIM provider's country code.
*
* @param subId for which SimCountryIso is returned
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
- public String getSimCountryIso(int subId) {
+ public static String getSimCountryIso(int subId) {
int phoneId = SubscriptionManager.getPhoneId(subId);
return getSimCountryIsoForPhone(phoneId);
}
@@ -3583,7 +3614,7 @@
* @hide
*/
@UnsupportedAppUsage
- public String getSimCountryIsoForPhone(int phoneId) {
+ public static String getSimCountryIsoForPhone(int phoneId) {
return getTelephonyProperty(phoneId, TelephonyProperties.icc_operator_iso_country(), "");
}
@@ -3647,7 +3678,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName());
+ return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3691,7 +3723,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
- return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName());
+ return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
@@ -3919,7 +3952,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName());
+ return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4086,7 +4120,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName());
+ return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4109,7 +4144,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName());
+ return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4159,7 +4195,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName());
+ number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4170,7 +4207,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName());
+ return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4249,7 +4287,7 @@
ITelephony telephony = getITelephony();
if (telephony != null)
alphaTag = telephony.getLine1AlphaTagForDisplay(subId,
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4260,7 +4298,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName());
+ return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4289,7 +4328,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName());
+ return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4344,7 +4384,7 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getMsisdnForSubscriber(subId, getOpPackageName());
+ return info.getMsisdnForSubscriber(subId, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4378,7 +4418,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName());
+ return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4502,8 +4543,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony
- .getVisualVoicemailPackageName(mContext.getOpPackageName(), getSubId());
+ return telephony.getVisualVoicemailPackageName(mContext.getOpPackageName(),
+ getFeatureId(), getSubId());
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -4950,7 +4991,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return 0;
- return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName());
+ return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -4986,7 +5028,8 @@
IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
- return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName());
+ return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -5365,7 +5408,7 @@
} else if (listener.mSubId != null) {
subId = listener.mSubId;
}
- registry.listenForSubscriber(subId, getOpPackageName(),
+ registry.listenForSubscriber(subId, getOpPackageName(), getFeatureId(),
listener.callback, events, notifyNow);
} else {
Rlog.w(TAG, "telephony registry not ready.");
@@ -5395,7 +5438,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return -1;
- return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5430,7 +5474,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return -1;
- return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5461,7 +5506,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName());
+ return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
// the phone process is restarting.
return null;
@@ -6964,7 +7010,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName());
+ return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName(),
+ getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -6997,7 +7044,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return 0;
return telephony.setForbiddenPlmns(
- getSubId(), APPTYPE_USIM, fplmns, getOpPackageName());
+ getSubId(), APPTYPE_USIM, fplmns, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
Rlog.e(TAG, "setForbiddenPlmns RemoteException: " + ex.getMessage());
} catch (NullPointerException ex) {
@@ -7018,7 +7065,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return new String[0];
- return telephony.getPcscfAddress(apnType, getOpPackageName());
+ return telephony.getPcscfAddress(apnType, getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
return new String[0];
}
@@ -8249,7 +8296,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isRadioOn(getOpPackageName());
+ return telephony.isRadioOnWithFeature(getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isRadioOn", e);
}
@@ -8524,7 +8571,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName());
+ return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -8882,7 +8930,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isVideoCallingEnabled(getOpPackageName());
+ return telephony.isVideoCallingEnabled(getOpPackageName(), getFeatureId());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e);
}
@@ -8898,7 +8946,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName());
+ return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#canChangeDtmfToneLength", e);
@@ -8917,7 +8966,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isWorldPhone(mSubId, getOpPackageName());
+ return telephony.isWorldPhone(mSubId, getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isWorldPhone", e);
@@ -9640,7 +9689,7 @@
ITelephony service = getITelephony();
if (service != null) {
retval = service.getSubIdForPhoneAccountHandle(
- phoneAccountHandle, mContext.getOpPackageName());
+ phoneAccountHandle, mContext.getOpPackageName(), mContext.getFeatureId());
}
} catch (RemoteException ex) {
Log.e(TAG, "getSubscriptionId RemoteException", ex);
@@ -10502,7 +10551,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getClientRequestStats(getOpPackageName(), subId);
+ return service.getClientRequestStats(getOpPackageName(), getFeatureId(), subId);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getClientRequestStats", e);
@@ -10790,7 +10839,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getNumberOfModemsWithSimultaneousDataConnections(
- getSubId(), getOpPackageName());
+ getSubId(), getOpPackageName(), getFeatureId());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -10813,6 +10862,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
public boolean setOpportunisticNetworkState(boolean enable) {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
boolean ret = false;
@@ -10840,6 +10890,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi
public boolean isOpportunisticNetworkEnabled() {
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
boolean isEnabled = false;
@@ -11092,7 +11143,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getEmergencyNumberList(mContext.getOpPackageName());
+ return telephony.getEmergencyNumberList(mContext.getOpPackageName(),
+ mContext.getFeatureId());
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -11147,7 +11199,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
emergencyNumberList = telephony.getEmergencyNumberList(
- mContext.getOpPackageName());
+ mContext.getOpPackageName(), mContext.getFeatureId());
if (emergencyNumberList != null) {
for (Integer subscriptionId : emergencyNumberList.keySet()) {
List<EmergencyNumber> numberList = emergencyNumberList.get(subscriptionId);
@@ -11368,12 +11420,14 @@
android.Manifest.permission.READ_PHONE_STATE
})
public int getPreferredOpportunisticDataSubscription() {
- String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String packageName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ String featureId = mContext != null ? mContext.getFeatureId() : null;
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
try {
IOns iOpportunisticNetworkService = getIOns();
if (iOpportunisticNetworkService != null) {
- subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug);
+ subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(
+ packageName, featureId);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getPreferredDataSubscriptionId RemoteException", ex);
@@ -11477,11 +11531,13 @@
* @param slotIndex which slot it's checking.
* @hide
*/
+ @SystemApi
public boolean isModemEnabledForSlot(int slotIndex) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName());
+ return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName(),
+ mContext.getFeatureId());
}
} catch (RemoteException ex) {
Log.e(TAG, "enableModem RemoteException", ex);
@@ -11586,7 +11642,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isMultiSimSupported(getOpPackageName());
+ return service.isMultiSimSupported(getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "isMultiSimSupported RemoteException", e);
@@ -11638,7 +11694,7 @@
ITelephony service = getITelephony();
if (service != null) {
return service.doesSwitchMultiSimConfigTriggerReboot(getSubId(),
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "doesSwitchMultiSimConfigTriggerReboot RemoteException", e);
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index 8e50a8f..ee09c1c 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -23,9 +23,13 @@
*/
interface ICarrierConfigLoader {
+ /** @deprecated Use {@link #getConfigForSubIdWithFeature(int, String, String) instead */
@UnsupportedAppUsage
PersistableBundle getConfigForSubId(int subId, String callingPackage);
+ PersistableBundle getConfigForSubIdWithFeature(int subId, String callingPackage,
+ String callingFeatureId);
+
void overrideConfig(int subId, in PersistableBundle overrides);
void notifyConfigChangedForSubId(int subId);
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 2c48b65..76b6951 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -83,7 +83,7 @@
* subscription id
*
*/
- int getPreferredDataSubscriptionId(String callingPackage);
+ int getPreferredDataSubscriptionId(String callingPackage, String callingFeatureId);
/**
* Update availability of a list of networks in the current location.
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 15e7fc2..28ef235 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -24,114 +24,128 @@
*/
interface IPhoneSubInfo {
+ /** @deprecated Use {@link #getDeviceIdWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ String getDeviceId(String callingPackage);
+
/**
* Retrieves the unique device ID, e.g., IMEI for GSM phones.
*/
- @UnsupportedAppUsage
- String getDeviceId(String callingPackage);
+ String getDeviceIdWithFeature(String callingPackage, String callingFeatureId);
/**
* Retrieves the unique Network Access ID
*/
- String getNaiForSubscriber(int subId, String callingPackage);
+ String getNaiForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the unique device ID of a phone for the device, e.g., IMEI
* for GSM phones.
*/
- String getDeviceIdForPhone(int phoneId, String callingPackage);
+ String getDeviceIdForPhone(int phoneId, String callingPackage, String callingFeatureId);
/**
* Retrieves the IMEI.
*/
- String getImeiForSubscriber(int subId, String callingPackage);
+ String getImeiForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the software version number for the device, e.g., IMEI/SV
* for GSM phones.
*/
- String getDeviceSvn(String callingPackage);
+ String getDeviceSvn(String callingPackage, String callingFeatureId);
/**
* Retrieves the software version number of a subId for the device, e.g., IMEI/SV
* for GSM phones.
*/
- String getDeviceSvnUsingSubId(int subId, String callingPackage);
+ String getDeviceSvnUsingSubId(int subId, String callingPackage, String callingFeatureId);
- /**
- * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
- */
+ /** @deprecated Use {@link #getSubscriberIdWithFeature(String, String) instead */
@UnsupportedAppUsage
String getSubscriberId(String callingPackage);
/**
+ * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
+ */
+ String getSubscriberIdWithFeature(String callingPackage, String callingComponenId);
+
+ /**
* Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
*/
- String getSubscriberIdForSubscriber(int subId, String callingPackage);
+ String getSubscriberIdForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the Group Identifier Level1 for GSM phones of a subId.
*/
- String getGroupIdLevel1ForSubscriber(int subId, String callingPackage);
+ String getGroupIdLevel1ForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
- /**
- * Retrieves the serial number of the ICC, if applicable.
- */
+ /** @deprecared Use {@link getIccSerialNumberWithFeature(String, String)} instead */
@UnsupportedAppUsage
String getIccSerialNumber(String callingPackage);
/**
+ * Retrieves the serial number of the ICC, if applicable.
+ */
+ String getIccSerialNumberWithFeature(String callingPackage, String callingFeatureId);
+
+ /**
* Retrieves the serial number of a given subId.
*/
- String getIccSerialNumberForSubscriber(int subId, String callingPackage);
+ String getIccSerialNumberForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the phone number string for line 1.
*/
- String getLine1Number(String callingPackage);
+ String getLine1Number(String callingPackage, String callingFeatureId);
/**
* Retrieves the phone number string for line 1 of a subcription.
*/
- String getLine1NumberForSubscriber(int subId, String callingPackage);
+ String getLine1NumberForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier for line 1.
*/
- String getLine1AlphaTag(String callingPackage);
+ String getLine1AlphaTag(String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier for line 1 of a subId.
*/
- String getLine1AlphaTagForSubscriber(int subId, String callingPackage);
+ String getLine1AlphaTagForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves MSISDN Number.
*/
- String getMsisdn(String callingPackage);
+ String getMsisdn(String callingPackage, String callingFeatureId);
/**
* Retrieves the Msisdn of a subId.
*/
- String getMsisdnForSubscriber(int subId, String callingPackage);
+ String getMsisdnForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Retrieves the voice mail number.
*/
- String getVoiceMailNumber(String callingPackage);
+ String getVoiceMailNumber(String callingPackage, String callingFeatureId);
/**
* Retrieves the voice mail number of a given subId.
*/
- String getVoiceMailNumberForSubscriber(int subId, String callingPackage);
+ String getVoiceMailNumberForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Retrieves the Carrier information used to encrypt IMSI and IMPI.
*/
ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
- String callingPackage);
+ String callingPackage);
/**
* Stores the Carrier information used to encrypt IMSI and IMPI.
@@ -149,13 +163,14 @@
/**
* Retrieves the alpha identifier associated with the voice mail number.
*/
- String getVoiceMailAlphaTag(String callingPackage);
+ String getVoiceMailAlphaTag(String callingPackage, String callingFeatureId);
/**
* Retrieves the alpha identifier associated with the voice mail number
* of a subId.
*/
- String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage);
+ String getVoiceMailAlphaTagForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 91aa3ce..ac4c8ec 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -573,7 +573,8 @@
*
* @param destAddress the destination address to test for possible short code
*/
- int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso);
+ int checkSmsShortCodeDestination(int subId, String callingApk, String callingFeatureId,
+ String destAddress, String countryIso);
/**
* Gets the SMSC address from (U)SIM.
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index d9d4b60..9865f76 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -18,7 +18,6 @@
import android.app.PendingIntent;
import android.net.Uri;
-import android.os.Bundle;
import java.util.List;
@@ -197,8 +196,8 @@
}
@Override
- public int checkSmsShortCodeDestination(
- int subid, String callingApk, String destAddress, String countryIso) {
+ public int checkSmsShortCodeDestination(int subid, String callingPackage,
+ String callingFeatureId, String destAddress, String countryIso) {
throw new UnsupportedOperationException();
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 7cc37d0d2..151aae8 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -23,47 +23,56 @@
interface ISub {
/**
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return a list of all subscriptions in the database, this includes
* all subscriptions that have been seen.
*/
- List<SubscriptionInfo> getAllSubInfoList(String callingPackage);
+ List<SubscriptionInfo> getAllSubInfoList(String callingPackage, String callingFeatureId);
/**
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return the count of all subscriptions in the database, this includes
* all subscriptions that have been seen.
*/
- int getAllSubInfoCount(String callingPackage);
+ int getAllSubInfoCount(String callingPackage, String callingFeatureId);
/**
* Get the active SubscriptionInfo with the subId key
* @param subId The unique SubscriptionInfo key in database
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Get the active SubscriptionInfo associated with the iccId
* @param iccId the IccId of SIM card
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, maybe null if its not active
*/
- SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage,
+ String callingFeatureId);
/**
* Get the active SubscriptionInfo associated with the slotIndex
* @param slotIndex the slot which the subscription is inserted
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* @return SubscriptionInfo, null for Remote-SIMs or non-active slotIndex.
*/
- SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage);
+ SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage,
+ String callingFeatureId);
/**
* Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
* by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
* @param callingPackage The package maing the call.
+ * @param callingFeatureId The feature in the package
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
@@ -80,13 +89,15 @@
* </li>
* </ul>
*/
- List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage);
+ List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage,
+ String callingFeatureId);
/**
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the number of active subscriptions
*/
- int getActiveSubInfoCount(String callingPackage);
+ int getActiveSubInfoCount(String callingPackage, String callingFeatureId);
/**
* @return the maximum number of subscriptions this device will support at any one time.
@@ -96,7 +107,8 @@
/**
* @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
*/
- List<SubscriptionInfo> getAvailableSubscriptionInfoList(String callingPackage);
+ List<SubscriptionInfo> getAvailableSubscriptionInfoList(String callingPackage,
+ String callingFeatureId);
/**
* @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
@@ -225,7 +237,8 @@
* Return opportunistic subscriptions that can be visible to the caller.
* @return the list of opportunistic subscription info. If none exists, an empty list.
*/
- List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage);
+ List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage,
+ String callingFeatureId);
void removeSubscriptionsFromGroup(in int[] subIdList, in ParcelUuid groupUuid,
String callingPackage);
@@ -233,7 +246,8 @@
void addSubscriptionsIntoGroup(in int[] subIdList, in ParcelUuid groupUuid,
String callingPackage);
- List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage);
+ List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage,
+ String callingFeatureId);
int getSlotIndex(int subId);
@@ -265,7 +279,8 @@
int setSubscriptionProperty(int subId, String propKey, String propValue);
- String getSubscriptionProperty(int subId, String propKey, String callingPackage);
+ String getSubscriptionProperty(int subId, String propKey, String callingPackage,
+ String callingFeatureId);
boolean setSubscriptionEnabled(boolean enable, int subId);
@@ -278,7 +293,7 @@
*/
int getSimStateForSlotIndex(int slotIndex);
- boolean isActiveSubId(int subId, String callingPackage);
+ boolean isActiveSubId(int subId, String callingPackage, String callingFeatureId);
boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 050388c..e96a078 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -89,22 +89,32 @@
@UnsupportedAppUsage
void call(String callingPackage, String number);
+ /** @deprecated Use {@link #isRadioOnWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ boolean isRadioOn(String callingPackage);
+
/**
* Check to see if the radio is on or not.
* @param callingPackage the name of the package making the call.
+ * @param callingFeatureId The feature in the package.
* @return returns true if the radio is on.
*/
+ boolean isRadioOnWithFeature(String callingPackage, String callingFeatureId);
+
+ /**
+ * @deprecated Use {@link #isRadioOnForSubscriberWithFeature(int, String, String) instead
+ */
@UnsupportedAppUsage
- boolean isRadioOn(String callingPackage);
+ boolean isRadioOnForSubscriber(int subId, String callingPackage);
/**
* Check to see if the radio is on or not on particular subId.
* @param subId user preferred subId.
* @param callingPackage the name of the package making the call.
+ * @param callingFeatureId The feature in the package.
* @return returns true if the radio is on.
*/
- @UnsupportedAppUsage
- boolean isRadioOnForSubscriber(int subId, String callingPackage);
+ boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId);
/**
* Supply a pin to unlock the SIM. Blocks until a result is determined.
@@ -302,7 +312,7 @@
* operator's MCC (Mobile Country Code).
* @see android.telephony.TelephonyManager#getNetworkCountryIso
*/
- String getNetworkCountryIsoForPhone(int phoneId, String callingPkg);
+ String getNetworkCountryIsoForPhone(int phoneId, String callingPkg, String callingFeatureId);
/**
* Returns the neighboring cell information of the device.
@@ -371,23 +381,27 @@
/**
* Returns the CDMA ERI icon index to display
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconIndex(String callingPackage);
+ int getCdmaEriIconIndex(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI icon index to display on particular subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage);
+ int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the CDMA ERI icon mode,
* 0 - ON
* 1 - FLASHING
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconMode(String callingPackage);
+ int getCdmaEriIconMode(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI icon mode on particular subId,
@@ -395,21 +409,25 @@
* 1 - FLASHING
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getCdmaEriIconModeForSubscriber(int subId, String callingPackage);
+ int getCdmaEriIconModeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the CDMA ERI text,
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String getCdmaEriText(String callingPackage);
+ String getCdmaEriText(String callingPackage, String callingFeatureId);
/**
* Returns the CDMA ERI text for particular subId,
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String getCdmaEriTextForSubscriber(int subId, String callingPackage);
+ String getCdmaEriTextForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns true if OTA service provisioning needs to run.
@@ -452,7 +470,8 @@
* @param subId user preferred subId.
* Returns the unread count of voicemails
*/
- int getVoiceMessageCountForSubscriber(int subId, String callingPackage);
+ int getVoiceMessageCountForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns true if current state supports both voice and data
@@ -462,7 +481,7 @@
Bundle getVisualVoicemailSettings(String callingPackage, int subId);
- String getVisualVoicemailPackageName(String callingPackage, int subId);
+ String getVisualVoicemailPackageName(String callingPackage, String callingFeatureId, int subId);
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
@@ -494,29 +513,35 @@
* Returns the network type of a subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getNetworkTypeForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns the network type for data transmission
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getDataNetworkType(String callingPackage);
+ int getDataNetworkType(String callingPackage, String callingFeatureId);
/**
* Returns the data network type of a subId
* @param subId user preferred subId.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- int getDataNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getDataNetworkTypeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the voice network type of a subId
* @param subId user preferred subId.
- * @param callingPackage package making the call.
+ * @param callingPackage package making the call.getLteOnCdmaMode
+ * @param callingFeatureId The feature in the package.
* Returns the network type
*/
- int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage);
+ int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Return true if an ICC card is present
@@ -537,10 +562,11 @@
* the mode may be unknown.
*
* @param callingPackage the name of the calling package
+ * @param callingFeatureId The feature in the package.
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaMode(String callingPackage);
+ int getLteOnCdmaMode(String callingPackage, String callingFeatureId);
/**
* Return if the current radio is LTE on CDMA. This
@@ -548,10 +574,11 @@
* the mode may be unknown.
*
* @param callingPackage the name of the calling package
+ * @param callingFeatureId The feature in the package.
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaModeForSubscriber(int subId, String callingPackage);
+ int getLteOnCdmaModeForSubscriber(int subId, String callingPackage, String callingFeatureId);
/**
* Returns all observed cell information of the device.
@@ -800,10 +827,11 @@
* Get the calculated preferred network type.
* Used for device configuration by some CDMA operators.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
*
* @return the calculated preferred network type, defined in RILConstants.java.
*/
- int getCalculatedPreferredNetworkType(String callingPackage);
+ int getCalculatedPreferredNetworkType(String callingPackage, String callingFeatureId);
/*
* Get the preferred network type.
@@ -981,8 +1009,9 @@
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
*/
- String[] getPcscfAddress(String apnType, String callingPackage);
+ String[] getPcscfAddress(String apnType, String callingPackage, String callingFeatureId);
/**
* Set IMS registration state
@@ -1072,9 +1101,10 @@
*
* @param subId whose dialing number for line 1 is returned.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the displayed dialing number if set, or null if not set.
*/
- String getLine1NumberForDisplay(int subId, String callingPackage);
+ String getLine1NumberForDisplay(int subId, String callingPackage, String callingFeatureId);
/**
* Returns the displayed alphatag of the dialing number if it was set
@@ -1082,10 +1112,11 @@
*
* @param subId whose alphatag associated with line 1 is returned.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return the displayed alphatag of the dialing number if set, or null if
* not set.
*/
- String getLine1AlphaTagForDisplay(int subId, String callingPackage);
+ String getLine1AlphaTagForDisplay(int subId, String callingPackage, String callingFeatureId);
/**
* Return the set of subscriber IDs that should be considered "merged together" for data usage
@@ -1097,7 +1128,7 @@
*
* @hide
*/
- String[] getMergedSubscriberIds(int subId, String callingPackage);
+ String[] getMergedSubscriberIds(int subId, String callingPackage, String callingFeatureId);
/**
* @hide
@@ -1196,26 +1227,29 @@
* Whether video calling has been enabled by the user.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the user has enabled video calling, {@code false} otherwise.
*/
- boolean isVideoCallingEnabled(String callingPackage);
+ boolean isVideoCallingEnabled(String callingPackage, String callingFeatureId);
/**
* Whether the DTMF tone length can be changed.
*
* @param subId The subscription to use.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the DTMF tone length can be changed.
*/
- boolean canChangeDtmfToneLength(int subId, String callingPackage);
+ boolean canChangeDtmfToneLength(int subId, String callingPackage, String callingFeatureId);
/**
* Whether the device is a world phone.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@code true} if the devices is a world phone.
*/
- boolean isWorldPhone(int subId, String callingPackage);
+ boolean isWorldPhone(int subId, String callingPackage, String callingFeatureId);
/**
* Whether the phone supports TTY mode.
@@ -1257,26 +1291,31 @@
*/
int getImsRegTechnologyForMmTel(int subId);
+ /** @deprecated Use {@link #getDeviceIdWithFeature(String, String) instead */
+ @UnsupportedAppUsage
+ String getDeviceId(String callingPackage);
+
/**
* Returns the unique device ID of phone, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- @UnsupportedAppUsage
- String getDeviceId(String callingPackage);
+ String getDeviceIdWithFeature(String callingPackage, String callingFeatureId);
/**
* Returns the IMEI for the given slot.
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getImeiForSlot(int slotIndex, String callingPackage);
+ String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId);
/**
* Returns the Type Allocation Code from the IMEI for the given slot.
@@ -1290,10 +1329,11 @@
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getMeidForSlot(int slotIndex, String callingPackage);
+ String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId);
/**
* Returns the Manufacturer Code from the MEID for the given slot.
@@ -1307,10 +1347,12 @@
*
* @param slotIndex - device slot.
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage);
+ String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage,
+ String callingFeatureId);
/**
* Returns the subscription ID associated with the specified PhoneAccount.
@@ -1321,7 +1363,7 @@
* Returns the subscription ID associated with the specified PhoneAccountHandle.
*/
int getSubIdForPhoneAccountHandle(in PhoneAccountHandle phoneAccountHandle,
- String callingPackage);
+ String callingPackage, String callingFeatureId);
/**
* Returns the PhoneAccountHandle associated with a subscription ID.
@@ -1605,10 +1647,12 @@
* Get Client request stats which will contain statistical information
* on each request made by client.
* @param callingPackage package making the call.
+ * @param callingFeatureId The feature in the package.
* @param subId Subscription index
* @hide
*/
- List<ClientRequestStats> getClientRequestStats(String callingPackage, int subid);
+ List<ClientRequestStats> getClientRequestStats(String callingPackage, String callingFeatureId,
+ int subid);
/**
* Set SIM card power state.
@@ -1627,7 +1671,8 @@
* @param subId subscription ID used for authentication
* @param appType the icc application type, like {@link #APPTYPE_USIM}
*/
- String[] getForbiddenPlmns(int subId, int appType, String callingPackage);
+ String[] getForbiddenPlmns(int subId, int appType, String callingPackage,
+ String callingFeatureId);
/**
* Set the forbidden PLMN list from the givven app type (ex APPTYPE_USIM) on a particular
@@ -1636,10 +1681,12 @@
* @param subId subId the id of the subscription
* @param appType appType the uicc app type, must be USIM or SIM.
* @param fplmns plmns the Forbiden plmns list that needed to be written to the SIM.
- * @param content callingPackage the op Package name.
+ * @param callingPackage the op Package name.
+ * @param callingFeatureId the feature in the package.
* @return number of fplmns that is successfully written to the SIM
*/
- int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage);
+ int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage,
+ String callingFeatureId);
/**
* Check if phone is in emergency callback mode
@@ -1783,7 +1830,8 @@
* How many modems can have simultaneous data connections.
* @hide
*/
- int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage);
+ int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Return the network selection mode on the subscription with id {@code subId}.
@@ -1799,7 +1847,7 @@
* Return the modem radio power state for slot index.
*
*/
- int getRadioPowerState(int slotIndex, String callingPackage);
+ int getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId);
// IMS specific AIDL commands, see ImsMmTelManager.java
@@ -1929,7 +1977,7 @@
/**
* Return the emergency number list from all the active subscriptions.
*/
- Map getEmergencyNumberList(String callingPackage);
+ Map getEmergencyNumberList(String callingPackage, String callingFeatureId);
/**
* Identify if the number is emergency number, based on all the active subscriptions.
@@ -2014,12 +2062,13 @@
* Returns if the usage of multiple SIM cards at the same time is supported.
*
* @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
* @return {@link #MULTISIM_ALLOWED} if the device supports multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_HARDWARE} if the device does not support multiple SIMs.
* {@link #MULTISIM_NOT_SUPPORTED_BY_CARRIER} in the device supports multiple SIMs, but the
* functionality is restricted by the carrier.
*/
- int isMultiSimSupported(String callingPackage);
+ int isMultiSimSupported(String callingPackage, String callingFeatureId);
/**
* Switch configs to enable multi-sim or switch back to single-sim
@@ -2031,7 +2080,8 @@
* Get if altering modems configurations will trigger reboot.
* @hide
*/
- boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage);
+ boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Get the mapping from logical slots to physical slots.
@@ -2050,7 +2100,7 @@
*/
boolean isApplicationOnUicc(int subId, int appType);
- boolean isModemEnabledForSlot(int slotIndex, String callingPackage);
+ boolean isModemEnabledForSlot(int slotIndex, String callingPackage, String callingFeatureId);
boolean isDataEnabledForApn(int apnType, int subId, String callingPackage);
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 8a852ee..6e20621 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -95,16 +96,19 @@
* inaccesible to carrier-privileged apps).
*/
public static boolean checkCallingOrSelfReadPhoneState(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
/** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
try {
- return checkCallingOrSelfReadPhoneState(context, subId, callingPackage, message);
+ return checkCallingOrSelfReadPhoneState(context, subId, callingPackage,
+ callingFeatureId, message);
} catch (SecurityException se) {
return false;
}
@@ -132,9 +136,11 @@
* devices.
*/
public static boolean checkReadPhoneState(
- Context context, int subId, int pid, int uid, String callingPackage, String message) {
+ Context context, int subId, int pid, int uid, String callingPackage,
+ @Nullable String callingFeatureId, String message) {
return checkReadPhoneState(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
+ context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingFeatureId,
+ message);
}
/**
@@ -153,7 +159,7 @@
@VisibleForTesting
public static boolean checkReadPhoneState(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -178,8 +184,8 @@
// We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
// revoked.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage)
- == AppOpsManager.MODE_ALLOWED;
+ return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
}
/**
@@ -196,16 +202,16 @@
* @return {@code true} if the app can read phone state or has carrier privilege;
* {@code false} otherwise.
*/
- public static boolean checkReadPhoneStateOnAnyActiveSub(
- Context context, int pid, int uid, String callingPackage, String message) {
+ public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid,
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid,
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
@VisibleForTesting
public static boolean checkReadPhoneStateOnAnyActiveSub(
Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
try {
context.enforcePermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -226,8 +232,8 @@
// We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
// revoked.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage) ==
- AppOpsManager.MODE_ALLOWED;
+ return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_STATE, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
}
/**
@@ -248,9 +254,10 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkCallingOrSelfReadDeviceIdentifiers(context,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message);
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, callingFeatureId,
+ message);
}
/**
@@ -271,9 +278,9 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- context, subId, callingPackage, message, true);
+ context, subId, callingPackage, callingFeatureId, message, true);
}
/**
@@ -293,9 +300,9 @@
* </ul>
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- context, subId, callingPackage, message, false);
+ context, subId, callingPackage, callingFeatureId, message, false);
}
/**
@@ -317,8 +324,8 @@
* </ul>
*/
private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
- Context context, int subId, String callingPackage, String message,
- boolean allowCarrierPrivilegeOnAnySub) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message, boolean allowCarrierPrivilegeOnAnySub) {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
// Allow system and root access to the device identifiers.
@@ -351,7 +358,7 @@
Context.APP_OPS_SERVICE);
try {
if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
- callingPackage) == AppOpsManager.MODE_ALLOWED) {
+ callingPackage, callingFeatureId, null) == AppOpsManager.MODE_ALLOWED) {
return true;
}
} finally {
@@ -444,15 +451,16 @@
* to it, {@code false} otherwise.
*/
public static boolean checkReadCallLog(
- Context context, int subId, int pid, int uid, String callingPackage) {
+ Context context, int subId, int pid, int uid, String callingPackage,
+ @Nullable String callingPackageName) {
return checkReadCallLog(
- context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage);
+ context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingPackageName);
}
@VisibleForTesting
public static boolean checkReadCallLog(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage) {
+ String callingPackage, @Nullable String callingFeatureId) {
if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
!= PERMISSION_GRANTED) {
@@ -468,8 +476,8 @@
// We have READ_CALL_LOG permission, so return true as long as the AppOps bit hasn't been
// revoked.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage) ==
- AppOpsManager.MODE_ALLOWED;
+ return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
}
/**
@@ -479,20 +487,21 @@
* default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
*/
public static boolean checkCallingOrSelfReadPhoneNumber(
- Context context, int subId, String callingPackage, String message) {
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
return checkReadPhoneNumber(
context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
- callingPackage, message);
+ callingPackage, callingFeatureId, message);
}
@VisibleForTesting
public static boolean checkReadPhoneNumber(
Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
- String callingPackage, String message) {
+ String callingPackage, @Nullable String callingFeatureId, String message) {
// Default SMS app can always read it.
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
- if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage) ==
- AppOpsManager.MODE_ALLOWED) {
+ if (appOps.noteOp(AppOpsManager.OPSTR_WRITE_SMS, uid, callingPackage, callingFeatureId,
+ null) == AppOpsManager.MODE_ALLOWED) {
return true;
}
@@ -502,14 +511,15 @@
// First, check if we can read the phone state.
try {
return checkReadPhoneState(
- context, telephonySupplier, subId, pid, uid, callingPackage, message);
+ context, telephonySupplier, subId, pid, uid, callingPackage, callingFeatureId,
+ message);
} catch (SecurityException readPhoneStateSecurityException) {
}
// Can be read with READ_SMS too.
try {
context.enforcePermission(android.Manifest.permission.READ_SMS, pid, uid, message);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_SMS, uid, callingPackage)
- == AppOpsManager.MODE_ALLOWED;
+ return appOps.noteOp(AppOpsManager.OPSTR_READ_SMS, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
} catch (SecurityException readSmsSecurityException) {
}
@@ -517,8 +527,8 @@
try {
context.enforcePermission(android.Manifest.permission.READ_PHONE_NUMBERS, pid, uid,
message);
- return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, uid, callingPackage)
- == AppOpsManager.MODE_ALLOWED;
+ return appOps.noteOp(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, uid, callingPackage,
+ callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
} catch (SecurityException readPhoneNumberSecurityException) {
}
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 9d3e120..85e5916 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -71,8 +71,8 @@
@Override
public int delete(String callingPackage, @Nullable String featureId, Uri url,
- String selection, String[] selectionArgs) throws RemoteException {
- return MockContentProvider.this.delete(url, selection, selectionArgs);
+ Bundle extras) throws RemoteException {
+ return MockContentProvider.this.delete(url, extras);
}
@Override
@@ -82,8 +82,8 @@
@Override
public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues initialValues) throws RemoteException {
- return MockContentProvider.this.insert(url, initialValues);
+ ContentValues initialValues, Bundle extras) throws RemoteException {
+ return MockContentProvider.this.insert(url, initialValues, extras);
}
@Override
@@ -109,9 +109,8 @@
@Override
public int update(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues values, String selection, String[] selectionArgs)
- throws RemoteException {
- return MockContentProvider.this.update(url, values, selection, selectionArgs);
+ ContentValues values, Bundle extras) throws RemoteException {
+ return MockContentProvider.this.update(url, values, extras);
}
@Override
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index e512b52..464abfb 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -51,7 +51,7 @@
@Override
@SuppressWarnings("unused")
public int delete(String callingPackage, @Nullable String featureId, Uri url,
- String selection, String[] selectionArgs) throws RemoteException {
+ Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -63,7 +63,7 @@
@Override
@SuppressWarnings("unused")
public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues initialValues) throws RemoteException {
+ ContentValues initialValues, Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -99,7 +99,7 @@
@Override
public int update(String callingPackage, @Nullable String featureId, Uri url,
- ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
+ ContentValues values, Bundle extras) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 5f62c08..9e5717b 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -208,6 +208,12 @@
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
return super.getSystemService(name);
}
+
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
+ return super.getSystemServiceName(serviceClass);
+ }
}
public class MockIpServerDependencies extends IpServer.Dependencies {
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 1d29a82..4d42a61 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -192,8 +192,8 @@
mService = new NetworkStatsService(
mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock,
- TelephonyManager.getDefault(), mSettings, mStatsFactory,
- new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir));
+ mServiceContext.getSystemService(TelephonyManager.class), mSettings,
+ mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir));
mHandlerThread = new HandlerThread("HandlerThread");
mHandlerThread.start();
Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService);
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index e883c6b..46105f4 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -241,8 +241,6 @@
flags = csv[1:]
if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
flags.append(FLAG_WHITELIST)
- elif FLAG_TEST_API in flags:
- flags.append(FLAG_GREYLIST)
self._dict[csv[0]].update(flags)
def assign_flag(self, flag, apis, source="<unknown>"):
diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py
index 4dc880b..55c3a7d 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists_test.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py
@@ -53,14 +53,22 @@
# Test new additions.
flags.parse_and_merge_csv([
'A,' + FLAG_GREYLIST,
- 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O ])
- self.assertEqual(flags.generate_csv(),
- [ 'A,' + FLAG_GREYLIST,
- 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O ])
+ 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O,
+ 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST,
+ 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API,
+ 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API,
+ ])
+ self.assertEqual(flags.generate_csv(), [
+ 'A,' + FLAG_GREYLIST,
+ 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O,
+ 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST,
+ 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API,
+ 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API,
+ ])
# Test unknown flag.
with self.assertRaises(AssertionError):
- flags.parse_and_merge_csv([ 'C,foo' ])
+ flags.parse_and_merge_csv([ 'Z,foo' ])
def test_assign_flag(self):
flags = FlagsDict()
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 93960de..a61a5af 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2257,6 +2257,8 @@
public static final long WIFI_FEATURE_MBO = 0x800000000L; // MBO Support
/** @hide */
public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support
+ /** @hide */
+ public static final long WIFI_FEATURE_INFRA_6G = 0x2000000000L; // Support 6 GHz band
private long getSupportedFeatures() {
try {
@@ -2271,6 +2273,7 @@
private boolean isFeatureSupported(long feature) {
return (getSupportedFeatures() & feature) == feature;
}
+
/**
* @return true if this adapter supports 5 GHz band
*/
@@ -2279,6 +2282,14 @@
}
/**
+ * @return true if the device supports operating in the 6 GHz band and Wi-Fi is enabled,
+ * false otherwise.
+ */
+ public boolean is6GHzBandSupported() {
+ return isFeatureSupported(WIFI_FEATURE_INFRA_6G);
+ }
+
+ /**
* @return true if this adapter supports Passpoint
* @hide
*/
@@ -3351,7 +3362,7 @@
/**
* Base class for soft AP callback. Should be extended by applications and set when calling
- * {@link WifiManager#registerSoftApCallback(SoftApCallback, Handler)}.
+ * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}.
*
* @hide
*/
@@ -3452,16 +3463,16 @@
* without the permission will trigger a {@link java.lang.SecurityException}.
* <p>
*
- * @param callback Callback for soft AP events
* @param executor The executor to execute the callbacks of the {@code executor}
* object. If null, then the application's main executor will be used.
+ * @param callback Callback for soft AP events
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
- public void registerSoftApCallback(@NonNull SoftApCallback callback,
- @Nullable @CallbackExecutor Executor executor) {
+ public void registerSoftApCallback(@Nullable @CallbackExecutor Executor executor,
+ @NonNull SoftApCallback callback) {
if (callback == null) throw new IllegalArgumentException("callback cannot be null");
Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor);
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 17f3bb2..6305277 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -702,7 +702,7 @@
@Test
public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
try {
- mWifiManager.registerSoftApCallback(null, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), null);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException expected) {
}
@@ -726,7 +726,7 @@
@Test
public void registerSoftApCallbackUsesMainLooperOnNullArgumentForHandler() {
when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
- mWifiManager.registerSoftApCallback(mSoftApCallback, null);
+ mWifiManager.registerSoftApCallback(null, mSoftApCallback);
verify(mContext).getMainExecutor();
}
@@ -735,7 +735,7 @@
*/
@Test
public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class),
any(ISoftApCallback.Stub.class), anyInt());
}
@@ -746,7 +746,7 @@
@Test
public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class);
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class),
any(ISoftApCallback.Stub.class), callbackIdentifier.capture());
@@ -761,7 +761,7 @@
public void softApCallbackProxyCallsOnStateChanged() throws Exception {
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
@@ -777,7 +777,7 @@
public void softApCallbackProxyCallsOnConnectedClientsChanged() throws Exception {
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
@@ -798,7 +798,7 @@
testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
@@ -817,7 +817,7 @@
testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
@@ -843,7 +843,7 @@
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
TestLooper altLooper = new TestLooper();
Handler altHandler = new Handler(altLooper.getLooper());
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(altHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(altHandler), mSoftApCallback);
verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
anyInt());
@@ -857,7 +857,7 @@
*/
@Test
public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception {
- mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler));
+ mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
mLooper.dispatchAll();
verify(mWifiService).registerSoftApCallback(any(IBinder.class),
any(ISoftApCallback.Stub.class), anyInt());
@@ -1586,6 +1586,7 @@
assertTrue(mWifiManager.isP2pSupported());
assertFalse(mWifiManager.isPortableHotspotSupported());
assertFalse(mWifiManager.is5GHzBandSupported());
+ assertFalse(mWifiManager.is6GHzBandSupported());
assertFalse(mWifiManager.isDeviceToDeviceRttSupported());
assertFalse(mWifiManager.isDeviceToApRttSupported());
assertFalse(mWifiManager.isPreferredNetworkOffloadSupported());