summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp48
-rw-r--r--apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java2
-rw-r--r--api/current.txt24
-rw-r--r--api/system-current.txt4
-rw-r--r--config/hiddenapi-greylist.txt1
-rw-r--r--core/java/android/app/ActivityManager.java3
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java10
-rw-r--r--core/java/android/content/pm/PackageInstaller.java9
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java4
-rw-r--r--core/java/android/os/ParcelFileDescriptor.aidl20
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/view/textclassifier/TEST_MAPPING8
-rw-r--r--core/java/android/widget/NumberPicker.java42
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java191
-rw-r--r--core/java/com/android/internal/util/ImageUtils.java62
-rw-r--r--core/proto/android/providers/settings/global.proto3
-rw-r--r--core/res/AndroidManifest.xml8
-rw-r--r--core/res/res/drawable/bottomsheet_background.xml4
-rw-r--r--core/res/res/drawable/ic_file_copy.xml24
-rw-r--r--core/res/res/layout/chooser_grid.xml59
-rw-r--r--core/res/res/values/config.xml18
-rw-r--r--core/res/res/values/strings.xml9
-rw-r--r--core/res/res/values/symbols.xml11
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java82
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java8
-rw-r--r--graphics/java/android/graphics/Typeface.java5
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java171
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java206
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java87
-rw-r--r--packages/SettingsLib/res/drawable/ic_system_update.xml25
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java7
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java38
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java3
-rw-r--r--services/core/java/com/android/server/am/CoreSettingsObserver.java1
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java23
-rw-r--r--services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java4
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java46
-rw-r--r--services/core/java/com/android/server/pm/ShortcutParser.java3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java12
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java28
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java23
-rw-r--r--telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl25
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl7
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp27
-rw-r--r--tools/aapt2/link/ManifestFixer_test.cpp90
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java12
55 files changed, 1111 insertions, 427 deletions
diff --git a/Android.bp b/Android.bp
index 0848d2b7668e..9602941adc1c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -602,6 +602,7 @@ java_defaults {
"telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
+ "telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl",
"telephony/java/com/android/internal/telephony/ISms.aidl",
"telephony/java/com/android/internal/telephony/ISub.aidl",
"telephony/java/com/android/internal/telephony/IOns.aidl",
@@ -741,7 +742,6 @@ java_defaults {
static_libs: [
"apex_aidl_interface-java",
- "networkstack-aidl-interfaces-java",
"framework-protos",
"game-driver-protos",
"mediaplayer2-protos",
@@ -1188,52 +1188,6 @@ packages_to_document = [
"org/apache/http/params",
]
-// The since flag (-since N.xml API_LEVEL) is used to add API Level information
-// to the reference documentation. Must be in order of oldest to newest.
-//
-// Conscrypt (com.android.org.conscrypt) is an implementation detail and should
-// not be referenced in the documentation.
-framework_docs_args = "-android -manifest $(location core/res/AndroidManifest.xml) " +
- "-hidePackage com.android.internal " +
- "-hidePackage com.android.internal.util " +
- "-hidePackage com.android.okhttp " +
- "-hidePackage com.android.org.conscrypt " +
- "-hidePackage com.android.server " +
- "-since $(location 1/public/api/android.xml) 1 " +
- "-since $(location 2/public/api/android.xml) 2 " +
- "-since $(location 3/public/api/android.xml) 3 " +
- "-since $(location 4/public/api/android.xml) 4 " +
- "-since $(location 5/public/api/android.xml) 5 " +
- "-since $(location 6/public/api/android.xml) 6 " +
- "-since $(location 7/public/api/android.xml) 7 " +
- "-since $(location 8/public/api/android.xml) 8 " +
- "-since $(location 9/public/api/android.xml) 9 " +
- "-since $(location 10/public/api/android.xml) 10 " +
- "-since $(location 11/public/api/android.xml) 11 " +
- "-since $(location 12/public/api/android.xml) 12 " +
- "-since $(location 13/public/api/android.xml) 13 " +
- "-since $(location 14/public/api/android.txt) 14 " +
- "-since $(location 15/public/api/android.txt) 15 " +
- "-since $(location 16/public/api/android.txt) 16 " +
- "-since $(location 17/public/api/android.txt) 17 " +
- "-since $(location 18/public/api/android.txt) 18 " +
- "-since $(location 19/public/api/android.txt) 19 " +
- "-since $(location 20/public/api/android.txt) 20 " +
- "-since $(location 21/public/api/android.txt) 21 " +
- "-since $(location 22/public/api/android.txt) 22 " +
- "-since $(location 23/public/api/android.txt) 23 " +
- "-since $(location 24/public/api/android.txt) 24 " +
- "-since $(location 25/public/api/android.txt) 25 " +
- "-since $(location 26/public/api/android.txt) 26 " +
- "-since $(location 27/public/api/android.txt) 27 " +
- "-since $(location 28/public/api/android.txt) 28 " +
- "-since $(location api/current.txt) Q " +
- "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
- "-overview $(location core/java/overview.html) " +
- // Federate Support Library references against local API file.
- "-federate SupportLib https://developer.android.com " +
- "-federationapi SupportLib $(location current/support-api.txt) "
-
framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
"-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
"-overview $(location core/java/overview.html) " +
diff --git a/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java b/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java
index ec46a75bd807..c506aec624d1 100644
--- a/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java
+++ b/apct-tests/perftests/core/src/android/textclassifier/TextClassifierPerfTest.java
@@ -64,7 +64,7 @@ public class TextClassifierPerfTest {
Context context = InstrumentationRegistry.getTargetContext();
TextClassificationManager textClassificationManager =
context.getSystemService(TextClassificationManager.class);
- mTextClassifier = textClassificationManager.getTextClassifier();
+ mTextClassifier = textClassificationManager.getLocalTextClassifier();
}
@Test
diff --git a/api/current.txt b/api/current.txt
index c5cd57378a9d..6f2751d58dbe 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -80,7 +80,6 @@ package android {
field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
field public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
- field public static final String GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY = "android.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY";
field public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field @Deprecated public static final String GET_TASKS = "android.permission.GET_TASKS";
field public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
@@ -131,6 +130,7 @@ package android {
field public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
+ field public static final String REQUEST_SCREEN_LOCK_COMPLEXITY = "android.permission.REQUEST_SCREEN_LOCK_COMPLEXITY";
field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final String SEND_SMS = "android.permission.SEND_SMS";
@@ -6646,7 +6646,7 @@ package android.app.admin {
method @Nullable public CharSequence getOrganizationName(@NonNull android.content.ComponentName);
method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(@NonNull android.content.ComponentName);
method @NonNull public android.app.admin.DevicePolicyManager getParentProfileInstance(@NonNull android.content.ComponentName);
- method @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY) public int getPasswordComplexity();
+ method @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY) public int getPasswordComplexity();
method public long getPasswordExpiration(@Nullable android.content.ComponentName);
method public long getPasswordExpirationTimeout(@Nullable android.content.ComponentName);
method public int getPasswordHistoryLength(@Nullable android.content.ComponentName);
@@ -6840,7 +6840,7 @@ package android.app.admin {
field public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final String EXTRA_DELEGATION_SCOPES = "android.app.extra.DELEGATION_SCOPES";
field public static final String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
- field @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY";
+ field @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY";
field public static final String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
field public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
@@ -11482,7 +11482,6 @@ package android.content.pm {
method public void setOriginatingUri(@Nullable android.net.Uri);
method public void setReferrerUri(@Nullable android.net.Uri);
method public void setSize(long);
- method public void setStaged();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionParams> CREATOR;
field public static final int MODE_FULL_INSTALL = 1; // 0x1
@@ -15409,28 +15408,38 @@ package android.graphics.drawable {
method public float getGradientCenterY();
method public float getGradientRadius();
method public int getGradientType();
+ method public int getInnerRadius();
+ method public float getInnerRadiusRatio();
method public int getOpacity();
method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
method public int getShape();
+ method public int getThickness();
+ method public float getThicknessRatio();
method public boolean getUseLevel();
method public void setAlpha(int);
method public void setColor(@ColorInt int);
method public void setColor(@Nullable android.content.res.ColorStateList);
method public void setColorFilter(@Nullable android.graphics.ColorFilter);
method public void setColors(@ColorInt int[]);
+ method public void setColors(@ColorInt int[], @Nullable float[]);
method public void setCornerRadii(@Nullable float[]);
method public void setCornerRadius(float);
method public void setDither(boolean);
method public void setGradientCenter(float, float);
method public void setGradientRadius(float);
method public void setGradientType(int);
+ method public void setInnerRadius(int);
+ method public void setInnerRadiusRatio(float);
method public void setOrientation(android.graphics.drawable.GradientDrawable.Orientation);
+ method public void setPadding(int, int, int, int);
method public void setShape(int);
method public void setSize(int, int);
method public void setStroke(int, @ColorInt int);
method public void setStroke(int, android.content.res.ColorStateList);
method public void setStroke(int, @ColorInt int, float, float);
method public void setStroke(int, android.content.res.ColorStateList, float, float);
+ method public void setThickness(int);
+ method public void setThicknessRatio(float);
method public void setUseLevel(boolean);
field public static final int LINE = 2; // 0x2
field public static final int LINEAR_GRADIENT = 0; // 0x0
@@ -45233,6 +45242,9 @@ package android.telephony {
field public static final int PHONE_TYPE_GSM = 1; // 0x1
field public static final int PHONE_TYPE_NONE = 0; // 0x0
field public static final int PHONE_TYPE_SIP = 3; // 0x3
+ field public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2; // 0x2
+ field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
+ field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
field public static final int SIM_STATE_ABSENT = 1; // 0x1
field public static final int SIM_STATE_CARD_IO_ERROR = 8; // 0x8
field public static final int SIM_STATE_CARD_RESTRICTED = 9; // 0x9
@@ -56691,6 +56703,8 @@ package android.widget {
method public int getMaxValue();
method public int getMinValue();
method public int getSelectionDividerHeight();
+ method @ColorInt public int getTextColor();
+ method @FloatRange(from=0.0, fromInclusive=false) public float getTextSize();
method public int getValue();
method public boolean getWrapSelectorWheel();
method public void setDisplayedValues(String[]);
@@ -56701,6 +56715,8 @@ package android.widget {
method public void setOnScrollListener(android.widget.NumberPicker.OnScrollListener);
method public void setOnValueChangedListener(android.widget.NumberPicker.OnValueChangeListener);
method public void setSelectionDividerHeight(@IntRange(from=0) @Px int);
+ method public void setTextColor(@ColorInt int);
+ method public void setTextSize(@FloatRange(from=0.0, fromInclusive=false) float);
method public void setValue(int);
method public void setWrapSelectorWheel(boolean);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e0973bfd9e3..bca77b4ea397 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -641,7 +641,7 @@ package android.app.admin {
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
method @Deprecated @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
- method public void setProfileOwnerCanAccessDeviceIdsForUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
+ method @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIdsForUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final String ACTION_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION";
@@ -1535,6 +1535,7 @@ package android.content.pm {
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
}
public class PackageItemInfo {
@@ -7764,6 +7765,7 @@ package android.telephony {
method public void requestEmbeddedSubscriptionInfoListRefresh(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @NonNull java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
field public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 010e4478459d..b72ce8977128 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2439,7 +2439,6 @@ Lcom/android/internal/telephony/cat/CatService;->isStkAppInstalled()Z
Lcom/android/internal/telephony/cat/CatService;->mCmdIf:Lcom/android/internal/telephony/CommandsInterface;
Lcom/android/internal/telephony/cat/CatService;->mContext:Landroid/content/Context;
Lcom/android/internal/telephony/cat/CatService;->mCurrntCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
-Lcom/android/internal/telephony/cat/CatService;->mHandlerThread:Landroid/os/HandlerThread;
Lcom/android/internal/telephony/cat/CatService;->mMenuCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
Lcom/android/internal/telephony/cat/CatService;->mMsgDecoder:Lcom/android/internal/telephony/cat/RilMessageDecoder;
Lcom/android/internal/telephony/cat/CatService;->mSlotId:I
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index db3b720642aa..ca3c72627e3b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2019,8 +2019,9 @@ public class ActivityManager {
return getTaskService().isActivityStartAllowedOnDisplay(displayId, intent,
intent.resolveTypeIfNeeded(context.getContentResolver()), context.getUserId());
} catch (RemoteException e) {
- throw new RuntimeException("Failure from system", e);
+ e.rethrowFromSystemServer();
}
+ return false;
}
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 886115103ccf..2f70c9d24936 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1376,7 +1376,7 @@ public class DevicePolicyManager {
* complexity, and use this activity with extra {@link #EXTRA_PASSWORD_COMPLEXITY} to suggest
* to users how complex the app wants the new screen lock to be. Note that both {@link
* #getPasswordComplexity()} and the extra {@link #EXTRA_PASSWORD_COMPLEXITY} require the
- * calling app to have the permission {@link permission#GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY}.
+ * calling app to have the permission {@link permission#REQUEST_SCREEN_LOCK_COMPLEXITY}.
*
* <p>If the intent is launched from within a managed profile with a profile
* owner built against {@link android.os.Build.VERSION_CODES#M} or before,
@@ -1404,7 +1404,7 @@ public class DevicePolicyManager {
*
* <p>If an invalid value is used, it will be treated as {@link #PASSWORD_COMPLEXITY_NONE}.
*/
- @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY)
+ @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY)
public static final String EXTRA_PASSWORD_COMPLEXITY =
"android.app.extra.PASSWORD_COMPLEXITY";
@@ -3346,10 +3346,10 @@ public class DevicePolicyManager {
*
* @throws IllegalStateException if the user is not unlocked.
* @throws SecurityException if the calling application does not have the permission
- * {@link permission#GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY}
+ * {@link permission#REQUEST_SCREEN_LOCK_COMPLEXITY}
*/
@PasswordComplexity
- @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY)
+ @RequiresPermission(android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY)
public int getPasswordComplexity() {
throwIfParentInstance("getPasswordComplexity");
if (mService == null) {
@@ -10537,6 +10537,8 @@ public class DevicePolicyManager {
* @hide
*/
@SystemApi
+ @RequiresPermission(value = android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS,
+ conditional = true)
public void setProfileOwnerCanAccessDeviceIdsForUser(
@NonNull ComponentName who, @NonNull UserHandle userHandle) {
if (mService == null) {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0ac4f6481fc4..80954731bffb 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -791,11 +791,6 @@ public class PackageInstaller {
* individual session IDs can be added with {@link #addChildSessionId(int)}
* and commit of the multi-package session will result in all child sessions
* being committed atomically.
- * <p>
- * If a package requires to be installed only at reboot, the session should
- * be marked as a staged session by calling {@link SessionParams#setStaged()}
- * with {@code true}. This can also apply to a multi-package session, in
- * which case all the packages in the session will be applied at reboot.
*/
public static class Session implements Closeable {
/** {@hide} */
@@ -1539,7 +1534,11 @@ public class PackageInstaller {
* Staged sessions are scheduled to be installed at next reboot. Staged sessions can also be
* multi-package. In that case, if any of the children sessions fail to install at reboot,
* all the other children sessions are aborted as well.
+ *
+ * {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public void setStaged() {
this.isStaged = true;
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index fe68b8a048c2..b1553250d638 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -2273,7 +2273,8 @@ public final class ShortcutInfo implements Parcelable {
CharSequence disabledMessage, int disabledMessageResId, String disabledMessageResName,
Set<String> categories, Intent[] intentsWithExtras, int rank, PersistableBundle extras,
long lastChangedTimestamp,
- int flags, int iconResId, String iconResName, String bitmapPath, int disabledReason) {
+ int flags, int iconResId, String iconResName, String bitmapPath, int disabledReason,
+ Person[] persons) {
mUserId = userId;
mId = id;
mPackageName = packageName;
@@ -2299,5 +2300,6 @@ public final class ShortcutInfo implements Parcelable {
mIconResName = iconResName;
mBitmapPath = bitmapPath;
mDisabledReason = disabledReason;
+ mPersons = persons;
}
}
diff --git a/core/java/android/os/ParcelFileDescriptor.aidl b/core/java/android/os/ParcelFileDescriptor.aidl
deleted file mode 100644
index c07b98055d5a..000000000000
--- a/core/java/android/os/ParcelFileDescriptor.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/os/ParcelFileDescriptor.aidl
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.os;
-
-parcelable ParcelFileDescriptor cpp_header "binder/ParcelFileDescriptor.h";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 22329baa5109..c4019adb5d85 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12347,6 +12347,12 @@ public final class Settings {
public static final String GAME_DRIVER_BLACKLIST = "game_driver_blacklist";
/**
+ * List of blacklists, each blacklist is a blacklist for a specific version of Game Driver.
+ * @hide
+ */
+ public static final String GAME_DRIVER_BLACKLISTS = "game_driver_blacklists";
+
+ /**
* Apps on the whitelist that are allowed to use Game Driver.
* The string is a list of application package names, seperated by comma.
* i.e. <apk1>,<apk2>,...,<apkN>
diff --git a/core/java/android/view/textclassifier/TEST_MAPPING b/core/java/android/view/textclassifier/TEST_MAPPING
index 0d3c3465f2d6..01a6edecf21e 100644
--- a/core/java/android/view/textclassifier/TEST_MAPPING
+++ b/core/java/android/view/textclassifier/TEST_MAPPING
@@ -10,14 +10,6 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
- },
- {
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.textclassifier.cts"
- }
- ]
}
]
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 89bb2738b899..dad2669d3de8 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -17,6 +17,8 @@
package android.widget;
import android.annotation.CallSuper;
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.Px;
@@ -340,7 +342,7 @@ public class NumberPicker extends LinearLayout {
/**
* The {@link Paint} for drawing the selector.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final Paint mSelectorWheelPaint;
/**
@@ -1718,6 +1720,44 @@ public class NumberPicker extends LinearLayout {
}
/**
+ * Sets the text color for all the states (normal, selected, focused) to be the given color.
+ *
+ * @param color A color value in the form 0xAARRGGBB.
+ */
+ public void setTextColor(@ColorInt int color) {
+ mSelectorWheelPaint.setColor(color);
+ mInputText.setTextColor(color);
+ invalidate();
+ }
+
+ /**
+ * @return the text color.
+ */
+ @ColorInt
+ public int getTextColor() {
+ return mSelectorWheelPaint.getColor();
+ }
+
+ /**
+ * Sets the text size to the given value. This value must be > 0
+ *
+ * @param size The size in pixel units.
+ */
+ public void setTextSize(@FloatRange(from = 0.0, fromInclusive = false) float size) {
+ mSelectorWheelPaint.setTextSize(size);
+ mInputText.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
+ invalidate();
+ }
+
+ /**
+ * @return the size (in pixels) of the text size in this NumberPicker.
+ */
+ @FloatRange(from = 0.0, fromInclusive = false)
+ public float getTextSize() {
+ return mSelectorWheelPaint.getTextSize();
+ }
+
+ /**
* Makes a measure spec that tries greedily to use the max value.
*
* @param measureSpec The measure spec.
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 119a015cd5ea..8ebcef5133b6 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -46,6 +46,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
+import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -69,6 +70,8 @@ import android.os.ResultReceiver;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
+import android.provider.DocumentsContract;
+import android.provider.OpenableColumns;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
import android.service.chooser.IChooserTargetResult;
@@ -87,7 +90,6 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -373,50 +375,6 @@ public class ChooserActivity extends ResolverActivity {
super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
null, false);
- Button copyButton = findViewById(R.id.copy_button);
- copyButton.setOnClickListener(view -> {
- Intent targetIntent = getTargetIntent();
- if (targetIntent == null) {
- finish();
- } else {
- final String action = targetIntent.getAction();
-
- ClipData clipData = null;
- if (Intent.ACTION_SEND.equals(action)) {
- String extraText = targetIntent.getStringExtra(Intent.EXTRA_TEXT);
- Uri extraStream = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
-
- if (extraText != null) {
- clipData = ClipData.newPlainText(null, extraText);
- } else if (extraStream != null) {
- clipData = ClipData.newUri(getContentResolver(), null, extraStream);
- } else {
- Log.w(TAG, "No data available to copy to clipboard");
- return;
- }
- } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
- final ArrayList<Uri> streams = targetIntent.getParcelableArrayListExtra(
- Intent.EXTRA_STREAM);
- clipData = ClipData.newUri(getContentResolver(), null, streams.get(0));
- for (int i = 1; i < streams.size(); i++) {
- clipData.addItem(getContentResolver(), new ClipData.Item(streams.get(i)));
- }
- } else {
- // expected to only be visible with ACTION_SEND or ACTION_SEND_MULTIPLE
- // so warn about unexpected action
- Log.w(TAG, "Action (" + action + ") not supported for copying to clipboard");
- return;
- }
-
- ClipboardManager clipboardManager = (ClipboardManager) getSystemService(
- Context.CLIPBOARD_SERVICE);
- clipboardManager.setPrimaryClip(clipData);
- Toast.makeText(getApplicationContext(), R.string.copied, Toast.LENGTH_SHORT).show();
-
- finish();
- }
- });
-
mChooserShownTime = System.currentTimeMillis();
final long systemCost = mChooserShownTime - intentReceivedTime;
@@ -474,6 +432,10 @@ public class ChooserActivity extends ResolverActivity {
return;
}
+ if (mChooserListAdapter == null || mChooserListAdapter.getCount() == 0) {
+ return;
+ }
+
int previewType = findPreferredContentPreview(targetIntent, getContentResolver());
getMetricsLogger().write(new LogMaker(MetricsEvent.ACTION_SHARE_WITH_PREVIEW)
@@ -481,6 +443,49 @@ public class ChooserActivity extends ResolverActivity {
displayContentPreview(previewType, targetIntent);
}
+ private void onCopyButtonClicked(View v) {
+ Intent targetIntent = getTargetIntent();
+ if (targetIntent == null) {
+ finish();
+ } else {
+ final String action = targetIntent.getAction();
+
+ ClipData clipData = null;
+ if (Intent.ACTION_SEND.equals(action)) {
+ String extraText = targetIntent.getStringExtra(Intent.EXTRA_TEXT);
+ Uri extraStream = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+
+ if (extraText != null) {
+ clipData = ClipData.newPlainText(null, extraText);
+ } else if (extraStream != null) {
+ clipData = ClipData.newUri(getContentResolver(), null, extraStream);
+ } else {
+ Log.w(TAG, "No data available to copy to clipboard");
+ return;
+ }
+ } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ final ArrayList<Uri> streams = targetIntent.getParcelableArrayListExtra(
+ Intent.EXTRA_STREAM);
+ clipData = ClipData.newUri(getContentResolver(), null, streams.get(0));
+ for (int i = 1; i < streams.size(); i++) {
+ clipData.addItem(getContentResolver(), new ClipData.Item(streams.get(i)));
+ }
+ } else {
+ // expected to only be visible with ACTION_SEND or ACTION_SEND_MULTIPLE
+ // so warn about unexpected action
+ Log.w(TAG, "Action (" + action + ") not supported for copying to clipboard");
+ return;
+ }
+
+ ClipboardManager clipboardManager = (ClipboardManager) getSystemService(
+ Context.CLIPBOARD_SERVICE);
+ clipboardManager.setPrimaryClip(clipData);
+ Toast.makeText(getApplicationContext(), R.string.copied, Toast.LENGTH_SHORT).show();
+
+ finish();
+ }
+ }
+
private void displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent) {
switch (previewType) {
case CONTENT_PREVIEW_TEXT:
@@ -501,6 +506,8 @@ public class ChooserActivity extends ResolverActivity {
ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_text_area);
contentPreviewLayout.setVisibility(View.VISIBLE);
+ findViewById(R.id.copy_button).setOnClickListener(this::onCopyButtonClicked);
+
CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT);
if (sharingText == null) {
findViewById(R.id.content_preview_text_layout).setVisibility(View.GONE);
@@ -510,7 +517,7 @@ public class ChooserActivity extends ResolverActivity {
}
String previewTitle = targetIntent.getStringExtra(Intent.EXTRA_TITLE);
- if (previewTitle == null || previewTitle.trim().isEmpty()) {
+ if (TextUtils.isEmpty(previewTitle)) {
findViewById(R.id.content_preview_title_layout).setVisibility(View.GONE);
} else {
TextView previewTitleView = findViewById(R.id.content_preview_title);
@@ -561,6 +568,7 @@ public class ChooserActivity extends ResolverActivity {
if (imageUris.size() == 0) {
Log.i(TAG, "Attempted to display image preview area with zero"
+ " available images detected in EXTRA_STREAM list");
+ contentPreviewLayout.setVisibility(View.GONE);
return;
}
@@ -580,15 +588,95 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ private static class FileInfo {
+ public final String name;
+ public final boolean hasThumbnail;
+
+ FileInfo(String name, boolean hasThumbnail) {
+ this.name = name;
+ this.hasThumbnail = hasThumbnail;
+ }
+ }
+
+ private FileInfo extractFileInfo(Uri uri, ContentResolver resolver) {
+ String fileName = null;
+ boolean hasThumbnail = false;
+ Cursor cursor = resolver.query(uri, null, null, null, null);
+ if (cursor != null && cursor.getCount() > 0) {
+ int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int flagsIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS);
+
+ cursor.moveToFirst();
+ fileName = cursor.getString(nameIndex);
+ if (flagsIndex != -1) {
+ hasThumbnail = (cursor.getInt(flagsIndex)
+ & DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
+ }
+ }
+
+ if (TextUtils.isEmpty(fileName)) {
+ fileName = uri.getPath();
+ int index = fileName.lastIndexOf('/');
+ if (index != -1) {
+ fileName = fileName.substring(index + 1);
+ }
+ }
+
+ return new FileInfo(fileName, hasThumbnail);
+ }
+
private void displayFileContentPreview(Intent targetIntent) {
- // support coming
+ ViewGroup contentPreviewLayout = findViewById(R.id.content_preview_file_area);
+ contentPreviewLayout.setVisibility(View.VISIBLE);
+
+ // TODO(b/120417119): Disable file copy until after moving to sysui,
+ // due to permissions issues
+ findViewById(R.id.file_copy_button).setVisibility(View.GONE);
+
+ ContentResolver resolver = getContentResolver();
+ TextView fileNameView = findViewById(R.id.content_preview_filename);
+ String action = targetIntent.getAction();
+ if (Intent.ACTION_SEND.equals(action)) {
+ Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+
+ FileInfo fileInfo = extractFileInfo(uri, resolver);
+ fileNameView.setText(fileInfo.name);
+
+ if (fileInfo.hasThumbnail) {
+ loadUriIntoView(R.id.content_preview_file_thumbnail, uri);
+ } else {
+ ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
+ fileIconView.setVisibility(View.VISIBLE);
+ fileIconView.setImageResource(R.drawable.ic_doc_generic);
+ }
+ } else {
+ List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+ if (uris.size() == 0) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ Log.i(TAG,
+ "Appears to be no uris available in EXTRA_STREAM, removing preview area");
+ return;
+ }
+
+ FileInfo fileInfo = extractFileInfo(uris.get(0), resolver);
+ int remFileCount = uris.size() - 1;
+ String fileName = getResources().getQuantityString(R.plurals.file_count,
+ remFileCount, fileInfo.name, remFileCount);
+
+ fileNameView.setText(fileName);
+ ImageView fileIconView = findViewById(R.id.content_preview_file_icon);
+ fileIconView.setVisibility(View.VISIBLE);
+ fileIconView.setImageResource(R.drawable.ic_file_copy);
+ }
}
private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri) {
RoundedRectImageView imageView = findViewById(imageResourceId);
- imageView.setVisibility(View.VISIBLE);
Bitmap bmp = loadThumbnail(uri, new Size(200, 200));
- imageView.setImageBitmap(bmp);
+ if (bmp != null) {
+ imageView.setVisibility(View.VISIBLE);
+ imageView.setImageBitmap(bmp);
+ }
return imageView;
}
@@ -1261,9 +1349,8 @@ public class ChooserActivity extends ResolverActivity {
}
try {
- return ImageUtils.decodeSampledBitmapFromStream(getContentResolver(),
- uri, size.getWidth(), size.getHeight());
- } catch (IOException | NullPointerException ex) {
+ return ImageUtils.loadThumbnail(getContentResolver(), uri, size);
+ } catch (IOException | NullPointerException | SecurityException ex) {
Log.w(TAG, "Error loading preview thumbnail for uri: " + uri.toString(), ex);
}
return null;
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index 195ae52ce977..274a5136d8e9 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -16,20 +16,25 @@
package com.android.internal.util;
+import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.ImageDecoder;
+import android.graphics.ImageDecoder.ImageInfo;
+import android.graphics.ImageDecoder.Source;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
+import android.util.Size;
import java.io.IOException;
-import java.io.InputStream;
/**
* Utility class for image analysis and processing.
@@ -166,21 +171,18 @@ public class ImageUtils {
/**
* @see https://developer.android.com/topic/performance/graphics/load-bitmap
*/
- public static int calculateInSampleSize(BitmapFactory.Options options,
- int reqWidth, int reqHeight) {
- // Raw height and width of image
- final int height = options.outHeight;
- final int width = options.outWidth;
+ public static int calculateSampleSize(Size currentSize, Size requestedSize) {
int inSampleSize = 1;
- if (height > reqHeight || width > reqWidth) {
- final int halfHeight = height / 2;
- final int halfWidth = width / 2;
+ if (currentSize.getHeight() > requestedSize.getHeight()
+ || currentSize.getWidth() > requestedSize.getWidth()) {
+ final int halfHeight = currentSize.getHeight() / 2;
+ final int halfWidth = currentSize.getWidth() / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
- while ((halfHeight / inSampleSize) >= reqHeight
- && (halfWidth / inSampleSize) >= reqWidth) {
+ while ((halfHeight / inSampleSize) >= requestedSize.getHeight()
+ && (halfWidth / inSampleSize) >= requestedSize.getWidth()) {
inSampleSize *= 2;
}
}
@@ -190,27 +192,27 @@ public class ImageUtils {
/**
* Load a bitmap, and attempt to downscale to the required size, to save
- * on memory.
+ * on memory. Updated to use newer and more compatible ImageDecoder.
*
* @see https://developer.android.com/topic/performance/graphics/load-bitmap
*/
- public static Bitmap decodeSampledBitmapFromStream(ContentResolver resolver,
- Uri uri, int reqWidth, int reqHeight) throws IOException {
-
- final BitmapFactory.Options options = new BitmapFactory.Options();
- try (InputStream is = resolver.openInputStream(uri)) {
- // First decode with inJustDecodeBounds=true to check dimensions
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(is, null, options);
-
- options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
- }
-
- // need to do this twice as the InputStream is consumed in the first call,
- // and not all InputStreams support marks
- try (InputStream is = resolver.openInputStream(uri)) {
- options.inJustDecodeBounds = false;
- return BitmapFactory.decodeStream(is, null, options);
+ public static Bitmap loadThumbnail(ContentResolver resolver, Uri uri, Size size)
+ throws IOException {
+
+ try (ContentProviderClient client = resolver.acquireContentProviderClient(uri)) {
+ final Bundle opts = new Bundle();
+ opts.putParcelable(ContentResolver.EXTRA_SIZE, Point.convert(size));
+
+ return ImageDecoder.decodeBitmap(ImageDecoder.createSource(() -> {
+ return client.openTypedAssetFile(uri, "image/*", opts, null);
+ }), (ImageDecoder decoder, ImageInfo info, Source source) -> {
+ decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
+
+ final int sample = calculateSampleSize(info.getSize(), size);
+ if (sample > 1) {
+ decoder.setTargetSampleSize(sample);
+ }
+ });
}
}
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index d5776534bb90..39d61a15eb28 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -448,6 +448,9 @@ message GlobalSettingsProto {
optional SettingProto game_driver_whitelist = 12;
// ANGLE - List of Apps that can check ANGLE rules
optional SettingProto angle_whitelist = 13;
+ // Game Driver - List of blacklists, each blacklist is a blacklist for
+ // a specific Game Driver version
+ optional SettingProto game_driver_blacklists = 14;
}
optional Gpu gpu = 59;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 34ec92e68511..5b74d90608f7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2151,13 +2151,13 @@
android:label="@string/permlab_disableKeyguard"
android:protectionLevel="normal" />
- <!-- Allows an application to get the screen lock complexity and prompt users to update the
+ <!-- Allows an application to request the screen lock complexity and prompt users to update the
screen lock to a certain complexity level.
<p>Protection level: normal
-->
- <permission android:name="android.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY"
- android:label="@string/permlab_getAndRequestScreenLockComplexity"
- android:description="@string/permdesc_getAndRequestScreenLockComplexity"
+ <permission android:name="android.permission.REQUEST_SCREEN_LOCK_COMPLEXITY"
+ android:label="@string/permlab_requestScreenLockComplexity"
+ android:description="@string/permdesc_requestScreenLockComplexity"
android:protectionLevel="normal" />
<!-- ================================== -->
diff --git a/core/res/res/drawable/bottomsheet_background.xml b/core/res/res/drawable/bottomsheet_background.xml
index bc32ba6e3896..3a8ad71187a0 100644
--- a/core/res/res/drawable/bottomsheet_background.xml
+++ b/core/res/res/drawable/bottomsheet_background.xml
@@ -16,7 +16,7 @@
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<corners
- android:topLeftRadius="?attr/dialogCornerRadius"
- android:topRightRadius="?attr/dialogCornerRadius" />
+ android:topLeftRadius="@dimen/config_bottomDialogCornerRadius"
+ android:topRightRadius="@dimen/config_bottomDialogCornerRadius"/>
<solid android:color="?attr/colorBackgroundFloating" />
</shape>
diff --git a/core/res/res/drawable/ic_file_copy.xml b/core/res/res/drawable/ic_file_copy.xml
new file mode 100644
index 000000000000..b6d5e7328c40
--- /dev/null
+++ b/core/res/res/drawable/ic_file_copy.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM15,5l6,6v10c0,1.1 -0.9,2 -2,2L7.99,23C6.89,23 6,22.1 6,21l0.01,-14c0,-1.1 0.89,-2 1.99,-2h7zM14,12h5.5L14,6.5L14,12z"
+ android:fillColor="#FF737373"/>
+</vector>
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 14a5310a4ff2..3683bfd02e87 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -213,6 +213,65 @@
</LinearLayout>
</LinearLayout>
+ <!-- Layout Option 3: File preview, icon, filename, copy-->
+ <LinearLayout
+ android:id="@+id/content_preview_file_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/chooser_view_spacing"
+ android:visibility="gone"
+ android:background="?attr/colorBackgroundFloating">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="@dimen/chooser_edge_margin_normal"
+ android:paddingRight="@dimen/chooser_edge_margin_normal"
+ android:layout_marginBottom="@dimen/chooser_view_spacing"
+ android:id="@+id/content_preview_file_layout">
+
+ <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+ android:id="@+id/content_preview_file_thumbnail"
+ android:layout_width="75dp"
+ android:layout_height="75dp"
+ android:layout_marginRight="16dp"
+ android:adjustViewBounds="true"
+ android:layout_gravity="center_vertical"
+ android:gravity="center"
+ android:scaleType="centerCrop"
+ android:visibility="gone"/>
+ <ImageView
+ android:id="@+id/content_preview_file_icon"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_marginRight="16dp"
+ android:adjustViewBounds="true"
+ android:layout_gravity="center_vertical"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/content_preview_filename"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:ellipsize="middle"
+ android:gravity="start|top"
+ android:paddingRight="24dp"
+ android:singleLine="true"/>
+ <Button
+ android:id="@+id/file_copy_button"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:gravity="center"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/ic_content_copy_gm2"/>
+ </LinearLayout>
+ </LinearLayout>
+
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 18eb7e96d748..d14164f69850 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3903,4 +3903,22 @@
The ambient color temperature (in cct) to which we fall back when the ambient brightness
drops beneath a certain threshold. -->
<item name="config_displayWhiteBalanceLowLightAmbientColorTemperature" format="float" type="dimen">6500.0</item>
+
+ <!-- See DisplayWhiteBalanceController.
+ A float array containing a list of ambient color temperatures, in Kelvin. This array,
+ together with config_displayWhiteBalanceDisplayTemperatureValues, is used to generate a
+ lookup table used in DisplayWhiteBalanceController. This lookup table is used to map
+ ambient color temperature readings to a target color temperature for the display.
+ This table is optional. If used, this array must,
+ 1) Contain at least two entries
+ 2) Be the same length as config_displayWhiteBalanceDisplayTemperatureValues. -->
+ <array name="config_displayWhiteBalanceAmbientTemperatureValues">
+ </array>
+
+ <!-- See DisplayWhiteBalanceController.
+ An array containing a list of display color temperatures, in Kelvin. See
+ config_displayWhiteBalanceAmbientTemperatureValues for additional details.
+ The same restrictions apply to this array. -->
+ <array name="config_displayWhiteBalanceDisplayTemperatureValues">
+ </array>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6d5bd4ba1645..0cdf38849d8b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1406,9 +1406,9 @@
re-enables the keylock when the call is finished.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
- <string name="permlab_getAndRequestScreenLockComplexity">get and request screen lock complexity</string>
+ <string name="permlab_requestScreenLockComplexity">request screen lock complexity</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
- <string name="permdesc_getAndRequestScreenLockComplexity">Allows the app to learn the screen
+ <string name="permdesc_requestScreenLockComplexity">Allows the app to learn the screen
lock complexity level (high, medium, low or none), which indicates the possible range of
length and type of the screen lock. The app can also suggest to users that they update the
screen lock to a certain level but users can freely ignore and navigate away. Note that the
@@ -5284,4 +5284,9 @@
<!-- Strings for car -->
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
<string name="car_loading_profile">Loading</string>
+
+ <plurals name="file_count">
+ <item quantity="one"><xliff:g id="file_name">%s</xliff:g> + <xliff:g id="count">%d</xliff:g> file</item>
+ <item quantity="other"><xliff:g id="file_name">%s</xliff:g> + <xliff:g id="count">%d</xliff:g> files</item>
+ </plurals>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8e251fd4ea6f..a1bafbf8de69 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -50,6 +50,11 @@
<java-symbol type="id" name="characterPicker" />
<java-symbol type="id" name="clearDefaultHint" />
<java-symbol type="id" name="contentPanel" />
+ <java-symbol type="id" name="content_preview_file_area" />
+ <java-symbol type="id" name="content_preview_file_icon" />
+ <java-symbol type="id" name="content_preview_file_layout" />
+ <java-symbol type="id" name="content_preview_file_thumbnail" />
+ <java-symbol type="id" name="content_preview_filename" />
<java-symbol type="id" name="content_preview_image_area" />
<java-symbol type="id" name="content_preview_image_1_large" />
<java-symbol type="id" name="content_preview_image_2_large" />
@@ -62,6 +67,7 @@
<java-symbol type="id" name="content_preview_title" />
<java-symbol type="id" name="content_preview_title_layout" />
<java-symbol type="id" name="copy_button" />
+ <java-symbol type="id" name="file_copy_button" />
<java-symbol type="id" name="current_scene" />
<java-symbol type="id" name="scene_layoutid_cache" />
<java-symbol type="id" name="customPanel" />
@@ -1266,6 +1272,7 @@
<java-symbol type="string" name="tooltip_popup_title" />
<java-symbol type="plurals" name="bugreport_countdown" />
+ <java-symbol type="plurals" name="file_count" />
<java-symbol type="plurals" name="last_num_days" />
<java-symbol type="plurals" name="matches_found" />
<java-symbol type="plurals" name="restr_pin_countdown" />
@@ -1307,6 +1314,7 @@
<java-symbol type="drawable" name="default_wallpaper" />
<java-symbol type="drawable" name="default_lock_wallpaper" />
<java-symbol type="drawable" name="indicator_input_error" />
+ <java-symbol type="drawable" name="ic_file_copy" />
<java-symbol type="drawable" name="popup_bottom_dark" />
<java-symbol type="drawable" name="popup_bottom_bright" />
<java-symbol type="drawable" name="popup_bottom_medium" />
@@ -3643,6 +3651,7 @@
<java-symbol type="array" name="config_displayWhiteBalanceDecreaseThresholds" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientBrightnessThreshold" />
<java-symbol type="dimen" name="config_displayWhiteBalanceLowLightAmbientColorTemperature" />
-
+ <java-symbol type="array" name="config_displayWhiteBalanceAmbientTemperatureValues" />
+ <java-symbol type="array" name="config_displayWhiteBalanceDisplayTemperatureValues" />
<java-symbol type="drawable" name="ic_action_open" />
</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 206682a1955b..b919553dd85d 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -491,6 +491,7 @@ public class SettingsBackupTest {
Settings.Global.GAME_DRIVER_ALL_APPS,
Settings.Global.GAME_DRIVER_OPT_IN_APPS,
Settings.Global.GAME_DRIVER_OPT_OUT_APPS,
+ Settings.Global.GAME_DRIVER_BLACKLISTS,
Settings.Global.GAME_DRIVER_BLACKLIST,
Settings.Global.GAME_DRIVER_WHITELIST,
Settings.Global.GPU_DEBUG_LAYER_APP,
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 3d59835a6719..7f104b1b0a14 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -409,8 +409,7 @@ public class ChooserActivityTest {
@Test
public void copyTextToClipboard() throws Exception {
Intent sendIntent = createSendTextIntent();
- List<ResolvedComponentInfo> resolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(1);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
Mockito.anyBoolean(),
@@ -421,6 +420,7 @@ public class ChooserActivityTest {
.launchActivity(Intent.createChooser(sendIntent, null));
waitForIdle();
+ onView(withId(R.id.copy_button)).check(matches(isDisplayed()));
onView(withId(R.id.copy_button)).perform(click());
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(
Context.CLIPBOARD_SERVICE);
@@ -439,8 +439,9 @@ public class ChooserActivityTest {
ArrayList<Uri> uris = new ArrayList<>();
uris.add(uri);
- Intent sendIntent = createSendImageIntentWithPreview(uris);
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
sOverrides.previewThumbnail = createBitmap();
+ sOverrides.isImageType = true;
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -464,8 +465,9 @@ public class ChooserActivityTest {
uris.add(uri);
uris.add(uri);
- Intent sendIntent = createSendImageIntentWithPreview(uris);
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
sOverrides.previewThumbnail = createBitmap();
+ sOverrides.isImageType = true;
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -492,8 +494,9 @@ public class ChooserActivityTest {
uris.add(uri);
uris.add(uri);
- Intent sendIntent = createSendImageIntentWithPreview(uris);
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
sOverrides.previewThumbnail = createBitmap();
+ sOverrides.isImageType = true;
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -538,12 +541,11 @@ public class ChooserActivityTest {
ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
waitForIdle();
- verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
+
+ verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
// First invocation is from onCreate
- assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
- assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
- is(CONTENT_PREVIEW_TEXT));
+ assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
+ is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
}
@Test
@@ -552,9 +554,17 @@ public class ChooserActivityTest {
MetricsLogger mockLogger = sOverrides.metricsLogger;
ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
waitForIdle();
- verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
+ verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
@@ -570,8 +580,9 @@ public class ChooserActivityTest {
ArrayList<Uri> uris = new ArrayList<>();
uris.add(uri);
- Intent sendIntent = createSendImageIntentWithPreview(uris);
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
sOverrides.previewThumbnail = createBitmap();
+ sOverrides.isImageType = true;
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -595,6 +606,51 @@ public class ChooserActivityTest {
is(CONTENT_PREVIEW_IMAGE));
}
+ @Test
+ public void oneVisibleFilePreview() throws InterruptedException {
+ Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
+
+ ArrayList<Uri> uris = new ArrayList<>();
+ uris.add(uri);
+
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
+ onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
+ onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
+ }
+
+
+ @Test
+ public void moreThanOneVisibleFilePreview() throws InterruptedException {
+ Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
+
+ ArrayList<Uri> uris = new ArrayList<>();
+ uris.add(uri);
+ uris.add(uri);
+ uris.add(uri);
+
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
+ onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 2 files")));
+ onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
+ }
+
private Intent createSendTextIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -615,7 +671,7 @@ public class ChooserActivityTest {
return sendIntent;
}
- private Intent createSendImageIntentWithPreview(ArrayList<Uri> uris) {
+ private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
Intent sendIntent = new Intent();
if (uris.size() > 1) {
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index f60467bd3df2..096b78b95fbd 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -89,11 +89,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
@Override
protected boolean isImageType(String mimeType) {
- if (sOverrides.previewThumbnail != null) {
- return true;
- }
-
- return super.isImageType(mimeType);
+ return sOverrides.isImageType;
}
@Override
@@ -112,6 +108,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
public Function<TargetInfo, Boolean> onSafelyStartCallback;
public ResolverListController resolverListController;
public Boolean isVoiceInteraction;
+ public boolean isImageType;
public Bitmap previewThumbnail;
public MetricsLogger metricsLogger;
@@ -120,6 +117,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
isVoiceInteraction = null;
createPackageManager = null;
previewThumbnail = null;
+ isImageType = false;
resolverListController = mock(ResolverListController.class);
metricsLogger = mock(MetricsLogger.class);
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 56be05b51d1a..ef9255f66695 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -127,7 +127,10 @@ public class Typeface {
static Typeface sDefaultTypeface;
// Following two fields are not used but left for hiddenapi private list
- @UnsupportedAppUsage
+ /**
+ * Use {@link SystemFonts#getAvailableFonts()} instead.
+ */
+ @UnsupportedAppUsage(trackingBug = 123769347)
static final Map<String, Typeface> sSystemFontMap;
// We cannot support sSystemFallbackMap since we will migrate to public FontFamily API.
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 991847ad27fa..6ecb62140532 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -44,6 +44,7 @@ import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.Xfermode;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -156,12 +157,12 @@ public class GradientDrawable extends Drawable {
private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
private GradientState mGradientState;
@UnsupportedAppUsage
private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051827)
private Rect mPadding;
@UnsupportedAppUsage
private Paint mStrokePaint; // optional, set by the caller
@@ -670,7 +671,28 @@ public class GradientDrawable extends Drawable {
* @see #setColor(int)
*/
public void setColors(@ColorInt int[] colors) {
+ setColors(colors, null);
+ }
+
+ /**
+ * Sets the colors and offsets used to draw the gradient.
+ * <p>
+ * Each color is specified as an ARGB integer and the array must contain at
+ * least 2 colors.
+ * <p>
+ * <strong>Note</strong>: changing colors will affect all instances of a
+ * drawable loaded from a resource. It is recommended to invoke
+ * {@link #mutate()} before changing the colors.
+ *
+ * @param colors an array containing 2 or more ARGB colors
+ * @param offsets optional array of floating point parameters representing the positions
+ * of the colors. Null evenly disperses the colors
+ * @see #mutate()
+ * @see #setColors(int[])
+ */
+ public void setColors(@ColorInt int[] colors, @Nullable float[] offsets) {
mGradientState.setGradientColors(colors);
+ mGradientState.mPositions = offsets;
mGradientIsDirty = true;
invalidateSelf();
}
@@ -849,6 +871,115 @@ public class GradientDrawable extends Drawable {
}
}
+ /**
+ * Inner radius of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #getInnerRadiusRatio()
+ * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ */
+ public void setInnerRadiusRatio(float innerRadiusRatio) {
+ mGradientState.mInnerRadiusRatio = innerRadiusRatio;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the inner radius of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #setInnerRadiusRatio(float)
+ * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ */
+ public float getInnerRadiusRatio() {
+ return mGradientState.mInnerRadiusRatio;
+ }
+
+ /**
+ * Configure the inner radius of the ring.
+ *
+ * @see #getInnerRadius()
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
+ */
+ public void setInnerRadius(int innerRadius) {
+ mGradientState.mInnerRadius = innerRadius;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Retrn the inner radius of the ring
+ *
+ * @see #setInnerRadius(int)
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
+ */
+ public int getInnerRadius() {
+ return mGradientState.mInnerRadius;
+ }
+
+ /**
+ * Configure the thickness of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #getThicknessRatio()
+ * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ */
+ public void setThicknessRatio(float thicknessRatio) {
+ mGradientState.mThicknessRatio = thicknessRatio;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the thickness ratio of the ring expressed as a ratio of the ring's width.
+ *
+ * @see #setThicknessRatio(float)
+ * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ */
+ public float getThicknessRatio() {
+ return mGradientState.mThicknessRatio;
+ }
+
+ /**
+ * Configure the thickness of the ring.
+ *
+ * @attr ref android.R.styleable#GradientDrawable_thickness
+ */
+ public void setThickness(int thickness) {
+ mGradientState.mThickness = thickness;
+ mPathIsDirty = true;
+ invalidateSelf();
+ }
+
+ /**
+ * Return the thickness of the ring
+ *
+ * @see #setThickness(int)
+ * @attr ref android.R.styleable#GradientDrawable_thickness
+ */
+ public int getThickness() {
+ return mGradientState.mThickness;
+ }
+
+ /**
+ * Configure the padding of the gradient shape
+ * @param left Left padding of the gradient shape
+ * @param top Top padding of the gradient shape
+ * @param right Right padding of the gradient shape
+ * @param bottom Bottom padding of the gradient shape
+ *
+ * @attr ref android.R.styleable#GradientDrawablePadding_left
+ * @attr ref android.R.styleable#GradientDrawablePadding_top
+ * @attr ref android.R.styleable#GradientDrawablePadding_right
+ * @attr ref android.R.styleable#GradientDrawablePadding_bottom
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ if (mGradientState.mPadding == null) {
+ mGradientState.mPadding = new Rect();
+ }
+
+ mGradientState.mPadding.set(left, top, right, bottom);
+ mPadding = mGradientState.mPadding;
+ invalidateSelf();
+ }
+
private Path buildRing(GradientState st) {
if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
mPathIsDirty = false;
@@ -1814,46 +1945,46 @@ public class GradientDrawable extends Drawable {
final static class GradientState extends ConstantState {
public @Config int mChangingConfigurations;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @Shape int mShape = RECTANGLE;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @GradientType int mGradient = LINEAR_GRADIENT;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mAngle = 0;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public Orientation mOrientation;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public ColorStateList mSolidColors;
public ColorStateList mStrokeColors;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public @ColorInt int[] mGradientColors;
public @ColorInt int[] mTempColors; // no need to copy
public float[] mTempPositions; // no need to copy
@UnsupportedAppUsage
public float[] mPositions;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mStrokeWidth = -1; // if >= 0 use stroking.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mStrokeDashWidth = 0.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mStrokeDashGap = 0.0f;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mRadius = 0.0f; // use this if mRadiusArray is null
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float[] mRadiusArray = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public Rect mPadding = null;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mWidth = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mHeight = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public int mInnerRadius = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050218)
public int mThickness = -1;
public boolean mDither = false;
public Insets mOpticalInsets = Insets.NONE;
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index f372fe55dfb0..24fa87a7f39b 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -15,11 +15,10 @@
*/
package android.ext.services.notification;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.app.RemoteAction;
+import android.app.RemoteInput;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Bundle;
@@ -27,7 +26,9 @@ import android.os.Parcelable;
import android.os.Process;
import android.service.notification.NotificationAssistantService;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.LruCache;
+import android.util.Pair;
import android.view.textclassifier.ConversationAction;
import android.view.textclassifier.ConversationActions;
import android.view.textclassifier.TextClassificationContext;
@@ -35,6 +36,8 @@ import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextClassifierEvent;
+import com.android.internal.util.ArrayUtils;
+
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
@@ -43,11 +46,13 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class SmartActionsHelper {
private static final String KEY_ACTION_TYPE = "action_type";
+ private static final String KEY_ACTION_SCORE = "action_score";
// If a notification has any of these flags set, it's inelgibile for actions being added.
private static final int FLAG_MASK_INELGIBILE_FOR_ACTIONS =
Notification.FLAG_ONGOING_EVENT
@@ -58,75 +63,136 @@ public class SmartActionsHelper {
private static final List<String> HINTS =
Collections.singletonList(ConversationActions.Request.HINT_FOR_NOTIFICATION);
+ private static final ConversationActions EMPTY_CONVERSATION_ACTIONS =
+ new ConversationActions(Collections.emptyList(), null);
private Context mContext;
- @Nullable
private TextClassifier mTextClassifier;
- @NonNull
private AssistantSettings mSettings;
- private LruCache<String, String> mNotificationKeyToResultIdCache =
- new LruCache<>(MAX_RESULT_ID_TO_CACHE);
+ private LruCache<String, Session> mSessionCache = new LruCache<>(MAX_RESULT_ID_TO_CACHE);
SmartActionsHelper(Context context, AssistantSettings settings) {
mContext = context;
TextClassificationManager textClassificationManager =
mContext.getSystemService(TextClassificationManager.class);
- if (textClassificationManager != null) {
- mTextClassifier = textClassificationManager.getTextClassifier();
- }
+ mTextClassifier = textClassificationManager.getTextClassifier();
mSettings = settings;
}
- SmartSuggestions suggest(@NonNull NotificationEntry entry) {
+ SmartSuggestions suggest(NotificationEntry entry) {
// Whenever suggest() is called on a notification, its previous session is ended.
- mNotificationKeyToResultIdCache.remove(entry.getSbn().getKey());
+ mSessionCache.remove(entry.getSbn().getKey());
boolean eligibleForReplyAdjustment =
mSettings.mGenerateReplies && isEligibleForReplyAdjustment(entry);
boolean eligibleForActionAdjustment =
mSettings.mGenerateActions && isEligibleForActionAdjustment(entry);
- List<ConversationAction> conversationActions =
+ ConversationActions conversationActionsResult =
suggestConversationActions(
entry,
eligibleForReplyAdjustment,
eligibleForActionAdjustment);
- ArrayList<CharSequence> replies = conversationActions.stream()
- .map(ConversationAction::getTextReply)
- .filter(textReply -> !TextUtils.isEmpty(textReply))
- .collect(Collectors.toCollection(ArrayList::new));
+ String resultId = conversationActionsResult.getId();
+ List<ConversationAction> conversationActions =
+ conversationActionsResult.getConversationActions();
+
+ ArrayList<CharSequence> replies = new ArrayList<>();
+ Map<CharSequence, Float> repliesScore = new ArrayMap<>();
+ for (ConversationAction conversationAction : conversationActions) {
+ CharSequence textReply = conversationAction.getTextReply();
+ if (TextUtils.isEmpty(textReply)) {
+ continue;
+ }
+ replies.add(textReply);
+ repliesScore.put(textReply, conversationAction.getConfidenceScore());
+ }
ArrayList<Notification.Action> actions = conversationActions.stream()
.filter(conversationAction -> conversationAction.getAction() != null)
- .map(action -> createNotificationAction(action.getAction(), action.getType()))
+ .map(action -> createNotificationAction(
+ action.getAction(), action.getType(), action.getConfidenceScore()))
.collect(Collectors.toCollection(ArrayList::new));
+
+ // Start a new session for logging if necessary.
+ if (!TextUtils.isEmpty(resultId)
+ && !conversationActions.isEmpty()
+ && suggestionsMightBeUsedInNotification(
+ entry, !actions.isEmpty(), !replies.isEmpty())) {
+ mSessionCache.put(entry.getSbn().getKey(), new Session(resultId, repliesScore));
+ }
+
return new SmartSuggestions(replies, actions);
}
/**
+ * Returns whether the suggestion might be used in the notifications in SysUI.
+ * <p>
+ * Currently, NAS has no idea if suggestions will actually be used in the notification, and thus
+ * this function tries to make a heuristic. This function tries to optimize the precision,
+ * that means when it is unsure, it will return false. The objective is to avoid false positive,
+ * which could pollute the log and CTR as we are logging click rate of suggestions that could
+ * be never visible to users. On the other hand, it is fine to have false negative because
+ * it would be just like sampling.
+ */
+ private boolean suggestionsMightBeUsedInNotification(
+ NotificationEntry notificationEntry, boolean hasSmartAction, boolean hasSmartReply) {
+ Notification notification = notificationEntry.getNotification();
+ boolean hasAppGeneratedContextualActions = !notification.getContextualActions().isEmpty();
+
+ Pair<RemoteInput, Notification.Action> freeformRemoteInputAndAction =
+ notification.findRemoteInputActionPair(/* requiresFreeform */ true);
+ boolean hasAppGeneratedReplies = false;
+ boolean allowGeneratedReplies = false;
+ if (freeformRemoteInputAndAction != null) {
+ RemoteInput freeformRemoteInput = freeformRemoteInputAndAction.first;
+ Notification.Action actionWithFreeformRemoteInput = freeformRemoteInputAndAction.second;
+ hasAppGeneratedReplies = !ArrayUtils.isEmpty(freeformRemoteInput.getChoices());
+ allowGeneratedReplies = actionWithFreeformRemoteInput.getAllowGeneratedReplies();
+ }
+
+ if (hasAppGeneratedReplies || hasAppGeneratedContextualActions) {
+ return false;
+ }
+ return hasSmartAction && notification.getAllowSystemGeneratedContextualActions()
+ || hasSmartReply && allowGeneratedReplies;
+ }
+
+ private void reportActionsGenerated(
+ String resultId, List<ConversationAction> conversationActions) {
+ if (TextUtils.isEmpty(resultId)) {
+ return;
+ }
+ TextClassifierEvent textClassifierEvent =
+ createTextClassifierEventBuilder(
+ TextClassifierEvent.TYPE_ACTIONS_GENERATED, resultId)
+ .setEntityTypes(conversationActions.stream()
+ .map(ConversationAction::getType)
+ .toArray(String[]::new))
+ .build();
+ mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ }
+
+ /**
* Adds action adjustments based on the notification contents.
*/
- @NonNull
- private List<ConversationAction> suggestConversationActions(
- @NonNull NotificationEntry entry,
+ private ConversationActions suggestConversationActions(
+ NotificationEntry entry,
boolean includeReplies,
boolean includeActions) {
if (!includeReplies && !includeActions) {
- return Collections.emptyList();
- }
- if (mTextClassifier == null) {
- return Collections.emptyList();
+ return EMPTY_CONVERSATION_ACTIONS;
}
List<ConversationActions.Message> messages = extractMessages(entry.getNotification());
if (messages.isEmpty()) {
- return Collections.emptyList();
+ return EMPTY_CONVERSATION_ACTIONS;
}
// Do not generate smart actions if the last message is from the local user.
ConversationActions.Message lastMessage = messages.get(messages.size() - 1);
if (arePersonsEqual(
ConversationActions.Message.PERSON_USER_SELF, lastMessage.getAuthor())) {
- return Collections.emptyList();
+ return EMPTY_CONVERSATION_ACTIONS;
}
TextClassifier.EntityConfig.Builder typeConfigBuilder =
@@ -146,25 +212,20 @@ public class SmartActionsHelper {
.setHints(HINTS)
.setTypeConfig(typeConfigBuilder.build())
.build();
-
- ConversationActions conversationActionsResult =
+ ConversationActions conversationActions =
mTextClassifier.suggestConversationActions(request);
-
- String resultId = conversationActionsResult.getId();
- if (!TextUtils.isEmpty(resultId)
- && !conversationActionsResult.getConversationActions().isEmpty()) {
- mNotificationKeyToResultIdCache.put(entry.getSbn().getKey(), resultId);
- }
- return conversationActionsResult.getConversationActions();
+ reportActionsGenerated(
+ conversationActions.getId(), conversationActions.getConversationActions());
+ return conversationActions;
}
- void onNotificationExpansionChanged(@NonNull NotificationEntry entry, boolean isUserAction,
+ void onNotificationExpansionChanged(NotificationEntry entry, boolean isUserAction,
boolean isExpanded) {
if (!isExpanded) {
return;
}
- String resultId = mNotificationKeyToResultIdCache.get(entry.getSbn().getKey());
- if (resultId == null) {
+ Session session = mSessionCache.get(entry.getSbn().getKey());
+ if (session == null) {
return;
}
// Only report if this is the first time the user sees these suggestions.
@@ -173,56 +234,50 @@ public class SmartActionsHelper {
}
entry.setShowActionEventLogged();
TextClassifierEvent textClassifierEvent =
- createTextClassifierEventBuilder(TextClassifierEvent.TYPE_ACTIONS_SHOWN,
- resultId)
+ createTextClassifierEventBuilder(
+ TextClassifierEvent.TYPE_ACTIONS_SHOWN, session.resultId)
.build();
// TODO: If possible, report which replies / actions are actually seen by user.
mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
- void onNotificationDirectReplied(@NonNull String key) {
- if (mTextClassifier == null) {
- return;
- }
- String resultId = mNotificationKeyToResultIdCache.get(key);
- if (resultId == null) {
+ void onNotificationDirectReplied(String key) {
+ Session session = mSessionCache.get(key);
+ if (session == null) {
return;
}
TextClassifierEvent textClassifierEvent =
- createTextClassifierEventBuilder(TextClassifierEvent.TYPE_MANUAL_REPLY, resultId)
+ createTextClassifierEventBuilder(
+ TextClassifierEvent.TYPE_MANUAL_REPLY, session.resultId)
.build();
mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
- void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+ void onSuggestedReplySent(String key, CharSequence reply,
@NotificationAssistantService.Source int source) {
- if (mTextClassifier == null) {
- return;
- }
if (source != NotificationAssistantService.SOURCE_FROM_ASSISTANT) {
return;
}
- String resultId = mNotificationKeyToResultIdCache.get(key);
- if (resultId == null) {
+ Session session = mSessionCache.get(key);
+ if (session == null) {
return;
}
TextClassifierEvent textClassifierEvent =
- createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
+ createTextClassifierEventBuilder(
+ TextClassifierEvent.TYPE_SMART_ACTION, session.resultId)
.setEntityTypes(ConversationAction.TYPE_TEXT_REPLY)
+ .setScore(session.repliesScores.getOrDefault(reply, 0f))
.build();
mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
- void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+ void onActionClicked(String key, Notification.Action action,
@NotificationAssistantService.Source int source) {
- if (mTextClassifier == null) {
- return;
- }
if (source != NotificationAssistantService.SOURCE_FROM_ASSISTANT) {
return;
}
- String resultId = mNotificationKeyToResultIdCache.get(key);
- if (resultId == null) {
+ Session session = mSessionCache.get(key);
+ if (session == null) {
return;
}
String actionType = action.getExtras().getString(KEY_ACTION_TYPE);
@@ -230,28 +285,32 @@ public class SmartActionsHelper {
return;
}
TextClassifierEvent textClassifierEvent =
- createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
+ createTextClassifierEventBuilder(
+ TextClassifierEvent.TYPE_SMART_ACTION, session.resultId)
.setEntityTypes(actionType)
.build();
mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
private Notification.Action createNotificationAction(
- RemoteAction remoteAction, String actionType) {
+ RemoteAction remoteAction, String actionType, float score) {
Icon icon = remoteAction.shouldShowIcon()
? remoteAction.getIcon()
: Icon.createWithResource(mContext, com.android.internal.R.drawable.ic_action_open);
+ Bundle extras = new Bundle();
+ extras.putString(KEY_ACTION_TYPE, actionType);
+ extras.putFloat(KEY_ACTION_SCORE, score);
return new Notification.Action.Builder(
icon,
remoteAction.getTitle(),
remoteAction.getActionIntent())
.setContextual(true)
- .addExtras(Bundle.forPair(KEY_ACTION_TYPE, actionType))
+ .addExtras(extras)
.build();
}
private TextClassifierEvent.Builder createTextClassifierEventBuilder(
- int eventType, @NonNull String resultId) {
+ int eventType, String resultId) {
return new TextClassifierEvent.Builder(
TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType)
.setEventTime(System.currentTimeMillis())
@@ -269,7 +328,7 @@ public class SmartActionsHelper {
* to fundamental phone functionality where any error would result in a very negative user
* experience.
*/
- private boolean isEligibleForActionAdjustment(@NonNull NotificationEntry entry) {
+ private boolean isEligibleForActionAdjustment(NotificationEntry entry) {
Notification notification = entry.getNotification();
String pkg = entry.getSbn().getPackageName();
if (!Process.myUserHandle().equals(entry.getSbn().getUser())) {
@@ -285,7 +344,7 @@ public class SmartActionsHelper {
return entry.isMessaging();
}
- private boolean isEligibleForReplyAdjustment(@NonNull NotificationEntry entry) {
+ private boolean isEligibleForReplyAdjustment(NotificationEntry entry) {
if (!Process.myUserHandle().equals(entry.getSbn().getUser())) {
return false;
}
@@ -306,8 +365,7 @@ public class SmartActionsHelper {
}
/** Returns the text most salient for action extraction in a notification. */
- @Nullable
- private List<ConversationActions.Message> extractMessages(@NonNull Notification notification) {
+ private List<ConversationActions.Message> extractMessages(Notification notification) {
Parcelable[] messages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES);
if (messages == null || messages.length == 0) {
return Collections.singletonList(new ConversationActions.Message.Builder(
@@ -343,7 +401,7 @@ public class SmartActionsHelper {
return new ArrayList<>(extractMessages);
}
- private static boolean arePersonsEqual(@NonNull Person left, @NonNull Person right) {
+ private static boolean arePersonsEqual(Person left, Person right) {
return Objects.equals(left.getKey(), right.getKey())
&& Objects.equals(left.getName(), right.getName())
&& Objects.equals(left.getUri(), right.getUri());
@@ -359,4 +417,14 @@ public class SmartActionsHelper {
this.actions = actions;
}
}
+
+ private static class Session {
+ public final String resultId;
+ public final Map<CharSequence, Float> repliesScores;
+
+ Session(String resultId, Map<CharSequence, Float> repliesScores) {
+ this.resultId = resultId;
+ this.repliesScores = repliesScores;
+ }
+ }
}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index 74c20fc09df2..d0b6d0061166 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -19,7 +19,9 @@ import static com.google.common.truth.Truth.assertAbout;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,8 +55,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.time.Instant;
@@ -71,9 +73,12 @@ import javax.annotation.Nullable;
public class SmartActionsHelperTest {
private static final String NOTIFICATION_KEY = "key";
private static final String RESULT_ID = "id";
+ private static final float SCORE = 0.7f;
+ private static final CharSequence SMART_REPLY = "Home";
private static final ConversationAction REPLY_ACTION =
new ConversationAction.Builder(ConversationAction.TYPE_TEXT_REPLY)
- .setTextReply("Home")
+ .setTextReply(SMART_REPLY)
+ .setConfidenceScore(SCORE)
.build();
private static final String MESSAGE = "Where are you?";
@@ -197,8 +202,16 @@ public class SmartActionsHelperTest {
List<ConversationActions.Message> messages =
runSuggestAndCaptureRequest().getConversation();
+
assertThat(messages).hasSize(1);
MessageSubject.assertThat(messages.get(0)).hasText(MESSAGE);
+ ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+ ArgumentCaptor.forClass(TextClassifierEvent.class);
+ verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+ TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+ assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_GENERATED);
+ assertThat(textClassifierEvent.getEntityTypes()).asList()
+ .containsExactly(ConversationAction.TYPE_TEXT_REPLY);
}
@Test
@@ -249,6 +262,14 @@ public class SmartActionsHelperTest {
MessageSubject.assertThat(fourthMessage).hasPerson(userB);
MessageSubject.assertThat(fourthMessage)
.hasReferenceTime(createZonedDateTimeFromMsUtc(4000));
+
+ ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+ ArgumentCaptor.forClass(TextClassifierEvent.class);
+ verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+ TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+ assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_GENERATED);
+ assertThat(textClassifierEvent.getEntityTypes()).asList()
+ .containsExactly(ConversationAction.TYPE_TEXT_REPLY);
}
@Test
@@ -299,13 +320,15 @@ public class SmartActionsHelperTest {
mSmartActionsHelper.suggest(createNotificationEntry());
mSmartActionsHelper.onSuggestedReplySent(
- NOTIFICATION_KEY, MESSAGE, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+ NOTIFICATION_KEY, SMART_REPLY, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
ArgumentCaptor<TextClassifierEvent> argumentCaptor =
ArgumentCaptor.forClass(TextClassifierEvent.class);
- verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
- TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
- assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_SMART_ACTION);
+ verify(mTextClassifier, times(2)).onTextClassifierEvent(argumentCaptor.capture());
+ List<TextClassifierEvent> events = argumentCaptor.getAllValues();
+ assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
+ assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_SMART_ACTION);
+ assertThat(events.get(1).getScore()).isEqualTo(SCORE);
}
@Test
@@ -317,24 +340,22 @@ public class SmartActionsHelperTest {
mSmartActionsHelper.onSuggestedReplySent(
"something_else", MESSAGE, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
- verify(mTextClassifier, never())
- .onTextClassifierEvent(Mockito.any(TextClassifierEvent.class));
+ verify(mTextClassifier, never()).onTextClassifierEvent(
+ argThat(new TextClassifierEventMatcher(TextClassifierEvent.TYPE_SMART_ACTION)));
}
@Test
public void testOnSuggestedReplySent_missingResultId() {
when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
- .thenReturn(new ConversationActions(Collections.emptyList(), null));
-
+ .thenReturn(new ConversationActions(Collections.singletonList(REPLY_ACTION), null));
Notification notification = createMessageNotification();
when(mStatusBarNotification.getNotification()).thenReturn(notification);
mSmartActionsHelper.suggest(createNotificationEntry());
mSmartActionsHelper.onSuggestedReplySent(
- "something_else", MESSAGE, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+ NOTIFICATION_KEY, SMART_REPLY, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
- verify(mTextClassifier, never())
- .onTextClassifierEvent(Mockito.any(TextClassifierEvent.class));
+ verify(mTextClassifier, never()).onTextClassifierEvent(any(TextClassifierEvent.class));
}
@Test
@@ -347,9 +368,10 @@ public class SmartActionsHelperTest {
ArgumentCaptor<TextClassifierEvent> argumentCaptor =
ArgumentCaptor.forClass(TextClassifierEvent.class);
- verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
- TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
- assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_MANUAL_REPLY);
+ verify(mTextClassifier, times(2)).onTextClassifierEvent(argumentCaptor.capture());
+ List<TextClassifierEvent> events = argumentCaptor.getAllValues();
+ assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
+ assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_MANUAL_REPLY);
}
@Test
@@ -362,9 +384,10 @@ public class SmartActionsHelperTest {
ArgumentCaptor<TextClassifierEvent> argumentCaptor =
ArgumentCaptor.forClass(TextClassifierEvent.class);
- verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
- TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
- assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_SHOWN);
+ verify(mTextClassifier, times(2)).onTextClassifierEvent(argumentCaptor.capture());
+ List<TextClassifierEvent> events = argumentCaptor.getAllValues();
+ assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
+ assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_ACTIONS_SHOWN);
}
@Test
@@ -376,7 +399,7 @@ public class SmartActionsHelperTest {
mSmartActionsHelper.onNotificationExpansionChanged(createNotificationEntry(), false, false);
verify(mTextClassifier, never()).onTextClassifierEvent(
- Mockito.any(TextClassifierEvent.class));
+ argThat(new TextClassifierEventMatcher(TextClassifierEvent.TYPE_ACTIONS_SHOWN)));
}
@Test
@@ -389,9 +412,10 @@ public class SmartActionsHelperTest {
ArgumentCaptor<TextClassifierEvent> argumentCaptor =
ArgumentCaptor.forClass(TextClassifierEvent.class);
- verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
- TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
- assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_SHOWN);
+ verify(mTextClassifier, times(2)).onTextClassifierEvent(argumentCaptor.capture());
+ List<TextClassifierEvent> events = argumentCaptor.getAllValues();
+ assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
+ assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_ACTIONS_SHOWN);
}
private ZonedDateTime createZonedDateTimeFromMsUtc(long msUtc) {
@@ -490,4 +514,21 @@ public class SmartActionsHelperTest {
return assertAbout(FACTORY).that(message);
}
}
+
+ private final class TextClassifierEventMatcher implements ArgumentMatcher<TextClassifierEvent> {
+
+ private int mType;
+
+ private TextClassifierEventMatcher(int type) {
+ mType = type;
+ }
+
+ @Override
+ public boolean matches(TextClassifierEvent textClassifierEvent) {
+ if (textClassifierEvent == null) {
+ return false;
+ }
+ return mType == textClassifierEvent.getEventType();
+ }
+ }
}
diff --git a/packages/SettingsLib/res/drawable/ic_system_update.xml b/packages/SettingsLib/res/drawable/ic_system_update.xml
new file mode 100644
index 000000000000..3325fdd5c01a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_system_update.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM16,12.5l-4,4l-4,-4l1.41,-1.41L11,12.67V8.5V8h2v0.5v4.17l1.59,-1.59L16,12.5z"/>
+</vector>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index d6448336e402..f5d58d8a2004 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -337,6 +337,9 @@
<string name="data_usage_uninstalled_apps">Removed apps</string>
<!-- Title of data usage item that represents all uninstalled applications or removed users. [CHAR LIMIT=48] -->
<string name="data_usage_uninstalled_apps_users">Removed apps and users</string>
+ <!-- Title of data usage item that represents system updates (OTAs). [CHAR LIMIT=48] -->
+ <string name="data_usage_ota">System updates</string>
+
<!-- Tethering controls, item title to go into the tethering settings -->
<!-- Tethering controls, item title to go into the tethering settings when only USB tethering is available [CHAR LIMIT=25]-->
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index a1bf93654774..c1933fd87633 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -73,9 +73,8 @@ public class HeadsetProfile implements LocalBluetoothProfile {
BluetoothProfile.STATE_CONNECTED);
device.refresh();
}
-
- mProfileManager.callServiceConnectedListeners();
mIsProfileReady=true;
+ mProfileManager.callServiceConnectedListeners();
}
public void onServiceDisconnected(int profile) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index c14f5588cddf..e3516158daac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -28,6 +28,7 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.TrafficStats;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -111,7 +112,7 @@ public class UidDetailProvider {
// handle special case labels
switch (uid) {
- case android.os.Process.SYSTEM_UID:
+ case Process.SYSTEM_UID:
detail.label = res.getString(R.string.process_kernel_label);
detail.icon = pm.getDefaultActivityIcon();
return detail;
@@ -127,6 +128,10 @@ public class UidDetailProvider {
detail.label = res.getString(Utils.getTetheringLabel(cm));
detail.icon = pm.getDefaultActivityIcon();
return detail;
+ case Process.OTA_UPDATE_UID:
+ detail.label = res.getString(R.string.data_usage_ota);
+ detail.icon = mContext.getDrawable(R.drawable.ic_system_update);
+ return detail;
}
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 6152b8cbd562..3caa139ab998 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -718,6 +718,9 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Global.GAME_DRIVER_WHITELIST,
GlobalSettingsProto.Gpu.GAME_DRIVER_WHITELIST);
+ dumpSetting(s, p,
+ Settings.Global.GAME_DRIVER_BLACKLISTS,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS);
p.end(gpuToken);
final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 94481e7fe456..5714556ae8a3 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -64,6 +64,9 @@
charged, say that it is charged. -->
<string name="keyguard_charged">Fully charged</string>
+ <!-- When the lock screen is showing and the phone plugged in, and the battery is not fully charged, say that it's wirelessly charging. [CHAR LIMIT=50] -->
+ <string name="keyguard_plugged_in_wireless"><xliff:g id="percentage" example="20%">%s</xliff:g> • Wirelessly Charging</string>
+
<!-- When the lock screen is showing and the phone plugged in, and the battery
is not fully charged, say that it's charging. -->
<string name="keyguard_plugged_in"><xliff:g id="percentage">%s</xliff:g> • Charging</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index db92ed258064..7d009b5a9f18 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -955,6 +955,9 @@
<!-- Interruption level: Alarms only. Optimized for narrow two-line display. [CHAR LIMIT=40] -->
<string name="interruption_level_alarms_twoline">Alarms\nonly</string>
+ <!-- Indication on the keyguard that is shown when the device is wirelessly charging. [CHAR LIMIT=80]-->
+ <string name="keyguard_indication_charging_time_wireless"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Wirelessly Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
+
<!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=50]-->
<string name="keyguard_indication_charging_time"><xliff:g id="percentage">%2$s</xliff:g> • Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index be749aef7f25..164f5826061e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -424,22 +424,28 @@ public class KeyguardIndicationController implements StateListener {
final boolean hasChargingTime = chargingTimeRemaining > 0;
int chargingId;
- switch (mChargingSpeed) {
- case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
- chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time_fast
- : R.string.keyguard_plugged_in_charging_fast;
- break;
- case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
- chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time_slowly
- : R.string.keyguard_plugged_in_charging_slowly;
- break;
- default:
- chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time
- : R.string.keyguard_plugged_in;
- break;
+ if (mPowerPluggedInWired) {
+ switch (mChargingSpeed) {
+ case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_fast
+ : R.string.keyguard_plugged_in_charging_fast;
+ break;
+ case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_slowly
+ : R.string.keyguard_plugged_in_charging_slowly;
+ break;
+ default:
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time
+ : R.string.keyguard_plugged_in;
+ break;
+ }
+ } else {
+ chargingId = hasChargingTime
+ ? R.string.keyguard_indication_charging_time_wireless
+ : R.string.keyguard_plugged_in_wireless;
}
String percentage = NumberFormat.getPercentInstance()
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 60a45bfe04bb..c4a9db6b7262 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6630,8 +6630,7 @@ public class ActivityManagerService extends IActivityManager.Stub
String msg;
if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup "
- + cpr.name.flattenToShortString()
+ throw new SecurityException("Content provider lookup " + name
+ " failed: association not allowed with package " + msg);
}
checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 01946247bd12..0bf54392465a 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -76,6 +76,7 @@ final class CoreSettingsObserver extends ContentObserver {
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class);
// add other global settings here...
}
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 7ae00af626c8..b9aa34e89216 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -18,6 +18,7 @@ package com.android.server.display.whitebalance;
import android.annotation.NonNull;
import android.util.Slog;
+import android.util.Spline;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
@@ -75,6 +76,9 @@ public class DisplayWhiteBalanceController implements
// Override the ambient color temperature for debugging purposes.
private float mAmbientColorTemperatureOverride;
+ // A piecewise linear relationship between ambient and display color temperatures
+ private Spline.LinearSpline mAmbientToDisplayTemperatureSpline;
+
/**
* @param brightnessSensor
* The sensor used to detect changes in the ambient brightness.
@@ -109,7 +113,8 @@ public class DisplayWhiteBalanceController implements
@NonNull AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
@NonNull AmbientFilter colorTemperatureFilter,
@NonNull DisplayWhiteBalanceThrottler throttler,
- float lowLightAmbientBrightnessThreshold, float lowLightAmbientColorTemperature) {
+ float lowLightAmbientBrightnessThreshold, float lowLightAmbientColorTemperature,
+ float[] ambientTemperatures, float[] displayTemperatures) {
validateArguments(brightnessSensor, brightnessFilter, colorTemperatureSensor,
colorTemperatureFilter, throttler);
mLoggingEnabled = false;
@@ -127,6 +132,14 @@ public class DisplayWhiteBalanceController implements
mLastAmbientColorTemperature = -1.0f;
mAmbientColorTemperatureHistory = new History(HISTORY_SIZE);
mAmbientColorTemperatureOverride = -1.0f;
+
+ try {
+ mAmbientToDisplayTemperatureSpline = new Spline.LinearSpline(ambientTemperatures,
+ displayTemperatures);
+ } catch (Exception e) {
+ mAmbientToDisplayTemperatureSpline = null;
+ }
+
mColorDisplayServiceInternal = LocalServices.getService(ColorDisplayServiceInternal.class);
}
@@ -227,6 +240,9 @@ public class DisplayWhiteBalanceController implements
writer.println(" mLastAmbientColorTemperature=" + mLastAmbientColorTemperature);
writer.println(" mAmbientColorTemperatureHistory=" + mAmbientColorTemperatureHistory);
writer.println(" mAmbientColorTemperatureOverride=" + mAmbientColorTemperatureOverride);
+ writer.println(" mAmbientToDisplayTemperatureSpline="
+ + (mAmbientToDisplayTemperatureSpline == null ? "unused" :
+ mAmbientToDisplayTemperatureSpline));
}
@Override // AmbientSensor.AmbientBrightnessSensor.Callbacks
@@ -250,6 +266,11 @@ public class DisplayWhiteBalanceController implements
final long time = System.currentTimeMillis();
float ambientColorTemperature = mColorTemperatureFilter.getEstimate(time);
+ if (mAmbientToDisplayTemperatureSpline != null) {
+ ambientColorTemperature =
+ mAmbientToDisplayTemperatureSpline.interpolate(ambientColorTemperature);
+ }
+
final float ambientBrightness = mBrightnessFilter.getEstimate(time);
if (ambientBrightness < mLowLightAmbientBrightnessThreshold) {
if (mLoggingEnabled) {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index fd78ddbda9c8..56f4ca339eb3 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -67,9 +67,14 @@ public class DisplayWhiteBalanceFactory {
final float lowLightAmbientColorTemperature = getFloat(resources,
com.android.internal.R.dimen
.config_displayWhiteBalanceLowLightAmbientColorTemperature);
+ final float[] ambientTemperatures = getFloatArray(resources,
+ com.android.internal.R.array.config_displayWhiteBalanceAmbientTemperatureValues);
+ final float[] displayTemperatures = getFloatArray(resources,
+ com.android.internal.R.array.config_displayWhiteBalanceDisplayTemperatureValues);
final DisplayWhiteBalanceController controller = new DisplayWhiteBalanceController(
brightnessSensor, brightnessFilter, colorTemperatureSensor, colorTemperatureFilter,
- throttler, lowLightAmbientBrightnessThreshold, lowLightAmbientColorTemperature);
+ throttler, lowLightAmbientBrightnessThreshold, lowLightAmbientColorTemperature,
+ ambientTemperatures, displayTemperatures);
brightnessSensor.setCallbacks(controller);
colorTemperatureSensor.setCallbacks(controller);
return controller;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 21965e4e83a2..f6bd2a95a4a3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -481,6 +481,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
+ if (params.isStaged) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);
+ }
+
if (!params.isMultiPackage) {
// Only system components can circumvent runtime permissions when installing.
if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 84c8b606a9d9..d9a5eb901344 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -18,6 +18,7 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.Person;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -33,6 +34,7 @@ import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.ShortcutService.DumpFilter;
@@ -71,6 +73,7 @@ class ShortcutPackage extends ShortcutPackageItem {
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_CATEGORIES = "categories";
+ private static final String TAG_PERSON = "person";
private static final String ATTR_NAME = "name";
private static final String ATTR_CALL_COUNT = "call-count";
@@ -96,6 +99,12 @@ class ShortcutPackage extends ShortcutPackageItem {
private static final String ATTR_ICON_RES_NAME = "icon-resname";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
+ private static final String ATTR_PERSON_NAME = "name";
+ private static final String ATTR_PERSON_URI = "uri";
+ private static final String ATTR_PERSON_KEY = "key";
+ private static final String ATTR_PERSON_IS_BOT = "is-bot";
+ private static final String ATTR_PERSON_IS_IMPORTANT = "is-important";
+
private static final String NAME_CATEGORIES = "categories";
private static final String TAG_STRING_ARRAY_XMLUTILS = "string-array";
@@ -1499,6 +1508,22 @@ class ShortcutPackage extends ShortcutPackageItem {
out.endTag(null, TAG_CATEGORIES);
}
}
+ if (!forBackup) { // Don't backup the persons field.
+ final Person[] persons = si.getPersons();
+ if (!ArrayUtils.isEmpty(persons)) {
+ for (int i = 0; i < persons.length; i++) {
+ final Person p = persons[i];
+
+ out.startTag(null, TAG_PERSON);
+ ShortcutService.writeAttr(out, ATTR_PERSON_NAME, p.getName());
+ ShortcutService.writeAttr(out, ATTR_PERSON_URI, p.getUri());
+ ShortcutService.writeAttr(out, ATTR_PERSON_KEY, p.getKey());
+ ShortcutService.writeAttr(out, ATTR_PERSON_IS_BOT, p.isBot());
+ ShortcutService.writeAttr(out, ATTR_PERSON_IS_IMPORTANT, p.isImportant());
+ out.endTag(null, TAG_PERSON);
+ }
+ }
+ }
final Intent[] intentsNoExtras = si.getIntentsNoExtras();
final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
final int numIntents = intentsNoExtras.length;
@@ -1588,6 +1613,7 @@ class ShortcutPackage extends ShortcutPackageItem {
String bitmapPath;
int backupVersionCode;
ArraySet<String> categories = null;
+ ArrayList<Person> persons = new ArrayList<>();
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1638,6 +1664,9 @@ class ShortcutPackage extends ShortcutPackageItem {
case TAG_CATEGORIES:
// This just contains string-array.
continue;
+ case TAG_PERSON:
+ persons.add(parsePerson(parser));
+ continue;
case TAG_STRING_ARRAY_XMLUTILS:
if (NAME_CATEGORIES.equals(ShortcutService.parseStringAttribute(parser,
ATTR_NAME_XMLUTILS))) {
@@ -1680,7 +1709,8 @@ class ShortcutPackage extends ShortcutPackageItem {
categories,
intents.toArray(new Intent[intents.size()]),
rank, extras, lastChangedTimestamp, flags,
- iconResId, iconResName, bitmapPath, disabledReason);
+ iconResId, iconResName, bitmapPath, disabledReason,
+ persons.toArray(new Person[persons.size()]));
}
private static Intent parseIntent(XmlPullParser parser)
@@ -1713,6 +1743,20 @@ class ShortcutPackage extends ShortcutPackageItem {
return intent;
}
+ private static Person parsePerson(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ CharSequence name = ShortcutService.parseStringAttribute(parser, ATTR_PERSON_NAME);
+ String uri = ShortcutService.parseStringAttribute(parser, ATTR_PERSON_URI);
+ String key = ShortcutService.parseStringAttribute(parser, ATTR_PERSON_KEY);
+ boolean isBot = ShortcutService.parseBooleanAttribute(parser, ATTR_PERSON_IS_BOT);
+ boolean isImportant = ShortcutService.parseBooleanAttribute(parser,
+ ATTR_PERSON_IS_IMPORTANT);
+
+ Person.Builder builder = new Person.Builder();
+ builder.setName(name).setUri(uri).setKey(key).setBot(isBot).setImportant(isImportant);
+ return builder.build();
+ }
+
@VisibleForTesting
List<ShortcutInfo> getAllShortcutsForTest() {
return new ArrayList<>(mShortcuts.values());
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index 90f08c30139a..668fc88b6b58 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -449,7 +449,8 @@ public class ShortcutParser {
iconResId,
null, // icon res name
null, // bitmap path
- disabledReason);
+ disabledReason,
+ null /* persons */);
}
private static String parseCategory(ShortcutService service, AttributeSet attrs) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 093ac89b97c0..9523202cbb0e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -17,8 +17,8 @@
package com.android.server.devicepolicy;
import static android.Manifest.permission.BIND_DEVICE_ADMIN;
-import static android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+import static android.Manifest.permission.REQUEST_SCREEN_LOCK_COMPLEXITY;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
@@ -4778,8 +4778,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int callingUserId = mInjector.userHandleGetCallingUserId();
enforceUserUnlocked(callingUserId);
mContext.enforceCallingOrSelfPermission(
- GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY,
- "Must have " + GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY + " permission.");
+ REQUEST_SCREEN_LOCK_COMPLEXITY,
+ "Must have " + REQUEST_SCREEN_LOCK_COMPLEXITY + " permission.");
synchronized (getLockObject()) {
int targetUserId = getCredentialOwner(callingUserId, /* parent= */ false);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 9ac91ddba5ec..de782a52eb53 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5199,7 +5199,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testGetPasswordComplexity_currentUserNoPassword() {
when(getServices().userManager.isUserUnlocked(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(true);
- mServiceContext.permissions.add(permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ mServiceContext.permissions.add(permission.REQUEST_SCREEN_LOCK_COMPLEXITY);
when(getServices().userManager.getCredentialOwnerProfile(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(DpmMockContext.CALLER_USER_HANDLE);
@@ -5209,7 +5209,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testGetPasswordComplexity_currentUserHasPassword() {
when(getServices().userManager.isUserUnlocked(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(true);
- mServiceContext.permissions.add(permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ mServiceContext.permissions.add(permission.REQUEST_SCREEN_LOCK_COMPLEXITY);
when(getServices().userManager.getCredentialOwnerProfile(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(DpmMockContext.CALLER_USER_HANDLE);
dpms.mUserPasswordMetrics.put(
@@ -5222,7 +5222,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testGetPasswordComplexity_unifiedChallengeReturnsParentUserPassword() {
when(getServices().userManager.isUserUnlocked(DpmMockContext.CALLER_USER_HANDLE))
.thenReturn(true);
- mServiceContext.permissions.add(permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY);
+ mServiceContext.permissions.add(permission.REQUEST_SCREEN_LOCK_COMPLEXITY);
UserInfo parentUser = new UserInfo();
parentUser.id = DpmMockContext.CALLER_USER_HANDLE + 10;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 8d0365b534b5..95043810128a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.verify;
import android.Manifest.permission;
import android.app.ActivityManager;
+import android.app.Person;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
@@ -890,6 +891,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setText("text")
.setDisabledMessage("dismes")
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
+ .setPerson(makePerson("person", "personKey", "personUri"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
@@ -901,6 +903,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setTitle("x")
.setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setPersons(list(makePerson("person1", "personKey1", "personUri1"),
+ makePerson("person2", "personKey2", "personUri2")).toArray(new Person[2]))
.setRank(456)
.build();
sorig2.setTimestamp(mInjectedCurrentTimeMillis);
@@ -936,6 +940,10 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
+ assertEquals(1, si.getPersons().length);
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(0, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
@@ -949,6 +957,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
// to test it.
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
assertEquals(1, si.getRank());
+ assertEquals(2, si.getPersons().length);
+ assertEquals("personUri2", si.getPersons()[1].getUri());
dumpUserFile(USER_10);
}
@@ -1114,6 +1124,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setDisabledMessage("dismes")
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setPerson(makePerson("person", "personKey", "personUri"))
.setRank(123)
.setExtras(pb)
.build();
@@ -1150,6 +1161,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
+ assertEquals(0, si.getPersons().length); // Don't backup the persons field
assertEquals(0, si.getRank());
assertEquals(1, si.getExtras().getInt("k"));
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 313146d5538b..3a4d33c18485 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -59,6 +59,7 @@ import android.util.DisplayMetrics;
import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.PhoneConstants;
@@ -72,6 +73,7 @@ import java.util.List;
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
@@ -2573,17 +2575,35 @@ public class SubscriptionManager {
* {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
* it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
* is used to determine which modem is preferred.
+ * @param needValidation whether validation is needed before switch happens.
+ * @param executor The executor of where the callback will execute.
+ * @param callback Callback will be triggered once it succeeds or failed.
+ * See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
+ * for more details. Pass null if don't care about the result.
+ *
* @hide
*
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void setPreferredDataSubscriptionId(int subId) {
+ public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+ @NonNull @CallbackExecutor Executor executor, Consumer<Integer> callback) {
if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
- if (iSub != null) {
- iSub.setPreferredDataSubscriptionId(subId);
- }
+ if (iSub == null) return;
+
+ ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ if (callback != null) {
+ callback.accept(result);
+ }
+ }));
+ }
+ };
+ iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
} catch (RemoteException ex) {
// ignore it
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2a03924fd58c..6690bd0f10b5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10094,6 +10094,29 @@ public class TelephonyManager {
return false;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
+ SET_OPPORTUNISTIC_SUB_SUCCESS,
+ SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
+ SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER})
+ public @interface SetOpportunisticSubscriptionResult {}
+
+ /**
+ * No error. Operation succeeded.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0;
+
+ /**
+ * Validation failed when trying to switch to preferred subscription.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1;
+
+ /**
+ * The parameter passed in is invalid.
+ */
+ public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2;
+
/**
* Set preferred opportunistic data subscription id.
*
diff --git a/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl b/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl
new file mode 100644
index 000000000000..7a78f3454aac
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Callback to provide asynchronous result of setPreferredOpportunisticData.
+ * @hide
+ */
+oneway interface ISetOpportunisticDataCallback {
+ void onComplete(int result);
+}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6ce9de4ca677..75a4d8227e23 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.telephony.SubscriptionInfo;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
interface ISub {
/**
@@ -217,10 +218,14 @@ interface ISub {
* designed to overwrite default data subscription temporarily.
*
* @param subId which subscription is preferred to for cellular data.
+ * @param needValidation whether validation is needed before switching.
+ * @param callback callback upon request completion.
+ *
* @hide
*
*/
- void setPreferredDataSubscriptionId(int subId);
+ void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+ ISetOpportunisticDataCallback callback);
/**
* Get which subscription is preferred for cellular data.
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 85bf6f218ba0..582a5b869c65 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -294,22 +294,6 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
}
}
- if (el->FindAttribute("", "platformBuildVersionCode") == nullptr) {
- auto versionCode = el->FindAttribute(xml::kSchemaAndroid, "versionCode");
- if (versionCode != nullptr) {
- el->attributes.push_back(xml::Attribute{"", "platformBuildVersionCode",
- versionCode->value});
- }
- }
-
- if (el->FindAttribute("", "platformBuildVersionName") == nullptr) {
- auto versionName = el->FindAttribute(xml::kSchemaAndroid, "versionName");
- if (versionName != nullptr) {
- el->attributes.push_back(xml::Attribute{"", "platformBuildVersionName",
- versionName->value});
- }
- }
-
return true;
});
@@ -489,8 +473,14 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
// Make sure we un-compile the value if it was set to something else.
attr->compiled_value = {};
+ attr->value = options_.compile_sdk_version.value();
+
+ attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
+ // Make sure we un-compile the value if it was set to something else.
+ attr->compiled_value = {};
attr->value = options_.compile_sdk_version.value();
+
}
if (options_.compile_sdk_version_codename) {
@@ -499,7 +489,12 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
// Make sure we un-compile the value if it was set to something else.
attr->compiled_value = {};
+ attr->value = options_.compile_sdk_version_codename.value();
+ attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
+
+ // Make sure we un-compile the value if it was set to something else.
+ attr->compiled_value = {};
attr->value = options_.compile_sdk_version_codename.value();
}
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index adea6273bc8b..4842f62e53b5 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -725,6 +725,43 @@ TEST_F(ManifestFixerTest, InsertCompileSdkVersions) {
attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
ASSERT_THAT(attr, NotNull());
EXPECT_THAT(attr->value, StrEq("P"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
+}
+
+TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
+ std::string input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
+ compileSdkVersion="27" compileSdkVersionCodename="O"
+ platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
+ ManifestFixerOptions options;
+ options.compile_sdk_version = {"28"};
+ options.compile_sdk_version_codename = {"P"};
+
+ std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
+ ASSERT_THAT(manifest, NotNull());
+
+ xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
}
TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
@@ -750,59 +787,6 @@ TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
ASSERT_THAT(manifest, IsNull());
}
-TEST_F(ManifestFixerTest, InsertPlatformBuildVersions) {
- // Test for insertion when versionCode and versionName are included in the manifest
- {
- std::string input = R"(
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
- android:versionCode="27" android:versionName="O"/>)";
- std::unique_ptr<xml::XmlResource> manifest = Verify(input);
- ASSERT_THAT(manifest, NotNull());
-
- xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("27"));
- attr = manifest->root->FindAttribute("", "platformBuildVersionName");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("O"));
- }
-
- // Test for insertion when versionCode and versionName defaults are specified
- {
- std::string input = R"(
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"/>)";
- ManifestFixerOptions options;
- options.version_code_default = {"27"};
- options.version_name_default = {"O"};
- std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
- ASSERT_THAT(manifest, NotNull());
-
- xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("27"));
- attr = manifest->root->FindAttribute("", "platformBuildVersionName");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("O"));
- }
-
- // Test that the platform build version attributes are not changed if they are currently present
- {
- std::string input = R"(
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
- android:versionCode="28" android:versionName="P"
- platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
- std::unique_ptr<xml::XmlResource> manifest = Verify(input);
- ASSERT_THAT(manifest, NotNull());
-
- xml::Attribute* attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("27"));
- attr = manifest->root->FindAttribute("", "platformBuildVersionName");
- ASSERT_THAT(attr, NotNull());
- EXPECT_THAT(attr->value, StrEq("O"));
- }
-}
-
TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
std::string input = R"(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 2cc1d8313225..5e5a59566ce5 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1149,9 +1149,6 @@ public class WifiManager {
* Return a list of all the networks configured for the current foreground
* user.
*
- * Requires the same permissions as {@link #getScanResults}.
- * If such access is not allowed, this API will always return an empty list.
- *
* Not all fields of WifiConfiguration are returned. Only the following
* fields are filled in:
* <ul>
@@ -1176,8 +1173,12 @@ public class WifiManager {
* when auto-connecting to wifi.
* <b>Compatibility Note:</b> For applications targeting
* {@link android.os.Build.VERSION_CODES#Q} or above, this API will return an empty list,
- * except to callers with Carrier privilege which will receive a restricted list only
- * containing configurations which they created.
+ * except for:
+ * <ul>
+ * <li>Device Owner (DO) & Profile Owner (PO) apps will have access to the full list.
+ * <li>Callers with Carrier privilege will receive a restricted list only containing
+ * configurations which they created.
+ * </ul>
*/
@Deprecated
@RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
@@ -4721,7 +4722,6 @@ public class WifiManager {
*
* @hide
*/
- @SystemApi
private static class EasyConnectCallbackProxy extends IDppCallback.Stub {
private final Executor mExecutor;
private final EasyConnectStatusCallback mEasyConnectStatusCallback;