Merge "Support DisplayAreas in protos" into rvc-dev
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 7af3f66..814ab6d 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -22,6 +22,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
@@ -214,7 +215,7 @@
}
/**
- * Delete an existing session and any data that was written to that session so far.
+ * Abandons an existing session and deletes any data that was written to that session so far.
*
* @param sessionId a unique id obtained via {@link #createSession(BlobHandle)} that
* represents a particular session.
@@ -223,9 +224,9 @@
* @throws SecurityException when the caller does not own the session, or
* the session does not exist or is invalid.
*/
- public void deleteSession(@IntRange(from = 1) long sessionId) throws IOException {
+ public void abandonSession(@IntRange(from = 1) long sessionId) throws IOException {
try {
- mService.deleteSession(sessionId, mContext.getOpPackageName());
+ mService.abandonSession(sessionId, mContext.getOpPackageName());
} catch (ParcelableException e) {
e.maybeRethrow(IOException.class);
throw new RuntimeException(e);
@@ -453,13 +454,13 @@
}
/**
- * Release all active leases to the blob represented by {@code blobHandle} which are
+ * Release any active lease to the blob represented by {@code blobHandle} which is
* currently held by the caller.
*
* @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to
- * release the leases for.
+ * release the lease for.
*
- * @throws IOException when there is an I/O error while releasing the releases to the blob.
+ * @throws IOException when there is an I/O error while releasing the release to the blob.
* @throws SecurityException when the blob represented by the {@code blobHandle} does not
* exist or the caller does not have access to it.
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
@@ -480,6 +481,7 @@
*
* @hide
*/
+ @TestApi
public void waitForIdle(long timeoutMillis) throws InterruptedException, TimeoutException {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
@@ -623,7 +625,7 @@
/**
* Close this session. It can be re-opened for writing/reading if it has not been
- * abandoned (using {@link #abandon}) or closed (using {@link #commit}).
+ * abandoned (using {@link #abandon}) or committed (using {@link #commit}).
*
* @throws IOException when there is an I/O error while closing the session.
* @throws SecurityException when the caller is not the owner of the session.
diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
index beeb03f..e783813 100644
--- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
+++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl
@@ -25,7 +25,7 @@
long createSession(in BlobHandle handle, in String packageName);
IBlobStoreSession openSession(long sessionId, in String packageName);
ParcelFileDescriptor openBlob(in BlobHandle handle, in String packageName);
- void deleteSession(long sessionId, in String packageName);
+ void abandonSession(long sessionId, in String packageName);
void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description,
long leaseTimeoutMillis, in String packageName);
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index ed3dda4..53a97ce 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -349,7 +349,7 @@
return session;
}
- private void deleteSessionInternal(long sessionId,
+ private void abandonSessionInternal(long sessionId,
int callingUid, String callingPackage) {
synchronized (mBlobsLock) {
final BlobStoreSession session = openSessionInternal(sessionId,
@@ -357,7 +357,7 @@
session.open();
session.abandon();
if (LOGV) {
- Slog.v(TAG, "Deleted session with id " + sessionId
+ Slog.v(TAG, "Abandoned session with id " + sessionId
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
writeBlobSessionsAsync();
@@ -1215,7 +1215,7 @@
}
@Override
- public void deleteSession(@IntRange(from = 1) long sessionId,
+ public void abandonSession(@IntRange(from = 1) long sessionId,
@NonNull String packageName) {
Preconditions.checkArgumentPositive(sessionId,
"sessionId must be positive: " + sessionId);
@@ -1224,7 +1224,7 @@
final int callingUid = Binder.getCallingUid();
verifyCallingPackage(callingUid, packageName);
- deleteSessionInternal(sessionId, callingUid, packageName);
+ abandonSessionInternal(sessionId, callingUid, packageName);
}
@Override
diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
index 30a8b45..0ac0c73 100644
--- a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ApexContext;
+import android.content.ApexEnvironment;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArrayMap;
@@ -258,8 +258,8 @@
@NonNull
private static File getFile(@NonNull UserHandle user) {
- ApexContext apexContext = ApexContext.getApexContext(APEX_MODULE_NAME);
- File dataDirectory = apexContext.getDeviceProtectedDataDirForUser(user);
+ ApexEnvironment apexEnvironment = ApexEnvironment.getApexEnvironment(APEX_MODULE_NAME);
+ File dataDirectory = apexEnvironment.getDeviceProtectedDataDirForUser(user);
return new File(dataDirectory, RUNTIME_PERMISSIONS_FILE_NAME);
}
}
diff --git a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
index 3031c82..2346c11 100644
--- a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ApexContext;
+import android.content.ApexEnvironment;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -211,8 +211,8 @@
@NonNull
private static File getFile(@NonNull UserHandle user) {
- ApexContext apexContext = ApexContext.getApexContext(APEX_MODULE_NAME);
- File dataDirectory = apexContext.getDeviceProtectedDataDirForUser(user);
+ ApexEnvironment apexEnvironment = ApexEnvironment.getApexEnvironment(APEX_MODULE_NAME);
+ File dataDirectory = apexEnvironment.getDeviceProtectedDataDirForUser(user);
return new File(dataDirectory, ROLES_FILE_NAME);
}
}
diff --git a/api/current.txt b/api/current.txt
index 6052d93..15f10fa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7583,12 +7583,12 @@
}
public class BlobStoreManager {
+ method public void abandonSession(@IntRange(from=1) long) throws java.io.IOException;
method public void acquireLease(@NonNull android.app.blob.BlobHandle, @IdRes int, long) throws java.io.IOException;
method public void acquireLease(@NonNull android.app.blob.BlobHandle, @NonNull CharSequence, long) throws java.io.IOException;
method public void acquireLease(@NonNull android.app.blob.BlobHandle, @IdRes int) throws java.io.IOException;
method public void acquireLease(@NonNull android.app.blob.BlobHandle, @NonNull CharSequence) throws java.io.IOException;
method @IntRange(from=1) public long createSession(@NonNull android.app.blob.BlobHandle) throws java.io.IOException;
- method public void deleteSession(@IntRange(from=1) long) throws java.io.IOException;
method @NonNull public android.os.ParcelFileDescriptor openBlob(@NonNull android.app.blob.BlobHandle) throws java.io.IOException;
method @NonNull public android.app.blob.BlobStoreManager.Session openSession(@IntRange(from=1) long) throws java.io.IOException;
method public void releaseLease(@NonNull android.app.blob.BlobHandle) throws java.io.IOException;
@@ -27053,7 +27053,8 @@
method public void registerRouteCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.RouteCallback, @NonNull android.media.RouteDiscoveryPreference);
method public void registerTransferCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaRouter2.TransferCallback);
method public void setOnGetControllerHintsListener(@Nullable android.media.MediaRouter2.OnGetControllerHintsListener);
- method public void transferTo(@Nullable android.media.MediaRoute2Info);
+ method public void stop();
+ method public void transferTo(@NonNull android.media.MediaRoute2Info);
method public void unregisterControllerCallback(@NonNull android.media.MediaRouter2.ControllerCallback);
method public void unregisterRouteCallback(@NonNull android.media.MediaRouter2.RouteCallback);
method public void unregisterTransferCallback(@NonNull android.media.MediaRouter2.TransferCallback);
@@ -27093,8 +27094,9 @@
public abstract static class MediaRouter2.TransferCallback {
ctor public MediaRouter2.TransferCallback();
+ method public void onStopped(@NonNull android.media.MediaRouter2.RoutingController);
method public void onTransferFailed(@NonNull android.media.MediaRoute2Info);
- method public void onTransferred(@NonNull android.media.MediaRouter2.RoutingController, @Nullable android.media.MediaRouter2.RoutingController);
+ method public void onTransferred(@NonNull android.media.MediaRouter2.RoutingController, @NonNull android.media.MediaRouter2.RoutingController);
}
public class MediaScannerConnection implements android.content.ServiceConnection {
@@ -43108,7 +43110,7 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method @NonNull public android.service.autofill.FillResponse.Builder addDataset(@Nullable android.service.autofill.Dataset);
- method @NonNull public android.service.autofill.FillResponse.Builder addInlineAction(@NonNull android.service.autofill.InlinePresentation);
+ method @NonNull public android.service.autofill.FillResponse.Builder addInlineAction(@NonNull android.service.autofill.InlineAction);
method @NonNull public android.service.autofill.FillResponse build();
method @NonNull public android.service.autofill.FillResponse.Builder disableAutofill(long);
method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews);
@@ -43138,6 +43140,15 @@
method public android.service.autofill.ImageTransformation build();
}
+ public final class InlineAction implements android.os.Parcelable {
+ ctor public InlineAction(@NonNull android.service.autofill.InlinePresentation, @NonNull android.content.IntentSender);
+ method public int describeContents();
+ method @NonNull public android.content.IntentSender getAction();
+ method @NonNull public android.service.autofill.InlinePresentation getInlinePresentation();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.InlineAction> CREATOR;
+ }
+
public final class InlinePresentation implements android.os.Parcelable {
ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.view.inline.InlinePresentationSpec, boolean);
method public int describeContents();
@@ -56155,7 +56166,7 @@
}
public static final class AccessibilityNodeInfo.ExtraRenderingInfo {
- method @Nullable public android.util.Size getLayoutParams();
+ method @Nullable public android.util.Size getLayoutSize();
method public float getTextSizeInPx();
method public int getTextSizeUnit();
}
diff --git a/api/system-current.txt b/api/system-current.txt
index d902949..25f16d3 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -388,6 +388,7 @@
field public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME = "android:audio_notification_volume";
field public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
field public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
+ field public static final String OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = "android:auto_revoke_permissions_if_unused";
field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
@@ -1758,8 +1759,8 @@
package android.content {
- public class ApexContext {
- method @NonNull public static android.content.ApexContext getApexContext(@NonNull String);
+ public class ApexEnvironment {
+ method @NonNull public static android.content.ApexEnvironment getApexEnvironment(@NonNull String);
method @NonNull public java.io.File getCredentialProtectedDataDirForUser(@NonNull android.os.UserHandle);
method @NonNull public java.io.File getDeviceProtectedDataDir();
method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
@@ -2215,9 +2216,7 @@
field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
field public static final int FLAGS_PERMISSION_RESERVED_PERMISSIONCONTROLLER = -268435456; // 0xf0000000
field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000
- field public static final int FLAG_PERMISSION_AUTO_REVOKED = 1048576; // 0x100000
- field public static final int FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED = 131072; // 0x20000
- field public static final int FLAG_PERMISSION_AUTO_REVOKE_USER_SET = 262144; // 0x40000
+ field public static final int FLAG_PERMISSION_AUTO_REVOKED = 131072; // 0x20000
field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
field public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 32768; // 0x8000
field public static final int FLAG_PERMISSION_ONE_TIME = 65536; // 0x10000
@@ -2301,7 +2300,7 @@
method public void onPermissionsChanged(int);
}
- @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME, android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED, android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKE_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
+ @IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME, android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
}
public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
@@ -6127,7 +6126,7 @@
}
public class EthernetManager {
- method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
}
public static interface EthernetManager.TetheredInterfaceCallback {
@@ -7815,9 +7814,6 @@
method public int getMaxNumberTxSpatialStreams();
method public boolean isChannelWidthSupported(int);
method public boolean isWifiStandardSupported(int);
- method public void setChannelWidthSupported(int, boolean);
- method public void setMaxNumberRxSpatialStreams(int);
- method public void setMaxNumberTxSpatialStreams(int);
method public void setWifiStandardSupport(int, boolean);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.nl80211.DeviceWiphyCapabilities> CREATOR;
@@ -9866,10 +9862,10 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method @NonNull public android.service.autofill.augmented.FillResponse build();
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@Nullable android.os.Bundle);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@Nullable android.service.autofill.augmented.FillWindow);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineActions(@Nullable java.util.List<android.service.autofill.InlinePresentation>);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@Nullable java.util.List<android.service.autofill.Dataset>);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@NonNull android.os.Bundle);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineActions(@NonNull java.util.List<android.service.autofill.InlineAction>);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@NonNull java.util.List<android.service.autofill.Dataset>);
}
public final class FillWindow implements java.lang.AutoCloseable {
@@ -11700,6 +11696,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int);
+ method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
@@ -11737,8 +11734,8 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
+ method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
method public void updateServiceLocation();
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
field public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE = "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE";
field public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE";
@@ -12248,7 +12245,7 @@
method public int getEmergencyServiceCategories();
method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
- method @Nullable public android.os.Bundle getProprietaryCallExtras();
+ method @NonNull public android.os.Bundle getProprietaryCallExtras();
method public int getRestrictCause();
method public int getServiceType();
method public static int getVideoStateFromCallType(int);
@@ -12706,8 +12703,8 @@
field public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; // 0x11
field public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23; // 0x17
field public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22; // 0x16
+ field public static final int KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC = 16; // 0x10
field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15
- field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10
field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf
field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc
field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21
diff --git a/api/test-current.txt b/api/test-current.txt
index c95bd09..9d284b5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -590,6 +590,14 @@
}
+package android.app.blob {
+
+ public class BlobStoreManager {
+ method public void waitForIdle(long) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+ }
+
+}
+
package android.app.prediction {
public final class AppPredictionContext implements android.os.Parcelable {
@@ -784,6 +792,8 @@
}
public abstract class ContentResolver {
+ method @NonNull public static android.net.Uri decodeFromFile(@NonNull java.io.File);
+ method @NonNull public static java.io.File encodeToFile(@NonNull android.net.Uri);
method public static String[] getSyncAdapterPackagesForAuthorityAsUser(String, int);
}
@@ -1727,7 +1737,7 @@
}
public class EthernetManager {
- method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
}
public static interface EthernetManager.TetheredInterfaceCallback {
@@ -2919,6 +2929,11 @@
method @NonNull public android.provider.DeviceConfig.Properties.Builder setString(@NonNull String, @Nullable String);
}
+ public final class DocumentsContract {
+ method public static boolean isManageMode(@NonNull android.net.Uri);
+ method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
+ }
+
public final class MediaStore {
method @NonNull @WorkerThread public static android.net.Uri scanFile(@NonNull android.content.ContentResolver, @NonNull java.io.File);
method @WorkerThread public static void scanVolume(@NonNull android.content.ContentResolver, @NonNull String);
@@ -3227,10 +3242,10 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method @NonNull public android.service.autofill.augmented.FillResponse build();
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@Nullable android.os.Bundle);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@Nullable android.service.autofill.augmented.FillWindow);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineActions(@Nullable java.util.List<android.service.autofill.InlinePresentation>);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@Nullable java.util.List<android.service.autofill.Dataset>);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@NonNull android.os.Bundle);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineActions(@NonNull java.util.List<android.service.autofill.InlineAction>);
+ method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@NonNull java.util.List<android.service.autofill.Dataset>);
}
public final class FillWindow implements java.lang.AutoCloseable {
@@ -3732,11 +3747,12 @@
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
+ method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void resetOtaEmergencyNumberDbFilePath();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
- method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
+ method @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -3837,7 +3853,7 @@
method public int getEmergencyServiceCategories();
method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
- method @Nullable public android.os.Bundle getProprietaryCallExtras();
+ method @NonNull public android.os.Bundle getProprietaryCallExtras();
method public int getRestrictCause();
method public int getServiceType();
method public static int getVideoStateFromCallType(int);
@@ -4292,8 +4308,8 @@
field public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17; // 0x11
field public static final int KEY_RCS_CAPABILITY_POLL_LIST_SUB_EXP_SEC = 23; // 0x17
field public static final int KEY_RCS_MAX_NUM_ENTRIES_IN_RCL = 22; // 0x16
+ field public static final int KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC = 16; // 0x10
field public static final int KEY_RCS_PUBLISH_SOURCE_THROTTLE_MS = 21; // 0x15
- field public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16; // 0x10
field public static final int KEY_RCS_PUBLISH_TIMER_SEC = 15; // 0xf
field public static final int KEY_REGISTRATION_DOMAIN_NAME = 12; // 0xc
field public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33; // 0x21
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 9645a46..80f9fea 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -7640,6 +7640,9 @@
// Whether AppOps is guarded by Runtime permission
optional bool is_runtime_permission = 11;
+
+ // Sampling rate used on device, from 0 to 100
+ optional int32 sampling_rate = 12;
}
/**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f613df2..e2ecf85 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1060,9 +1060,12 @@
/** @hide Access telephony call audio */
public static final int OP_ACCESS_CALL_AUDIO = 96;
+ /** @hide Auto-revoke app permissions if app is unused for an extended period */
+ public static final int OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97;
+
/** @hide */
@UnsupportedAppUsage
- public static final int _NUM_OP = 97;
+ public static final int _NUM_OP = 98;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1357,6 +1360,11 @@
@SystemApi
public static final String OPSTR_ACCESS_CALL_AUDIO = "android:access_call_audio";
+ /** @hide Auto-revoke app permissions if app is unused for an extended period */
+ @SystemApi
+ public static final String OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED =
+ "android:auto_revoke_permissions_if_unused";
+
/** @hide Communicate cross-profile within the same profile group. */
@SystemApi
public static final String OPSTR_INTERACT_ACROSS_PROFILES = "android:interact_across_profiles";
@@ -1446,6 +1454,7 @@
OP_INTERACT_ACROSS_PROFILES,
OP_LOADER_USAGE_STATS,
OP_ACCESS_CALL_AUDIO,
+ OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
};
/**
@@ -1554,6 +1563,7 @@
OP_ACTIVATE_PLATFORM_VPN, // ACTIVATE_PLATFORM_VPN
OP_LOADER_USAGE_STATS, // LOADER_USAGE_STATS
OP_ACCESS_CALL_AUDIO, // ACCESS_CALL_AUDIO
+ OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, //AUTO_REVOKE_PERMISSIONS_IF_UNUSED
};
/**
@@ -1657,6 +1667,7 @@
OPSTR_ACTIVATE_PLATFORM_VPN,
OPSTR_LOADER_USAGE_STATS,
OPSTR_ACCESS_CALL_AUDIO,
+ OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
};
/**
@@ -1761,6 +1772,7 @@
"ACTIVATE_PLATFORM_VPN",
"LOADER_USAGE_STATS",
"ACCESS_CALL_AUDIO",
+ "AUTO_REVOKE_PERMISSIONS_IF_UNUSED",
};
/**
@@ -1866,6 +1878,7 @@
null, // no permission for OP_ACTIVATE_PLATFORM_VPN
android.Manifest.permission.LOADER_USAGE_STATS,
Manifest.permission.ACCESS_CALL_AUDIO,
+ null, // no permission for OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
};
/**
@@ -1971,6 +1984,7 @@
null, // ACTIVATE_PLATFORM_VPN
null, // LOADER_USAGE_STATS
null, // ACCESS_CALL_AUDIO
+ null, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED
};
/**
@@ -2075,6 +2089,7 @@
false, // ACTIVATE_PLATFORM_VPN
false, // LOADER_USAGE_STATS
false, // ACCESS_CALL_AUDIO
+ false, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED
};
/**
@@ -2178,6 +2193,7 @@
AppOpsManager.MODE_IGNORED, // ACTIVATE_PLATFORM_VPN
AppOpsManager.MODE_DEFAULT, // LOADER_USAGE_STATS
AppOpsManager.MODE_DEFAULT, // ACCESS_CALL_AUDIO
+ AppOpsManager.MODE_DEFAULT, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED
};
/**
@@ -2285,6 +2301,7 @@
false, // ACTIVATE_PLATFORM_VPN
false, // LOADER_USAGE_STATS
false, // ACCESS_CALL_AUDIO
+ false, // AUTO_REVOKE_PERMISSIONS_IF_UNUSED
};
/**
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 6b1afda..c2b2063 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -23,6 +23,7 @@
import com.android.internal.annotations.Immutable;
import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
/**
* When an {@link AppOpsManager#noteOp(String, int, String, String, String) app-op is noted} and the
@@ -40,7 +41,7 @@
@DataClass.Suppress({"getOpCode"})
public final class AsyncNotedAppOp implements Parcelable {
/** Op that was noted */
- private final @IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int mOpCode;
+ private final @IntRange(from = 0) int mOpCode;
/** Uid that noted the op */
private final @IntRange(from = 0) int mNotingUid;
@@ -61,6 +62,12 @@
return AppOpsManager.opToPublicName(mOpCode);
}
+ //TODO eugenesusla: support inlinable expressions in annotation params of @DataClass members to
+ // allow validating via @IntRange(from = 0, to = AppOpsManager._NUM_OP - 1)
+ private void onConstructed() {
+ Preconditions.checkArgumentInRange(mOpCode, 0, AppOpsManager._NUM_OP - 1, "opCode");
+ }
+
// Code below generated by codegen v1.0.14.
@@ -93,7 +100,7 @@
*/
@DataClass.Generated.Member
public AsyncNotedAppOp(
- @IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
+ @IntRange(from = 0) int opCode,
@IntRange(from = 0) int notingUid,
@Nullable String featureId,
@NonNull String message,
@@ -101,8 +108,7 @@
this.mOpCode = opCode;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOpCode,
- "from", 0,
- "to", AppOpsManager._NUM_OP - 1);
+ "from", 0);
this.mNotingUid = notingUid;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mNotingUid,
@@ -116,7 +122,7 @@
IntRange.class, null, mTime,
"from", 0);
- // onConstructed(); // You can define this method to get a callback
+ onConstructed();
}
/**
@@ -223,8 +229,7 @@
this.mOpCode = opCode;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOpCode,
- "from", 0,
- "to", AppOpsManager._NUM_OP - 1);
+ "from", 0);
this.mNotingUid = notingUid;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mNotingUid,
@@ -238,7 +243,7 @@
IntRange.class, null, mTime,
"from", 0);
- // onConstructed(); // You can define this method to get a callback
+ onConstructed();
}
@DataClass.Generated.Member
@@ -256,10 +261,10 @@
};
@DataClass.Generated(
- time = 1581728574427L,
+ time = 1583375913345L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=96L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/WindowContext.java b/core/java/android/app/WindowContext.java
index 5684562..878993e 100644
--- a/core/java/android/app/WindowContext.java
+++ b/core/java/android/app/WindowContext.java
@@ -60,7 +60,6 @@
mWms = WindowManagerGlobal.getWindowManagerService();
mToken = new WindowTokenClient();
-
final ContextImpl contextImpl = createBaseWindowContext(base, mToken);
attachBaseContext(contextImpl);
contextImpl.setOuterContext(this);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b219394..c532279 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8781,18 +8781,20 @@
}
/**
+ * This method is mostly deprecated.
+ * Most of the settings that still have an effect have dedicated setter methods or user
+ * restrictions. See individual settings for details.
+ * <p>
* Called by device owner to update {@link android.provider.Settings.Global} settings.
* Validation that the value of the setting is in the correct form for the setting type should
* be performed by the caller.
* <p>
* The settings that can be updated with this method are:
* <ul>
- * <li>{@link android.provider.Settings.Global#ADB_ENABLED}</li>
- * <li>{@link android.provider.Settings.Global#AUTO_TIME}</li>
- * <li>{@link android.provider.Settings.Global#AUTO_TIME_ZONE}</li>
- * <li>{@link android.provider.Settings.Global#DATA_ROAMING}</li>
+ * <li>{@link android.provider.Settings.Global#ADB_ENABLED} : use
+ * {@link UserManager#DISALLOW_DEBUGGING_FEATURES} instead to restrict users from enabling
+ * debugging features and this setting to turn adb on.</li>
* <li>{@link android.provider.Settings.Global#USB_MASS_STORAGE_ENABLED}</li>
- * <li>{@link android.provider.Settings.Global#WIFI_SLEEP_POLICY}</li>
* <li>{@link android.provider.Settings.Global#STAY_ON_WHILE_PLUGGED_IN} This setting is only
* available from {@link android.os.Build.VERSION_CODES#M} onwards and can only be set if
* {@link #setMaximumTimeToLock} is not used to set a timeout.</li>
@@ -8800,6 +8802,16 @@
* setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards.</li>
* </ul>
* <p>
+ * The following settings used to be supported, but can be controlled in other ways:
+ * <ul>
+ * <li>{@link android.provider.Settings.Global#AUTO_TIME} : Use {@link #setAutoTime} and
+ * {@link UserManager#DISALLOW_CONFIG_DATE_TIME} instead.</li>
+ * <li>{@link android.provider.Settings.Global#AUTO_TIME_ZONE} : Use {@link #setAutoTimeZone}
+ * and {@link UserManager#DISALLOW_CONFIG_DATE_TIME} instead.</li>
+ * <li>{@link android.provider.Settings.Global#DATA_ROAMING} : Use
+ * {@link UserManager#DISALLOW_DATA_ROAMING} instead.</li>
+ * </ul>
+ * <p>
* Changing the following settings has no effect as of {@link android.os.Build.VERSION_CODES#M}:
* <ul>
* <li>{@link android.provider.Settings.Global#BLUETOOTH_ON}. Use
@@ -8811,6 +8823,7 @@
* <li>{@link android.provider.Settings.Global#NETWORK_PREFERENCE}</li>
* <li>{@link android.provider.Settings.Global#WIFI_ON}. Use
* {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li>
+ * <li>{@link android.provider.Settings.Global#WIFI_SLEEP_POLICY}. No longer has effect.</li>
* </ul>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -8989,6 +9002,11 @@
}
/**
+ * This method is mostly deprecated.
+ * Most of the settings that still have an effect have dedicated setter methods
+ * (e.g. {@link #setLocationEnabled}) or user restrictions.
+ * <p>
+ *
* Called by profile or device owners to update {@link android.provider.Settings.Secure}
* settings. Validation that the value of the setting is in the correct form for the setting
* type should be performed by the caller.
@@ -9001,7 +9019,7 @@
* <p>
* A device owner can additionally update the following settings:
* <ul>
- * <li>{@link android.provider.Settings.Secure#LOCATION_MODE}</li>
+ * <li>{@link android.provider.Settings.Secure#LOCATION_MODE}, but see note below.</li>
* </ul>
*
* <strong>Note: Starting from Android O, apps should no longer call this method with the
@@ -10355,19 +10373,23 @@
}
/**
- * Indicates the entity that controls the device or profile owner. Two users/profiles are
- * affiliated if the set of ids set by their device or profile owners intersect.
+ * Indicates the entity that controls the device. Two users are
+ * affiliated if the set of ids set by the device owner and the admin of the secondary user.
*
- * <p>A user/profile that is affiliated with the device owner user is considered to be
+ * <p>A user that is affiliated with the device owner user is considered to be
* affiliated with the device.
*
* <p><strong>Note:</strong> Features that depend on user affiliation (such as security logging
- * or {@link #bindDeviceAdminServiceAsUser}) won't be available when a secondary user or profile
+ * or {@link #bindDeviceAdminServiceAsUser}) won't be available when a secondary user
* is created, until it becomes affiliated. Therefore it is recommended that the appropriate
- * affiliation ids are set by its profile owner as soon as possible after the user/profile is
+ * affiliation ids are set by its owner as soon as possible after the user is
* created.
+ * <p>
+ * Note: This method used to be available for affiliating device owner and profile
+ * owner. However, since Android 11, this combination is not possible. This method is now
+ * only useful for affiliating the primary user with managed secondary users.
*
- * @param admin Which profile or device owner this request is associated with.
+ * @param admin Which device owner, or owner of secondary user, this request is associated with.
* @param ids A set of opaque non-empty affiliation ids.
*
* @throws IllegalArgumentException if {@code ids} is null or contains an empty string.
@@ -10399,10 +10421,10 @@
}
/**
- * Returns whether this user/profile is affiliated with the device.
+ * Returns whether this user is affiliated with the device.
* <p>
* By definition, the user that the device owner runs on is always affiliated with the device.
- * Any other user/profile is considered affiliated with the device if the set specified by its
+ * Any other user is considered affiliated with the device if the set specified by its
* profile owner via {@link #setAffiliationIds} intersects with the device owner's.
* @see #setAffiliationIds
*/
@@ -10706,14 +10728,18 @@
}
/**
- * Called by a device owner to bind to a service from a profile owner or vice versa.
- * See {@link #getBindDeviceAdminTargetUsers} for a definition of which
- * device/profile owners are allowed to bind to services of another profile/device owner.
+ * Called by a device owner to bind to a service from a secondary managed user or vice versa.
+ * See {@link #getBindDeviceAdminTargetUsers} for the pre-requirements of a
+ * device owner to bind to services of another managed user.
* <p>
* The service must be protected by {@link android.Manifest.permission#BIND_DEVICE_ADMIN}.
* Note that the {@link Context} used to obtain this
* {@link DevicePolicyManager} instance via {@link Context#getSystemService(Class)} will be used
* to bind to the {@link android.app.Service}.
+ * <p>
+ * Note: This method used to be available for communication between device owner and profile
+ * owner. However, since Android 11, this combination is not possible. This method is now
+ * only useful for communication between device owner and managed secondary users.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param serviceIntent Identifies the service to connect to. The Intent must specify either an
@@ -10751,14 +10777,11 @@
}
/**
- * Returns the list of target users that the calling device or profile owner can use when
- * calling {@link #bindDeviceAdminServiceAsUser}.
+ * Returns the list of target users that the calling device owner or owner of secondary user
+ * can use when calling {@link #bindDeviceAdminServiceAsUser}.
* <p>
- * A device owner can bind to a service from a profile owner and vice versa, provided that:
- * <ul>
- * <li>Both belong to the same package name.
- * <li>Both users are affiliated. See {@link #setAffiliationIds}.
- * </ul>
+ * A device owner can bind to a service from a secondary managed user and vice versa, provided
+ * that both users are affiliated. See {@link #setAffiliationIds}.
*/
public @NonNull List<UserHandle> getBindDeviceAdminTargetUsers(@NonNull ComponentName admin) {
throwIfParentInstance("getBindDeviceAdminTargetUsers");
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 66bfcbd..6ae68fc 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1229,10 +1229,11 @@
public boolean factoryReset() {
try {
mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.factoryReset();
+ if (mService != null && mService.factoryReset()
+ && mManagerService != null && mManagerService.onFactoryReset()) {
+ return true;
}
- Log.e(TAG, "factoryReset(): IBluetooth Service is null");
+ Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later");
SystemProperties.set("persist.bluetooth.factoryreset", "true");
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/content/ApexContext.java b/core/java/android/content/ApexEnvironment.java
similarity index 80%
rename from core/java/android/content/ApexContext.java
rename to core/java/android/content/ApexEnvironment.java
index fe5cedc..b4cc3c2 100644
--- a/core/java/android/content/ApexContext.java
+++ b/core/java/android/content/ApexEnvironment.java
@@ -30,29 +30,29 @@
* @hide
*/
@SystemApi
-public class ApexContext {
+public class ApexEnvironment {
private static final String APEX_DATA = "apexdata";
/**
- * Returns an ApexContext instance for the APEX with the provided {@code apexModuleName}.
+ * Returns an ApexEnvironment instance for the APEX with the provided {@code apexModuleName}.
*
- * <p>To preserve the safety and integrity of APEX modules, you must only obtain the ApexContext
- * for your specific APEX, and you <em>must never</em> attempt to obtain an ApexContext for
- * another APEX. Any coordination between APEXs must be performed through well-defined
- * interfaces; attempting to directly read or write raw files belonging to another APEX will
- * violate the hermetic storage requirements placed upon each module.
+ * <p>To preserve the safety and integrity of APEX modules, you must only obtain the
+ * ApexEnvironment for your specific APEX, and you <em>must never</em> attempt to obtain an
+ * ApexEnvironment for another APEX. Any coordination between APEXs must be performed through
+ * well-defined interfaces; attempting to directly read or write raw files belonging to another
+ * APEX will violate the hermetic storage requirements placed upon each module.
*/
@NonNull
- public static ApexContext getApexContext(@NonNull String apexModuleName) {
+ public static ApexEnvironment getApexEnvironment(@NonNull String apexModuleName) {
Objects.requireNonNull(apexModuleName, "apexModuleName cannot be null");
//TODO(b/141148175): Check that apexModuleName is an actual APEX name
- return new ApexContext(apexModuleName);
+ return new ApexEnvironment(apexModuleName);
}
private final String mApexModuleName;
- private ApexContext(String apexModuleName) {
+ private ApexEnvironment(String apexModuleName) {
mApexModuleName = apexModuleName;
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index ae786aa..911ffa0 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
@@ -4014,6 +4015,10 @@
* @hide
*/
@SystemApi
+ @TestApi
+ // We can't accept an already-opened FD here, since these methods are
+ // rewriting actual filesystem paths
+ @SuppressLint("StreamFiles")
public static @NonNull Uri decodeFromFile(@NonNull File file) {
return translateDeprecatedDataPath(file.getAbsolutePath());
}
@@ -4030,6 +4035,10 @@
* @hide
*/
@SystemApi
+ @TestApi
+ // We can't accept an already-opened FD here, since these methods are
+ // rewriting actual filesystem paths
+ @SuppressLint("StreamFiles")
public static @NonNull File encodeToFile(@NonNull Uri uri) {
return new File(translateDeprecatedDataPath(uri));
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4065b11..7600a08 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3403,29 +3403,12 @@
public static final int FLAG_PERMISSION_ONE_TIME = 1 << 16;
/**
- * Permission flag: The permission is whitelisted to not be auto-revoked when app goes unused.
- *
- * @hide
- */
- @SystemApi
- public static final int FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED = 1 << 17;
-
- /**
- * Permission flag: Whether {@link #FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED} state was set by
- * user.
- *
- * @hide
- */
- @SystemApi
- public static final int FLAG_PERMISSION_AUTO_REVOKE_USER_SET = 1 << 18;
-
- /**
* Permission flag: Whether permission was revoked by auto-revoke.
*
* @hide
*/
@SystemApi
- public static final int FLAG_PERMISSION_AUTO_REVOKED = 1 << 20;
+ public static final int FLAG_PERMISSION_AUTO_REVOKED = 1 << 17;
/**
* Permission flags: Reserved for use by the permission controller.
@@ -3479,8 +3462,6 @@
| FLAG_PERMISSION_GRANTED_BY_ROLE
| FLAG_PERMISSION_REVOKED_COMPAT
| FLAG_PERMISSION_ONE_TIME
- | FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED
- | FLAG_PERMISSION_AUTO_REVOKE_USER_SET
| FLAG_PERMISSION_AUTO_REVOKED;
/**
@@ -4305,8 +4286,6 @@
FLAG_PERMISSION_GRANTED_BY_ROLE,
FLAG_PERMISSION_REVOKED_COMPAT,
FLAG_PERMISSION_ONE_TIME,
- FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED,
- FLAG_PERMISSION_AUTO_REVOKE_USER_SET,
FLAG_PERMISSION_AUTO_REVOKED
})
@Retention(RetentionPolicy.SOURCE)
@@ -7474,8 +7453,6 @@
case FLAG_PERMISSION_GRANTED_BY_ROLE: return "GRANTED_BY_ROLE";
case FLAG_PERMISSION_REVOKED_COMPAT: return "REVOKED_COMPAT";
case FLAG_PERMISSION_ONE_TIME: return "ONE_TIME";
- case FLAG_PERMISSION_AUTO_REVOKE_IF_UNUSED: return "AUTO_REVOKE_IF_UNUSED";
- case FLAG_PERMISSION_AUTO_REVOKE_USER_SET: return "AUTO_REVOKE_USER_SET";
case FLAG_PERMISSION_AUTO_REVOKED: return "AUTO_REVOKED";
default: return Integer.toString(flag);
}
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 139f5be..83b5f63 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -248,6 +249,10 @@
* interface, the existing interface will be used.
* @param callback A callback to be called once the request has been fulfilled.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_STACK,
+ android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+ })
@NonNull
public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
@NonNull final TetheredInterfaceCallback callback) {
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 47f2461..a10a456 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentInterface;
import android.content.ContentProvider;
@@ -1303,6 +1304,7 @@
* {@hide}
*/
@SystemApi
+ @TestApi
public static @NonNull Uri setManageMode(@NonNull Uri uri) {
Preconditions.checkNotNull(uri, "uri can not be null");
return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
@@ -1314,6 +1316,7 @@
* {@hide}
*/
@SystemApi
+ @TestApi
public static boolean isManageMode(@NonNull Uri uri) {
Preconditions.checkNotNull(uri, "uri can not be null");
return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 97f7533..629dc8b 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -25,6 +25,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -4036,6 +4037,7 @@
* @hide
*/
@ChangeId
+ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q)
public static final long APN_READING_PERMISSION_CHANGE_ID = 124107808L;
}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index e8e1223..06b5fa0 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -89,7 +89,7 @@
private final @Nullable int[] mCancelIds;
private final boolean mSupportsInlineSuggestions;
// TODO(b/149240554): revert back to use ParceledListSlice after the bug is resolved.
- private final @Nullable ArrayList<InlinePresentation> mInlineActions;
+ private final @Nullable ArrayList<InlineAction> mInlineActions;
private FillResponse(@NonNull Builder builder) {
mDatasets = (builder.mDatasets != null) ? new ParceledListSlice<>(builder.mDatasets) : null;
@@ -213,7 +213,7 @@
}
/** @hide */
- public @Nullable List<InlinePresentation> getInlineActions() {
+ public @Nullable List<InlineAction> getInlineActions() {
return mInlineActions;
}
@@ -239,7 +239,7 @@
private UserData mUserData;
private int[] mCancelIds;
private boolean mSupportsInlineSuggestions;
- private ArrayList<InlinePresentation> mInlineActions;
+ private ArrayList<InlineAction> mInlineActions;
/**
* Triggers a custom UI before before autofilling the screen with any data set in this
@@ -656,15 +656,12 @@
}
/**
- * Adds a new {@link InlinePresentation} to this response representing an action UI.
- *
- * <p> For example, the UI can be associated with an intent which can open an activity for
- * the user to manage the Autofill provider settings.
+ * Adds a new {@link InlineAction} to this response representing an action UI.
*
* @return This builder.
*/
@NonNull
- public Builder addInlineAction(@NonNull InlinePresentation inlineAction) {
+ public Builder addInlineAction(@NonNull InlineAction inlineAction) {
throwIfDestroyed();
throwIfAuthenticationCalled();
if (mInlineActions == null) {
@@ -881,10 +878,10 @@
final int[] cancelIds = parcel.createIntArray();
builder.setPresentationCancelIds(cancelIds);
- final List<InlinePresentation> inlineActions = parcel.createTypedArrayList(
- InlinePresentation.CREATOR);
+ final List<InlineAction> inlineActions = parcel.createTypedArrayList(
+ InlineAction.CREATOR);
if (inlineActions != null) {
- for (InlinePresentation inlineAction : inlineActions) {
+ for (InlineAction inlineAction : inlineActions) {
builder.addInlineAction(inlineAction);
}
}
diff --git a/core/java/android/service/autofill/InlineAction.aidl b/core/java/android/service/autofill/InlineAction.aidl
new file mode 100644
index 0000000..7f85118
--- /dev/null
+++ b/core/java/android/service/autofill/InlineAction.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 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.service.autofill;
+
+parcelable InlineAction;
diff --git a/core/java/android/service/autofill/InlineAction.java b/core/java/android/service/autofill/InlineAction.java
new file mode 100644
index 0000000..17c4b33
--- /dev/null
+++ b/core/java/android/service/autofill/InlineAction.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 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.service.autofill;
+
+import android.annotation.NonNull;
+import android.content.IntentSender;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Represents an inline action as part of the autofill/augmented autofill response.
+ *
+ * <p> It includes both the action intent and the UI presentation. For example, the UI can be
+ * associated with an intent which can open an activity for the user to manage the Autofill provider
+ * settings.
+ */
+@DataClass(
+ genToString = true,
+ genHiddenConstDefs = true,
+ genEqualsHashCode = true)
+public final class InlineAction implements Parcelable {
+
+ /**
+ * Representation of the inline action.
+ */
+ private final @NonNull InlinePresentation mInlinePresentation;
+
+ /**
+ * The associated intent which will be triggered when the action is selected. It will only be
+ * called by the OS.
+ */
+ private final @NonNull IntentSender mAction;
+
+
+
+ // Code below generated by codegen v1.0.15.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/InlineAction.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new InlineAction.
+ *
+ * @param inlinePresentation
+ * Representation of the inline action.
+ * @param action
+ * The associated intent which will be triggered when the action is selected. It will only be
+ * invoked by the OS.
+ */
+ @DataClass.Generated.Member
+ public InlineAction(
+ @NonNull InlinePresentation inlinePresentation,
+ @NonNull IntentSender action) {
+ this.mInlinePresentation = inlinePresentation;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mInlinePresentation);
+ this.mAction = action;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAction);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * Representation of the inline action.
+ */
+ @DataClass.Generated.Member
+ public @NonNull InlinePresentation getInlinePresentation() {
+ return mInlinePresentation;
+ }
+
+ /**
+ * The associated intent which will be triggered when the action is selected. It will only be
+ * invoked by the OS.
+ */
+ @DataClass.Generated.Member
+ public @NonNull IntentSender getAction() {
+ return mAction;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InlineAction { " +
+ "inlinePresentation = " + mInlinePresentation + ", " +
+ "action = " + mAction +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(InlineAction other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ InlineAction that = (InlineAction) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mInlinePresentation, that.mInlinePresentation)
+ && java.util.Objects.equals(mAction, that.mAction);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mInlinePresentation);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAction);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeTypedObject(mInlinePresentation, flags);
+ dest.writeTypedObject(mAction, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ InlineAction(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ InlinePresentation inlinePresentation = (InlinePresentation) in.readTypedObject(InlinePresentation.CREATOR);
+ IntentSender action = (IntentSender) in.readTypedObject(IntentSender.CREATOR);
+
+ this.mInlinePresentation = inlinePresentation;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mInlinePresentation);
+ this.mAction = action;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAction);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InlineAction> CREATOR
+ = new Parcelable.Creator<InlineAction>() {
+ @Override
+ public InlineAction[] newArray(int size) {
+ return new InlineAction[size];
+ }
+
+ @Override
+ public InlineAction createFromParcel(@NonNull android.os.Parcel in) {
+ return new InlineAction(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1583798182424L,
+ codegenVersion = "1.0.15",
+ sourceFile = "frameworks/base/core/java/android/service/autofill/InlineAction.java",
+ inputSignatures = "private final @android.annotation.NonNull android.service.autofill.InlinePresentation mInlinePresentation\nprivate final @android.annotation.NonNull android.content.IntentSender mAction\nclass InlineAction extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index fe792b1..ed27dd5 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -40,7 +40,7 @@
import android.os.SystemClock;
import android.service.autofill.Dataset;
import android.service.autofill.FillEventHistory;
-import android.service.autofill.InlinePresentation;
+import android.service.autofill.InlineAction;
import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
import android.util.Log;
import android.util.Pair;
@@ -559,7 +559,7 @@
}
void reportResult(@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable List<InlinePresentation> inlineActions) {
+ @Nullable List<InlineAction> inlineActions) {
try {
mCallback.onSuccess(inlineSuggestionsData, inlineActions);
} catch (RemoteException e) {
diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
index b7fdf5a..f564b3b 100644
--- a/core/java/android/service/autofill/augmented/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -21,7 +21,7 @@
import android.annotation.TestApi;
import android.os.Bundle;
import android.service.autofill.Dataset;
-import android.service.autofill.InlinePresentation;
+import android.service.autofill.InlineAction;
import com.android.internal.util.DataClass;
@@ -53,11 +53,10 @@
private @Nullable List<Dataset> mInlineSuggestions;
/**
- * The {@link InlinePresentation}s representing the inline actions. Defaults to null if no
- * inline actions are provided.
+ * Defaults to null if no inline actions are provided.
*/
@DataClass.PluralOf("inlineAction")
- private @Nullable List<InlinePresentation> mInlineActions;
+ private @Nullable List<InlineAction> mInlineActions;
/**
* The client state that {@link AugmentedAutofillService} implementation can put anything in to
@@ -74,7 +73,7 @@
return null;
}
- private static List<InlinePresentation> defaultInlineActions() {
+ private static List<InlineAction> defaultInlineActions() {
return null;
}
@@ -86,12 +85,12 @@
/** @hide */
abstract static class BaseBuilder {
abstract FillResponse.Builder addInlineSuggestion(@NonNull Dataset value);
- abstract FillResponse.Builder addInlineAction(@NonNull InlinePresentation value);
+ abstract FillResponse.Builder addInlineAction(@NonNull InlineAction value);
}
- // Code below generated by codegen v1.0.14.
+ // Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -108,7 +107,7 @@
/* package-private */ FillResponse(
@Nullable FillWindow fillWindow,
@Nullable List<Dataset> inlineSuggestions,
- @Nullable List<InlinePresentation> inlineActions,
+ @Nullable List<InlineAction> inlineActions,
@Nullable Bundle clientState) {
this.mFillWindow = fillWindow;
this.mInlineSuggestions = inlineSuggestions;
@@ -140,13 +139,12 @@
}
/**
- * The {@link InlinePresentation}s representing the inline actions. Defaults to null if no
- * inline actions are provided.
+ * Defaults to null if no inline actions are provided.
*
* @hide
*/
@DataClass.Generated.Member
- public @Nullable List<InlinePresentation> getInlineActions() {
+ public @Nullable List<InlineAction> getInlineActions() {
return mInlineActions;
}
@@ -171,7 +169,7 @@
private @Nullable FillWindow mFillWindow;
private @Nullable List<Dataset> mInlineSuggestions;
- private @Nullable List<InlinePresentation> mInlineActions;
+ private @Nullable List<InlineAction> mInlineActions;
private @Nullable Bundle mClientState;
private long mBuilderFieldsSet = 0L;
@@ -183,7 +181,7 @@
* The {@link FillWindow} used to display the Autofill UI.
*/
@DataClass.Generated.Member
- public @NonNull Builder setFillWindow(@Nullable FillWindow value) {
+ public @NonNull Builder setFillWindow(@NonNull FillWindow value) {
checkNotUsed();
mBuilderFieldsSet |= 0x1;
mFillWindow = value;
@@ -195,7 +193,7 @@
* inline suggestions are available from the service.
*/
@DataClass.Generated.Member
- public @NonNull Builder setInlineSuggestions(@Nullable List<Dataset> value) {
+ public @NonNull Builder setInlineSuggestions(@NonNull List<Dataset> value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
mInlineSuggestions = value;
@@ -212,11 +210,10 @@
}
/**
- * The {@link InlinePresentation}s representing the inline actions. Defaults to null if no
- * inline actions are provided.
+ * Defaults to null if no inline actions are provided.
*/
@DataClass.Generated.Member
- public @NonNull Builder setInlineActions(@Nullable List<InlinePresentation> value) {
+ public @NonNull Builder setInlineActions(@NonNull List<InlineAction> value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
mInlineActions = value;
@@ -226,7 +223,7 @@
/** @see #setInlineActions */
@DataClass.Generated.Member
@Override
- @NonNull FillResponse.Builder addInlineAction(@NonNull InlinePresentation value) {
+ @NonNull FillResponse.Builder addInlineAction(@NonNull InlineAction value) {
if (mInlineActions == null) setInlineActions(new ArrayList<>());
mInlineActions.add(value);
return this;
@@ -238,7 +235,7 @@
* {@link AugmentedAutofillService#getFillEventHistory()}.
*/
@DataClass.Generated.Member
- public @NonNull Builder setClientState(@Nullable Bundle value) {
+ public @NonNull Builder setClientState(@NonNull Bundle value) {
checkNotUsed();
mBuilderFieldsSet |= 0x8;
mClientState = value;
@@ -279,10 +276,10 @@
}
@DataClass.Generated(
- time = 1582682935951L,
- codegenVersion = "1.0.14",
+ time = 1583793032373L,
+ codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/service/autofill/augmented/FillResponse.java",
- inputSignatures = "private @android.annotation.Nullable android.service.autofill.augmented.FillWindow mFillWindow\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineSuggestion\") @android.annotation.Nullable java.util.List<android.service.autofill.Dataset> mInlineSuggestions\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineAction\") @android.annotation.Nullable java.util.List<android.service.autofill.InlinePresentation> mInlineActions\nprivate @android.annotation.Nullable android.os.Bundle mClientState\nprivate static android.service.autofill.augmented.FillWindow defaultFillWindow()\nprivate static java.util.List<android.service.autofill.Dataset> defaultInlineSuggestions()\nprivate static java.util.List<android.service.autofill.InlinePresentation> defaultInlineActions()\nprivate static android.os.Bundle defaultClientState()\nclass FillResponse extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genHiddenGetters=true)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineSuggestion(android.service.autofill.Dataset)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineAction(android.service.autofill.InlinePresentation)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "private @android.annotation.Nullable android.service.autofill.augmented.FillWindow mFillWindow\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineSuggestion\") @android.annotation.Nullable java.util.List<android.service.autofill.Dataset> mInlineSuggestions\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineAction\") @android.annotation.Nullable java.util.List<android.service.autofill.InlineAction> mInlineActions\nprivate @android.annotation.Nullable android.os.Bundle mClientState\nprivate static android.service.autofill.augmented.FillWindow defaultFillWindow()\nprivate static java.util.List<android.service.autofill.Dataset> defaultInlineSuggestions()\nprivate static java.util.List<android.service.autofill.InlineAction> defaultInlineActions()\nprivate static android.os.Bundle defaultClientState()\nclass FillResponse extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genHiddenGetters=true)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineSuggestion(android.service.autofill.Dataset)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineAction(android.service.autofill.InlineAction)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
index bf0adcd..545dab2 100644
--- a/core/java/android/service/autofill/augmented/IFillCallback.aidl
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -20,7 +20,7 @@
import android.os.ICancellationSignal;
import android.service.autofill.Dataset;
-import android.service.autofill.InlinePresentation;
+import android.service.autofill.InlineAction;
import java.util.List;
@@ -32,7 +32,7 @@
interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
void onSuccess(in @nullable List<Dataset> inlineSuggestionsData,
- in @nullable List<InlinePresentation> inlineActions);
+ in @nullable List<InlineAction> inlineActions);
boolean isCompleted();
void cancel();
}
diff --git a/core/java/android/service/contentcapture/DataShareReadAdapter.java b/core/java/android/service/contentcapture/DataShareReadAdapter.java
index a481ec8..8cd9eea 100644
--- a/core/java/android/service/contentcapture/DataShareReadAdapter.java
+++ b/core/java/android/service/contentcapture/DataShareReadAdapter.java
@@ -20,6 +20,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.ParcelFileDescriptor;
+import android.view.contentcapture.ContentCaptureManager.DataShareError;
/**
* Adapter class to be used for the Content Capture Service app to propagate the status of the
@@ -46,5 +47,5 @@
* these 2 events is not defined, and it's important that the service treats end of stream
* correctly in this situation.
**/
- void onError(int errorCode);
+ void onError(@DataShareError int errorCode);
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 73601d9..84ac90b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -724,11 +724,12 @@
/**
* Called to get the expected window insets.
- * TODO(window-context): Remove when new insets flag is available.
+ *
+ * @return {@code true} if system bars are always comsumed.
*/
- void getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
+ boolean getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
out Rect outContentInsets, out Rect outStableInsets,
- out DisplayCutout.ParcelableWrapper displayCutout);
+ out DisplayCutout.ParcelableWrapper outDisplayCutout, out InsetsState outInsetsState);
/**
* Called to show global actions.
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index f52960c..302d4f3 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -724,12 +724,13 @@
mApplier = new SyncRtSurfaceTransactionApplier(mViewRoot.mView);
}
if (mViewRoot.mView.isHardwareAccelerated()) {
- mApplier.scheduleApply(params);
+ mApplier.scheduleApply(false /* earlyWakeup */, params);
} else {
// Window doesn't support hardware acceleration, no synchronization for now.
// TODO(b/149342281): use mViewRoot.mSurface.getNextFrameNumber() to sync on every
// frame instead.
- mApplier.applyParams(new Transaction(), -1 /* frame */, params);
+ mApplier.applyParams(new Transaction(), -1 /* frame */, false /* earlyWakeup */,
+ params);
}
}
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index e4aa410..c2ad74a 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -80,6 +80,12 @@
})
public @interface InternalInsetsType {}
+ /**
+ * Special value to be used to by methods returning an {@link InternalInsetsType} to indicate
+ * that the objects/parameters aren't associated with an {@link InternalInsetsType}
+ */
+ public static final int ITYPE_INVALID = -1;
+
static final int FIRST_TYPE = 0;
public static final int ITYPE_STATUS_BAR = FIRST_TYPE;
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index b04372a..3c22ed8 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -20,9 +20,11 @@
import static android.view.RemoteAnimationTargetProto.CONTENT_INSETS;
import static android.view.RemoteAnimationTargetProto.IS_TRANSLUCENT;
import static android.view.RemoteAnimationTargetProto.LEASH;
+import static android.view.RemoteAnimationTargetProto.LOCAL_BOUNDS;
import static android.view.RemoteAnimationTargetProto.MODE;
import static android.view.RemoteAnimationTargetProto.POSITION;
import static android.view.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
+import static android.view.RemoteAnimationTargetProto.SCREEN_SPACE_BOUNDS;
import static android.view.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
import static android.view.RemoteAnimationTargetProto.START_BOUNDS;
import static android.view.RemoteAnimationTargetProto.START_LEASH;
@@ -130,19 +132,38 @@
* The source position of the app, in screen spaces coordinates. If the position of the leash
* is modified from the controlling app, any animation transform needs to be offset by this
* amount.
+ * @deprecated Use {@link #localBounds} instead.
*/
+ @Deprecated
@UnsupportedAppUsage
public final Point position;
/**
+ * Bounds of the target relative to its parent.
+ * When the app target animating on its parent, we need to use the local coordinates relative to
+ * its parent with {@code localBounds.left} & {@code localBounds.top} rather than using
+ * {@code position} in screen coordinates.
+ */
+ public final Rect localBounds;
+
+ /**
* The bounds of the source container the app lives in, in screen space coordinates. If the crop
* of the leash is modified from the controlling app, it needs to take the source container
* bounds into account when calculating the crop.
+ * @deprecated Renamed to {@link #screenSpaceBounds}
*/
+ @Deprecated
@UnsupportedAppUsage
public final Rect sourceContainerBounds;
/**
+ * Bounds of the target relative to the screen. If the crop of the leash is modified from the
+ * controlling app, it needs to take the screen space bounds into account when calculating the
+ * crop.
+ */
+ public final Rect screenSpaceBounds;
+
+ /**
* The starting bounds of the source container in screen space coordinates. This is {@code null}
* if the animation target isn't MODE_CHANGING. Since this is the starting bounds, it's size
* should be equivalent to the size of the starting thumbnail. Note that sourceContainerBounds
@@ -165,7 +186,8 @@
public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
- Rect sourceContainerBounds, WindowConfiguration windowConfig, boolean isNotInRecents,
+ Rect localBounds, Rect screenSpaceBounds,
+ WindowConfiguration windowConfig, boolean isNotInRecents,
SurfaceControl startLeash, Rect startBounds) {
this.mode = mode;
this.taskId = taskId;
@@ -175,7 +197,9 @@
this.contentInsets = new Rect(contentInsets);
this.prefixOrderIndex = prefixOrderIndex;
this.position = new Point(position);
- this.sourceContainerBounds = new Rect(sourceContainerBounds);
+ this.localBounds = new Rect(localBounds);
+ this.sourceContainerBounds = new Rect(screenSpaceBounds);
+ this.screenSpaceBounds = new Rect(screenSpaceBounds);
this.windowConfiguration = windowConfig;
this.isNotInRecents = isNotInRecents;
this.startLeash = startLeash;
@@ -191,7 +215,9 @@
contentInsets = in.readParcelable(null);
prefixOrderIndex = in.readInt();
position = in.readParcelable(null);
+ localBounds = in.readParcelable(null);
sourceContainerBounds = in.readParcelable(null);
+ screenSpaceBounds = in.readParcelable(null);
windowConfiguration = in.readParcelable(null);
isNotInRecents = in.readBoolean();
startLeash = in.readParcelable(null);
@@ -213,7 +239,9 @@
dest.writeParcelable(contentInsets, 0 /* flags */);
dest.writeInt(prefixOrderIndex);
dest.writeParcelable(position, 0 /* flags */);
+ dest.writeParcelable(localBounds, 0 /* flags */);
dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
+ dest.writeParcelable(screenSpaceBounds, 0 /* flags */);
dest.writeParcelable(windowConfiguration, 0 /* flags */);
dest.writeBoolean(isNotInRecents);
dest.writeParcelable(startLeash, 0 /* flags */);
@@ -229,6 +257,8 @@
pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex);
pw.print(" position="); position.printShortString(pw);
pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw);
+ pw.print(" screenSpaceBounds="); screenSpaceBounds.printShortString(pw);
+ pw.print(" localBounds="); localBounds.printShortString(pw);
pw.println();
pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration);
pw.print(prefix); pw.print("leash="); pw.println(leash);
@@ -245,6 +275,8 @@
proto.write(PREFIX_ORDER_INDEX, prefixOrderIndex);
position.dumpDebug(proto, POSITION);
sourceContainerBounds.dumpDebug(proto, SOURCE_CONTAINER_BOUNDS);
+ screenSpaceBounds.dumpDebug(proto, SCREEN_SPACE_BOUNDS);
+ localBounds.dumpDebug(proto, LOCAL_BOUNDS);
windowConfiguration.dumpDebug(proto, WINDOW_CONFIGURATION);
if (startLeash != null) {
startLeash.dumpDebug(proto, START_LEASH);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index fb7c04a..1f7c3504 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -605,7 +605,7 @@
mTmpRect.set(0, 0, mSurfaceWidth, mSurfaceHeight);
}
SyncRtSurfaceTransactionApplier applier = new SyncRtSurfaceTransactionApplier(this);
- applier.scheduleApply(
+ applier.scheduleApply(false /* earlyWakeup */,
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(mSurfaceControl)
.withWindowCrop(mTmpRect)
.build());
diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index 206e4f9..9c97f3e 100644
--- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -53,10 +53,11 @@
/**
* Schedules applying surface parameters on the next frame.
*
+ * @param earlyWakeup Whether to set {@link Transaction#setEarlyWakeup()} on transaction.
* @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
* this method to avoid synchronization issues.
*/
- public void scheduleApply(final SurfaceParams... params) {
+ public void scheduleApply(boolean earlyWakeup, final SurfaceParams... params) {
if (mTargetViewRootImpl == null) {
return;
}
@@ -66,7 +67,7 @@
return;
}
Transaction t = new Transaction();
- applyParams(t, frame, params);
+ applyParams(t, frame, earlyWakeup, params);
});
// Make sure a frame gets scheduled.
@@ -77,10 +78,12 @@
* Applies surface parameters on the next frame.
* @param t transaction to apply all parameters in.
* @param frame frame to synchronize to. Set -1 when sync is not required.
+ * @param earlyWakeup Whether to set {@link Transaction#setEarlyWakeup()} on transaction.
* @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
* this method to avoid synchronization issues.
*/
- void applyParams(Transaction t, long frame, final SurfaceParams... params) {
+ void applyParams(Transaction t, long frame, boolean earlyWakeup,
+ final SurfaceParams... params) {
for (int i = params.length - 1; i >= 0; i--) {
SurfaceParams surfaceParams = params[i];
SurfaceControl surface = surfaceParams.surface;
@@ -89,7 +92,9 @@
}
applyParams(t, surfaceParams, mTmpFloat9);
}
- t.setEarlyWakeup();
+ if (earlyWakeup) {
+ t.setEarlyWakeup();
+ }
t.apply();
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b6c46be..7d4ec3d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3714,7 +3714,7 @@
if (extraDataKey.equals(AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY)) {
final AccessibilityNodeInfo.ExtraRenderingInfo extraRenderingInfo =
AccessibilityNodeInfo.ExtraRenderingInfo.obtain();
- extraRenderingInfo.setLayoutParams(getLayoutParams().width, getLayoutParams().height);
+ extraRenderingInfo.setLayoutSize(getLayoutParams().width, getLayoutParams().height);
info.setExtraRenderingInfo(extraRenderingInfo);
}
}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 6435b42..4050da1 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -18,8 +18,11 @@
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import android.annotation.NonNull;
import android.app.ResourcesManager;
@@ -215,9 +218,9 @@
@Override
public WindowMetrics getCurrentWindowMetrics() {
final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
- final Rect bound = getCurrentBounds(context);
+ final Rect bounds = getCurrentBounds(context);
- return new WindowMetrics(toSize(bound), computeWindowInsets());
+ return new WindowMetrics(toSize(bounds), computeWindowInsets(bounds));
}
private static Rect getCurrentBounds(Context context) {
@@ -228,7 +231,8 @@
@Override
public WindowMetrics getMaximumWindowMetrics() {
- return new WindowMetrics(toSize(getMaximumBounds()), computeWindowInsets());
+ final Rect maxBounds = getMaximumBounds();
+ return new WindowMetrics(toSize(maxBounds), computeWindowInsets(maxBounds));
}
private Size toSize(Rect frame) {
@@ -244,9 +248,8 @@
return new Rect(0, 0, displaySize.x, displaySize.y);
}
- private WindowInsets computeWindowInsets() {
- // TODO(b/118118435): This can only be properly implemented
- // once we flip the new insets mode flag.
+ // TODO(b/150095967): Set window type to LayoutParams
+ private WindowInsets computeWindowInsets(Rect bounds) {
// Initialize params which used for obtaining all system insets.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
@@ -257,21 +260,34 @@
params.setFitInsetsTypes(0);
params.setFitInsetsSides(0);
- return getWindowInsetsFromServer(params);
+ return getWindowInsetsFromServer(params, bounds);
}
- private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) {
+ private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs, Rect bounds) {
try {
final Rect systemWindowInsets = new Rect();
final Rect stableInsets = new Rect();
final DisplayCutout.ParcelableWrapper displayCutout =
new DisplayCutout.ParcelableWrapper();
- WindowManagerGlobal.getWindowManagerService().getWindowInsets(attrs,
- mContext.getDisplayId(), systemWindowInsets, stableInsets, displayCutout);
- return new WindowInsets.Builder()
- .setSystemWindowInsets(Insets.of(systemWindowInsets))
- .setStableInsets(Insets.of(stableInsets))
- .setDisplayCutout(displayCutout.get()).build();
+ final InsetsState insetsState = new InsetsState();
+ final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
+ .getWindowInsets(attrs, mContext.getDisplayId(), systemWindowInsets,
+ stableInsets, displayCutout, insetsState);
+ final boolean isScreenRound =
+ mContext.getResources().getConfiguration().isScreenRound();
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+ return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
+ isScreenRound, alwaysConsumeSystemBars, displayCutout.get(),
+ systemWindowInsets, stableInsets, SOFT_INPUT_ADJUST_NOTHING,
+ SYSTEM_UI_FLAG_VISIBLE, null /* typeSideMap */);
+ } else {
+ return new WindowInsets.Builder()
+ .setAlwaysConsumeSystemBars(alwaysConsumeSystemBars)
+ .setRound(isScreenRound)
+ .setSystemWindowInsets(Insets.of(systemWindowInsets))
+ .setStableInsets(Insets.of(stableInsets))
+ .setDisplayCutout(displayCutout.get()).build();
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index f2cbf89..5fccf40 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -559,14 +559,6 @@
public static final String ACTION_ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT =
"android.view.accessibility.action.ARGUMENT_PRESS_AND_HOLD_DURATION_MILLIS_INT";
- /**
- * Argument to represent the IME action Id to press the returning key on a node.
- * For use with R.id.accessibilityActionImeEnter
- * @hide
- */
- public static final String ACTION_ARGUMENT_IME_ACTION_ID_INT =
- "android.view.accessibility.action.ARGUMENT_IME_ACTION_ID_INT";
-
// Focus types
/**
@@ -649,7 +641,7 @@
* argument.
* <p>
* The data can be retrieved from the {@link ExtraRenderingInfo} returned by
- * {@link #getExtraRenderingInfo()} using {@link ExtraRenderingInfo#getLayoutParams},
+ * {@link #getExtraRenderingInfo()} using {@link ExtraRenderingInfo#getLayoutSize},
* {@link ExtraRenderingInfo#getTextSizeInPx()} and
* {@link ExtraRenderingInfo#getTextSizeUnit()}. For layout params, it is supported by both
* {@link TextView} and {@link ViewGroup}. For text size and unit, it is only supported by
@@ -657,7 +649,6 @@
*
* @see #refreshWithExtraData(String, Bundle)
*/
-
public static final String EXTRA_DATA_RENDERING_INFO_KEY =
"android.view.accessibility.extra.DATA_RENDERING_INFO_KEY";
@@ -1038,8 +1029,8 @@
* with this mechanism is generally expensive to retrieve, so should only be
* requested when needed. See
* {@link #EXTRA_DATA_RENDERING_INFO_KEY},
- * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
- * {@link #getAvailableExtraData()}.
+ * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY},
+ * {@link #getAvailableExtraData()} and {@link #getExtraRenderingInfo()}.
* @param args A bundle of arguments for the request. These depend on the particular request.
*
* @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
@@ -2437,9 +2428,13 @@
}
/**
- * Gets the conformance info if the node is meant to be refreshed with extra data.
+ * Gets the {@link ExtraRenderingInfo extra rendering info} if the node is meant to be
+ * refreshed with extra data to examine rendering related accessibility issues.
*
- * @return The conformance info.
+ * @return The {@link ExtraRenderingInfo extra rendering info}.
+ *
+ * @see #EXTRA_DATA_RENDERING_INFO_KEY
+ * @see #refreshWithExtraData(String, Bundle)
*/
@Nullable
public ExtraRenderingInfo getExtraRenderingInfo() {
@@ -2447,14 +2442,15 @@
}
/**
- * Sets the conformance info if the node is meant to be refreshed with extra data.
+ * Sets the extra rendering info, <code>extraRenderingInfo<code/>, if the node is meant to be
+ * refreshed with extra data.
* <p>
* <strong>Note:</strong> Cannot be called from an
* {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
*
- * @param extraRenderingInfo The conformance info.
+ * @param extraRenderingInfo The {@link ExtraRenderingInfo extra rendering info}.
* @hide
*/
public void setExtraRenderingInfo(@NonNull ExtraRenderingInfo extraRenderingInfo) {
@@ -3925,7 +3921,7 @@
}
if (isBitSet(nonDefaultFields, fieldIndex++)) {
- parcel.writeValue(mExtraRenderingInfo.getLayoutParams());
+ parcel.writeValue(mExtraRenderingInfo.getLayoutSize());
parcel.writeFloat(mExtraRenderingInfo.getTextSizeInPx());
parcel.writeInt(mExtraRenderingInfo.getTextSizeUnit());
}
@@ -4189,7 +4185,7 @@
if (isBitSet(nonDefaultFields, fieldIndex++)) {
if (mExtraRenderingInfo != null) mExtraRenderingInfo.recycle();
mExtraRenderingInfo = ExtraRenderingInfo.obtain();
- mExtraRenderingInfo.mLayoutParams = (Size) parcel.readValue(null);
+ mExtraRenderingInfo.mLayoutSize = (Size) parcel.readValue(null);
mExtraRenderingInfo.mTextSizeInPx = parcel.readFloat();
mExtraRenderingInfo.mTextSizeUnit = parcel.readInt();
}
@@ -4969,10 +4965,11 @@
new AccessibilityAction(R.id.accessibilityActionPressAndHold);
/**
- * Action to send an ime action which is from
- * {@link android.view.inputmethod.EditorInfo#actionId}. This action would be
+ * Action to send an ime actionId which is from
+ * {@link android.view.inputmethod.EditorInfo#actionId}. This ime actionId sets by
+ * {@link TextView#setImeActionLabel(CharSequence, int)}, or it would be
* {@link android.view.inputmethod.EditorInfo#IME_ACTION_UNSPECIFIED} if no specific
- * actionId defined. A node should expose this action only for views that are currently
+ * actionId has set. A node should expose this action only for views that are currently
* with input focus and editable.
*/
@NonNull public static final AccessibilityAction ACTION_IME_ENTER =
@@ -5808,7 +5805,7 @@
private static final SynchronizedPool<ExtraRenderingInfo> sPool =
new SynchronizedPool<>(MAX_POOL_SIZE);
- private Size mLayoutParams;
+ private Size mLayoutSize;
private float mTextSizeInPx = UNDEFINED_VALUE;
private int mTextSizeUnit = UNDEFINED_VALUE;
@@ -5828,32 +5825,36 @@
/** Obtains a pooled instance that is a clone of another one. */
private static ExtraRenderingInfo obtain(ExtraRenderingInfo other) {
ExtraRenderingInfo extraRenderingInfo = ExtraRenderingInfo.obtain();
- extraRenderingInfo.mLayoutParams = other.mLayoutParams;
+ extraRenderingInfo.mLayoutSize = other.mLayoutSize;
extraRenderingInfo.mTextSizeInPx = other.mTextSizeInPx;
extraRenderingInfo.mTextSizeUnit = other.mTextSizeUnit;
return extraRenderingInfo;
}
/**
- * Creates a new conformance info of a view, and this new instance is initialized from
+ * Creates a new rendering info of a view, and this new instance is initialized from
* the given <code>other</code>.
*
* @param other The instance to clone.
*/
private ExtraRenderingInfo(@Nullable ExtraRenderingInfo other) {
if (other != null) {
- mLayoutParams = other.mLayoutParams;
+ mLayoutSize = other.mLayoutSize;
mTextSizeInPx = other.mTextSizeInPx;
mTextSizeUnit = other.mTextSizeUnit;
}
}
/**
+ * Gets the size object containing the height and the width of layout params if the node is
+ * a {@link ViewGroup} or a {@link TextView}, or null otherwise. Useful for accessibility
+ * scanning tool to understand whether the text is scalable and fits the view or not.
+ *
* @return a {@link Size} stores layout height and layout width of the view,
* or null otherwise.
*/
- public @Nullable Size getLayoutParams() {
- return mLayoutParams;
+ public @Nullable Size getLayoutSize() {
+ return mLayoutSize;
}
/**
@@ -5863,11 +5864,15 @@
* @param height The layout height.
* @hide
*/
- public void setLayoutParams(int width, int height) {
- mLayoutParams = new Size(width, height);
+ public void setLayoutSize(int width, int height) {
+ mLayoutSize = new Size(width, height);
}
/**
+ * Gets the text size if the node is a {@link TextView}, or -1 otherwise. Useful for
+ * accessibility scanning tool to understand whether the text is scalable and fits the view
+ * or not.
+ *
* @return the text size of a {@code TextView}, or -1 otherwise.
*/
public float getTextSizeInPx() {
@@ -5885,6 +5890,11 @@
}
/**
+ * Gets the text size unit if the node is a {@link TextView}, or -1 otherwise.
+ * Text size returned from {@link #getTextSizeInPx} in raw pixels may scale by factors and
+ * convert from other units. Useful for accessibility scanning tool to understand whether
+ * the text is scalable and fits the view or not.
+ *
* @return the text size unit which type is {@link TypedValue#TYPE_DIMENSION} of a
* {@code TextView}, or -1 otherwise.
*
@@ -5915,7 +5925,7 @@
}
private void clear() {
- mLayoutParams = null;
+ mLayoutSize = null;
mTextSizeInPx = UNDEFINED_VALUE;
mTextSizeUnit = UNDEFINED_VALUE;
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index b7b54c8..b988927 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -217,6 +217,15 @@
public static final int DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED = 3;
/** @hide */
+ @IntDef(flag = false, value = {
+ DATA_SHARE_ERROR_UNKNOWN,
+ DATA_SHARE_ERROR_CONCURRENT_REQUEST,
+ DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DataShareError {}
+
+ /** @hide */
public static final int RESULT_CODE_OK = 0;
/** @hide */
public static final int RESULT_CODE_TRUE = 1;
diff --git a/core/java/android/view/contentcapture/DataShareWriteAdapter.java b/core/java/android/view/contentcapture/DataShareWriteAdapter.java
index 2beaede..3b5b756 100644
--- a/core/java/android/view/contentcapture/DataShareWriteAdapter.java
+++ b/core/java/android/view/contentcapture/DataShareWriteAdapter.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.os.ParcelFileDescriptor;
+import android.view.contentcapture.ContentCaptureManager.DataShareError;
/** Adapter class used by apps to share data with the Content Capture service. */
public interface DataShareWriteAdapter {
@@ -42,7 +43,7 @@
*
* @param errorCode the error code corresponding to an ERROR_* value.
*/
- default void onError(int errorCode) {
+ default void onError(@DataShareError int errorCode) {
/* do nothing - stub */
}
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 13c1f67..816612f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4587,7 +4587,8 @@
protected int mHorizontalGravity;
// Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
private float mTouchOffsetY;
- // Where the touch position should be on the handle to ensure a maximum cursor visibility
+ // Where the touch position should be on the handle to ensure a maximum cursor visibility.
+ // This is the distance in pixels from the top of the handle view.
private float mIdealVerticalOffset;
// Parent's (TextView) previous position in window
private int mLastParentX, mLastParentY;
@@ -4612,6 +4613,11 @@
// when magnifier is used.
private float mTextViewScaleX;
private float mTextViewScaleY;
+ /**
+ * The vertical distance in pixels from finger to the cursor Y while dragging.
+ * See {@link Editor.InsertionPointCursorController#getLineDuringDrag}.
+ */
+ private final int mIdealFingerToCursorOffset;
private HandleView(Drawable drawableLtr, Drawable drawableRtl, final int id) {
super(mTextView.getContext());
@@ -4633,12 +4639,17 @@
final int handleHeight = getPreferredHeight();
mTouchOffsetY = -0.3f * handleHeight;
mIdealVerticalOffset = 0.7f * handleHeight;
+ mIdealFingerToCursorOffset = (int)(mIdealVerticalOffset - mTouchOffsetY);
}
public float getIdealVerticalOffset() {
return mIdealVerticalOffset;
}
+ final int getIdealFingerToCursorOffset() {
+ return mIdealFingerToCursorOffset;
+ }
+
void setDrawables(final Drawable drawableLtr, final Drawable drawableRtl) {
mDrawableLtr = drawableLtr;
mDrawableRtl = drawableRtl;
@@ -6123,36 +6134,34 @@
*/
private int getLineDuringDrag(MotionEvent event) {
final Layout layout = mTextView.getLayout();
- if (mTouchState.isOnHandle()) {
- // The drag was initiated from the handle, so no need to apply the snap logic. See
- // InsertionHandleView.touchThrough().
+ if (mPrevLineDuringDrag == UNSET_LINE) {
return getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, event.getY());
}
+ // In case of touch through on handle (when isOnHandle() returns true), event.getY()
+ // returns the midpoint of the cursor vertical bar, while event.getRawY() returns the
+ // finger location on the screen. See {@link InsertionHandleView#touchThrough}.
+ final float fingerY = mTouchState.isOnHandle()
+ ? event.getRawY() - mTextView.getLocationOnScreen()[1]
+ : event.getY();
+ final float cursorY = fingerY - getHandle().getIdealFingerToCursorOffset();
+ int line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
if (mIsTouchSnappedToHandleDuringDrag) {
- float cursorY = event.getY() - getHandle().getIdealVerticalOffset();
- return getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
- }
- int line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, event.getY());
- if (mPrevLineDuringDrag == UNSET_LINE || line <= mPrevLineDuringDrag) {
- // User's finger is on the same line or moving up; continue positioning the cursor
- // directly at the touch location.
+ // Just returns the line hit by cursor Y when already snapped.
return line;
}
- // User's finger is moving downwards; delay jumping to the lower line to allow the
- // touch to move to the handle.
- float cursorY = event.getY() - getHandle().getIdealVerticalOffset();
- line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
if (line < mPrevLineDuringDrag) {
- return mPrevLineDuringDrag;
+ // The cursor Y aims too high & not yet snapped, check the finger Y.
+ // If finger Y is moving downwards, don't jump to lower line (until snap).
+ // If finger Y is moving upwards, can jump to upper line.
+ return Math.min(mPrevLineDuringDrag,
+ getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, fingerY));
}
- // User's finger is now over the handle, at the ideal offset from the cursor. From now
- // on, position the cursor higher up from the actual touch location so that the user's
- // finger stays "snapped" to the handle. This provides better visibility of the text.
+ // The cursor Y aims not too high, so snap!
mIsTouchSnappedToHandleDuringDrag = true;
if (TextView.DEBUG_CURSOR) {
logCursor("InsertionPointCursorController",
- "snapped touch to handle: eventY=%d, cursorY=%d, mLastLine=%d, line=%d",
- (int) event.getY(), (int) cursorY, mPrevLineDuringDrag, line);
+ "snapped touch to handle: fingerY=%d, cursorY=%d, mLastLine=%d, line=%d",
+ (int) fingerY, (int) cursorY, mPrevLineDuringDrag, line);
}
return line;
}
@@ -6252,7 +6261,7 @@
}
}
- private InsertionHandleView getHandle() {
+ public InsertionHandleView getHandle() {
if (mHandle == null) {
loadHandleDrawables(false /* overwrite */);
mHandle = new InsertionHandleView(mSelectHandleCenter);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f3243aa..0d82065 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11763,13 +11763,8 @@
if (isTextEditable() && isFocused()) {
CharSequence imeActionLabel = mContext.getResources().getString(
com.android.internal.R.string.keyboardview_keycode_enter);
- if (getImeActionId() != 0 && getImeActionLabel() != null) {
+ if (getImeActionLabel() != null) {
imeActionLabel = getImeActionLabel();
- final int imeActionId = getImeActionId();
- // put ime action id into the extra data with ACTION_ARGUMENT_IME_ACTION_ID_INT.
- final Bundle argument = info.getExtras();
- argument.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_IME_ACTION_ID_INT,
- imeActionId);
}
AccessibilityNodeInfo.AccessibilityAction action =
new AccessibilityNodeInfo.AccessibilityAction(
@@ -11881,7 +11876,7 @@
if (extraDataKey.equals(AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY)) {
final AccessibilityNodeInfo.ExtraRenderingInfo extraRenderingInfo =
AccessibilityNodeInfo.ExtraRenderingInfo.obtain();
- extraRenderingInfo.setLayoutParams(getLayoutParams().width, getLayoutParams().height);
+ extraRenderingInfo.setLayoutSize(getLayoutParams().width, getLayoutParams().height);
extraRenderingInfo.setTextSizeInPx(getTextSize());
extraRenderingInfo.setTextSizeUnit(getTextSizeUnit());
info.setExtraRenderingInfo(extraRenderingInfo);
@@ -12100,13 +12095,7 @@
} return true;
case R.id.accessibilityActionImeEnter: {
if (isFocused() && isTextEditable()) {
- final int imeActionId = (arguments != null) ? arguments.getInt(
- AccessibilityNodeInfo.ACTION_ARGUMENT_IME_ACTION_ID_INT,
- EditorInfo.IME_ACTION_UNSPECIFIED)
- : EditorInfo.IME_ACTION_UNSPECIFIED;
- if (imeActionId == getImeActionId()) {
- onEditorAction(imeActionId);
- }
+ onEditorAction(getImeActionId());
}
} return true;
default: {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4e139a3..2128f99 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -134,6 +134,11 @@
static bool gIsSecurityEnforced = true;
/**
+ * True if the app process is running in its mount namespace.
+ */
+static bool gInAppMountNamespace = false;
+
+/**
* The maximum number of characters (not including a null terminator) that a
* process name may contain.
*/
@@ -548,6 +553,17 @@
}
}
+static void ensureInAppMountNamespace(fail_fn_t fail_fn) {
+ if (gInAppMountNamespace) {
+ // In app mount namespace already
+ return;
+ }
+ if (unshare(CLONE_NEWNS) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unshare(): %s", strerror(errno)));
+ }
+ gInAppMountNamespace = true;
+}
+
// Sets the resource limits via setrlimit(2) for the values in the
// two-dimensional array of integers that's passed in. The second dimension
// contains a tuple of length 3: (resource, rlim_cur, rlim_max). nullptr is
@@ -811,9 +827,7 @@
}
// Create a second private mount namespace for our process
- if (unshare(CLONE_NEWNS) == -1) {
- fail_fn(CREATE_ERROR("Failed to unshare(): %s", strerror(errno)));
- }
+ ensureInAppMountNamespace(fail_fn);
// Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
if (mount_mode == MOUNT_EXTERNAL_NONE) {
@@ -1319,6 +1333,7 @@
if ((size % 3) != 0) {
fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
}
+ ensureInAppMountNamespace(fail_fn);
// Mount tmpfs on all possible data directories, so app no longer see the original apps data.
char internalCePath[PATH_MAX];
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
index b4f3d1e..22f2498 100644
--- a/core/proto/android/bluetooth/enums.proto
+++ b/core/proto/android/bluetooth/enums.proto
@@ -40,6 +40,7 @@
ENABLE_DISABLE_REASON_CRASH = 7;
ENABLE_DISABLE_REASON_USER_SWITCH = 8;
ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9;
+ ENABLE_DISABLE_REASON_FACTORY_RESET = 10;
}
enum DirectionEnum {
diff --git a/core/proto/android/view/remote_animation_target.proto b/core/proto/android/view/remote_animation_target.proto
index 24d2785..150493d 100644
--- a/core/proto/android/view/remote_animation_target.proto
+++ b/core/proto/android/view/remote_animation_target.proto
@@ -44,4 +44,6 @@
optional .android.app.WindowConfigurationProto window_configuration = 10;
optional .android.view.SurfaceControlProto start_leash = 11;
optional .android.graphics.RectProto start_bounds = 12;
+ optional .android.graphics.RectProto local_bounds = 13;
+ optional .android.graphics.RectProto screen_space_bounds = 14;
}
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index caec9ed..632c400 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1631,12 +1631,9 @@
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Verhoog volume bo aanbevole vlak?\n\nOm lang tydperke teen hoë volume te luister, kan jou gehoor beskadig."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gebruik toeganklikheidkortpad?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word."</string>
- <!-- no translation found for accessibility_select_shortcut_menu_title (7310194076629867377) -->
- <skip />
- <!-- no translation found for accessibility_edit_shortcut_menu_button_title (6096484087245145325) -->
- <skip />
- <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (4849108668454490699) -->
- <skip />
+ <string name="accessibility_select_shortcut_menu_title" msgid="7310194076629867377">"Tik op die toeganklikheidprogram wat jy wil gebruik"</string>
+ <string name="accessibility_edit_shortcut_menu_button_title" msgid="6096484087245145325">"Kies programme wat jy met toeganklikheidknoppie wil gebruik"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="4849108668454490699">"Kies programme wat jy met die volumesleutelkortpad wil gebruik"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Wysig kortpaaie"</string>
<string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Kanselleer"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Skakel kortpad af"</string>
@@ -2033,29 +2030,19 @@
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> is in die BEPERK-groep geplaas"</string>
<string name="resolver_personal_tab" msgid="2051260504014442073">"Persoonlik"</string>
<string name="resolver_work_tab" msgid="2690019516263167035">"Werk"</string>
- <!-- no translation found for resolver_personal_tab_accessibility (5739524949153091224) -->
- <skip />
- <!-- no translation found for resolver_work_tab_accessibility (4753168230363802734) -->
- <skip />
+ <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Persoonlike aansig"</string>
+ <string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Werkaansig"</string>
<string name="resolver_cant_share_with_work_apps" msgid="7539495559434146897">"Kan nie met werkprogramme deel nie"</string>
<string name="resolver_cant_share_with_personal_apps" msgid="8020581735267157241">"Kan nie met persoonlike programme deel nie"</string>
- <!-- no translation found for resolver_cant_share_cross_profile_explanation (5556640604460901386) -->
- <skip />
- <!-- no translation found for resolver_cant_access_work_apps (375634344111233790) -->
- <skip />
- <!-- no translation found for resolver_cant_access_work_apps_explanation (3958762224516867388) -->
- <skip />
- <!-- no translation found for resolver_cant_access_personal_apps (1953215925406474177) -->
- <skip />
- <!-- no translation found for resolver_cant_access_personal_apps_explanation (1725572276741281136) -->
- <skip />
- <!-- no translation found for resolver_turn_on_work_apps_share (619263911204978175) -->
- <skip />
- <!-- no translation found for resolver_turn_on_work_apps_view (3073389230905543680) -->
- <skip />
+ <string name="resolver_cant_share_cross_profile_explanation" msgid="5556640604460901386">"Jou IT-admin het deling tussen persoonlike en werkprofiele geblokkeer"</string>
+ <string name="resolver_cant_access_work_apps" msgid="375634344111233790">"Kan nie toegang tot werkprogramme kry nie"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="3958762224516867388">"Jou IT-admin laat jou nie toe om persoonlike inhoud in werkprogramme te bekyk nie"</string>
+ <string name="resolver_cant_access_personal_apps" msgid="1953215925406474177">"Kan nie toegang tot persoonlike programme kry nie"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1725572276741281136">"Jou IT-admin laat jou nie toe om werkinhoud in persoonlike programme te bekyk nie"</string>
+ <string name="resolver_turn_on_work_apps_share" msgid="619263911204978175">"Skakel werkprofiel aan om inhoud te deel"</string>
+ <string name="resolver_turn_on_work_apps_view" msgid="3073389230905543680">"Skakel werkprofiel aan om inhoud te bekyk"</string>
<string name="resolver_no_apps_available" msgid="7710339903040989654">"Geen programme beskikbaar nie"</string>
- <!-- no translation found for resolver_switch_on_work (2873009160846966379) -->
- <skip />
+ <string name="resolver_switch_on_work" msgid="2873009160846966379">"Skakel aan"</string>
<string name="permlab_accessCallAudio" msgid="1682957511874097664">"Neem oudio in telefonie-oproepe op of speel dit"</string>
<string name="permdesc_accessCallAudio" msgid="8448360894684277823">"Laat hierdie program, indien dit as die verstekbellerprogram aangewys is, toe om oudio in telefonie-oproepe op te neem of te speel."</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 63497aa..1a7f301 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1631,12 +1631,9 @@
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"推奨レベルを超えるまで音量を上げますか?\n\n大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ユーザー補助機能のショートカットの使用"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ショートカットが ON の場合、両方の音量ボタンを 3 秒ほど長押しするとユーザー補助機能が起動します。"</string>
- <!-- no translation found for accessibility_select_shortcut_menu_title (7310194076629867377) -->
- <skip />
- <!-- no translation found for accessibility_edit_shortcut_menu_button_title (6096484087245145325) -->
- <skip />
- <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (4849108668454490699) -->
- <skip />
+ <string name="accessibility_select_shortcut_menu_title" msgid="7310194076629867377">"使用するユーザー補助アプリをタップ"</string>
+ <string name="accessibility_edit_shortcut_menu_button_title" msgid="6096484087245145325">"ユーザー補助機能ボタンで使用できるアプリを選択"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="4849108668454490699">"音量キーのショートカットで使用できるアプリを選択"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ショートカットの編集"</string>
<string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"キャンセル"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ショートカットを OFF にする"</string>
@@ -2033,29 +2030,19 @@
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> は RESTRICTED バケットに移動しました。"</string>
<string name="resolver_personal_tab" msgid="2051260504014442073">"個人用"</string>
<string name="resolver_work_tab" msgid="2690019516263167035">"仕事用"</string>
- <!-- no translation found for resolver_personal_tab_accessibility (5739524949153091224) -->
- <skip />
- <!-- no translation found for resolver_work_tab_accessibility (4753168230363802734) -->
- <skip />
+ <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"個人用ビュー"</string>
+ <string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"仕事用ビュー"</string>
<string name="resolver_cant_share_with_work_apps" msgid="7539495559434146897">"仕事用アプリと共有できません"</string>
<string name="resolver_cant_share_with_personal_apps" msgid="8020581735267157241">"個人用アプリと共有できません"</string>
- <!-- no translation found for resolver_cant_share_cross_profile_explanation (5556640604460901386) -->
- <skip />
- <!-- no translation found for resolver_cant_access_work_apps (375634344111233790) -->
- <skip />
- <!-- no translation found for resolver_cant_access_work_apps_explanation (3958762224516867388) -->
- <skip />
- <!-- no translation found for resolver_cant_access_personal_apps (1953215925406474177) -->
- <skip />
- <!-- no translation found for resolver_cant_access_personal_apps_explanation (1725572276741281136) -->
- <skip />
- <!-- no translation found for resolver_turn_on_work_apps_share (619263911204978175) -->
- <skip />
- <!-- no translation found for resolver_turn_on_work_apps_view (3073389230905543680) -->
- <skip />
+ <string name="resolver_cant_share_cross_profile_explanation" msgid="5556640604460901386">"IT 管理者が個人用プロファイルと仕事用プロファイルの間の共有をブロックしました"</string>
+ <string name="resolver_cant_access_work_apps" msgid="375634344111233790">"仕事用アプリにアクセスできません"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="3958762224516867388">"IT 管理者は個人用コンテンツを仕事用アプリで表示することを許可していません"</string>
+ <string name="resolver_cant_access_personal_apps" msgid="1953215925406474177">"個人用アプリにアクセスできません"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1725572276741281136">"IT 管理者は仕事用コンテンツを個人用アプリで表示することを許可していません"</string>
+ <string name="resolver_turn_on_work_apps_share" msgid="619263911204978175">"コンテンツを共有するには、仕事用プロファイルをオンにしてください"</string>
+ <string name="resolver_turn_on_work_apps_view" msgid="3073389230905543680">"コンテンツを表示するには、仕事用プロファイルをオンにしてください"</string>
<string name="resolver_no_apps_available" msgid="7710339903040989654">"利用できるアプリはありません"</string>
- <!-- no translation found for resolver_switch_on_work (2873009160846966379) -->
- <skip />
+ <string name="resolver_switch_on_work" msgid="2873009160846966379">"オンにする"</string>
<string name="permlab_accessCallAudio" msgid="1682957511874097664">"通話中に録音または音声の再生を行う"</string>
<string name="permdesc_accessCallAudio" msgid="8448360894684277823">"デフォルトの電話アプリケーションとして割り当てられている場合、このアプリに通話中の録音または音声の再生を許可します。"</string>
</resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 7b17305..4054a3a 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1631,12 +1631,9 @@
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Хүртээмжийн товчлолыг ашиглах уу?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Товчлол асаалттай үед дууны түвшний хоёр товчлуурыг хамтад нь 3 секунд дарснаар хандалтын онцлогийг эхлүүлнэ."</string>
- <!-- no translation found for accessibility_select_shortcut_menu_title (7310194076629867377) -->
- <skip />
- <!-- no translation found for accessibility_edit_shortcut_menu_button_title (6096484087245145325) -->
- <skip />
- <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (4849108668454490699) -->
- <skip />
+ <string name="accessibility_select_shortcut_menu_title" msgid="7310194076629867377">"Ашиглахыг хүсэж буй хандалтын аппаа товших"</string>
+ <string name="accessibility_edit_shortcut_menu_button_title" msgid="6096484087245145325">"Хандалтын товчлуурын тусламжтай ашиглахыг хүсэж буй аппуудаа сонгох"</string>
+ <string name="accessibility_edit_shortcut_menu_volume_title" msgid="4849108668454490699">"Дууны түвшин тохируулах түлхүүрийн товчлолын тусламжтай ашиглахыг хүсэж буй аппуудаа сонгох"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Товчлолуудыг засах"</string>
<string name="cancel_accessibility_shortcut_menu_button" msgid="1817413122335452474">"Болих"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Товчлолыг унтраах"</string>
@@ -2033,29 +2030,19 @@
<string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>-г ХЯЗГААРЛАСАН сагс руу орууллаа"</string>
<string name="resolver_personal_tab" msgid="2051260504014442073">"Хувийн"</string>
<string name="resolver_work_tab" msgid="2690019516263167035">"Ажил"</string>
- <!-- no translation found for resolver_personal_tab_accessibility (5739524949153091224) -->
- <skip />
- <!-- no translation found for resolver_work_tab_accessibility (4753168230363802734) -->
- <skip />
+ <string name="resolver_personal_tab_accessibility" msgid="5739524949153091224">"Хувийн харагдах байдал"</string>
+ <string name="resolver_work_tab_accessibility" msgid="4753168230363802734">"Ажлын харагдах байдал"</string>
<string name="resolver_cant_share_with_work_apps" msgid="7539495559434146897">"Ажлын аппуудтай хуваалцах боломжгүй"</string>
<string name="resolver_cant_share_with_personal_apps" msgid="8020581735267157241">"Хувийн аппуудтай хуваалцах боломжгүй"</string>
- <!-- no translation found for resolver_cant_share_cross_profile_explanation (5556640604460901386) -->
- <skip />
- <!-- no translation found for resolver_cant_access_work_apps (375634344111233790) -->
- <skip />
- <!-- no translation found for resolver_cant_access_work_apps_explanation (3958762224516867388) -->
- <skip />
- <!-- no translation found for resolver_cant_access_personal_apps (1953215925406474177) -->
- <skip />
- <!-- no translation found for resolver_cant_access_personal_apps_explanation (1725572276741281136) -->
- <skip />
- <!-- no translation found for resolver_turn_on_work_apps_share (619263911204978175) -->
- <skip />
- <!-- no translation found for resolver_turn_on_work_apps_view (3073389230905543680) -->
- <skip />
+ <string name="resolver_cant_share_cross_profile_explanation" msgid="5556640604460901386">"Таны IT админ хувийн болон ажлын профайлуудын хооронд хуваалцахыг блоклосон"</string>
+ <string name="resolver_cant_access_work_apps" msgid="375634344111233790">"Ажлын аппуудад хандах боломжгүй байна"</string>
+ <string name="resolver_cant_access_work_apps_explanation" msgid="3958762224516867388">"Таны IT админ ажлын аппууд дахь хувийн контентыг харахыг танд зөвшөөрөхгүй байна"</string>
+ <string name="resolver_cant_access_personal_apps" msgid="1953215925406474177">"Хувийн аппуудад хандах боломжгүй байна"</string>
+ <string name="resolver_cant_access_personal_apps_explanation" msgid="1725572276741281136">"Таны IT админ хувийн аппууд дахь ажлын контентыг харахыг танд зөвшөөрөхгүй байна"</string>
+ <string name="resolver_turn_on_work_apps_share" msgid="619263911204978175">"Контентыг хуваалцахын тулд ажлын профайлыг асаана уу"</string>
+ <string name="resolver_turn_on_work_apps_view" msgid="3073389230905543680">"Контентыг харахын тулд ажлын профайлыг асаана уу"</string>
<string name="resolver_no_apps_available" msgid="7710339903040989654">"Боломжтой апп алга байна"</string>
- <!-- no translation found for resolver_switch_on_work (2873009160846966379) -->
- <skip />
+ <string name="resolver_switch_on_work" msgid="2873009160846966379">"Асаах"</string>
<string name="permlab_accessCallAudio" msgid="1682957511874097664">"Утасны дуудлагын үеэр аудио бичих эсвэл тоглуулах"</string>
<string name="permdesc_accessCallAudio" msgid="8448360894684277823">"Энэ аппыг залгагч өгөгдмөл аппликэйшн болгосон үед түүнд утасны дуудлагын үеэр аудио бичих эсвэл тоглуулахыг зөвшөөрдөг."</string>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 008c991..d30fdce 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3402,8 +3402,6 @@
<!-- A notification is shown when connected network without internet due to private dns validation failed. This is the notification's message. [CHAR LIMIT=NONE] -->
<string name="private_dns_broken_detailed">Private DNS server cannot be accessed</string>
- <!-- A notification is shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the message of notification. [CHAR LIMIT=50] -->
- <string name="captive_portal_logged_in_detailed">Connected</string>
<!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's title. [CHAR LIMIT=50] -->
<string name="network_partial_connectivity"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has limited connectivity</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9015cc4..826379d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -688,7 +688,6 @@
<java-symbol type="string" name="capability_title_canControlMagnification" />
<java-symbol type="string" name="capability_desc_canPerformGestures" />
<java-symbol type="string" name="capability_title_canPerformGestures" />
- <java-symbol type="string" name="captive_portal_logged_in_detailed" />
<java-symbol type="string" name="capital_off" />
<java-symbol type="string" name="capital_on" />
<java-symbol type="string" name="cfTemplateForwarded" />
diff --git a/core/tests/coretests/src/android/content/ApexContextTest.java b/core/tests/coretests/src/android/content/ApexEnvironmentTest.java
similarity index 75%
rename from core/tests/coretests/src/android/content/ApexContextTest.java
rename to core/tests/coretests/src/android/content/ApexEnvironmentTest.java
index d15c64d..438c5ae 100644
--- a/core/tests/coretests/src/android/content/ApexContextTest.java
+++ b/core/tests/coretests/src/android/content/ApexEnvironmentTest.java
@@ -28,20 +28,21 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class ApexContextTest {
+public class ApexEnvironmentTest {
@Test
public void dataDirectoryPathsAreAsExpected() {
- ApexContext apexContext = ApexContext.getApexContext("my.apex");
+ ApexEnvironment apexEnvironment = ApexEnvironment.getApexEnvironment("my.apex");
assertEquals("/data/misc/apexdata/my.apex",
- apexContext.getDeviceProtectedDataDir().getAbsolutePath());
+ apexEnvironment.getDeviceProtectedDataDir().getAbsolutePath());
assertEquals("/data/misc_de/5/apexdata/my.apex",
- apexContext.getDeviceProtectedDataDirForUser(UserHandle.of(5)).getAbsolutePath());
+ apexEnvironment
+ .getDeviceProtectedDataDirForUser(UserHandle.of(5)).getAbsolutePath());
assertEquals("/data/misc_ce/16/apexdata/my.apex",
- apexContext.getCredentialProtectedDataDirForUser(
+ apexEnvironment.getCredentialProtectedDataDirForUser(
UserHandle.of(16)).getAbsolutePath());
}
}
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index 0a094c61d..f81964c 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -35,10 +35,13 @@
import android.app.Activity;
import android.app.Instrumentation;
+import android.graphics.Rect;
import android.text.Layout;
+import android.util.ArraySet;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -50,11 +53,13 @@
import com.google.common.base.Strings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@RunWith(AndroidJUnit4.class)
@@ -70,6 +75,7 @@
private Instrumentation mInstrumentation;
private Activity mActivity;
+ private Set<MotionEvent> mMotionEvents = new ArraySet<>();
@Before
public void before() throws Throwable {
@@ -77,6 +83,14 @@
mActivity = mActivityRule.getActivity();
}
+ @After
+ public void after() throws Throwable {
+ for (MotionEvent event : mMotionEvents) {
+ event.recycle();
+ }
+ mMotionEvents.clear();
+ }
+
@Test
public void testCursorDrag_horizontal_whenTextViewContentsFitOnScreen() throws Throwable {
String text = "Hello world!";
@@ -243,45 +257,45 @@
// Simulate a tap-and-drag gesture.
long event1Time = 1001;
- MotionEvent event1 = downEvent(event1Time, event1Time, 5f, 10f);
+ MotionEvent event1 = downEvent(tv, event1Time, event1Time, 5f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event2Time = 1002;
- MotionEvent event2 = moveEvent(event1Time, event2Time, 50f, 10f);
+ MotionEvent event2 = moveEvent(tv, event1Time, event2Time, 50f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2));
assertTrue(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event3Time = 1003;
- MotionEvent event3 = moveEvent(event1Time, event3Time, 100f, 10f);
+ MotionEvent event3 = moveEvent(tv, event1Time, event3Time, 100f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3));
assertTrue(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event4Time = 2004;
- MotionEvent event4 = upEvent(event1Time, event4Time, 100f, 10f);
+ MotionEvent event4 = upEvent(tv, event1Time, event4Time, 100f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event4));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
// Simulate a quick tap after the drag, near the location where the drag ended.
long event5Time = 2005;
- MotionEvent event5 = downEvent(event5Time, event5Time, 90f, 10f);
+ MotionEvent event5 = downEvent(tv, event5Time, event5Time, 90f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event5));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event6Time = 2006;
- MotionEvent event6 = upEvent(event5Time, event6Time, 90f, 10f);
+ MotionEvent event6 = upEvent(tv, event5Time, event6Time, 90f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event6));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
// Simulate another quick tap in the same location; now selection should be triggered.
long event7Time = 2007;
- MotionEvent event7 = downEvent(event7Time, event7Time, 90f, 10f);
+ MotionEvent event7 = downEvent(tv, event7Time, event7Time, 90f, 10f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event7));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertTrue(editor.getSelectionController().isCursorBeingModified());
@@ -298,19 +312,19 @@
// Simulate a mouse click and drag. This should NOT trigger a cursor drag.
long event1Time = 1001;
- MotionEvent event1 = mouseDownEvent(event1Time, event1Time, 20f, 30f);
+ MotionEvent event1 = mouseDownEvent(tv, event1Time, event1Time, 20f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event2Time = 1002;
- MotionEvent event2 = mouseMoveEvent(event1Time, event2Time, 120f, 30f);
+ MotionEvent event2 = mouseMoveEvent(tv, event1Time, event2Time, 120f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertTrue(editor.getSelectionController().isCursorBeingModified());
long event3Time = 1003;
- MotionEvent event3 = mouseUpEvent(event1Time, event3Time, 120f, 30f);
+ MotionEvent event3 = mouseUpEvent(tv, event1Time, event3Time, 120f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
@@ -327,25 +341,25 @@
// Simulate a tap-and-drag gesture. This should trigger a cursor drag.
long event1Time = 1001;
- MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ MotionEvent event1 = downEvent(tv, event1Time, event1Time, 20f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event2Time = 1002;
- MotionEvent event2 = moveEvent(event1Time, event2Time, 21f, 30f);
+ MotionEvent event2 = moveEvent(tv, event1Time, event2Time, 21f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event3Time = 1003;
- MotionEvent event3 = moveEvent(event1Time, event3Time, 120f, 30f);
+ MotionEvent event3 = moveEvent(tv, event1Time, event3Time, 120f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3));
assertTrue(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event4Time = 1004;
- MotionEvent event4 = upEvent(event1Time, event4Time, 120f, 30f);
+ MotionEvent event4 = upEvent(tv, event1Time, event4Time, 120f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event4));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
@@ -362,31 +376,31 @@
// Simulate a double-tap followed by a drag. This should trigger a selection drag.
long event1Time = 1001;
- MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ MotionEvent event1 = downEvent(tv, event1Time, event1Time, 20f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event2Time = 1002;
- MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
+ MotionEvent event2 = upEvent(tv, event1Time, event2Time, 20f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event2));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
long event3Time = 1003;
- MotionEvent event3 = downEvent(event3Time, event3Time, 20f, 30f);
+ MotionEvent event3 = downEvent(tv, event3Time, event3Time, 20f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event3));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertTrue(editor.getSelectionController().isCursorBeingModified());
long event4Time = 1004;
- MotionEvent event4 = moveEvent(event3Time, event4Time, 120f, 30f);
+ MotionEvent event4 = moveEvent(tv, event3Time, event4Time, 120f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event4));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertTrue(editor.getSelectionController().isCursorBeingModified());
long event5Time = 1005;
- MotionEvent event5 = upEvent(event3Time, event5Time, 120f, 30f);
+ MotionEvent event5 = upEvent(tv, event3Time, event5Time, 120f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event5));
assertFalse(editor.getInsertionController().isCursorBeingModified());
assertFalse(editor.getSelectionController().isCursorBeingModified());
@@ -403,7 +417,7 @@
// Simulate a tap. No error should be thrown.
long event1Time = 1001;
- MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ MotionEvent event1 = downEvent(tv, event1Time, event1Time, 20f, 30f);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
// Swipe left to right. No error should be thrown.
@@ -440,7 +454,8 @@
public void testCursorDrag_snapToHandle() throws Throwable {
String text = "line1: This is the 1st line: A\n"
+ "line2: This is the 2nd line: B\n"
- + "line3: This is the 3rd line: C\n";
+ + "line3: This is the 3rd line: C\n"
+ + "line4: This is the 4th line: D\n";
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
TextView tv = mActivity.findViewById(R.id.textview);
@@ -454,8 +469,8 @@
// Start dragging along the first line
motionEventInfo(text.indexOf("line1"), 1.0f),
motionEventInfo(text.indexOf("This is the 1st"), 1.0f),
- // Move to the bottom of the third line; cursor should end up on second line
- motionEventInfo(text.indexOf("he 3rd"), 0.0f, text.indexOf("he 2nd")),
+ // Move to the middle of the fourth line; cursor should end up on second line
+ motionEventInfo(text.indexOf("he 4th"), 0.5f, text.indexOf("he 2nd")),
// Move to the middle of the second line; cursor should end up on the first line
motionEventInfo(text.indexOf("he 2nd"), 0.5f, text.indexOf("he 1st"))
};
@@ -473,37 +488,137 @@
simulateDrag(tv, events, true);
}
- private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
- return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
+ @Test
+ public void testCursorDrag_snapDistance() throws Throwable {
+ String text = "line1: This is the 1st line: A\n"
+ + "line2: This is the 2nd line: B\n"
+ + "line3: This is the 3rd line: C\n";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ TextView tv = mActivity.findViewById(R.id.textview);
+ Editor editor = tv.getEditorForTesting();
+ final int startIndex = text.indexOf("he 2nd");
+ Layout layout = tv.getLayout();
+ final float cursorStartX = layout.getPrimaryHorizontal(startIndex) + tv.getTotalPaddingLeft();
+ final float cursorStartY = layout.getLineTop(1) + tv.getTotalPaddingTop();
+ final float dragHandleStartX = 20;
+ final float dragHandleStartY = 20;
+
+ // Drag the handle from the 2nd line to the 3rd line.
+ tapAtPoint(tv, cursorStartX, cursorStartY);
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(startIndex));
+ View handleView = editor.getInsertionController().getHandle();
+ final int rawYOfHandleDrag = dragDownUntilLineChange(
+ handleView, dragHandleStartX, dragHandleStartY, tv.getSelectionStart());
+
+ // Drag the cursor from the 2nd line to the 3rd line.
+ tapAtPoint(tv, cursorStartX, cursorStartY);
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(startIndex));
+ final int rawYOfCursorDrag =
+ dragDownUntilLineChange(tv, cursorStartX, cursorStartY, tv.getSelectionStart());
+
+ // Drag the handle with touch through from the 2nd line to the 3rd line.
+ tv.getEditorForTesting().setFlagInsertionHandleGesturesEnabled(true);
+ tapAtPoint(tv, cursorStartX, cursorStartY);
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(startIndex));
+ handleView = editor.getInsertionController().getHandle();
+ int rawYOfHandleDragWithTouchThrough =
+ dragDownUntilLineChange(handleView, dragHandleStartX, dragHandleStartY, tv.getSelectionStart());
+
+ String msg = String.format(
+ "rawYOfHandleDrag: %d, rawYOfCursorDrag: %d, rawYOfHandleDragWithTouchThrough: %d",
+ rawYOfHandleDrag, rawYOfCursorDrag, rawYOfHandleDragWithTouchThrough);
+ final int max = Math.max(
+ rawYOfCursorDrag, Math.max(rawYOfHandleDrag, rawYOfHandleDragWithTouchThrough));
+ final int min = Math.min(
+ rawYOfCursorDrag, Math.min(rawYOfHandleDrag, rawYOfHandleDragWithTouchThrough));
+ // The drag step is 5 pixels in dragDownUntilLineChange().
+ // The difference among the 3 raw Y values should be no bigger than the drag step.
+ assertWithMessage(msg).that(max - min).isLessThan(6);
}
- private static MotionEvent upEvent(long downTime, long eventTime, float x, float y) {
- return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
+ private void dispatchTouchEvent(View view, MotionEvent event) {
+ mInstrumentation.runOnMainSync(() -> view.dispatchTouchEvent(event));
}
- private static MotionEvent moveEvent(long downTime, long eventTime, float x, float y) {
- return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
+ private void tapAtPoint(TextView tv, final float x, final float y) {
+ long downTime = sTicker.addAndGet(10_000);
+ dispatchTouchEvent(tv, downEvent(tv, downTime, downTime, x, y));
+ dispatchTouchEvent(tv, upEvent(tv, downTime, downTime + 1, x, y));
}
- private static MotionEvent mouseDownEvent(long downTime, long eventTime, float x, float y) {
- MotionEvent event = downEvent(downTime, eventTime, x, y);
- event.setSource(InputDevice.SOURCE_MOUSE);
- event.setButtonState(MotionEvent.BUTTON_PRIMARY);
+ private int dragDownUntilLineChange(View view, final float startX, final float startY,
+ final int startOffset) {
+ TextView tv = mActivity.findViewById(R.id.textview);
+ final int startLine = tv.getLayout().getLineForOffset(startOffset);
+
+ int rawY = 0;
+ long downTime = sTicker.addAndGet(10_000);
+ long eventTime = downTime;
+ // Move horizontally first to initiate the cursor drag.
+ dispatchTouchEvent(view, downEvent(view, downTime, eventTime++, startX, startY));
+ dispatchTouchEvent(view, moveEvent(view, downTime, eventTime++, startX + 50, startY));
+ dispatchTouchEvent(view, moveEvent(view, downTime, eventTime++, startX, startY));
+ // Move downwards 5 pixels at a time until a line change occurs.
+ for (int i = 0; i < 200; i++) {
+ MotionEvent ev = moveEvent(view, downTime, eventTime++, startX, startY + i * 5);
+ rawY = (int) ev.getRawY();
+ dispatchTouchEvent(view, ev);
+ if (tv.getLayout().getLineForOffset(tv.getSelectionStart()) > startLine) {
+ break;
+ }
+ }
+ String msg = String.format("The cursor didn't jump from %d!", startOffset);
+ assertWithMessage(msg).that(
+ tv.getLayout().getLineForOffset(tv.getSelectionStart())).isGreaterThan(startLine);
+ dispatchTouchEvent(view, upEvent(view, downTime, eventTime, startX, startY));
+ return rawY;
+ }
+
+ private MotionEvent obtainTouchEvent(
+ View view, int action, long downTime, long eventTime, float x, float y) {
+ Rect r = new Rect();
+ view.getBoundsOnScreen(r);
+ float rawX = x + r.left;
+ float rawY = y + r.top;
+ MotionEvent event =
+ MotionEvent.obtain(downTime, eventTime, action, rawX, rawY, 0);
+ view.toLocalMotionEvent(event);
+ mMotionEvents.add(event);
return event;
}
- private static MotionEvent mouseUpEvent(long downTime, long eventTime, float x, float y) {
- MotionEvent event = upEvent(downTime, eventTime, x, y);
+ private MotionEvent obtainMouseEvent(
+ View view, int action, long downTime, long eventTime, float x, float y) {
+ MotionEvent event = obtainTouchEvent(view, action, downTime, eventTime, x, y);
event.setSource(InputDevice.SOURCE_MOUSE);
- event.setButtonState(0);
+ if (action != MotionEvent.ACTION_UP) {
+ event.setButtonState(MotionEvent.BUTTON_PRIMARY);
+ }
return event;
}
- private static MotionEvent mouseMoveEvent(long downTime, long eventTime, float x, float y) {
- MotionEvent event = moveEvent(downTime, eventTime, x, y);
- event.setSource(InputDevice.SOURCE_MOUSE);
- event.setButtonState(MotionEvent.BUTTON_PRIMARY);
- return event;
+ private MotionEvent downEvent(View view, long downTime, long eventTime, float x, float y) {
+ return obtainTouchEvent(view, MotionEvent.ACTION_DOWN, downTime, eventTime, x, y);
+ }
+
+ private MotionEvent moveEvent(View view, long downTime, long eventTime, float x, float y) {
+ return obtainTouchEvent(view, MotionEvent.ACTION_MOVE, downTime, eventTime, x, y);
+ }
+
+ private MotionEvent upEvent(View view, long downTime, long eventTime, float x, float y) {
+ return obtainTouchEvent(view, MotionEvent.ACTION_UP, downTime, eventTime, x, y);
+ }
+
+ private MotionEvent mouseDownEvent(View view, long downTime, long eventTime, float x, float y) {
+ return obtainMouseEvent(view, MotionEvent.ACTION_DOWN, downTime, eventTime, x, y);
+ }
+
+ private MotionEvent mouseMoveEvent(View view, long downTime, long eventTime, float x, float y) {
+ return obtainMouseEvent(view, MotionEvent.ACTION_MOVE, downTime, eventTime, x, y);
+ }
+
+ private MotionEvent mouseUpEvent(View view, long downTime, long eventTime, float x, float y) {
+ return obtainMouseEvent(view, MotionEvent.ACTION_UP, downTime, eventTime, x, y);
}
public static MotionEventInfo motionEventInfo(int index, float ratioToLineTop) {
@@ -543,14 +658,15 @@
float[] downCoords = events[0].getCoordinates(tv);
long downEventTime = sTicker.addAndGet(10_000);
- MotionEvent downEvent = downEvent(downEventTime, downEventTime,
+ MotionEvent downEvent = downEvent(tv, downEventTime, downEventTime,
downCoords[0], downCoords[1]);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(downEvent));
for (int i = 1; i < events.length; i++) {
float[] moveCoords = events[i].getCoordinates(tv);
long eventTime = downEventTime + i;
- MotionEvent event = moveEvent(downEventTime, eventTime, moveCoords[0], moveCoords[1]);
+ MotionEvent event = moveEvent(tv, downEventTime, eventTime, moveCoords[0],
+ moveCoords[1]);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event));
assertCursorPosition(tv, events[i].expectedCursorIndex, runAssertions);
}
@@ -558,7 +674,7 @@
MotionEventInfo lastEvent = events[events.length - 1];
float[] upCoords = lastEvent.getCoordinates(tv);
long upEventTime = downEventTime + events.length;
- MotionEvent upEvent = upEvent(downEventTime, upEventTime, upCoords[0], upCoords[1]);
+ MotionEvent upEvent = upEvent(tv, downEventTime, upEventTime, upCoords[0], upCoords[1]);
mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(upEvent));
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 88a6f9e..a72be25 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -497,7 +497,7 @@
@Test
public void testInsertionHandle_multiLine() {
- final String text = "abcd\n" + "efg\n" + "hijk\n";
+ final String text = "abcd\n" + "efg\n" + "hijk\n" + "lmn\n";
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length()));
@@ -506,12 +506,12 @@
final TextView textView = mActivity.findViewById(R.id.textview);
onHandleView(com.android.internal.R.id.insertion_handle)
- .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a')));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("a")));
-
- onHandleView(com.android.internal.R.id.insertion_handle)
.perform(dragHandle(textView, Handle.INSERTION, text.indexOf('f')));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f")));
+
+ onHandleView(com.android.internal.R.id.insertion_handle)
+ .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('i')));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("i")));
}
private void enableFlagsForInsertionHandleGestures() {
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 45b849f..37e2ab5 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -377,7 +377,9 @@
* @see TransferCallback#onTransferred
* @see TransferCallback#onTransferFailed
*/
- public void transferTo(@Nullable MediaRoute2Info route) {
+ public void transferTo(@NonNull MediaRoute2Info route) {
+ Objects.requireNonNull(route, "route must not be null");
+
List<RoutingController> controllers = getControllers();
RoutingController controller = controllers.get(controllers.size() - 1);
@@ -385,19 +387,25 @@
}
/**
+ * Stops the current media routing. If the {@link #getSystemController() system controller}
+ * controls the media routing, this method is a no-op.
+ */
+ public void stop() {
+ List<RoutingController> controllers = getControllers();
+ RoutingController controller = controllers.get(controllers.size() - 1);
+
+ controller.release();
+ }
+
+ /**
* Transfers the media of a routing controller to the given route.
* @param controller a routing controller controlling media routing.
- * @param route the route you want to transfer the media to. Pass {@code null} to stop
- * routing controlled by the given controller.
+ * @param route the route you want to transfer the media to.
* @hide
*/
- void transfer(@NonNull RoutingController controller, @Nullable MediaRoute2Info route) {
+ void transfer(@NonNull RoutingController controller, @NonNull MediaRoute2Info route) {
Objects.requireNonNull(controller, "controller must not be null");
-
- if (route == null) {
- controller.release();
- return;
- }
+ Objects.requireNonNull(route, "route must not be null");
// TODO: Check thread-safety
if (!mRoutes.containsKey(route.getId())) {
@@ -681,7 +689,7 @@
if (removed) {
matchingController.release();
- notifyControllerReleased(matchingController);
+ notifyStopped(matchingController);
}
}
@@ -738,16 +746,16 @@
}
}
- private void notifyControllerUpdated(RoutingController controller) {
- for (ControllerCallbackRecord record: mControllerCallbackRecords) {
- record.mExecutor.execute(() -> record.mCallback.onControllerUpdated(controller));
+ private void notifyStopped(RoutingController controller) {
+ for (TransferCallbackRecord record: mTransferCallbackRecords) {
+ record.mExecutor.execute(
+ () -> record.mTransferCallback.onStopped(controller));
}
}
- private void notifyControllerReleased(RoutingController controller) {
- for (TransferCallbackRecord record: mTransferCallbackRecords) {
- record.mExecutor.execute(
- () -> record.mTransferCallback.onTransferred(controller, null));
+ private void notifyControllerUpdated(RoutingController controller) {
+ for (ControllerCallbackRecord record: mControllerCallbackRecords) {
+ record.mExecutor.execute(() -> record.mCallback.onControllerUpdated(controller));
}
}
@@ -788,20 +796,26 @@
* This can happen by calling {@link #transferTo(MediaRoute2Info)} or
* {@link RoutingController#release()}.
*
- * @param oldController the previous controller that controlled routing.
- * @param newController the new controller to control routing or {@code null} if the
- * previous controller is released.
+ * @param oldController the previous controller that controlled routing
+ * @param newController the new controller to control routing
* @see #transferTo(MediaRoute2Info)
*/
public void onTransferred(@NonNull RoutingController oldController,
- @Nullable RoutingController newController) {}
+ @NonNull RoutingController newController) {}
/**
* Called when {@link #transferTo(MediaRoute2Info)} failed.
*
- * @param requestedRoute the route info which was used for the transfer.
+ * @param requestedRoute the route info which was used for the transfer
*/
public void onTransferFailed(@NonNull MediaRoute2Info requestedRoute) {}
+
+ /**
+ * Called when a media routing stops. It can be stopped by a user or a provider.
+ *
+ * @param controller the controller that controlled the stopped media routing.
+ */
+ public void onStopped(@NonNull RoutingController controller) { }
}
/**
@@ -1186,7 +1200,7 @@
}
if (removed) {
- mHandler.post(() -> notifyControllerReleased(RoutingController.this));
+ mHandler.post(() -> notifyStopped(RoutingController.this));
}
if (stub != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index 7e78a78..eb0ddfb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -24,6 +24,7 @@
import static android.media.MediaRoute2Info.TYPE_UNKNOWN;
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
import android.app.Notification;
import android.bluetooth.BluetoothAdapter;
@@ -50,6 +51,7 @@
public class InfoMediaManager extends MediaManager {
private static final String TAG = "InfoMediaManager";
+ private static final boolean DEBUG = false;
@VisibleForTesting
final RouterManagerCallback mMediaRouterCallback = new RouterManagerCallback();
@@ -339,6 +341,9 @@
private void buildAllRoutes() {
for (MediaRoute2Info route : mRouterManager.getAllRoutes()) {
+ if (DEBUG) {
+ Log.d(TAG, "buildAllRoutes() route : " + route.getName());
+ }
if (route.isSystemRoute()) {
addMediaDevice(route);
}
@@ -347,6 +352,9 @@
private void buildAvailableRoutes() {
for (MediaRoute2Info route : mRouterManager.getAvailableRoutes(mPackageName)) {
+ if (DEBUG) {
+ Log.d(TAG, "buildAvailableRoutes() route : " + route.getName());
+ }
addMediaDevice(route);
}
}
@@ -363,7 +371,8 @@
mediaDevice = new InfoMediaDevice(mContext, mRouterManager, route,
mPackageName);
if (!TextUtils.isEmpty(mPackageName)
- && TextUtils.equals(route.getClientPackageName(), mPackageName)) {
+ && TextUtils.equals(route.getClientPackageName(), mPackageName)
+ && mCurrentConnectedDevice == null) {
mCurrentConnectedDevice = mediaDevice;
}
break;
@@ -409,12 +418,41 @@
@Override
public void onRoutesChanged(List<MediaRoute2Info> routes) {
- refreshDevices();
+ mMediaDevices.clear();
+ mCurrentConnectedDevice = null;
+ if (TextUtils.isEmpty(mPackageName)) {
+ buildAllRoutes();
+ } else {
+ buildAvailableRoutes();
+ }
+
+ final String id = mCurrentConnectedDevice != null
+ ? mCurrentConnectedDevice.getId()
+ : null;
+ dispatchConnectedDeviceChanged(id);
}
@Override
public void onRoutesRemoved(List<MediaRoute2Info> routes) {
refreshDevices();
}
+
+ @Override
+ public void onTransferred(RoutingSessionInfo oldSession, RoutingSessionInfo newSession) {
+ if (DEBUG) {
+ Log.d(TAG, "onTransferred() oldSession : " + oldSession.getName()
+ + ", newSession : " + newSession.getName());
+ }
+ }
+
+ @Override
+ public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
+ dispatchOnRequestFailed(REASON_UNKNOWN_ERROR);
+ }
+
+ @Override
+ public void onRequestFailed(int reason) {
+ dispatchOnRequestFailed(reason);
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index adb3c11..90f55dd6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -142,20 +142,11 @@
mCurrentConnectedDevice.disconnect();
}
- boolean isConnected = false;
if (TextUtils.isEmpty(mPackageName)) {
- isConnected = mInfoMediaManager.connectDeviceWithoutPackageName(device);
+ mInfoMediaManager.connectDeviceWithoutPackageName(device);
} else {
- isConnected = device.connect();
+ device.connect();
}
- if (isConnected) {
- mCurrentConnectedDevice = device;
- }
-
- final int state = isConnected
- ? MediaDeviceState.STATE_CONNECTED
- : MediaDeviceState.STATE_DISCONNECTED;
- dispatchSelectedDeviceStateChanged(device, state);
}
void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
@@ -186,6 +177,12 @@
}
}
+ void dispatchOnRequestFailed(int reason) {
+ for (DeviceCallback callback : getCallbacks()) {
+ callback.onRequestFailed(reason);
+ }
+ }
+
/**
* Stop scan MediaDevice
*/
@@ -337,7 +334,7 @@
MediaDevice phoneMediaDevice = null;
for (MediaDevice device : mMediaDevices) {
if (device instanceof BluetoothMediaDevice) {
- if (isConnected(((BluetoothMediaDevice) device).getCachedDevice())) {
+ if (isActiveDevice(((BluetoothMediaDevice) device).getCachedDevice())) {
return device;
}
} else if (device instanceof PhoneMediaDevice) {
@@ -347,7 +344,7 @@
return mMediaDevices.contains(phoneMediaDevice) ? phoneMediaDevice : null;
}
- private boolean isConnected(CachedBluetoothDevice device) {
+ private boolean isActiveDevice(CachedBluetoothDevice device) {
return device.isActiveDevice(BluetoothProfile.A2DP)
|| device.isActiveDevice(BluetoothProfile.HEARING_AID);
}
@@ -423,20 +420,28 @@
@Override
public void onConnectedDeviceChanged(String id) {
- final MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
+ MediaDevice connectDevice = getMediaDeviceById(mMediaDevices, id);
+ connectDevice = connectDevice != null
+ ? connectDevice : updateCurrentConnectedDevice();
if (connectDevice == mCurrentConnectedDevice) {
Log.d(TAG, "onConnectedDeviceChanged() this device all ready connected!");
return;
}
mCurrentConnectedDevice = connectDevice;
- dispatchDeviceAttributesChanged();
+ dispatchSelectedDeviceStateChanged(mCurrentConnectedDevice,
+ MediaDeviceState.STATE_CONNECTED);
}
@Override
public void onDeviceAttributesChanged() {
dispatchDeviceAttributesChanged();
}
+
+ @Override
+ public void onRequestFailed(int reason) {
+ dispatchOnRequestFailed(reason);
+ }
}
@@ -467,6 +472,18 @@
* Callback for notifying the device attributes is changed.
*/
default void onDeviceAttributesChanged() {};
+
+ /**
+ * Callback for notifying that transferring is failed.
+ *
+ * @param reason the reason that the request has failed. Can be one of followings:
+ * {@link android.media.MediaRoute2ProviderService#REASON_UNKNOWN_ERROR},
+ * {@link android.media.MediaRoute2ProviderService#REASON_REJECTED},
+ * {@link android.media.MediaRoute2ProviderService#REASON_NETWORK_ERROR},
+ * {@link android.media.MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE},
+ * {@link android.media.MediaRoute2ProviderService#REASON_INVALID_COMMAND},
+ */
+ default void onRequestFailed(int reason){};
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
index 73551f60..e8cbab8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
@@ -110,6 +110,12 @@
}
}
+ protected void dispatchOnRequestFailed(int reason) {
+ for (MediaDeviceCallback callback : getCallbacks()) {
+ callback.onRequestFailed(reason);
+ }
+ }
+
private Collection<MediaDeviceCallback> getCallbacks() {
return new CopyOnWriteArrayList<>(mCallbacks);
}
@@ -158,5 +164,17 @@
* (e.g: device name, connection state, subtitle) is changed.
*/
void onDeviceAttributesChanged();
+
+ /**
+ * Callback for notifying that transferring is failed.
+ *
+ * @param reason the reason that the request has failed. Can be one of followings:
+ * {@link android.media.MediaRoute2ProviderService#REASON_UNKNOWN_ERROR},
+ * {@link android.media.MediaRoute2ProviderService#REASON_REJECTED},
+ * {@link android.media.MediaRoute2ProviderService#REASON_NETWORK_ERROR},
+ * {@link android.media.MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE},
+ * {@link android.media.MediaRoute2ProviderService#REASON_INVALID_COMMAND},
+ */
+ void onRequestFailed(int reason);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index 7cd0a7c..7f93f69 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -16,6 +16,9 @@
package com.android.settingslib.media;
+import static android.media.MediaRoute2ProviderService.REASON_NETWORK_ERROR;
+import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
@@ -54,6 +57,8 @@
private MediaRouter2Manager mRouterManager;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
+ @Mock
+ private MediaManager.MediaDeviceCallback mCallback;
private InfoMediaManager mInfoMediaManager;
private Context mContext;
@@ -144,6 +149,8 @@
@Test
public void onRoutesChanged_getAvailableRoutes_shouldAddMediaDevice() {
final MediaRoute2Info info = mock(MediaRoute2Info.class);
+ mInfoMediaManager.registerCallback(mCallback);
+
when(info.getId()).thenReturn(TEST_ID);
when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
@@ -160,11 +167,14 @@
assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice);
assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size());
+ verify(mCallback).onConnectedDeviceChanged(TEST_ID);
}
@Test
public void onRoutesChanged_buildAllRoutes_shouldAddMediaDevice() {
final MediaRoute2Info info = mock(MediaRoute2Info.class);
+ mInfoMediaManager.registerCallback(mCallback);
+
when(info.getId()).thenReturn(TEST_ID);
when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
when(info.isSystemRoute()).thenReturn(true);
@@ -182,6 +192,7 @@
final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0);
assertThat(infoDevice.getId()).isEqualTo(TEST_ID);
assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size());
+ verify(mCallback).onConnectedDeviceChanged(null);
}
@Test
@@ -493,4 +504,22 @@
assertThat(mInfoMediaManager.getSessionName()).isEqualTo(TEST_NAME);
}
+
+ @Test
+ public void onTransferFailed_shouldDispatchOnRequestFailed() {
+ mInfoMediaManager.registerCallback(mCallback);
+
+ mInfoMediaManager.mMediaRouterCallback.onTransferFailed(null, null);
+
+ verify(mCallback).onRequestFailed(REASON_UNKNOWN_ERROR);
+ }
+
+ @Test
+ public void onRequestFailed_shouldDispatchOnRequestFailed() {
+ mInfoMediaManager.registerCallback(mCallback);
+
+ mInfoMediaManager.mMediaRouterCallback.onRequestFailed(REASON_NETWORK_ERROR);
+
+ verify(mCallback).onRequestFailed(REASON_NETWORK_ERROR);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index 3611dfe..1e888da 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -477,4 +477,13 @@
assertThat(mLocalMediaManager.mMediaDevices).hasSize(3);
verify(mCallback).onDeviceListUpdate(any());
}
+
+ @Test
+ public void onRequestFailed_shouldDispatchOnRequestFailed() {
+ mLocalMediaManager.registerCallback(mCallback);
+
+ mLocalMediaManager.mMediaDeviceCallback.onRequestFailed(1);
+
+ verify(mCallback).onRequestFailed(1);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
index ead2be4..a50965a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaManagerTest.java
@@ -136,4 +136,14 @@
assertThat(device).isNull();
}
+
+ @Test
+ public void dispatchOnRequestFailed_registerCallback_shouldDispatchCallback() {
+ mMediaManager.registerCallback(mCallback);
+
+ mMediaManager.dispatchOnRequestFailed(1);
+
+ verify(mCallback).onRequestFailed(1);
+ }
+
}
diff --git a/packages/SettingsProvider/res/values-ta/strings.xml b/packages/SettingsProvider/res/values-ta/strings.xml
index fa6b8cd..54d2242 100644
--- a/packages/SettingsProvider/res/values-ta/strings.xml
+++ b/packages/SettingsProvider/res/values-ta/strings.xml
@@ -20,8 +20,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="4567566098528588863">"அமைப்புகளின் சேமிப்பிடம்"</string>
- <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
- <skip />
- <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
- <skip />
+ <string name="wifi_softap_config_change" msgid="5688373762357941645">"ஹாட்ஸ்பாட் அமைப்புகள் மாற்றப்பட்டன"</string>
+ <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"விவரங்களைப் பார்க்க, தட்டவும்"</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index ca88f13..aed7c21 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -44,7 +44,9 @@
public final Rect clipRect;
public final int prefixOrderIndex;
public final Point position;
+ public final Rect localBounds;
public final Rect sourceContainerBounds;
+ public final Rect screenSpaceBounds;
public final boolean isNotInRecents;
public final Rect contentInsets;
@@ -57,7 +59,9 @@
isTranslucent = app.isTranslucent;
clipRect = app.clipRect;
position = app.position;
+ localBounds = app.localBounds;
sourceContainerBounds = app.sourceContainerBounds;
+ screenSpaceBounds = app.screenSpaceBounds;
prefixOrderIndex = app.prefixOrderIndex;
isNotInRecents = app.isNotInRecents;
contentInsets = app.contentInsets;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
index 7cfa289..d33c653 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestReceiver.java
@@ -20,6 +20,7 @@
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.IBinder;
+import android.util.Size;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.View;
@@ -43,13 +44,27 @@
mOpacity = opacity;
}
- /** Called whenever a surface view request is received. */
+ /** See {@link #onReceive(Context, Bundle, View, Size)}. */
public void onReceive(Context context, Bundle bundle, View view) {
+ onReceive(context, bundle, view, null);
+ }
+
+ /**
+ * Called whenever a surface view request is received.
+ * @param view the view rendering content, on the receiver end of the surface request.
+ * @param viewSize when {@param viewSize} is not specified, we will use the surface control size
+ * to attach the view to the window.
+ */
+ public void onReceive(Context context, Bundle bundle, View view, Size viewSize) {
if (mSurfaceControlViewHost != null) {
mSurfaceControlViewHost.die();
}
SurfaceControl surfaceControl = SurfaceViewRequestUtils.getSurfaceControl(bundle);
if (surfaceControl != null) {
+ if (viewSize == null) {
+ viewSize = new Size(surfaceControl.getWidth(), surfaceControl.getHeight());
+ }
+
IBinder hostToken = SurfaceViewRequestUtils.getHostToken(bundle);
WindowlessWindowManager windowlessWindowManager =
@@ -59,12 +74,22 @@
context.getDisplayNoVerify(), windowlessWindowManager);
WindowManager.LayoutParams layoutParams =
new WindowManager.LayoutParams(
- surfaceControl.getWidth(),
- surfaceControl.getHeight(),
+ viewSize.getWidth(),
+ viewSize.getHeight(),
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
mOpacity);
+ // This aspect scales the view to fit in the surface and centers it
+ final float scale = Math.min(surfaceControl.getWidth() / (float) viewSize.getWidth(),
+ surfaceControl.getHeight() / (float) viewSize.getHeight());
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ view.setPivotX(0);
+ view.setPivotY(0);
+ view.setTranslationX((surfaceControl.getWidth() - scale * viewSize.getWidth()) / 2);
+ view.setTranslationY((surfaceControl.getHeight() - scale * viewSize.getHeight()) / 2);
+
mSurfaceControlViewHost.addView(view, layoutParams);
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java
index 0cbd541..4409276 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SurfaceViewRequestUtils.java
@@ -36,7 +36,7 @@
}
/**
- * Retrieves the SurfaceControl from an Intent created by
+ * Retrieves the SurfaceControl from a bundle created by
* {@link #createSurfaceBundle(SurfaceView)}.
**/
public static SurfaceControl getSurfaceControl(Bundle bundle) {
@@ -44,7 +44,7 @@
}
/**
- * Retrieves the input token from an Intent created by
+ * Retrieves the input token from a bundle created by
* {@link #createSurfaceBundle(SurfaceView)}.
**/
public static @Nullable IBinder getHostToken(Bundle bundle) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7ca2308..4240209c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -279,7 +279,8 @@
/**
* @return the display id of the virtual display on which bubble contents is drawn.
*/
- int getDisplayId() {
+ @Override
+ public int getDisplayId() {
return mExpandedView != null ? mExpandedView.getVirtualDisplayId() : INVALID_DISPLAY;
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index d754725..22c2c7e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -1175,23 +1175,17 @@
* status bar, otherwise returns {@link Display#INVALID_DISPLAY}.
*/
public int getExpandedDisplayId(Context context) {
- final Bubble bubble = getExpandedBubble(context);
- return bubble != null ? bubble.getDisplayId() : INVALID_DISPLAY;
- }
-
- @Nullable
- private Bubble getExpandedBubble(Context context) {
if (mStackView == null) {
- return null;
+ return INVALID_DISPLAY;
}
final boolean defaultDisplay = context.getDisplay() != null
&& context.getDisplay().getDisplayId() == DEFAULT_DISPLAY;
- final Bubble expandedBubble = mStackView.getExpandedBubble();
- if (defaultDisplay && expandedBubble != null && isStackExpanded()
+ final BubbleViewProvider expandedViewProvider = mStackView.getExpandedBubble();
+ if (defaultDisplay && expandedViewProvider != null && isStackExpanded()
&& !mNotificationShadeWindowController.getPanelExpanded()) {
- return expandedBubble;
+ return expandedViewProvider.getDisplayId();
}
- return null;
+ return INVALID_DISPLAY;
}
@VisibleForTesting
@@ -1256,7 +1250,7 @@
@Override
public void onSingleTaskDisplayEmpty(int displayId) {
- final Bubble expandedBubble = mStackView != null
+ final BubbleViewProvider expandedBubble = mStackView != null
? mStackView.getExpandedBubble()
: null;
int expandedId = expandedBubble != null ? expandedBubble.getDisplayId() : -1;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java
index e800011..19733a5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java
@@ -59,13 +59,15 @@
return FORCE_SHOW_USER_EDUCATION || forceShow;
}
- static String formatBubblesString(List<Bubble> bubbles, Bubble selected) {
+ static String formatBubblesString(List<Bubble> bubbles, BubbleViewProvider selected) {
StringBuilder sb = new StringBuilder();
for (Bubble bubble : bubbles) {
if (bubble == null) {
sb.append(" <null> !!!!!\n");
} else {
- boolean isSelected = (selected != null && bubble == selected);
+ boolean isSelected = (selected != null
+ && selected.getKey() != BubbleOverflow.KEY
+ && bubble == selected);
String arrow = isSelected ? "=>" : " ";
sb.append(String.format("%s Bubble{act=%12d, ongoing=%d, key=%s}\n",
arrow,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
index 313bb42..4fb2d08 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
@@ -16,6 +16,7 @@
package com.android.systemui.bubbles;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.GONE;
import static com.android.systemui.bubbles.BadgedImageView.DEFAULT_PATH_SIZE;
@@ -45,7 +46,7 @@
public static final String KEY = "Overflow";
private BadgedImageView mOverflowBtn;
- private BubbleExpandedView mOverflowExpandedView;
+ private BubbleExpandedView mExpandedView;
private LayoutInflater mInflater;
private Context mContext;
private Bitmap mIcon;
@@ -63,11 +64,11 @@
}
void setUpOverflow(ViewGroup parentViewGroup, BubbleStackView stackView) {
- mOverflowExpandedView = (BubbleExpandedView) mInflater.inflate(
+ mExpandedView = (BubbleExpandedView) mInflater.inflate(
R.layout.bubble_expanded_view, parentViewGroup /* root */,
false /* attachToRoot */);
- mOverflowExpandedView.setOverflow(true);
- mOverflowExpandedView.setStackView(stackView);
+ mExpandedView.setOverflow(true);
+ mExpandedView.setStackView(stackView);
updateIcon(mContext, parentViewGroup);
}
@@ -124,7 +125,7 @@
@Override
public BubbleExpandedView getExpandedView() {
- return mOverflowExpandedView;
+ return mExpandedView;
}
@Override
@@ -149,7 +150,7 @@
@Override
public void setContentVisibility(boolean visible) {
- mOverflowExpandedView.setContentVisibility(visible);
+ mExpandedView.setContentVisibility(visible);
}
@Override
@@ -167,4 +168,9 @@
public String getKey() {
return BubbleOverflow.KEY;
}
+
+ @Override
+ public int getDisplayId() {
+ return mExpandedView != null ? mExpandedView.getVirtualDisplayId() : INVALID_DISPLAY;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 96c887f..e8acbab 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -908,14 +908,8 @@
* The {@link Bubble} that is expanded, null if one does not exist.
*/
@Nullable
- Bubble getExpandedBubble() {
- if (mExpandedBubble == null
- || (BubbleExperimentConfig.allowBubbleOverflow(mContext)
- && mExpandedBubble.getIconView() == mBubbleOverflow.getBtn()
- && BubbleOverflow.KEY.equals(mExpandedBubble.getKey()))) {
- return null;
- }
- return (Bubble) mExpandedBubble;
+ BubbleViewProvider getExpandedBubble() {
+ return mExpandedBubble;
}
// via BubbleData.Listener
@@ -1245,7 +1239,8 @@
}
/**
- * @deprecated use {@link #setExpanded(boolean)} and {@link #setSelectedBubble(Bubble)}
+ * @deprecated use {@link #setExpanded(boolean)} and
+ * {@link BubbleData#setSelectedBubble(Bubble)}
*/
@Deprecated
@MainThread
@@ -1287,7 +1282,7 @@
if (DEBUG_BUBBLE_STACK_VIEW) {
Log.d(TAG, "animateCollapse");
Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
- getExpandedBubble()));
+ mExpandedBubble));
}
updateOverflowBtnVisibility(/* apply */ false);
mBubbleContainer.cancelAllAnimations();
@@ -1861,17 +1856,16 @@
}
private void updatePointerPosition() {
- Bubble expandedBubble = getExpandedBubble();
- if (expandedBubble == null) {
+ if (mExpandedBubble == null) {
return;
}
- int index = getBubbleIndex(expandedBubble);
+ int index = getBubbleIndex(mExpandedBubble);
float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index);
float halfBubble = mBubbleSize / 2f;
float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble;
// Padding might be adjusted for insets, so get it directly from the view
bubbleCenter -= mExpandedViewContainer.getPaddingLeft();
- expandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
+ mExpandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
}
/**
@@ -1893,11 +1887,10 @@
* is between 0 and the bubble count minus 1.
*/
int getBubbleIndex(@Nullable BubbleViewProvider provider) {
- if (provider == null || provider.getKey() == BubbleOverflow.KEY) {
+ if (provider == null) {
return 0;
}
- Bubble b = (Bubble) provider;
- return mBubbleContainer.indexOfChild(b.getIconView());
+ return mBubbleContainer.indexOfChild(provider.getIconView());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java
index f04933a..ef84c73 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewProvider.java
@@ -41,4 +41,6 @@
Path getDotPath();
boolean showDot();
+
+ int getDisplayId();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 53605e5..7c06157 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -282,7 +282,7 @@
.withCornerRadius(mCornerRadius)
.withVisibility(true)
.build();
- mSyncRtTransactionApplier.scheduleApply(params);
+ mSyncRtTransactionApplier.scheduleApply(true /* earlyWakeup */, params);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 742e652..78160c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -399,7 +399,8 @@
// Switch which bubble is expanded
mBubbleController.selectBubble(mRow.getEntry().getKey());
mBubbleData.setExpanded(true);
- assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
+ assertEquals(mRow.getEntry(),
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow.getEntry()));
@@ -492,21 +493,25 @@
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
// Last added is the one that is expanded
- assertEquals(mRow2.getEntry(), stackView.getExpandedBubble().getEntry());
+ assertEquals(mRow2.getEntry(),
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow2.getEntry()));
// Dismiss currently expanded
- mBubbleController.removeBubble(stackView.getExpandedBubble().getEntry(),
+ mBubbleController.removeBubble(
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
BubbleController.DISMISS_USER_GESTURE);
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
// Make sure first bubble is selected
- assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
+ assertEquals(mRow.getEntry(),
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry());
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
// Dismiss that one
- mBubbleController.removeBubble(stackView.getExpandedBubble().getEntry(),
+ mBubbleController.removeBubble(
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 22ef3f3..5ef4cd2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -130,19 +130,15 @@
private KeyguardBypassController mKeyguardBypassController;
@Mock
private FloatingContentCoordinator mFloatingContentCoordinator;
-
@Captor
private ArgumentCaptor<NotifCollectionListener> mNotifListenerCaptor;
-
private TestableBubbleController mBubbleController;
private NotificationShadeWindowController mNotificationShadeWindowController;
private NotifCollectionListener mEntryListener;
-
private NotificationTestHelper mNotificationTestHelper;
private ExpandableNotificationRow mRow;
private ExpandableNotificationRow mRow2;
private ExpandableNotificationRow mNonBubbleNotifRow;
-
@Mock
private BubbleController.BubbleStateChangeListener mBubbleStateChangeListener;
@Mock
@@ -309,7 +305,7 @@
verify(mNotifCallback, times(1)).invalidateNotifications(anyString());
assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
mBubbleController.updateBubble(mRow2.getEntry());
- verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
+ verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey()));
assertTrue(mBubbleController.hasBubbles());
@@ -379,7 +375,8 @@
// Switch which bubble is expanded
mBubbleController.selectBubble(mRow.getEntry().getKey());
mBubbleData.setExpanded(true);
- assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
+ assertEquals(mRow.getEntry(),
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow.getEntry()));
@@ -471,21 +468,25 @@
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
// Last added is the one that is expanded
- assertEquals(mRow2.getEntry(), stackView.getExpandedBubble().getEntry());
+ assertEquals(mRow2.getEntry(),
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry());
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
mRow2.getEntry()));
// Dismiss currently expanded
- mBubbleController.removeBubble(stackView.getExpandedBubble().getEntry(),
+ mBubbleController.removeBubble(
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
BubbleController.DISMISS_USER_GESTURE);
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
// Make sure first bubble is selected
- assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
+ assertEquals(mRow.getEntry(),
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry());
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
// Dismiss that one
- mBubbleController.removeBubble(stackView.getExpandedBubble().getEntry(),
+ mBubbleController.removeBubble(
+ mBubbleData.getBubbleWithKey(stackView.getExpandedBubble().getKey()).getEntry(),
BubbleController.DISMISS_USER_GESTURE);
// Make sure state changes and collapse happens
@@ -645,7 +646,7 @@
}
@Test
- public void removeBubble_intercepted() {
+ public void removeBubble_intercepted() {
mEntryListener.onEntryAdded(mRow.getEntry());
mBubbleController.updateBubble(mRow.getEntry());
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index cc36f4a..a402ffa 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -288,10 +288,18 @@
@Override
public void setLimit(String iface, long quotaBytes) {
- mLog.i("setLimit: " + iface + "," + quotaBytes);
// Listen for all iface is necessary since upstream might be changed after limit
// is set.
mHandler.post(() -> {
+ final Long curIfaceQuota = mInterfaceQuotas.get(iface);
+
+ // If the quota is set to unlimited, the value set to HAL is Long.MAX_VALUE,
+ // which is ~8.4 x 10^6 TiB, no one can actually reach it. Thus, it is not
+ // useful to set it multiple times.
+ // Otherwise, the quota needs to be updated to tell HAL to re-count from now even
+ // if the quota is the same as the existing one.
+ if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return;
+
if (quotaBytes == QUOTA_UNLIMITED) {
mInterfaceQuotas.remove(iface);
} else {
@@ -323,7 +331,6 @@
@Override
public void requestStatsUpdate(int token) {
- mLog.i("requestStatsUpdate: " + token);
// Do not attempt to update stats by querying the offload HAL
// synchronously from a different thread than the Handler thread. http://b/64771555.
mHandler.post(() -> {
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 2420e69..e73f9ce 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -37,7 +37,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.Dataset;
-import android.service.autofill.InlinePresentation;
+import android.service.autofill.InlineAction;
import android.service.autofill.augmented.AugmentedAutofillService;
import android.service.autofill.augmented.IAugmentedAutofillService;
import android.service.autofill.augmented.IFillCallback;
@@ -167,7 +167,7 @@
new IFillCallback.Stub() {
@Override
public void onSuccess(@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable List<InlinePresentation> inlineActions) {
+ @Nullable List<InlineAction> inlineActions) {
mCallbacks.resetLastResponse();
maybeRequestShowInlineSuggestions(sessionId,
inlineSuggestionsRequest, inlineSuggestionsData,
@@ -237,7 +237,7 @@
private void maybeRequestShowInlineSuggestions(int sessionId,
@Nullable InlineSuggestionsRequest request,
@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable List<InlinePresentation> inlineActions, @NonNull AutofillId focusedId,
+ @Nullable List<InlineAction> inlineActions, @NonNull AutofillId focusedId,
@Nullable Function<InlineSuggestionsResponse, Boolean> inlineSuggestionsCallback,
@NonNull IAutoFillManagerClient client, @NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
@@ -250,7 +250,7 @@
final InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createAugmentedInlineSuggestionsResponse(
- request, inlineSuggestionsData, inlineActions, focusedId, mContext,
+ request, inlineSuggestionsData, inlineActions, focusedId,
dataset -> {
mCallbacks.logAugmentedAutofillSelected(sessionId,
dataset.getId());
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index f14a7e9..5619478 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -137,7 +137,6 @@
private final Handler mHandler;
private final Object mLock;
private final AutoFillUI mUi;
- private final Context mContext;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
@@ -695,7 +694,6 @@
mLock = lock;
mUi = ui;
mHandler = handler;
- mContext = context;
mRemoteFillService = serviceComponentName == null ? null
: new RemoteFillService(context, serviceComponentName, userId, this,
bindInstantServiceAllowed);
@@ -2680,7 +2678,7 @@
InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createInlineSuggestionsResponse(
inlineSuggestionsRequest.get(),
- response, filterText, response.getInlineActions(), mCurrentViewId, mContext,
+ response, filterText, response.getInlineActions(), mCurrentViewId,
this, () -> {
synchronized (mLock) {
requestHideFillUi(mCurrentViewId);
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 4cf4463..82e5003 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -21,12 +21,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.Context;
+import android.content.IntentSender;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.IInlineSuggestionUiCallback;
+import android.service.autofill.InlineAction;
import android.service.autofill.InlinePresentation;
import android.text.TextUtils;
import android.util.Slog;
@@ -39,7 +40,6 @@
import android.view.inputmethod.InlineSuggestionInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
-import android.widget.Toast;
import com.android.internal.view.inline.IInlineContentCallback;
import com.android.internal.view.inline.IInlineContentProvider;
@@ -73,8 +73,8 @@
@Nullable
public static InlineSuggestionsResponse createInlineSuggestionsResponse(
@NonNull InlineSuggestionsRequest request, @NonNull FillResponse response,
- @Nullable String filterText, @Nullable List<InlinePresentation> inlineActions,
- @NonNull AutofillId autofillId, @NonNull Context context,
+ @Nullable String filterText, @Nullable List<InlineAction> inlineActions,
+ @NonNull AutofillId autofillId,
@NonNull AutoFillUI.AutoFillUiCallback client, @NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");
@@ -97,7 +97,7 @@
response.getAuthentication() == null ? null : response.getInlinePresentation();
return createInlineSuggestionsResponseInternal(/* isAugmented= */ false, request,
response.getDatasets(), filterText, inlineAuthentication, inlineActions, autofillId,
- context, onErrorCallback, onClickFactory, remoteRenderService);
+ onErrorCallback, onClickFactory, remoteRenderService);
}
/**
@@ -107,15 +107,14 @@
@Nullable
public static InlineSuggestionsResponse createAugmentedInlineSuggestionsResponse(
@NonNull InlineSuggestionsRequest request, @NonNull List<Dataset> datasets,
- @Nullable List<InlinePresentation> inlineActions,
- @NonNull AutofillId autofillId, @NonNull Context context,
+ @Nullable List<InlineAction> inlineActions, @NonNull AutofillId autofillId,
@NonNull InlineSuggestionUiCallback inlineSuggestionUiCallback,
@NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
if (sDebug) Slog.d(TAG, "createAugmentedInlineSuggestionsResponse called");
return createInlineSuggestionsResponseInternal(/* isAugmented= */ true, request,
datasets, /* filterText= */ null, /* inlineAuthentication= */ null,
- inlineActions, autofillId, context, onErrorCallback,
+ inlineActions, autofillId, onErrorCallback,
(dataset, datasetIndex) ->
inlineSuggestionUiCallback.autofill(dataset), remoteRenderService);
}
@@ -125,9 +124,8 @@
boolean isAugmented, @NonNull InlineSuggestionsRequest request,
@Nullable List<Dataset> datasets, @Nullable String filterText,
@Nullable InlinePresentation inlineAuthentication,
- @Nullable List<InlinePresentation> inlineActions, @NonNull AutofillId autofillId,
- @NonNull Context context, @NonNull Runnable onErrorCallback,
- @NonNull BiConsumer<Dataset, Integer> onClickFactory,
+ @Nullable List<InlineAction> inlineActions, @NonNull AutofillId autofillId,
+ @NonNull Runnable onErrorCallback, @NonNull BiConsumer<Dataset, Integer> onClickFactory,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
@@ -171,12 +169,13 @@
}
// We should only add inline actions if there is at least one suggestion.
if (!inlineSuggestions.isEmpty() && inlineActions != null) {
- for (InlinePresentation inlinePresentation : inlineActions) {
- final InlineSuggestion inlineAction = createInlineAction(isAugmented, context,
- mergedInlinePresentation(request, 0, inlinePresentation),
+ for (InlineAction inlineAction : inlineActions) {
+ final InlineSuggestion inlineActionSuggestion = createInlineAction(isAugmented,
+ mergedInlinePresentation(request, 0, inlineAction.getInlinePresentation()),
+ inlineAction.getAction(),
remoteRenderService, onErrorCallback, request.getHostInputToken(),
request.getHostDisplayId());
- inlineSuggestions.add(inlineAction);
+ inlineSuggestions.add(inlineActionSuggestion);
}
}
return new InlineSuggestionsResponse(inlineSuggestions);
@@ -215,22 +214,30 @@
private static InlineSuggestion createInlineAction(boolean isAugmented,
- @NonNull Context context,
- @NonNull InlinePresentation inlinePresentation,
+ @NonNull InlinePresentation presentation,
+ @NonNull IntentSender action,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService,
@NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken,
int displayId) {
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
- inlinePresentation.getInlinePresentationSpec(),
+ presentation.getInlinePresentationSpec(),
isAugmented ? InlineSuggestionInfo.SOURCE_PLATFORM
: InlineSuggestionInfo.SOURCE_AUTOFILL,
- inlinePresentation.getAutofillHints(),
- InlineSuggestionInfo.TYPE_ACTION, inlinePresentation.isPinned());
+ presentation.getAutofillHints(), InlineSuggestionInfo.TYPE_ACTION,
+ presentation.isPinned());
final Runnable onClickAction = () -> {
- Toast.makeText(context, "icon clicked", Toast.LENGTH_SHORT).show();
+ try {
+ // TODO(b/150499490): route the intent to the client app to have it fired there,
+ // so that it will appear as a part of the same task as the client app (similar
+ // to the authentication flow).
+ action.sendIntent(null, 0, null, null, null);
+ } catch (IntentSender.SendIntentException e) {
+ onErrorCallback.run();
+ Slog.w(TAG, "Error sending inline action intent");
+ }
};
return new InlineSuggestion(inlineSuggestionInfo,
- createInlineContentProvider(inlinePresentation, onClickAction, onErrorCallback,
+ createInlineContentProvider(presentation, onClickAction, onErrorCallback,
remoteRenderService, hostInputToken, displayId));
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index a4a42bc..03ca1c6 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -85,6 +85,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -272,6 +273,46 @@
}
};
+ public boolean onFactoryReset() {
+ // Wait for stable state if bluetooth is temporary state.
+ int state = getState();
+ if (state == BluetoothAdapter.STATE_BLE_TURNING_ON
+ || state == BluetoothAdapter.STATE_TURNING_ON
+ || state == BluetoothAdapter.STATE_TURNING_OFF) {
+ if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) {
+ return false;
+ }
+ }
+
+ // Clear registered LE apps to force shut-off Bluetooth
+ clearBleApps();
+ state = getState();
+ try {
+ mBluetoothLock.readLock().lock();
+ if (mBluetooth == null) {
+ return false;
+ }
+ if (state == BluetoothAdapter.STATE_BLE_ON) {
+ addActiveLog(
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
+ mContext.getPackageName(), false);
+ mBluetooth.onBrEdrDown();
+ return true;
+ } else if (state == BluetoothAdapter.STATE_ON) {
+ addActiveLog(
+ BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET,
+ mContext.getPackageName(), false);
+ mBluetooth.disable();
+ return true;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to shutdown Bluetooth", e);
+ } finally {
+ mBluetoothLock.readLock().unlock();
+ }
+ return false;
+ }
+
public void onAirplaneModeChanged() {
synchronized (this) {
if (isBluetoothPersistedStateOn()) {
@@ -1670,7 +1711,8 @@
// the previous Bluetooth process has exited. The
// waiting period has three components:
// (a) Wait until the local state is STATE_OFF. This
- // is accomplished by "waitForOnOff(false, true)".
+ // is accomplished by
+ // "waitForState(Set.of(BluetoothAdapter.STATE_OFF))".
// (b) Wait until the STATE_OFF state is updated to
// all components.
// (c) Wait until the Bluetooth process exits, and
@@ -1680,7 +1722,7 @@
// message. The delay time is backed off if Bluetooth
// continuously failed to turn on itself.
//
- waitForOnOff(false, true);
+ waitForState(Set.of(BluetoothAdapter.STATE_OFF));
Message restartMsg =
mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
@@ -1693,10 +1735,15 @@
}
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
if (mEnable && mBluetooth != null) {
- waitForOnOff(true, false);
+ waitForState(Set.of(BluetoothAdapter.STATE_ON));
mEnable = false;
handleDisable();
- waitForOnOff(false, false);
+ waitForState(Set.of(BluetoothAdapter.STATE_OFF,
+ BluetoothAdapter.STATE_TURNING_ON,
+ BluetoothAdapter.STATE_TURNING_OFF,
+ BluetoothAdapter.STATE_BLE_TURNING_ON,
+ BluetoothAdapter.STATE_BLE_ON,
+ BluetoothAdapter.STATE_BLE_TURNING_OFF));
} else {
mEnable = false;
handleDisable();
@@ -1819,9 +1866,14 @@
}
if (!mEnable) {
- waitForOnOff(true, false);
+ waitForState(Set.of(BluetoothAdapter.STATE_ON));
handleDisable();
- waitForOnOff(false, false);
+ waitForState(Set.of(BluetoothAdapter.STATE_OFF,
+ BluetoothAdapter.STATE_TURNING_ON,
+ BluetoothAdapter.STATE_TURNING_OFF,
+ BluetoothAdapter.STATE_BLE_TURNING_ON,
+ BluetoothAdapter.STATE_BLE_ON,
+ BluetoothAdapter.STATE_BLE_TURNING_OFF));
}
break;
}
@@ -1853,7 +1905,7 @@
== BluetoothAdapter.STATE_OFF)) {
if (mEnable) {
Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
- waitForOnOff(false, true);
+ waitForState(Set.of(BluetoothAdapter.STATE_OFF));
Message restartMsg =
mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
@@ -1982,7 +2034,7 @@
mState = BluetoothAdapter.STATE_TURNING_ON;
}
- waitForOnOff(true, false);
+ waitForState(Set.of(BluetoothAdapter.STATE_ON));
if (mState == BluetoothAdapter.STATE_TURNING_ON) {
bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
@@ -1997,7 +2049,8 @@
bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
BluetoothAdapter.STATE_TURNING_OFF);
- boolean didDisableTimeout = !waitForOnOff(false, true);
+ boolean didDisableTimeout =
+ !waitForState(Set.of(BluetoothAdapter.STATE_OFF));
bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
BluetoothAdapter.STATE_OFF);
@@ -2243,12 +2296,7 @@
}
}
- /**
- * if on is true, wait for state become ON
- * if off is true, wait for state become OFF
- * if both on and off are false, wait for state not ON
- */
- private boolean waitForOnOff(boolean on, boolean off) {
+ private boolean waitForState(Set<Integer> states) {
int i = 0;
while (i < 10) {
try {
@@ -2256,18 +2304,8 @@
if (mBluetooth == null) {
break;
}
- if (on) {
- if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) {
- return true;
- }
- } else if (off) {
- if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) {
- return true;
- }
- } else {
- if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) {
- return true;
- }
+ if (states.contains(mBluetooth.getState())) {
+ return true;
}
} catch (RemoteException e) {
Slog.e(TAG, "getState()", e);
@@ -2275,14 +2313,10 @@
} finally {
mBluetoothLock.readLock().unlock();
}
- if (on || off) {
- SystemClock.sleep(300);
- } else {
- SystemClock.sleep(50);
- }
+ SystemClock.sleep(300);
i++;
}
- Slog.e(TAG, "waitForOnOff time out");
+ Slog.e(TAG, "waitForState " + states + " time out");
return false;
}
@@ -2343,7 +2377,7 @@
mContext.getPackageName(), false);
handleDisable();
- waitForOnOff(false, true);
+ waitForState(Set.of(BluetoothAdapter.STATE_OFF));
sendBluetoothServiceDownCallback();
@@ -2533,6 +2567,8 @@
return "USER_SWITCH";
case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
return "RESTORE_USER_SETTING";
+ case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET:
+ return "FACTORY_RESET";
case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
default: return "UNKNOWN[" + reason + "]";
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ff41d1cc..7287a44 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -273,9 +273,6 @@
// connect anyway?" dialog after the user selects a network that doesn't validate.
private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000;
- // How long to dismiss network notification.
- private static final int TIMEOUT_NOTIFICATION_DELAY_MS = 20 * 1000;
-
// Default to 30s linger time-out. Modifiable only for testing.
private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
@@ -523,18 +520,13 @@
private static final int EVENT_PROVISIONING_NOTIFICATION = 43;
/**
- * This event can handle dismissing notification by given network id.
- */
- private static final int EVENT_TIMEOUT_NOTIFICATION = 44;
-
- /**
* Used to specify whether a network should be used even if connectivity is partial.
* arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for
* false)
* arg2 = whether to remember this choice in the future (1 for true or 0 for false)
* obj = network
*/
- private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 45;
+ private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 44;
/**
* Event for NetworkMonitor to inform ConnectivityService that the probe status has changed.
@@ -543,7 +535,7 @@
* arg1 = A bitmask to describe which probes are completed.
* arg2 = A bitmask to describe which probes are successful.
*/
- public static final int EVENT_PROBE_STATUS_CHANGED = 46;
+ public static final int EVENT_PROBE_STATUS_CHANGED = 45;
/**
* Event for NetworkMonitor to inform ConnectivityService that captive portal data has changed.
@@ -551,7 +543,7 @@
* arg2 = netId
* obj = captive portal data
*/
- private static final int EVENT_CAPPORT_DATA_CHANGED = 47;
+ private static final int EVENT_CAPPORT_DATA_CHANGED = 46;
/**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
@@ -2877,13 +2869,6 @@
final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0);
final boolean wasValidated = nai.lastValidated;
final boolean wasDefault = isDefaultNetwork(nai);
- // Only show a connected notification if the network is pending validation
- // after the captive portal app was open, and it has now validated.
- if (nai.captivePortalValidationPending && valid) {
- // User is now logged in, network validated.
- nai.captivePortalValidationPending = false;
- showNetworkNotification(nai, NotificationType.LOGGED_IN);
- }
if (DBG) {
final String logMsg = !TextUtils.isEmpty(redirectUrl)
@@ -3764,12 +3749,6 @@
new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
- // This runs on a random binder thread, but getNetworkAgentInfoForNetwork is thread-safe,
- // and captivePortalValidationPending is volatile.
- final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai != null) {
- nai.captivePortalValidationPending = true;
- }
Binder.withCleanCallingIdentity(() ->
mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
}
@@ -3888,14 +3867,6 @@
final String action;
final boolean highPriority;
switch (type) {
- case LOGGED_IN:
- action = Settings.ACTION_WIFI_SETTINGS;
- mHandler.removeMessages(EVENT_TIMEOUT_NOTIFICATION);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NOTIFICATION,
- nai.network.netId, 0), TIMEOUT_NOTIFICATION_DELAY_MS);
- // High priority because it is a direct result of the user logging in to a portal.
- highPriority = true;
- break;
case NO_INTERNET:
action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
// High priority because it is only displayed for explicitly selected networks.
@@ -3923,7 +3894,7 @@
}
Intent intent = new Intent(action);
- if (type != NotificationType.LOGGED_IN && type != NotificationType.PRIVATE_DNS_BROKEN) {
+ if (type != NotificationType.PRIVATE_DNS_BROKEN) {
intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName("com.android.settings",
@@ -4139,9 +4110,6 @@
case EVENT_DATA_SAVER_CHANGED:
handleRestrictBackgroundChanged(toBool(msg.arg1));
break;
- case EVENT_TIMEOUT_NOTIFICATION:
- mNotifier.clearNotification(msg.arg1, NotificationType.LOGGED_IN);
- break;
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9058ac4..f64272b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4766,7 +4766,8 @@
packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
: ApplicationExitInfo.REASON_USER_REQUESTED,
ApplicationExitInfo.SUBREASON_UNKNOWN,
- packageName == null ? ("stop user " + userId) : ("stop " + packageName));
+ (packageName == null ? ("stop user " + userId) : ("stop " + packageName))
+ + " due to " + reason);
didSomething |=
mAtmInternal.onForceStopPackage(packageName, doit, evenPersistent, userId);
@@ -17066,6 +17067,7 @@
proc.lastCachedPss = pss;
proc.lastCachedSwapPss = swapPss;
}
+ proc.mLastRss = rss;
final SparseArray<Pair<Long, String>> watchUids
= mMemWatchProcesses.getMap().get(proc.processName);
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index df9417e..028a059 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -505,9 +505,13 @@
@VisibleForTesting
void onPackageRemoved(String packageName, int uid, boolean allUsers) {
if (packageName != null) {
- mAppExitInfoSourceZygote.removeByUid(uid, allUsers);
- mAppExitInfoSourceLmkd.removeByUid(uid, allUsers);
- mIsolatedUidRecords.removeAppUid(uid, allUsers);
+ final boolean removeUid = TextUtils.isEmpty(
+ mService.mPackageManagerInt.getNameForUid(uid));
+ if (removeUid) {
+ mAppExitInfoSourceZygote.removeByUid(uid, allUsers);
+ mAppExitInfoSourceLmkd.removeByUid(uid, allUsers);
+ mIsolatedUidRecords.removeAppUid(uid, allUsers);
+ }
removePackage(packageName, allUsers ? UserHandle.USER_ALL : UserHandle.getUserId(uid));
schedulePersistProcessExitInfo(true);
}
@@ -533,6 +537,11 @@
mService.mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ boolean replacing = intent.getBooleanExtra(
+ Intent.EXTRA_REPLACING, false);
+ if (replacing) {
+ return;
+ }
int uid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
boolean allUsers = intent.getBooleanExtra(
Intent.EXTRA_REMOVED_FOR_ALL_USERS, false);
@@ -835,8 +844,8 @@
info.setReason(ApplicationExitInfo.REASON_UNKNOWN);
info.setStatus(0);
info.setImportance(procStateToImportance(app.setProcState));
- info.setPss(app.lastMemInfo == null ? 0 : app.lastMemInfo.getTotalPss());
- info.setRss(app.lastMemInfo == null ? 0 : app.lastMemInfo.getTotalRss());
+ info.setPss(app.lastPss);
+ info.setRss(app.mLastRss);
info.setTimestamp(System.currentTimeMillis());
return info;
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 7cc2e8eb..1f826b5 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -16,12 +16,6 @@
# Windows & Activities
ogunwale@google.com
-jjaggi@google.com
-racarr@google.com
-chaviw@google.com
-vishnun@google.com
-akulian@google.com
-roosa@google.com
# Permissions & Packages
svetoslavganov@google.com
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index f2ca1da..c029811 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -323,6 +323,8 @@
// set of disabled compat changes for the process (all others are enabled)
long[] mDisabledCompatChanges;
+ long mLastRss; // Last computed memory rss.
+
// The precede instance of the process, which would exist when the previous process is killed
// but not fully dead yet; in this case, the new instance of the process should be held until
// this precede instance is fully dead.
@@ -431,6 +433,7 @@
pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, lastSwapPss*1024);
pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss*1024);
pw.print(" lastCachedSwapPss="); DebugUtils.printSizeValue(pw, lastCachedSwapPss*1024);
+ pw.print(" lastRss="); DebugUtils.printSizeValue(pw, mLastRss * 1024);
pw.println();
pw.print(prefix); pw.print("procStateMemTracker: ");
procStateMemTracker.dumpLine(pw);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 23b954c..2f04715 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -160,10 +160,6 @@
// Whether a captive portal was found during the last network validation attempt.
public boolean lastCaptivePortalDetected;
- // Indicates the captive portal app was opened to show a login UI to the user, but the network
- // has not validated yet.
- public volatile boolean captivePortalValidationPending;
-
// Set to true when partial connectivity was detected.
public boolean partialConnectivity;
@@ -638,7 +634,6 @@
+ "acceptUnvalidated{" + networkAgentConfig.acceptUnvalidated + "} "
+ "everCaptivePortalDetected{" + everCaptivePortalDetected + "} "
+ "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} "
- + "captivePortalValidationPending{" + captivePortalValidationPending + "} "
+ "partialConnectivity{" + partialConnectivity + "} "
+ "acceptPartialConnectivity{" + networkAgentConfig.acceptPartialConnectivity + "} "
+ "clat{" + clatd + "} "
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 25c761a..0925de8 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -51,7 +51,6 @@
LOST_INTERNET(SystemMessage.NOTE_NETWORK_LOST_INTERNET),
NETWORK_SWITCH(SystemMessage.NOTE_NETWORK_SWITCH),
NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET),
- LOGGED_IN(SystemMessage.NOTE_NETWORK_LOGGED_IN),
PARTIAL_CONNECTIVITY(SystemMessage.NOTE_NETWORK_PARTIAL_CONNECTIVITY),
SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN),
PRIVATE_DNS_BROKEN(SystemMessage.NOTE_NETWORK_PRIVATE_DNS_BROKEN);
@@ -114,14 +113,10 @@
}
}
- private static int getIcon(int transportType, NotificationType notifyType) {
- if (transportType != TRANSPORT_WIFI) {
- return R.drawable.stat_notify_rssi_in_range;
- }
-
- return notifyType == NotificationType.LOGGED_IN
- ? R.drawable.ic_wifi_signal_4
- : R.drawable.stat_notify_wifi_in_range; // TODO: Distinguish ! from ?.
+ private static int getIcon(int transportType) {
+ return (transportType == TRANSPORT_WIFI)
+ ? R.drawable.stat_notify_wifi_in_range : // TODO: Distinguish ! from ?.
+ R.drawable.stat_notify_rssi_in_range;
}
/**
@@ -185,7 +180,7 @@
Resources r = mContext.getResources();
final CharSequence title;
final CharSequence details;
- int icon = getIcon(transportType, notifyType);
+ int icon = getIcon(transportType);
if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.wifi_no_internet,
WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID()));
@@ -235,9 +230,6 @@
details = r.getString(R.string.network_available_sign_in_detailed, name);
break;
}
- } else if (notifyType == NotificationType.LOGGED_IN) {
- title = WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID());
- details = r.getString(R.string.captive_portal_logged_in_detailed);
} else if (notifyType == NotificationType.NETWORK_SWITCH) {
String fromTransport = getTransportName(transportType);
String toTransport = getTransportName(approximateTransportType(switchToNai));
@@ -379,7 +371,6 @@
case NETWORK_SWITCH:
return 2;
case LOST_INTERNET:
- case LOGGED_IN:
return 1;
default:
return 0;
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 32cff3b..98579af5 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -24,6 +24,8 @@
import static android.os.Process.getUidForPid;
import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
+import static android.util.MathUtils.abs;
+import static android.util.MathUtils.constrain;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
@@ -146,12 +148,15 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
+import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -169,6 +174,9 @@
private static final String TAG = "StatsPullAtomService";
private static final boolean DEBUG = true;
+ // Random seed stable for StatsPullAtomService life cycle - can be used for stable sampling
+ private static final int RANDOM_SEED = new Random().nextInt();
+
/**
* Lowest available uid for apps.
*
@@ -256,6 +264,8 @@
private StatsPullAtomCallbackImpl mStatsCallbackImpl;
+ private int mAppOpsSamplingRate = 0;
+
public StatsPullAtomService(Context context) {
super(context);
mContext = context;
@@ -2877,44 +2887,7 @@
HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS);
-
- for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
- final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
- final int uid = uidOps.getUid();
- for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
- final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
- for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) {
- final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx);
-
- StatsEvent.Builder e = StatsEvent.newBuilder();
- e.setAtomId(atomTag);
- e.writeInt(uid);
- e.writeString(packageOps.getPackageName());
- e.writeInt(op.getOpCode());
- e.writeLong(op.getForegroundAccessCount(OP_FLAGS_PULLED));
- e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_PULLED));
- e.writeLong(op.getForegroundRejectCount(OP_FLAGS_PULLED));
- e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_PULLED));
- e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_PULLED));
- e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_PULLED));
-
- String perm = AppOpsManager.opToPermission(op.getOpCode());
- if (perm == null) {
- e.writeBoolean(false);
- } else {
- PermissionInfo permInfo;
- try {
- permInfo = mContext.getPackageManager().getPermissionInfo(perm, 0);
- e.writeBoolean(permInfo.getProtection() == PROTECTION_DANGEROUS);
- } catch (PackageManager.NameNotFoundException exception) {
- e.writeBoolean(false);
- }
- }
-
- pulledData.add(e.build());
- }
- }
- }
+ processHistoricalOps(histOps, atomTag, pulledData);
} catch (Throwable t) {
// TODO: catch exceptions at a more granular level
Slog.e(TAG, "Could not read appops", t);
@@ -2945,54 +2918,12 @@
new HistoricalOpsRequest.Builder(0, Long.MAX_VALUE).setFlags(
OP_FLAGS_PULLED).build();
appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete);
-
HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS);
-
- for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
- final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
- final int uid = uidOps.getUid();
- for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
- final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
- for (int featureIdx = 0; featureIdx < packageOps.getFeatureCount();
- featureIdx++) {
- final AppOpsManager.HistoricalFeatureOps featureOps =
- packageOps.getFeatureOpsAt(featureIdx);
- for (int opIdx = 0; opIdx < featureOps.getOpCount(); opIdx++) {
- final AppOpsManager.HistoricalOp op = featureOps.getOpAt(opIdx);
- StatsEvent.Builder e = StatsEvent.newBuilder();
- e.setAtomId(atomTag);
- e.writeInt(uid);
- e.writeString(packageOps.getPackageName());
- e.writeString(featureOps.getFeatureId());
- e.writeString(op.getOpName());
- e.writeLong(op.getForegroundAccessCount(OP_FLAGS_PULLED));
- e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_PULLED));
- e.writeLong(op.getForegroundRejectCount(OP_FLAGS_PULLED));
- e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_PULLED));
- e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_PULLED));
- e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_PULLED));
-
- String perm = AppOpsManager.opToPermission(op.getOpCode());
- if (perm == null) {
- e.writeBoolean(false);
- } else {
- PermissionInfo permInfo;
- try {
- permInfo = mContext.getPackageManager().getPermissionInfo(perm,
- 0);
- e.writeBoolean(
- permInfo.getProtection() == PROTECTION_DANGEROUS);
- } catch (PackageManager.NameNotFoundException exception) {
- e.writeBoolean(false);
- }
- }
- pulledData.add(e.build());
- }
-
- }
- }
+ if (mAppOpsSamplingRate == 0) {
+ mAppOpsSamplingRate = constrain((5000 * 100) / estimateAppOpsSize(), 1, 100);
}
+ processHistoricalOps(histOps, atomTag, pulledData);
} catch (Throwable t) {
// TODO: catch exceptions at a more granular level
Slog.e(TAG, "Could not read appops", t);
@@ -3003,6 +2934,111 @@
return StatsManager.PULL_SUCCESS;
}
+ private int estimateAppOpsSize() throws Exception {
+ AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+
+ CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
+ HistoricalOpsRequest histOpsRequest =
+ new HistoricalOpsRequest.Builder(
+ Instant.now().minus(1, ChronoUnit.DAYS).toEpochMilli(),
+ Long.MAX_VALUE).setFlags(
+ OP_FLAGS_PULLED).build();
+ appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete);
+ HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS);
+ return processHistoricalOps(histOps, FrameworkStatsLog.APP_FEATURES_OPS, null);
+ }
+
+ int processHistoricalOps(HistoricalOps histOps, int atomTag, List<StatsEvent> pulledData) {
+ int counter = 0;
+ for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
+ final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
+ final int uid = uidOps.getUid();
+ for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
+ final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
+ if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ for (int featureIdx = 0; featureIdx < packageOps.getFeatureCount();
+ featureIdx++) {
+ final AppOpsManager.HistoricalFeatureOps featureOps =
+ packageOps.getFeatureOpsAt(featureIdx);
+ for (int opIdx = 0; opIdx < featureOps.getOpCount(); opIdx++) {
+ final AppOpsManager.HistoricalOp op = featureOps.getOpAt(opIdx);
+ counter += processHistoricalOp(op, atomTag, pulledData, uid,
+ packageOps.getPackageName(), featureOps.getFeatureId());
+ }
+ }
+ } else if (atomTag == FrameworkStatsLog.APP_OPS) {
+ for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) {
+ final AppOpsManager.HistoricalOp op = packageOps.getOpAt(opIdx);
+ counter += processHistoricalOp(op, atomTag, pulledData, uid,
+ packageOps.getPackageName(), null);
+ }
+ }
+ }
+ }
+ return counter;
+ }
+
+ private int processHistoricalOp(AppOpsManager.HistoricalOp op, int atomTag,
+ @Nullable List<StatsEvent> pulledData, int uid, String packageName,
+ @Nullable String feature) {
+ if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ if (pulledData == null) { // this is size estimation call
+ if (op.getForegroundAccessCount(OP_FLAGS_PULLED) + op.getBackgroundAccessCount(
+ OP_FLAGS_PULLED) == 0) {
+ return 0;
+ } else {
+ return 32 + packageName.length() + (feature == null ? 1 : feature.length());
+ }
+ } else {
+ if (abs((op.getOpCode() + feature + packageName).hashCode() + RANDOM_SEED) % 100
+ >= mAppOpsSamplingRate) {
+ return 0;
+ }
+ }
+ }
+
+ StatsEvent.Builder e = StatsEvent.newBuilder();
+ e.setAtomId(atomTag);
+ e.writeInt(uid);
+ e.writeString(packageName);
+ if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ e.writeString(feature);
+ }
+ if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ e.writeString(op.getOpName());
+ } else {
+ e.writeInt(op.getOpCode());
+ }
+ e.writeLong(op.getForegroundAccessCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getForegroundRejectCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_PULLED));
+ e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_PULLED));
+
+ String perm = AppOpsManager.opToPermission(op.getOpCode());
+ if (perm == null) {
+ e.writeBoolean(false);
+ } else {
+ PermissionInfo permInfo;
+ try {
+ permInfo = mContext.getPackageManager().getPermissionInfo(
+ perm,
+ 0);
+ e.writeBoolean(
+ permInfo.getProtection() == PROTECTION_DANGEROUS);
+ } catch (PackageManager.NameNotFoundException exception) {
+ e.writeBoolean(false);
+ }
+ }
+ if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ e.writeInt(mAppOpsSamplingRate);
+ }
+ pulledData.add(e.build());
+ return 0;
+ }
+
int pullRuntimeAppOpAccessMessage(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index d7a80bf..68224b5 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -27,7 +27,6 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
-import android.app.Service;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -127,7 +126,7 @@
public boolean setWindowsForAccessibilityCallbackLocked(int displayId,
WindowsForAccessibilityCallback callback) {
if (callback != null) {
- final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
+ final DisplayContent dc = mService.mRoot.getDisplayContentOrCreate(displayId);
if (dc == null) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index a9517fe..b6ad241 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3151,7 +3151,7 @@
// Reset the last saved PiP snap fraction on removal.
mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent);
-
+ mWmService.mEmbeddedWindowController.onActivityRemoved(this);
mRemovingFromDisplay = false;
}
@@ -7626,7 +7626,7 @@
return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
record.mAdapter.mCapturedLeash, !fillsParent(),
mainWindow.mWinAnimator.mLastClipRect, insets,
- getPrefixOrderIndex(), record.mAdapter.mPosition,
+ getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
record.mAdapter.mStackBounds, task.getWindowConfiguration(),
false /*isNotInRecents*/,
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 94decc7..c18ed7d 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -114,7 +114,6 @@
return st.addToSync(wc);
}
- // TODO(b/148476626): TIMEOUTS!
void setReady(int id) {
final SyncState st = mPendingSyncs.get(id);
st.setReady();
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 884f769..484a5a8 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -17,11 +17,15 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.Slog;
import android.view.IWindow;
import android.view.InputApplicationHandle;
@@ -33,12 +37,15 @@
* the host window to send pointerDownOutsideFocus.
*/
class EmbeddedWindowController {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "EmbeddedWindowController" : TAG_WM;
/* maps input token to an embedded window */
private ArrayMap<IBinder /*input token */, EmbeddedWindow> mWindows = new ArrayMap<>();
- private final Object mWmLock;
+ private final Object mGlobalLock;
+ private final ActivityTaskManagerService mAtmService;
- EmbeddedWindowController(Object wmLock) {
- mWmLock = wmLock;
+ EmbeddedWindowController(ActivityTaskManagerService atmService) {
+ mAtmService = atmService;
+ mGlobalLock = atmService.getGlobalLock();
}
/**
@@ -46,13 +53,14 @@
*
* @param inputToken input channel token passed in by the embedding process when it requests
* the server to add an input channel to the embedded surface.
- * @param embeddedWindow An {@link EmbeddedWindow} object to add to this controller.
+ * @param window An {@link EmbeddedWindow} object to add to this controller.
*/
- void add(IBinder inputToken, EmbeddedWindow embeddedWindow) {
+ void add(IBinder inputToken, EmbeddedWindow window) {
try {
- mWindows.put(inputToken, embeddedWindow);
- embeddedWindow.mClient.asBinder().linkToDeath(()-> {
- synchronized (mWmLock) {
+ mWindows.put(inputToken, window);
+ updateProcessController(window);
+ window.mClient.asBinder().linkToDeath(()-> {
+ synchronized (mGlobalLock) {
mWindows.remove(inputToken);
}
}, 0);
@@ -62,6 +70,23 @@
}
}
+ /**
+ * Track the host activity in the embedding process so we can determine if the
+ * process is currently showing any UI to the user.
+ */
+ private void updateProcessController(EmbeddedWindow window) {
+ if (window.mHostActivityRecord == null) {
+ return;
+ }
+ final WindowProcessController processController =
+ mAtmService.getProcessController(window.mOwnerPid, window.mOwnerUid);
+ if (processController == null) {
+ Slog.w(TAG, "Could not find the embedding process.");
+ } else {
+ processController.addHostActivity(window.mHostActivityRecord);
+ }
+ }
+
WindowState getHostWindow(IBinder inputToken) {
EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
return embeddedWindow != null ? embeddedWindow.mHostWindowState : null;
@@ -76,7 +101,7 @@
}
}
- void removeWindowsWithHost(WindowState host) {
+ void onWindowRemoved(WindowState host) {
for (int i = mWindows.size() - 1; i >= 0; i--) {
if (mWindows.valueAt(i).mHostWindowState == host) {
mWindows.removeAt(i);
@@ -88,9 +113,23 @@
return mWindows.get(inputToken);
}
+ void onActivityRemoved(ActivityRecord activityRecord) {
+ for (int i = mWindows.size() - 1; i >= 0; i--) {
+ final EmbeddedWindow window = mWindows.valueAt(i);
+ if (window.mHostActivityRecord == activityRecord) {
+ final WindowProcessController processController =
+ mAtmService.getProcessController(window.mOwnerPid, window.mOwnerUid);
+ if (processController != null) {
+ processController.removeHostActivity(activityRecord);
+ }
+ }
+ }
+ }
+
static class EmbeddedWindow {
final IWindow mClient;
@Nullable final WindowState mHostWindowState;
+ @Nullable final ActivityRecord mHostActivityRecord;
final int mOwnerUid;
final int mOwnerPid;
@@ -107,6 +146,8 @@
int ownerPid) {
mClient = clientToken;
mHostWindowState = hostWindowState;
+ mHostActivityRecord = (mHostWindowState != null) ? mHostWindowState.mActivityRecord
+ : null;
mOwnerUid = ownerUid;
mOwnerPid = ownerPid;
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index e1906da..6ff029b 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -18,10 +18,14 @@
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsState.ITYPE_INVALID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.sNewInsetsMode;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,6 +36,7 @@
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
+import android.view.WindowManager;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -74,15 +79,40 @@
* @param target The client we dispatch the state to.
* @return The state stripped of the necessary information.
*/
- InsetsState getInsetsForDispatch(WindowState target) {
+ InsetsState getInsetsForDispatch(@NonNull WindowState target) {
final InsetsSourceProvider provider = target.getControllableInsetProvider();
if (provider == null) {
return mState;
}
+ final @InternalInsetsType int type = provider.getSource().getType();
+ return getInsetsForType(type);
+ }
+ InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
+ final @InternalInsetsType int type = getInsetsTypeForWindowType(attrs.type);
+ if (type == ITYPE_INVALID) {
+ return mState;
+ }
+ return getInsetsForType(type);
+ }
+
+ @InternalInsetsType
+ private static int getInsetsTypeForWindowType(int type) {
+ switch(type) {
+ case TYPE_STATUS_BAR:
+ return ITYPE_STATUS_BAR;
+ case TYPE_NAVIGATION_BAR:
+ return ITYPE_NAVIGATION_BAR;
+ case TYPE_INPUT_METHOD:
+ return ITYPE_IME;
+ default:
+ return ITYPE_INVALID;
+ }
+ }
+
+ private InsetsState getInsetsForType(@InternalInsetsType int type) {
final InsetsState state = new InsetsState();
state.set(mState);
- final int type = provider.getSource().getType();
state.removeSource(type);
// Navigation bar doesn't get influenced by anything else
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 5cd0169..3e5cb50 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -820,15 +820,19 @@
private @AnimationType int mLastAnimationType;
private final boolean mIsRecentTaskInvisible;
private RemoteAnimationTarget mTarget;
- private final Point mPosition = new Point();
private final Rect mBounds = new Rect();
+ // The bounds of the target relative to its parent.
+ private Rect mLocalBounds = new Rect();
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
mIsRecentTaskInvisible = isRecentTaskInvisible;
- final WindowContainer container = mTask.getParent();
- mBounds.set(container.getDisplayedBounds());
- mPosition.set(mBounds.left, mBounds.top);
+ mBounds.set(mTask.getDisplayedBounds());
+
+ mLocalBounds.set(mBounds);
+ Point tmpPos = new Point();
+ mTask.getRelativeDisplayedPosition(tmpPos);
+ mLocalBounds.offsetTo(tmpPos.x, tmpPos.y);
}
RemoteAnimationTarget createRemoteAnimationTarget() {
@@ -847,8 +851,9 @@
: MODE_CLOSING;
mTarget = new RemoteAnimationTarget(mTask.mTaskId, mode, mCapturedLeash,
!topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
- insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
- mTask.getWindowConfiguration(), mIsRecentTaskInvisible, null, null);
+ insets, mTask.getPrefixOrderIndex(), new Point(mBounds.left, mBounds.top),
+ mLocalBounds, mBounds, mTask.getWindowConfiguration(),
+ mIsRecentTaskInvisible, null, null);
return mTarget;
}
@@ -862,8 +867,8 @@
@AnimationType int type, OnAnimationFinishedCallback finishCallback) {
// Restore z-layering, position and stack crop until client has a chance to modify it.
t.setLayer(animationLeash, mTask.getPrefixOrderIndex());
- t.setPosition(animationLeash, mPosition.x, mPosition.y);
- mTmpRect.set(mBounds);
+ t.setPosition(animationLeash, mLocalBounds.left, mLocalBounds.top);
+ mTmpRect.set(mLocalBounds);
mTmpRect.offsetTo(0, 0);
t.setWindowCrop(animationLeash, mTmpRect);
mCapturedLeash = animationLeash;
@@ -897,7 +902,7 @@
pw.print(prefix); pw.println("Target: null");
}
pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible);
- pw.println("mPosition=" + mPosition);
+ pw.println("mLocalBounds=" + mLocalBounds);
pw.println("mBounds=" + mBounds);
pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible);
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 0eb9daf..35f8d34 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -80,16 +80,17 @@
*
* @param windowContainer The windows to animate.
* @param position The position app bounds, in screen coordinates.
+ * @param localBounds The bounds of the app relative to its parent.
* @param stackBounds The stack bounds of the app relative to position.
* @param startBounds The stack bounds before the transition, in screen coordinates
* @return The record representing animation(s) to run on the app.
*/
RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
- Point position, Rect stackBounds, Rect startBounds) {
+ Point position, Rect localBounds, Rect stackBounds, Rect startBounds) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
windowContainer);
- final RemoteAnimationRecord adapters =
- new RemoteAnimationRecord(windowContainer, position, stackBounds, startBounds);
+ final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
+ localBounds, stackBounds, startBounds);
mPendingAnimations.add(adapters);
return adapters;
}
@@ -355,17 +356,18 @@
final WindowContainer mWindowContainer;
final Rect mStartBounds;
- RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect endBounds,
- Rect startBounds) {
+ RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds,
+ Rect endBounds, Rect startBounds) {
mWindowContainer = windowContainer;
- mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, endBounds);
+ mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds);
if (startBounds != null) {
mStartBounds = new Rect(startBounds);
mTmpRect.set(startBounds);
mTmpRect.offsetTo(0, 0);
if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
mThumbnailAdapter =
- new RemoteAnimationAdapterWrapper(this, new Point(0, 0), mTmpRect);
+ new RemoteAnimationAdapterWrapper(this, new Point(0, 0), localBounds,
+ mTmpRect);
}
} else {
mStartBounds = null;
@@ -401,12 +403,14 @@
private OnAnimationFinishedCallback mCapturedFinishCallback;
private @AnimationType int mAnimationType;
final Point mPosition = new Point();
+ final Rect mLocalBounds;
final Rect mStackBounds = new Rect();
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
- Rect stackBounds) {
+ Rect localBounds, Rect stackBounds) {
mRecord = record;
mPosition.set(position.x, position.y);
+ mLocalBounds = localBounds;
mStackBounds.set(stackBounds);
}
diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
index bd70599..f467015 100644
--- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
@@ -92,7 +92,7 @@
*/
RemoteAnimationTarget createRemoteAnimationTarget() {
mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false, null, null,
- mWallpaperToken.getPrefixOrderIndex(), new Point(), null,
+ mWallpaperToken.getPrefixOrderIndex(), new Point(), null, null,
mWallpaperToken.getWindowConfiguration(), true, null, null);
return mTarget;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 809931d..e8897e1 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2103,9 +2103,11 @@
// Delaying animation start isn't compatible with remote animations at all.
if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
+ final Rect localBounds = new Rect(mTmpRect);
+ localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
final RemoteAnimationController.RemoteAnimationRecord adapters =
- controller.createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
- (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
+ controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,
+ mTmpRect, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
} else if (isChanging) {
final float durationScale = mWmService.getTransitionAnimationScaleLocked();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3f4f629..42a66ad 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1287,7 +1287,7 @@
mConstants.start(new HandlerExecutor(mH));
LocalServices.addService(WindowManagerInternal.class, new LocalService());
- mEmbeddedWindowController = new EmbeddedWindowController(mGlobalLock);
+ mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
mContext.getResources());
@@ -1900,7 +1900,7 @@
if (dc.mCurrentFocus == null) {
dc.mWinRemovedSinceNullFocus.add(win);
}
- mEmbeddedWindowController.removeWindowsWithHost(win);
+ mEmbeddedWindowController.onWindowRemoved(win);
mPendingRemove.remove(win);
mResizingWindows.remove(win);
updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
@@ -2610,7 +2610,8 @@
if (type == TYPE_WALLPAPER) {
new WallpaperWindowToken(this, binder, true, dc, callerCanManageAppTokens);
} else {
- new WindowToken(this, binder, type, true, dc, callerCanManageAppTokens);
+ new WindowToken(this, binder, type, true, dc, callerCanManageAppTokens,
+ false /* roundedCornerOverlay */, fromClientToken);
}
}
} finally {
@@ -4661,6 +4662,7 @@
public static final int RECOMPUTE_FOCUS = 61;
public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62;
public static final int LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED = 63;
+ public static final int WINDOW_STATE_BLAST_SYNC_TIMEOUT = 64;
/**
* Used to denote that an integer field in a message will not be used.
@@ -5041,6 +5043,13 @@
}
break;
}
+ case WINDOW_STATE_BLAST_SYNC_TIMEOUT: {
+ synchronized (mGlobalLock) {
+ final WindowState ws = (WindowState) msg.obj;
+ ws.finishDrawing(null);
+ }
+ break;
+ }
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");
@@ -6126,7 +6135,7 @@
}
mRoot.forAllWindows((w) -> {
- if ((!visibleOnly || w.mWinAnimator.getShown())
+ if ((!visibleOnly || w.isVisible())
&& (!appsOnly || w.mActivityRecord != null)) {
windows.add(w);
}
@@ -8010,9 +8019,9 @@
}
@Override
- public void getWindowInsets(WindowManager.LayoutParams attrs,
+ public boolean getWindowInsets(WindowManager.LayoutParams attrs,
int displayId, Rect outContentInsets, Rect outStableInsets,
- DisplayCutout.ParcelableWrapper displayCutout) {
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InsetsState outInsetsState) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -8022,8 +8031,13 @@
+ "could not be found!");
}
final WindowToken windowToken = dc.getWindowToken(attrs.token);
- dc.getDisplayPolicy().getLayoutHint(attrs, windowToken, mTmpRect /* outFrame */,
- outContentInsets, outStableInsets, displayCutout);
+ final InsetsStateController insetsStateController =
+ dc.getInsetsStateController();
+ outInsetsState.set(insetsStateController.getInsetsForWindowMetrics(attrs));
+
+ return dc.getDisplayPolicy().getLayoutHint(attrs, windowToken,
+ mTmpRect /* outFrame */, outContentInsets, outStableInsets,
+ outDisplayCutout);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 03dc4c9..833bb83 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -41,6 +41,7 @@
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.IApplicationThread;
import android.app.ProfilerInfo;
@@ -185,6 +186,13 @@
// Registered display id as a listener to override config change
private int mDisplayId;
private ActivityRecord mConfigActivityRecord;
+ /**
+ * Activities that hosts some UI drawn by the current process. The activities live
+ * in another process. This is used to check if the process is currently showing anything
+ * visible to the user.
+ */
+ @Nullable
+ private final ArrayList<ActivityRecord> mHostActivities = new ArrayList<>();
/** Whether our process is currently running a {@link RecentsAnimation} */
private boolean mRunningRecentsAnimation;
@@ -672,6 +680,23 @@
return true;
}
}
+ if (isEmbedded()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return {@code true} if this process is rendering content on to a window shown by
+ * another process.
+ */
+ private boolean isEmbedded() {
+ for (int i = mHostActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = mHostActivities.get(i);
+ if (r.isInterestingToUserLocked()) {
+ return true;
+ }
}
return false;
}
@@ -814,6 +839,19 @@
}
}
+ /** Adds an activity that hosts UI drawn by the current process. */
+ void addHostActivity(ActivityRecord r) {
+ if (mHostActivities.contains(r)) {
+ return;
+ }
+ mHostActivities.add(r);
+ }
+
+ /** Removes an activity that hosts UI drawn by the current process. */
+ void removeHostActivity(ActivityRecord r) {
+ mHostActivities.remove(r);
+ }
+
public interface ComputeOomAdjCallback {
void onVisibleActivity();
void onPausedActivity();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d1f97f8..fc28cd5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -138,6 +138,7 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT;
import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
@@ -669,6 +670,8 @@
*/
int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET;
+ static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */
+
/**
* @return The insets state as requested by the client, i.e. the dispatched insets state
* for which the visibilities are overridden with what the client requested.
@@ -5673,6 +5676,11 @@
mWaitingListener = waitingListener;
mWaitingSyncId = waitingId;
mUsingBLASTSyncTransaction = true;
+
+ mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
+ mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
+ BLAST_TIMEOUT_DURATION);
+
return true;
}
@@ -5680,6 +5688,8 @@
if (!mUsingBLASTSyncTransaction) {
return mWinAnimator.finishDrawingLocked(postDrawTransaction);
}
+
+ mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
if (postDrawTransaction == null) {
postDrawTransaction = new SurfaceControl.Transaction();
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index f41d5a5..b7c6af2 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -50,6 +50,7 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.protolog.common.ProtoLog;
@@ -99,7 +100,8 @@
private Configuration mLastReportedConfig;
private int mLastReportedDisplay = INVALID_DISPLAY;
- private final boolean mFromClientToken;
+ @VisibleForTesting
+ final boolean mFromClientToken;
/**
* Used to fix the transform of the token to be rotated to a rotation different than it's
@@ -180,13 +182,13 @@
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
DisplayContent dc, boolean ownerCanManageAppTokens) {
this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
- false /* roundedCornersOverlay */);
+ false /* roundedCornerOverlay */);
}
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
- DisplayContent dc, boolean ownerCanManageAppTokens, boolean fromClientToken) {
+ DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
- false /* roundedCornersOverlay */, fromClientToken);
+ roundedCornerOverlay, false /* fromClientToken */);
}
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index 6083ce34..95f4e83 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -847,8 +847,8 @@
app.connectionGroup = connectionGroup;
app.setProcState = procState;
app.lastMemInfo = spy(new Debug.MemoryInfo());
- doReturn((int) pss).when(app.lastMemInfo).getTotalPss();
- doReturn((int) rss).when(app.lastMemInfo).getTotalRss();
+ app.lastPss = pss;
+ app.mLastRss = rss;
return app;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 4722b39..e5ec1f7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -36,6 +36,7 @@
import com.android.server.testables.TestableDeviceConfig;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -267,9 +268,7 @@
@Test
public void useFreeze_doesNotListenToDeviceConfigChanges() throws InterruptedException {
- if (!mCachedAppOptimizerUnderTest.isFreezerSupported()) {
- return;
- }
+ Assume.assumeTrue(mCachedAppOptimizerUnderTest.isFreezerSupported());
assertThat(mCachedAppOptimizerUnderTest.useFreezer()).isEqualTo(
CachedAppOptimizer.DEFAULT_USE_FREEZER);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index c7f94ef..34ac835 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -98,7 +98,7 @@
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
try {
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
@@ -136,7 +136,7 @@
public void testCancel() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
@@ -150,7 +150,7 @@
public void testTimeout() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
@@ -170,7 +170,8 @@
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
"testWin");
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
- win.mActivityRecord, new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
+ null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
@@ -201,7 +202,7 @@
public void testNotReallyStarted() {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null);
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
mController.goodToGo();
verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
}
@@ -211,9 +212,9 @@
final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
mController.createRemoteAnimationRecord(win1.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null);
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
@@ -234,7 +235,7 @@
public void testRemovedBeforeStarted() {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
win.mActivityRecord.removeImmediately();
@@ -250,7 +251,7 @@
mDisplayContent.mChangingContainers.add(win.mActivityRecord);
try {
final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
- win.mActivityRecord, new Point(50, 100), new Rect(50, 100, 150, 150),
+ win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
new Rect(0, 0, 200, 200));
assertNotNull(record.mThumbnailAdapter);
((AnimationAdapter) record.mAdapter)
@@ -304,7 +305,7 @@
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
try {
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
@@ -333,7 +334,7 @@
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
try {
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 35723ab..da4bde5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -16,9 +16,16 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
import android.content.pm.PackageManager;
+import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -57,4 +64,25 @@
return getInstrumentation().getTargetContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE);
}
+
+ @Test
+ public void testAddWindowToken() {
+ IBinder token = mock(IBinder.class);
+ mWm.addWindowToken(token, TYPE_TOAST, mDisplayContent.getDisplayId());
+
+ WindowToken windowToken = mWm.mRoot.getWindowToken(token);
+ assertFalse(windowToken.mRoundedCornerOverlay);
+ assertFalse(windowToken.mFromClientToken);
+ }
+
+ @Test
+ public void testAddWindowTokenWithOptions() {
+ IBinder token = mock(IBinder.class);
+ mWm.addWindowTokenWithOptions(token, TYPE_TOAST, mDisplayContent.getDisplayId(),
+ null /* options */, null /* options */);
+
+ WindowToken windowToken = mWm.mRoot.getWindowToken(token);
+ assertFalse(windowToken.mRoundedCornerOverlay);
+ assertTrue(windowToken.mFromClientToken);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index e6aed49..38f643d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -25,7 +25,9 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -129,4 +131,28 @@
// Verify that the token windows are no longer attached to it.
assertEquals(0, token.getWindowsCount());
}
+
+ /**
+ * Test that {@link WindowToken} constructor parameters is set with expectation.
+ */
+ @Test
+ public void testWindowTokenConstructorSanity() {
+ WindowToken token = new WindowToken(mDisplayContent.mWmService, mock(IBinder.class),
+ TYPE_TOAST, true /* persistOnEmpty */, mDisplayContent,
+ true /* ownerCanManageAppTokens */);
+ assertFalse(token.mRoundedCornerOverlay);
+ assertFalse(token.mFromClientToken);
+
+ token = new WindowToken(mDisplayContent.mWmService, mock(IBinder.class), TYPE_TOAST,
+ true /* persistOnEmpty */, mDisplayContent, true /* ownerCanManageAppTokens */,
+ true /* roundedCornerOverlay */);
+ assertTrue(token.mRoundedCornerOverlay);
+ assertFalse(token.mFromClientToken);
+
+ token = new WindowToken(mDisplayContent.mWmService, mock(IBinder.class), TYPE_TOAST,
+ true /* persistOnEmpty */, mDisplayContent, true /* ownerCanManageAppTokens */,
+ true /* roundedCornerOverlay */, true /* fromClientToken */);
+ assertTrue(token.mRoundedCornerOverlay);
+ assertTrue(token.mFromClientToken);
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index c5c08c2..2d31d95 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4021,7 +4021,8 @@
sDefaults.putBoolean(KEY_USE_CALLER_ID_USSD_BOOL, false);
sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
- "connected_mmwave:5G,connected:5G");
+ "connected_mmwave:5G,connected:5G,not_restricted_rrc_idle:5G,"
+ + "not_restricted_rrc_con:5G");
sDefaults.putInt(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0);
/* Default value is 1 hour. */
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index fe75266..34bac5d 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -34,8 +34,9 @@
private Context mContext;
/**
- * <p>Broadcast Action: Indicates that an IMS operation was rejected by the network due to it
- * not being authorized on the network.
+ * <p>Broadcast Action: Indicates that a previously allowed IMS operation was rejected by the
+ * network due to the network returning a "forbidden" response. This may be due to a
+ * provisioning change from the network.
* May include the {@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX} extra to also specify
* which subscription the operation was rejected for.
* <p class="note">
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 40def40..3c40e35 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -54,6 +54,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -11648,11 +11649,9 @@
}
/**
- * Override the file path for testing OTA emergency number database in a file partition.
+ * Override the file path for OTA emergency number database in a file partition.
*
- * @param otaFilePath The test OTA emergency number database file path;
- * if "RESET", recover the original database file partition.
- * Format: <root file folder>@<file path>
+ * @param otaParcelFileDescriptor parcelable file descriptor for OTA emergency number database.
*
* <p> Requires permission:
* {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
@@ -11662,16 +11661,42 @@
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
@SystemApi
@TestApi
- public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String otaFilePath) {
+ public void updateOtaEmergencyNumberDbFilePath(
+ @NonNull ParcelFileDescriptor otaParcelFileDescriptor) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- telephony.updateTestOtaEmergencyNumberDbFilePath(otaFilePath);
+ telephony.updateOtaEmergencyNumberDbFilePath(otaParcelFileDescriptor);
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- Log.e(TAG, "notifyOtaEmergencyNumberDatabaseInstalled RemoteException", ex);
+ Log.e(TAG, "updateOtaEmergencyNumberDbFilePath RemoteException", ex);
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Reset the file path to default for OTA emergency number database in a file partition.
+ *
+ * <p> Requires permission:
+ * {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+ @SystemApi
+ @TestApi
+ public void resetOtaEmergencyNumberDbFilePath() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.resetOtaEmergencyNumberDbFilePath();
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "resetOtaEmergencyNumberDbFilePath RemoteException", ex);
ex.rethrowAsRuntimeException();
}
}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 9c1be48..1597cd5 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -18,7 +18,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -718,11 +717,16 @@
* @return A {@link Bundle} containing proprietary call extras that were not set by the
* platform.
*/
- public @Nullable Bundle getProprietaryCallExtras() {
+ public @NonNull Bundle getProprietaryCallExtras() {
if (mCallExtras == null) {
- return null;
+ return new Bundle();
}
- return mCallExtras.getBundle(EXTRA_OEM_EXTRAS);
+ Bundle proprietaryExtras = mCallExtras.getBundle(EXTRA_OEM_EXTRAS);
+ if (proprietaryExtras == null) {
+ return new Bundle();
+ }
+ // Make a copy so users do not accidentally change this copy of the extras.
+ return new Bundle(proprietaryExtras);
}
public ImsStreamMediaProfile getMediaProfile() {
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
index bc124044..460a032 100644
--- a/telephony/java/android/telephony/ims/ImsUtListener.java
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -49,7 +49,8 @@
* {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_RESTRICTED}, and
* {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_ALLOWED}.
* @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)}
- * instead.
+ * instead, this key has been added for backwards compatibility with older proprietary
+ * implementations only and is being phased out.
*/
@Deprecated
public static final String BUNDLE_KEY_CLIR = "queryClir";
@@ -60,7 +61,8 @@
* response. The value will be an instance of {@link ImsSsInfo}, which contains the response to
* the query.
* @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)}
- * instead.
+ * instead, this key has been added for backwards compatibility with older proprietary
+ * implementations only and is being phased out.
*/
@Deprecated
public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
@@ -123,7 +125,7 @@
try {
mServiceInterface.lineIdentificationSupplementaryServiceResponse(id, configuration);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "onLineIdentificationSupplementaryServicesResponse: remote exception");
+ e.rethrowFromSystemServer();
}
}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 0370846..00fa942 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -305,13 +305,13 @@
/**
* An integer key associated with the carrier configured expiration time in seconds for
- * RCS presence published offline availability in RCS presence.
+ * published offline availability in RCS presence provided, which is provided to the network.
* <p>
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
* @see #getProvisioningIntValue(int)
*/
- public static final int KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC = 16;
+ public static final int KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC = 16;
/**
* An integer key associated with whether or not capability discovery is provisioned for this
@@ -326,8 +326,10 @@
public static final int KEY_RCS_CAPABILITY_DISCOVERY_ENABLED = 17;
/**
- * An integer key associated with the period of time the capability information of each contact
- * is cached on the device.
+ * An integer key associated with the period of time in seconds the capability information of
+ * each contact is cached on the device.
+ * <p>
+ * Seconds are used because this is usually measured in the span of days.
* <p>
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
@@ -337,7 +339,8 @@
/**
* An integer key associated with the period of time in seconds that the availability
- * information of a contact is cached on the device.
+ * information of a contact is cached on the device, which is based on the carrier provisioning
+ * configuration from the network.
* <p>
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
@@ -347,7 +350,8 @@
/**
* An integer key associated with the carrier configured interval in seconds expected between
- * successive capability polling attempts.
+ * successive capability polling attempts, which is based on the carrier provisioning
+ * configuration from the network.
* <p>
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
@@ -357,7 +361,7 @@
/**
* An integer key representing the minimum time allowed between two consecutive presence publish
- * messages from the device.
+ * messages from the device in milliseconds.
* <p>
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
@@ -378,7 +382,7 @@
/**
* An integer associated with the expiration timer used during the SIP subscription of a
* Request Contained List (RCL), which is used to retrieve the RCS capabilities of the contact
- * book.
+ * book. This timer value is sent in seconds to the network.
* <p>
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
@@ -470,7 +474,8 @@
public static final int KEY_SIP_KEEP_ALIVE_ENABLED = 32;
/**
- * Registration retry Base Time value in seconds.
+ * Registration retry Base Time value in seconds, which is based off of the carrier
+ * configuration.
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
* @see #getProvisioningIntValue(int)
@@ -478,7 +483,8 @@
public static final int KEY_REGISTRATION_RETRY_BASE_TIME_SEC = 33;
/**
- * Registration retry Max Time value in seconds.
+ * Registration retry Max Time value in seconds, which is based off of the carrier
+ * configuration.
* Value is in Integer format.
* @see #setProvisioningIntValue(int, int)
* @see #getProvisioningIntValue(int)
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 58e9b70..30306c7 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -24,12 +24,10 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
-import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.provider.Telephony;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
@@ -138,7 +136,7 @@
* UCE.
* @hide
*/
- public static final int PUBLISH_STATE_200_OK = 1;
+ public static final int PUBLISH_STATE_OK = 1;
/**
* The hasn't published its capabilities since boot or hasn't gotten any publish response yet.
@@ -178,7 +176,7 @@
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "PUBLISH_STATE_", value = {
- PUBLISH_STATE_200_OK,
+ PUBLISH_STATE_OK,
PUBLISH_STATE_NOT_PUBLISHED,
PUBLISH_STATE_VOLTE_PROVISION_ERROR,
PUBLISH_STATE_RCS_PROVISION_ERROR,
@@ -305,7 +303,7 @@
* Gets the last publish result from the UCE service if the device is using an RCS presence
* server.
* @return The last publish result from the UCE service. If the device is using SIP OPTIONS,
- * this method will return {@link #PUBLISH_STATE_200_OK} as well.
+ * this method will return {@link #PUBLISH_STATE_OK} as well.
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 96f77d8..d0cec52d 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -270,11 +270,12 @@
/**
* Requested expiration for Published Offline availability.
* Value is in Integer format.
- * @deprecated use {@link ProvisioningManager#KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC}.
+ * @deprecated use
+ * {@link ProvisioningManager#KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC}.
*/
@Deprecated
public static final int PUBLISH_TIMER_EXTENDED =
- ProvisioningManager.KEY_RCS_PUBLISH_TIMER_EXTENDED_SEC;
+ ProvisioningManager.KEY_RCS_PUBLISH_OFFLINE_AVAILABILITY_TIMER_SEC;
/**
*
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index af5089f..dcf339c 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -22,6 +22,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Messenger;
+import android.os.ParcelFileDescriptor;
import android.os.ResultReceiver;
import android.os.WorkSource;
import android.net.NetworkStats;
@@ -2121,9 +2122,14 @@
void notifyOtaEmergencyNumberDbInstalled();
/**
- * Override the file partition name for testing OTA emergency number database.
+ * Override a customized file partition name for OTA emergency number database.
*/
- void updateTestOtaEmergencyNumberDbFilePath(String otaFilePath);
+ void updateOtaEmergencyNumberDbFilePath(in ParcelFileDescriptor otaParcelFileDescriptor);
+
+ /**
+ * Reset file partition to default for OTA emergency number database.
+ */
+ void resetOtaEmergencyNumberDbFilePath();
/**
* Enable or disable a logical modem stack associated with the slotIndex.
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 70be83f..a616c61 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -127,18 +127,12 @@
/**
* Test rollbacks of staged installs involving only apks with bad update.
- * Trigger rollback phase. This is expected to fail due to watchdog
- * rebooting the test out from under it.
+ * Trigger rollback phase.
*/
@Test
public void testBadApkOnly_Phase3() throws Exception {
// One more crash to trigger rollback
RollbackUtils.sendCrashBroadcast(TestApp.A, 1);
-
- // We expect the device to be rebooted automatically. Wait for that to happen.
- // This device method will fail and the host will catch the assertion.
- // If reboot doesn't happen, the host will fail the assertion.
- Thread.sleep(TimeUnit.SECONDS.toMillis(120));
}
/**
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 4afebb5..282f012 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -22,7 +22,6 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
-import static org.testng.Assert.assertThrows;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -136,7 +135,10 @@
getDevice().reboot();
runPhase("testBadApkOnly_Phase2");
- assertThrows(AssertionError.class, () -> runPhase("testBadApkOnly_Phase3"));
+ // Trigger rollback and wait for reboot to happen
+ runPhase("testBadApkOnly_Phase3");
+ assertTrue(getDevice().waitForDeviceNotAvailable(TimeUnit.MINUTES.toMillis(2)));
+
getDevice().waitForDeviceAvailable();
runPhase("testBadApkOnly_Phase4");
diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java
index ca4ba63..7a60cc1 100644
--- a/tests/net/common/java/android/net/CaptivePortalTest.java
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -18,19 +18,26 @@
import static org.junit.Assert.assertEquals;
+import android.os.Build;
import android.os.RemoteException;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class CaptivePortalTest {
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
private static final int DEFAULT_TIMEOUT_MS = 5000;
private static final String TEST_PACKAGE_NAME = "com.google.android.test";
@@ -84,6 +91,7 @@
assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS);
}
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
@Test
public void testReevaluateNetwork() {
final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.reevaluateNetwork());
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index 06c6301..99dac14 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -28,8 +28,8 @@
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import static com.android.testutils.MiscAssertsKt.assertEqualBothWays;
+import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static com.android.testutils.MiscAssertsKt.assertNotEqualEitherWay;
-import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
import static org.junit.Assert.assertEquals;
@@ -38,11 +38,17 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.os.Build;
import android.os.SystemClock;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,6 +63,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LinkAddressTest {
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
private static final String V4 = "192.0.2.1";
private static final String V6 = "2001:db8::1";
@@ -318,15 +326,29 @@
l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
assertParcelingIsLossless(l);
- l = new LinkAddress(V6_ADDRESS, 64, 123, 456,
- 1L, 3600000L);
- assertParcelingIsLossless(l);
l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
- assertParcelSane(l, 6);
+ assertParcelingIsLossless(l);
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testLifetimeParceling() {
+ final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, 456, 1L, 3600000L);
+ assertParcelingIsLossless(l);
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.Q)
+ public void testFieldCount_Q() {
+ assertFieldCountEquals(4, LinkAddress.class);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testFieldCount() {
+ // Make sure any new field is covered by the above parceling tests when changing this number
+ assertFieldCountEquals(6, LinkAddress.class);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testDeprecationTime() {
try {
new LinkAddress(V6_ADDRESS, 64, 0, 456,
@@ -347,7 +369,7 @@
} catch (IllegalArgumentException expected) { }
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testExpirationTime() {
try {
new LinkAddress(V6_ADDRESS, 64, 0, 456,
@@ -366,10 +388,13 @@
public void testGetFlags() {
LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST);
assertEquals(123, l.getFlags());
+ }
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testGetFlags_Deprecation() {
// Test if deprecated bit was added/remove automatically based on the provided deprecation
// time
- l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
+ LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
1L, LinkAddress.LIFETIME_PERMANENT);
// Check if the flag is added automatically.
assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0);
@@ -458,8 +483,11 @@
(IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
RT_SCOPE_UNIVERSE);
assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
+ }
- l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testIsGlobalPreferred_DeprecatedInFuture() {
+ final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000,
SystemClock.elapsedRealtime() + 200000);
// Although the deprecated bit is set, but the deprecation time is in the future, test
diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
index d250ad3..173dbd1 100644
--- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
@@ -16,16 +16,23 @@
package android.net
+import android.os.Build
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.assertParcelSane
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SmallTest
class NetworkAgentConfigTest {
- @Test
+ @Rule @JvmField
+ val ignoreRule = DevSdkIgnoreRule()
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
fun testParcelNetworkAgentConfig() {
val config = NetworkAgentConfig.Builder().apply {
setExplicitlySelected(true)
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c2c3ba3..8c0c36b 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -2751,9 +2751,6 @@
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
- // Expect no notification to be shown when captive portal disappears by itself
- verify(mNotificationManager, never()).notifyAsUser(
- anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any());
// Break network connectivity.
// Expect NET_CAPABILITY_VALIDATED onLost callback.
@@ -2815,8 +2812,6 @@
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
- verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
- eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
mCm.unregisterNetworkCallback(validatedCallback);
mCm.unregisterNetworkCallback(captivePortalCallback);
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index d57f225..47db5d4 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -238,20 +238,6 @@
}
@Test
- public void testSameLevelNotifications() {
- final int id = 101;
- final String tag = NetworkNotificationManager.tagFor(id);
-
- mManager.showNotification(id, LOGGED_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(LOGGED_IN.eventId), any(), any());
-
- mManager.showNotification(id, LOST_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(LOST_INTERNET.eventId), any(), any());
- }
-
- @Test
public void testClearNotificationByType() {
final int id = 101;
final String tag = NetworkNotificationManager.tagFor(id);
@@ -259,31 +245,25 @@
// clearNotification(int id, NotificationType notifyType) will check if given type is equal
// to previous type or not. If they are equal then clear the notification; if they are not
// equal then return.
-
- mManager.showNotification(id, LOGGED_IN, mWifiNai, mCellNai, null, false);
+ mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(LOGGED_IN.eventId), any(), any());
+ .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
- // Previous notification is LOGGED_IN and given type is LOGGED_IN too. The notification
+ // Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification
// should be cleared.
- mManager.clearNotification(id, LOGGED_IN);
+ mManager.clearNotification(id, NO_INTERNET);
verify(mNotificationManager, times(1))
- .cancelAsUser(eq(tag), eq(LOGGED_IN.eventId), any());
+ .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
- mManager.showNotification(id, LOGGED_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(2))
- .notifyAsUser(eq(tag), eq(LOGGED_IN.eventId), any(), any());
-
- // LOST_INTERNET notification popup after LOGGED_IN notification.
- mManager.showNotification(id, LOST_INTERNET, mWifiNai, mCellNai, null, false);
+ // SIGN_IN is popped-up.
+ mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(LOST_INTERNET.eventId), any(), any());
+ .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
- // Previous notification is LOST_INTERNET and given type is LOGGED_IN. The notification
- // shouldn't be cleared.
- mManager.clearNotification(id, LOGGED_IN);
- // LOST_INTERNET shouldn't be cleared.
+ // The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be
+ // cleared.
+ mManager.clearNotification(id, PARTIAL_CONNECTIVITY);
verify(mNotificationManager, never())
- .cancelAsUser(eq(tag), eq(LOST_INTERNET.eventId), any());
+ .cancelAsUser(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId), any());
}
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 9256c57..70542b5 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,16 +16,15 @@
package android.net.wifi;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.wifi.WifiAnnotations.ChannelWidth;
+import android.net.wifi.WifiAnnotations.WifiStandard;
import android.os.Parcel;
import android.os.Parcelable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -313,17 +312,6 @@
*/
public static final int WIFI_STANDARD_11AX = 6;
- /** @hide */
- @IntDef(prefix = { "WIFI_STANDARD_" }, value = {
- WIFI_STANDARD_UNKNOWN,
- WIFI_STANDARD_LEGACY,
- WIFI_STANDARD_11N,
- WIFI_STANDARD_11AC,
- WIFI_STANDARD_11AX
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface WifiStandard{}
-
/**
* AP wifi standard.
*/
@@ -368,7 +356,7 @@
* {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}
* or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}.
*/
- public int channelWidth;
+ public @ChannelWidth int channelWidth;
/**
* Not used if the AP bandwidth is 20 MHz
diff --git a/wifi/java/android/net/wifi/WifiAnnotations.java b/wifi/java/android/net/wifi/WifiAnnotations.java
index 05e5b1d..acda7e0 100644
--- a/wifi/java/android/net/wifi/WifiAnnotations.java
+++ b/wifi/java/android/net/wifi/WifiAnnotations.java
@@ -61,6 +61,26 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Bandwidth {}
+ @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = {
+ ScanResult.CHANNEL_WIDTH_20MHZ,
+ ScanResult.CHANNEL_WIDTH_40MHZ,
+ ScanResult.CHANNEL_WIDTH_80MHZ,
+ ScanResult.CHANNEL_WIDTH_160MHZ,
+ ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelWidth{}
+
+ @IntDef(prefix = { "WIFI_STANDARD_" }, value = {
+ ScanResult.WIFI_STANDARD_UNKNOWN,
+ ScanResult.WIFI_STANDARD_LEGACY,
+ ScanResult.WIFI_STANDARD_11N,
+ ScanResult.WIFI_STANDARD_11AC,
+ ScanResult.WIFI_STANDARD_11AX,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiStandard{}
+
@IntDef(prefix = { "PROTOCOL_" }, value = {
ScanResult.PROTOCOL_NONE,
ScanResult.PROTOCOL_WPA,
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 5a7bf4b..ceb2907 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -503,6 +503,8 @@
break;
case SECURITY_TYPE_EAP_SUITE_B:
allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 142854a..70c5e72 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -103,7 +103,7 @@
/**
* Wi-Fi standard for the connection
*/
- private @ScanResult.WifiStandard int mWifiStandard;
+ private @WifiAnnotations.WifiStandard int mWifiStandard;
/**
* The unit in which links speeds are expressed.
@@ -518,7 +518,7 @@
* Sets the Wi-Fi standard
* @hide
*/
- public void setWifiStandard(@ScanResult.WifiStandard int wifiStandard) {
+ public void setWifiStandard(@WifiAnnotations.WifiStandard int wifiStandard) {
mWifiStandard = wifiStandard;
}
@@ -526,7 +526,7 @@
* Get connection Wi-Fi standard
* @return the connection Wi-Fi standard
*/
- public @ScanResult.WifiStandard int getWifiStandard() {
+ public @WifiAnnotations.WifiStandard int getWifiStandard() {
return mWifiStandard;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9703fa6..ff62296 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2563,7 +2563,7 @@
* valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
* @return {@code true} if supported, {@code false} otherwise.
*/
- public boolean isWifiStandardSupported(@ScanResult.WifiStandard int standard) {
+ public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) {
try {
return mService.isWifiStandardSupported(standard);
} catch (RemoteException e) {
diff --git a/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java b/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
index a045aad..bb0cc97 100644
--- a/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
+++ b/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
@@ -19,6 +19,8 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiAnnotations.ChannelWidth;
+import android.net.wifi.WifiAnnotations.WifiStandard;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
@@ -28,6 +30,9 @@
/**
* DeviceWiphyCapabilities for wificond
*
+ * Contains the WiFi physical layer attributes and capabilities of the device.
+ * It is used to collect these attributes from the device driver via wificond.
+ *
* @hide
*/
@SystemApi
@@ -61,7 +66,7 @@
* valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
* @return {@code true} if supported, {@code false} otherwise.
*/
- public boolean isWifiStandardSupported(int standard) {
+ public boolean isWifiStandardSupported(@WifiStandard int standard) {
switch (standard) {
case ScanResult.WIFI_STANDARD_LEGACY:
return true;
@@ -84,7 +89,7 @@
* valid values from {@link ScanResult}'s {@code WIFI_STANDARD_}
* @param support {@code true} if supported, {@code false} otherwise.
*/
- public void setWifiStandardSupport(int standard, boolean support) {
+ public void setWifiStandardSupport(@WifiStandard int standard, boolean support) {
switch (standard) {
case ScanResult.WIFI_STANDARD_11N:
m80211nSupported = support;
@@ -107,7 +112,7 @@
*
* @return {@code true} if supported, {@code false} otherwise.
*/
- public boolean isChannelWidthSupported(int chWidth) {
+ public boolean isChannelWidthSupported(@ChannelWidth int chWidth) {
switch (chWidth) {
case ScanResult.CHANNEL_WIDTH_20MHZ:
return true;
@@ -131,8 +136,10 @@
* @param chWidth valid values are {@link ScanResult#CHANNEL_WIDTH_160MHZ} and
* {@link ScanResult#CHANNEL_WIDTH_80MHZ_PLUS_MHZ}
* @param support {@code true} if supported, {@code false} otherwise.
+ *
+ * @hide
*/
- public void setChannelWidthSupported(int chWidth, boolean support) {
+ public void setChannelWidthSupported(@ChannelWidth int chWidth, boolean support) {
switch (chWidth) {
case ScanResult.CHANNEL_WIDTH_160MHZ:
mChannelWidth160MhzSupported = support;
@@ -159,6 +166,8 @@
* Set maximum number of transmit spatial streams
*
* @param streams number of spatial streams
+ *
+ * @hide
*/
public void setMaxNumberTxSpatialStreams(int streams) {
mMaxNumberTxSpatialStreams = streams;
@@ -177,6 +186,8 @@
* Set maximum number of receive spatial streams
*
* @param streams number of streams
+ *
+ * @hide
*/
public void setMaxNumberRxSpatialStreams(int streams) {
mMaxNumberRxSpatialStreams = streams;
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index b5c74d1..4c22d5d 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -42,7 +42,7 @@
public static final int TEST_LEVEL = -56;
public static final int TEST_FREQUENCY = 2412;
public static final long TEST_TSF = 04660l;
- public static final @ScanResult.WifiStandard int TEST_WIFI_STANDARD =
+ public static final @WifiAnnotations.WifiStandard int TEST_WIFI_STANDARD =
ScanResult.WIFI_STANDARD_11AC;
/**
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 047a64b..91c74f3 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -456,6 +456,8 @@
config.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B);
assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+ assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP));
+ assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
assertTrue(config.allowedPairwiseCiphers.get(WifiConfiguration.PairwiseCipher.GCMP_256));
assertTrue(config.allowedGroupCiphers.get(WifiConfiguration.GroupCipher.GCMP_256));
assertTrue(config.allowedGroupManagementCiphers