Merge "Update the resources owner files"
diff --git a/ApiDocs.bp b/ApiDocs.bp
index a926ddc..8af2e02 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -112,7 +112,6 @@
}
// Defaults module for doc-stubs targets that use module source code as input.
-// This is the default/normal.
stubs_defaults {
name: "framework-doc-stubs-sources-default",
defaults: ["framework-doc-stubs-default"],
@@ -147,12 +146,6 @@
}
droidstubs {
- name: "framework-doc-stubs",
- defaults: ["framework-doc-stubs-sources-default"],
- args: metalava_framework_docs_args,
-}
-
-droidstubs {
name: "framework-doc-system-stubs",
defaults: ["framework-doc-stubs-sources-default"],
args: metalava_framework_docs_args +
@@ -160,11 +153,8 @@
api_levels_sdk_type: "system",
}
-// Experimental target building doc stubs with module stub source code as input.
-// This is intended to eventually replace framework-doc-stubs, once all diffs
-// have been eliminated.
droidstubs {
- name: "framework-doc-stubs-module-stubs",
+ name: "framework-doc-stubs",
defaults: ["framework-doc-stubs-default"],
args: metalava_framework_docs_args,
srcs: [
diff --git a/apex/blobstore/README.md b/apex/blobstore/README.md
new file mode 100644
index 0000000..69af436
--- /dev/null
+++ b/apex/blobstore/README.md
@@ -0,0 +1,125 @@
+<!--
+ Copyright (C) 2021 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
+-->
+
+# BlobStore Manager
+
+## Introduction
+* BlobStoreManager is a system service added in Android R release that facilitates sharing of
+ data blobs among apps.
+* Apps that would like to share data blobs with other apps can do so by contributing those
+ data blobs with the System and can choose how they would like the System to share the data blobs
+ with other apps.
+* Apps can access data blobs shared by other apps from the System using checksum of the data blobs
+ (plus some other data attributes. More details [below](#blob-handle)).
+* The APIs provided by the BlobStoreManager are meant to reduce storage and network usage by
+ reusing the data available on the device instead of downloading the same data again and having
+ multiple copies of the same data on disk.
+* It is not meant to provide access to the data which apps otherwise would not be able to access.
+ In other words, if an app’s only means of obtaining access to certain data is through
+ BlobStoreManager, then that use case is not really intended or supported.
+* For example, if earlier an app was downloading certain shared data from a server, then by using
+ BlobStoreManager, it can first check whether or not the data is already available on the device
+ before downloading.
+
+## Concepts
+### Blob handle
+Blob handle is the identifier of the data and it is what apps need to use for referring to the
+data blobs. Currently, this is made of following bits of information:
+* SHA256 checksum of data
+* Data label: A user readable string that indicates what the data blob is.
+ This is meant to be used when surfacing a list of blobs to the user.
+* Data expiry time: A timestamp after which the data blob should be considered invalid and not
+ allowed to be accessed by any app.
+* Data tag: An opaque string associated with the blob. System does not interpret this in any way or
+ use it for any purposes other than when checking whether two Blob handle identifiers are referring
+ to the same data blob. This is meant to be used by the apps, either for categorization for
+ data blobs or for adding additional identifiers. For example, an app can add tags like
+ *machine_learning* or *media* depending on the data blob if necessary.
+
+When comparing two Blob handles, the System will compare all the pieces of information above and
+only when two Blob handles are equal, the data blobs corresponding to those identifiers are
+considered equal.
+
+### Blob sharing session
+Session is a way to allow apps to contribute data over multiple time intervals. Each session is
+associated with a unique Identifier that is created and obtained by the apps by calling
+[BlobStoreManager#createSession](https://developer.android.com/reference/android/app/blob/BlobStoreManager#createSession(android.app.blob.BlobHandle)).
+Apps can save the Identifier associated with a session and use it to open and close it
+multiple times for contributing the data. For example, if an app is downloading
+some content over the network, it can start a Session and start contributing this data to the
+System immediately and if the network connection is lost for any reason, the app can close this
+session. When the download resumes, the app can reopen the session and start contributing again.
+Note that once the entire data is contributed, the app has no reason to hold on to the Session Id.
+
+### Blob commit
+Since a data blob can be contributed in a session over multiple time intervals, an app closing a
+session does not imply that the contribution is completed. So, *commit* is added as an explicit
+event / signal for the app to indicate that the contribution of the data blob is completed.
+At this point, the System can verify the data blob does indeed correspond to the Blob handle used
+by the app and prevent the app from making any further modifications to the data blob. Once the
+data blob is committed and verified by the System, it is available for other applications to access.
+
+### Access modes
+When an application contributes a data blob to the System, it can choose to specify how it would
+like the System to share this data blob with other applications. Access modes refer to the type of
+access that apps specified when contributing a data blob. As of Android S release, there are
+four access modes:
+* Allow specific packages: Apps can specify a specific set of applications that are allowed to
+ access their data blob.
+* Allow packages with the same signature: Apps can specify that only the applications that are
+ signed with the same certificate as them can access their data blob.
+* Allow public access: Apps can specify that any other app on the device can access their data blob.
+* Allow private access: Apps can specify that no other app can access their data blob unless they
+ happen to contribute the same data blob.
+ * Note that in this case, two apps might download the same data blob and contribute to the System
+ in which case we are not saving anything in terms of bandwidth usage, but we would still be
+ saving disk usage since we would be keeping only one copy of data on disk.
+
+### Lease
+Leasing a blob is a way to specify that an application is interested in using a data blob
+and would like the System to not delete this data blob. Applications can also access a blob
+without holding a lease on it, in which case the System can choose to delete the data blob at any
+time. So, if an application wants to make sure a data blob is available for access for a certain
+period, it is recommended that the application acquire a lease on the data blob. Applications can
+either specify upfront how long they would like to hold the lease for (which is called the lease
+expiry time), or they can acquire a lease without specifying a time period and release the lease
+when they are done with the data blob.
+
+## Sharing data blobs across users
+By default, data blobs are only accessible to applications in the user in which the data blob was
+contributed, but if an application holds the permission
+[ACCESS_BLOBS_ACROSS_USERS](https://developer.android.com/reference/android/Manifest.permission#ACCESS_BLOBS_ACROSS_USERS),
+then they are allowed to access blobs that are contributed by the applications in the other users.
+As of Android S, this permission is only available to following set of applications:
+* Apps signed with the platform certificate
+* Privileged applications
+* Applications holding the
+ [ASSISTANT](https://developer.android.com/reference/android/app/role/RoleManager#ROLE_ASSISTANT)
+ role
+* Development applications
+
+Note that the access modes that applications choose while committing the data blobs still apply
+when these data blobs are accessed across users. So for example, if *appA* contributed a
+data blob in *user0* and specified to share this data blob with only a specific set of
+applications [*appB*, *appC*], then *appD* on *user10* will not be able to access this data blob
+even if the app is granted the `ACCESS_BLOBS_ACROSS_USERS` permission.
+
+When apps that are allowed to access blobs across users
+(i.e. those holding the permission `ACCESS_BLOBS_ACROSS_USERS`) try to access a data blob,
+they can do so as if it is any other data blob. In other words, the applications don’t need to
+know where the data blob is contributed, because the System will automatically check and will
+allow access if this data blob is available either on the user in which the calling application
+is running in or other users.
\ No newline at end of file
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 4e46aa3..9564dde 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -41,6 +41,10 @@
private IActivityManager mAm;
private IPackageManager mPm;
+ Am() {
+ svcInit();
+ }
+
/**
* Command-line entry point.
*
@@ -50,6 +54,20 @@
(new Am()).run(args);
}
+ private void svcInit() {
+ mAm = ActivityManager.getService();
+ if (mAm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ return;
+ }
+
+ mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ if (mPm == null) {
+ System.err.println(NO_SYSTEM_ERROR_CODE);
+ return;
+ }
+ }
+
@Override
public void onShowUsage(PrintStream out) {
try {
@@ -61,19 +79,6 @@
@Override
public void onRun() throws Exception {
-
- mAm = ActivityManager.getService();
- if (mAm == null) {
- System.err.println(NO_SYSTEM_ERROR_CODE);
- throw new AndroidException("Can't connect to activity manager; is the system running?");
- }
-
- mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- if (mPm == null) {
- System.err.println(NO_SYSTEM_ERROR_CODE);
- throw new AndroidException("Can't connect to package manager; is the system running?");
- }
-
String op = nextArgRequired();
if (op.equals("instrument")) {
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 1e72ddf..0b439df 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -545,6 +545,8 @@
mWm.setAnimationScales(oldAnims);
}
}
+ // Exit from here instead of going down the path of normal shutdown which is slow.
+ System.exit(0);
}
private static String readLogcat(long startTimeMs) {
diff --git a/core/api/current.txt b/core/api/current.txt
index 6f4a779..9d1a171 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8648,12 +8648,14 @@
method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
method public int getState();
+ method public int isCisCentralSupported();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
method public boolean isEnabled();
method public boolean isLe2MPhySupported();
method public boolean isLeCodedPhySupported();
method public boolean isLeExtendedAdvertisingSupported();
method public boolean isLePeriodicAdvertisingSupported();
+ method public int isLePeriodicAdvertisingSyncTransferSenderSupported();
method public boolean isMultipleAdvertisementSupported();
method public boolean isOffloadedFilteringSupported();
method public boolean isOffloadedScanBatchingSupported();
@@ -9123,8 +9125,10 @@
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]);
field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
@@ -9143,11 +9147,14 @@
public abstract class BluetoothGattCallback {
ctor public BluetoothGattCallback();
- method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
- method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
+ method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
+ method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]);
+ method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
+ method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
- method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
+ method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
+ method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]);
method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
@@ -9164,20 +9171,20 @@
method public int describeContents();
method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
- method public Float getFloatValue(int, int);
+ method @Deprecated public Float getFloatValue(int, int);
method public int getInstanceId();
- method public Integer getIntValue(int, int);
+ method @Deprecated public Integer getIntValue(int, int);
method public int getPermissions();
method public int getProperties();
method public android.bluetooth.BluetoothGattService getService();
- method public String getStringValue(int);
+ method @Deprecated public String getStringValue(int);
method public java.util.UUID getUuid();
- method public byte[] getValue();
+ method @Deprecated public byte[] getValue();
method public int getWriteType();
- method public boolean setValue(byte[]);
- method public boolean setValue(int, int, int);
- method public boolean setValue(int, int, int, int);
- method public boolean setValue(String);
+ method @Deprecated public boolean setValue(byte[]);
+ method @Deprecated public boolean setValue(int, int, int);
+ method @Deprecated public boolean setValue(int, int, int, int);
+ method @Deprecated public boolean setValue(String);
method public void setWriteType(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
@@ -9217,8 +9224,8 @@
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
method public int getPermissions();
method public java.util.UUID getUuid();
- method public byte[] getValue();
- method public boolean setValue(byte[]);
+ method @Deprecated public byte[] getValue();
+ method @Deprecated public boolean setValue(byte[]);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
field public static final byte[] DISABLE_NOTIFICATION_VALUE;
@@ -9506,7 +9513,12 @@
field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
+ field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa
+ field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65
+ field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66
field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
+ field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8
+ field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9
field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
field public static final int SUCCESS = 0; // 0x0
}
@@ -31470,6 +31482,7 @@
method @Nullable public android.os.PersistableBundle readPersistableBundle();
method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
method @Nullable public java.io.Serializable readSerializable();
+ method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
method @NonNull public android.util.Size readSize();
method @NonNull public android.util.SizeF readSizeF();
method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 49df45a..9af6c1b 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -113,6 +113,11 @@
public class AudioManager {
method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
+ method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
+ method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
+ method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
+ method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpSamplingRate(int);
+ method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpVolume(int);
method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
@@ -292,6 +297,10 @@
method @Nullable public android.os.IBinder getOrThrow() throws android.os.StatsServiceManager.ServiceNotFoundException;
}
+ public class SystemConfigManager {
+ method @NonNull public java.util.List<android.content.ComponentName> getEnabledComponentOverrides(@NonNull String);
+ }
+
}
package android.os.storage {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index db3cedd..78e6a07 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -475,6 +475,8 @@
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_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
+ field public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
field public static final String OPSTR_GPS = "android:gps";
field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
@@ -8579,7 +8581,6 @@
public class SystemConfigManager {
method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
- method @NonNull public java.util.List<java.lang.String> getEnabledComponentOverrides(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public int[] getSystemPermissionUids(@NonNull String);
}
@@ -9149,6 +9150,7 @@
field public static final String NAMESPACE_BIOMETRICS = "biometrics";
field public static final String NAMESPACE_BLOBSTORE = "blobstore";
field public static final String NAMESPACE_BLUETOOTH = "bluetooth";
+ field public static final String NAMESPACE_CAPTIVEPORTALLOGIN = "captive_portal_login";
field public static final String NAMESPACE_CLIPBOARD = "clipboard";
field public static final String NAMESPACE_CONNECTIVITY = "connectivity";
field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
@@ -9184,6 +9186,7 @@
field public static final String NAMESPACE_SYSTEMUI = "systemui";
field public static final String NAMESPACE_SYSTEM_TIME = "system_time";
field public static final String NAMESPACE_TELEPHONY = "telephony";
+ field public static final String NAMESPACE_TETHERING = "tethering";
field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
field public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot";
}
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 0d6a079..e6cdcc0 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -31,6 +31,7 @@
import com.android.internal.annotations.GuardedBy;
+import java.util.Objects;
import java.util.Set;
/**
@@ -86,6 +87,12 @@
if (TextUtils.isEmpty(type)) {
throw new IllegalArgumentException("the type must not be empty: " + type);
}
+ if (name.length() > 200) {
+ throw new IllegalArgumentException("account name is longer than 200 characters");
+ }
+ if (type.length() > 200) {
+ throw new IllegalArgumentException("account type is longer than 200 characters");
+ }
this.name = name;
this.type = type;
this.accessId = accessId;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index db5dcc5..af59ea1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -77,7 +77,6 @@
import android.os.Looper;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager.ServiceNotFoundException;
@@ -8788,9 +8787,7 @@
* the activity is visible after the screen is turned on when the lockscreen is up. In addition,
* if this flag is set and the activity calls {@link
* KeyguardManager#requestDismissKeyguard(Activity, KeyguardManager.KeyguardDismissCallback)}
- * the screen will turn on. If the screen is off and device is not secured, this flag can turn
- * screen on and dismiss keyguard to make this activity visible and resume, which can be used to
- * replace {@link PowerManager#ACQUIRE_CAUSES_WAKEUP}
+ * the screen will turn on.
*
* @param turnScreenOn {@code true} to turn on the screen; {@code false} otherwise.
*
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 6c3795d..bfff27a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -464,11 +464,7 @@
@Override
public int hashCode() {
- return hashCode(authority, userId);
- }
-
- public static int hashCode(final String auth, final int userIdent) {
- return ((auth != null) ? auth.hashCode() : 0) ^ userIdent;
+ return ((authority != null) ? authority.hashCode() : 0) ^ userId;
}
}
@@ -490,7 +486,7 @@
// Note we never removes items from this map but that's okay because there are only so many
// users and so many authorities.
@GuardedBy("mGetProviderKeys")
- final SparseArray<ProviderKey> mGetProviderKeys = new SparseArray<>();
+ final ArrayMap<ProviderKey, ProviderKey> mGetProviderKeys = new ArrayMap<>();
final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
= new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
@@ -7020,11 +7016,11 @@
}
private ProviderKey getGetProviderKey(String auth, int userId) {
- final int key = ProviderKey.hashCode(auth, userId);
+ final ProviderKey key = new ProviderKey(auth, userId);
synchronized (mGetProviderKeys) {
ProviderKey lock = mGetProviderKeys.get(key);
if (lock == null) {
- lock = new ProviderKey(auth, userId);
+ lock = key;
mGetProviderKeys.put(key, lock);
}
return lock;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 0b336f6..63f700b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1313,9 +1313,23 @@
public static final int OP_RECORD_INCOMING_PHONE_AUDIO =
AppProtoEnums.APP_OP_RECORD_INCOMING_PHONE_AUDIO;
+ /**
+ * VPN app establishes a connection through the VpnService API.
+ *
+ * @hide
+ */
+ public static final int OP_ESTABLISH_VPN_SERVICE = AppProtoEnums.APP_OP_ESTABLISH_VPN_SERVICE;
+
+ /**
+ * VPN app establishes a connection through the VpnManager API.
+ *
+ * @hide
+ */
+ public static final int OP_ESTABLISH_VPN_MANAGER = AppProtoEnums.APP_OP_ESTABLISH_VPN_MANAGER;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 117;
+ public static final int _NUM_OP = 119;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1754,6 +1768,22 @@
public static final String OPSTR_RECORD_INCOMING_PHONE_AUDIO =
"android:record_incoming_phone_audio";
+ /**
+ * VPN app establishes a connection through the VpnService API.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
+
+ /**
+ * VPN app establishes a connection through the VpnManager API.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String OPSTR_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1970,6 +2000,8 @@
OP_BLUETOOTH_ADVERTISE, // OP_BLUETOOTH_ADVERTISE
OP_RECORD_INCOMING_PHONE_AUDIO, // OP_RECORD_INCOMING_PHONE_AUDIO
OP_NEARBY_WIFI_DEVICES, // OP_NEARBY_WIFI_DEVICES
+ OP_ESTABLISH_VPN_SERVICE, // OP_ESTABLISH_VPN_SERVICE
+ OP_ESTABLISH_VPN_MANAGER, // OP_ESTABLISH_VPN_MANAGER
};
/**
@@ -2093,6 +2125,8 @@
OPSTR_BLUETOOTH_ADVERTISE,
OPSTR_RECORD_INCOMING_PHONE_AUDIO,
OPSTR_NEARBY_WIFI_DEVICES,
+ OPSTR_ESTABLISH_VPN_SERVICE,
+ OPSTR_ESTABLISH_VPN_MANAGER,
};
/**
@@ -2216,7 +2250,9 @@
"ACTIVITY_RECOGNITION_SOURCE",
"BLUETOOTH_ADVERTISE",
"RECORD_INCOMING_PHONE_AUDIO",
- "NEARBY_WIFI_DEVICES"
+ "NEARBY_WIFI_DEVICES",
+ "ESTABLISH_VPN_SERVICE",
+ "ESTABLISH_VPN_MANAGER",
};
/**
@@ -2342,6 +2378,8 @@
Manifest.permission.BLUETOOTH_ADVERTISE,
null, // no permission for OP_RECORD_INCOMING_PHONE_AUDIO,
Manifest.permission.NEARBY_WIFI_DEVICES,
+ null, // no permission for OP_ESTABLISH_VPN_SERVICE
+ null, // no permission for OP_ESTABLISH_VPN_MANAGER
};
/**
@@ -2467,6 +2505,8 @@
null, // BLUETOOTH_ADVERTISE
null, // RECORD_INCOMING_PHONE_AUDIO
null, // NEARBY_WIFI_DEVICES
+ null, // ESTABLISH_VPN_SERVICE
+ null, // ESTABLISH_VPN_MANAGER
};
/**
@@ -2591,6 +2631,8 @@
null, // BLUETOOTH_ADVERTISE
null, // RECORD_INCOMING_PHONE_AUDIO
null, // NEARBY_WIFI_DEVICES
+ null, // ESTABLISH_VPN_SERVICE
+ null, // ESTABLISH_VPN_MANAGER
};
/**
@@ -2714,6 +2756,8 @@
AppOpsManager.MODE_ALLOWED, // BLUETOOTH_ADVERTISE
AppOpsManager.MODE_ALLOWED, // RECORD_INCOMING_PHONE_AUDIO
AppOpsManager.MODE_ALLOWED, // NEARBY_WIFI_DEVICES
+ AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_SERVICE
+ AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_MANAGER
};
/**
@@ -2841,6 +2885,8 @@
false, // BLUETOOTH_ADVERTISE
false, // RECORD_INCOMING_PHONE_AUDIO
false, // NEARBY_WIFI_DEVICES
+ false, // OP_ESTABLISH_VPN_SERVICE
+ false, // OP_ESTABLISH_VPN_MANAGER
};
/**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 06ce053..dac8ffe 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2272,6 +2272,66 @@
return false;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_UNKNOWN,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED,
+ })
+ public @interface LeFeatureReturnValues {}
+
+ /**
+ * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Connected Isochronous Stream Central
+ * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
+ * the feature is not supported or an error code.
+ *
+ * @return whether the chipset supports the LE Connected Isochronous Stream Central feature
+ */
+ @RequiresNoPermission
+ public @LeFeatureReturnValues int isCisCentralSupported() {
+ if (!getLeAccess()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.isCisCentralSupported();
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
+ }
+
+ /**
+ * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
+ * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
+ * feature is not supported or an error code
+ *
+ * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
+ */
+ @RequiresNoPermission
+ public @LeFeatureReturnValues int isLePeriodicAdvertisingSyncTransferSenderSupported() {
+ if (!getLeAccess()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.isLePeriodicAdvertisingSyncTransferSenderSupported();
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
+ }
+
/**
* Return the maximum LE advertising data length in bytes,
* if LE Extended Advertising feature is supported, 0 otherwise.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c71fcc6..6e918bd 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1340,7 +1340,10 @@
if (alias == null) {
return getName();
}
- return alias;
+ return alias
+ .replace('\t', ' ')
+ .replace('\n', ' ')
+ .replace('\r', ' ');
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index ca898bd..4e7c01a 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
@@ -29,6 +31,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -140,27 +144,6 @@
public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
/**
- * A GATT writeCharacteristic request is started successfully.
- *
- * @hide
- */
- public static final int GATT_WRITE_REQUEST_SUCCESS = 0;
-
- /**
- * A GATT writeCharacteristic request failed to start.
- *
- * @hide
- */
- public static final int GATT_WRITE_REQUEST_FAIL = 1;
-
- /**
- * A GATT writeCharacteristic request is issued to a busy remote device.
- *
- * @hide
- */
- public static final int GATT_WRITE_REQUEST_BUSY = 2;
-
- /**
* No authentication required.
*
* @hide
@@ -430,6 +413,9 @@
if (callback != null) {
if (status == 0) characteristic.setValue(value);
callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
+ value, status);
+ // Keep calling deprecated callback to maintain app compatibility
+ callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
status);
}
}
@@ -443,7 +429,8 @@
*/
@Override
@SuppressLint("AndroidFrameworkRequiresPermission")
- public void onCharacteristicWrite(String address, int status, int handle) {
+ public void onCharacteristicWrite(String address, int status, int handle,
+ byte[] value) {
if (VDBG) {
Log.d(TAG, "onCharacteristicWrite() - Device=" + address
+ " handle=" + handle + " Status=" + status);
@@ -467,12 +454,13 @@
try {
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
- int requestStatus = GATT_WRITE_REQUEST_FAIL;
+ int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
requestStatus = mService.writeCharacteristic(mClientIf, address,
handle, characteristic.getWriteType(), authReq,
- characteristic.getValue(), mAttributionSource);
- if (requestStatus != GATT_WRITE_REQUEST_BUSY) {
+ value, mAttributionSource);
+ if (requestStatus
+ != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
break;
}
try {
@@ -488,7 +476,6 @@
}
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
-
runOrQueueCallback(new Runnable() {
@Override
public void run() {
@@ -525,6 +512,9 @@
if (callback != null) {
characteristic.setValue(value);
callback.onCharacteristicChanged(BluetoothGatt.this,
+ characteristic, value);
+ // Keep calling deprecated callback to maintain app compatibility
+ callback.onCharacteristicChanged(BluetoothGatt.this,
characteristic);
}
}
@@ -578,6 +568,9 @@
final BluetoothGattCallback callback = mCallback;
if (callback != null) {
if (status == 0) descriptor.setValue(value);
+ callback.onDescriptorRead(BluetoothGatt.this, descriptor, status,
+ value);
+ // Keep calling deprecated callback to maintain app compatibility
callback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
}
}
@@ -590,7 +583,8 @@
*/
@Override
@SuppressLint("AndroidFrameworkRequiresPermission")
- public void onDescriptorWrite(String address, int status, int handle) {
+ public void onDescriptorWrite(String address, int status, int handle,
+ byte[] value) {
if (VDBG) {
Log.d(TAG,
"onDescriptorWrite() - Device=" + address + " handle=" + handle);
@@ -614,7 +608,7 @@
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
mService.writeDescriptor(mClientIf, address, handle,
- authReq, descriptor.getValue(), mAttributionSource);
+ authReq, value, mAttributionSource);
mAuthRetryState++;
return;
} catch (RemoteException e) {
@@ -1194,8 +1188,8 @@
* Reads the requested characteristic from the associated remote device.
*
* <p>This is an asynchronous operation. The result of the read operation
- * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
- * callback.
+ * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
+ * BluetoothGattCharacteristic, byte[], int)} callback.
*
* @param characteristic Characteristic to read from the remote device
* @return true, if the read operation was initiated successfully
@@ -1240,8 +1234,8 @@
* Reads the characteristic using its UUID from the associated remote device.
*
* <p>This is an asynchronous operation. The result of the read operation
- * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
- * callback.
+ * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
+ * BluetoothGattCharacteristic, byte[], int)} callback.
*
* @param uuid UUID of characteristic to read from the remote device
* @return true, if the read operation was initiated successfully
@@ -1284,40 +1278,94 @@
*
* @param characteristic Characteristic to write on the remote device
* @return true, if the write operation was initiated successfully
+ * @throws IllegalArgumentException if characteristic or its value are null
+ *
+ * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[],
+ * int)} as this is not memory safe.
*/
+ @Deprecated
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
+ try {
+ return writeCharacteristic(characteristic, characteristic.getValue(),
+ characteristic.getWriteType()) == BluetoothStatusCodes.SUCCESS;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
+ BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
+ BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+ BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
+ BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
+ BluetoothStatusCodes.ERROR_UNKNOWN
+ })
+ public @interface WriteOperationReturnValues{}
+
+ /**
+ * Writes a given characteristic and its values to the associated remote device.
+ *
+ * <p>Once the write operation has been completed, the
+ * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
+ * reporting the result of the operation.
+ *
+ * @param characteristic Characteristic to write on the remote device
+ * @return whether the characteristic was successfully written to
+ * @throws IllegalArgumentException if characteristic or value are null
+ */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @WriteOperationReturnValues
+ public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic,
+ @NonNull byte[] value, int writeType) {
+ if (characteristic == null) {
+ throw new IllegalArgumentException("characteristic must not be null");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException("value must not be null");
+ }
+ if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
&& (characteristic.getProperties()
& BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
- return false;
+ return BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED;
+ }
+ if (mService == null || mClientIf == 0) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
}
- if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
- if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
-
BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
+ if (service == null) {
+ throw new IllegalArgumentException("Characteristic must have a non-null service");
+ }
BluetoothDevice device = service.getDevice();
- if (device == null) return false;
+ if (device == null) {
+ throw new IllegalArgumentException("Service must have a non-null device");
+ }
synchronized (mDeviceBusyLock) {
if (mDeviceBusy) {
- return false;
+ return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
}
mDeviceBusy = true;
}
- int requestStatus = GATT_WRITE_REQUEST_FAIL;
+ int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
try {
for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(),
- characteristic.getInstanceId(), characteristic.getWriteType(),
- AUTHENTICATION_NONE, characteristic.getValue(), mAttributionSource);
- if (requestStatus != GATT_WRITE_REQUEST_BUSY) {
+ characteristic.getInstanceId(), writeType, AUTHENTICATION_NONE, value,
+ mAttributionSource);
+ if (requestStatus != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
break;
}
try {
@@ -1330,10 +1378,10 @@
synchronized (mDeviceBusyLock) {
mDeviceBusy = false;
}
- return false;
+ throw e.rethrowFromSystemServer();
}
- return requestStatus == GATT_WRITE_REQUEST_SUCCESS;
+ return requestStatus;
}
/**
@@ -1384,45 +1432,86 @@
/**
* Write the value of a given descriptor to the associated remote device.
*
- * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
- * triggered to report the result of the write operation.
+ * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
+ * result of the write operation.
*
* @param descriptor Descriptor to write to the associated remote device
* @return true, if the write operation was initiated successfully
+ * @throws IllegalArgumentException if descriptor or its value are null
+ *
+ * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as
+ * this is not memory safe.
*/
+ @Deprecated
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
+ try {
+ return writeDescriptor(descriptor, descriptor.getValue())
+ == BluetoothStatusCodes.SUCCESS;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Write the value of a given descriptor to the associated remote device.
+ *
+ * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
+ * result of the write operation.
+ *
+ * @param descriptor Descriptor to write to the associated remote device
+ * @return true, if the write operation was initiated successfully
+ * @throws IllegalArgumentException if descriptor or value are null
+ */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @WriteOperationReturnValues
+ public int writeDescriptor(@NonNull BluetoothGattDescriptor descriptor,
+ @NonNull byte[] value) {
+ if (descriptor == null) {
+ throw new IllegalArgumentException("descriptor must not be null");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException("value must not be null");
+ }
if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
- if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false;
+ if (mService == null || mClientIf == 0) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
- if (characteristic == null) return false;
+ if (characteristic == null) {
+ throw new IllegalArgumentException("Descriptor must have a non-null characteristic");
+ }
BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
+ if (service == null) {
+ throw new IllegalArgumentException("Characteristic must have a non-null service");
+ }
BluetoothDevice device = service.getDevice();
- if (device == null) return false;
+ if (device == null) {
+ throw new IllegalArgumentException("Service must have a non-null device");
+ }
synchronized (mDeviceBusyLock) {
- if (mDeviceBusy) return false;
+ if (mDeviceBusy) return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
mDeviceBusy = true;
}
try {
- mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(),
- AUTHENTICATION_NONE, descriptor.getValue(), mAttributionSource);
+ return mService.writeDescriptor(mClientIf, device.getAddress(),
+ descriptor.getInstanceId(), AUTHENTICATION_NONE, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
synchronized (mDeviceBusyLock) {
mDeviceBusy = false;
}
- return false;
+ e.rethrowFromSystemServer();
}
-
- return true;
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
}
/**
@@ -1431,9 +1520,9 @@
* <p>Once a reliable write transaction has been initiated, all calls
* to {@link #writeCharacteristic} are sent to the remote device for
* verification and queued up for atomic execution. The application will
- * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
- * in response to every {@link #writeCharacteristic} call and is responsible
- * for verifying if the value has been transmitted accurately.
+ * receive a {@link BluetoothGattCallback#onCharacteristicWrite} callback in response to every
+ * {@link #writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} call and is
+ * responsible for verifying if the value has been transmitted accurately.
*
* <p>After all characteristics have been queued up and verified,
* {@link #executeReliableWrite} will execute all writes. If a characteristic
@@ -1530,9 +1619,9 @@
* Enable or disable notifications/indications for a given characteristic.
*
* <p>Once notifications are enabled for a characteristic, a
- * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
- * triggered if the remote device indicates that the given characteristic
- * has changed.
+ * {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
+ * BluetoothGattCharacteristic, byte[])} callback will be triggered if the remote device
+ * indicates that the given characteristic has changed.
*
* @param characteristic The characteristic for which to enable notifications
* @param enable Set to true to enable notifications/indications
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 1c40cff..d0a5a1e 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -80,16 +80,34 @@
/**
* Callback reporting the result of a characteristic read operation.
*
- * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
+ * @param gatt GATT client invoked
+ * {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
* @param characteristic Characteristic that was read from the associated remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
- * successfully.
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+ * successfully.
+ * @deprecated Use {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
+ * BluetoothGattCharacteristic, byte[], int)} as it is memory safe
*/
+ @Deprecated
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
}
/**
+ * Callback reporting the result of a characteristic read operation.
+ *
+ * @param gatt GATT client invoked
+ * {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}
+ * @param characteristic Characteristic that was read from the associated remote device.
+ * @param value the value of the characteristic
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+ * successfully.
+ */
+ public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull
+ BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) {
+ }
+
+ /**
* Callback indicating the result of a characteristic write operation.
*
* <p>If this callback is invoked while a reliable write transaction is
@@ -98,10 +116,13 @@
* value to the desired value to be written. If the values don't match,
* the application must abort the reliable write transaction.
*
- * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
+ * @param gatt GATT client that invoked
+ * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic,
+ * byte[], int)}
* @param characteristic Characteristic that was written to the associated remote device.
- * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
+ * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if
+ * the
+ * operation succeeds.
*/
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
@@ -110,33 +131,68 @@
/**
* Callback triggered as a result of a remote characteristic notification.
*
- * @param gatt GATT client the characteristic is associated with
+ * @param gatt GATT client the characteristic is associated with
* @param characteristic Characteristic that has been updated as a result of a remote
- * notification event.
+ * notification event.
+ * @deprecated Use {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
+ * BluetoothGattCharacteristic, byte[])} as it is memory safe by providing the characteristic
+ * value at the time of notification.
*/
+ @Deprecated
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
}
/**
+ * Callback triggered as a result of a remote characteristic notification. Note that the value
+ * within the characteristic object may have changed since receiving the remote characteristic
+ * notification, so check the parameter value for the value at the time of notification.
+ *
+ * @param gatt GATT client the characteristic is associated with
+ * @param characteristic Characteristic that has been updated as a result of a remote
+ * notification event.
+ * @param value notified characteristic value
+ */
+ public void onCharacteristicChanged(@NonNull BluetoothGatt gatt,
+ @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
+ }
+
+ /**
* Callback reporting the result of a descriptor read operation.
*
- * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
+ * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
* @param descriptor Descriptor that was read from the associated remote device.
- * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
- * successfully
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+ * successfully
+ * @deprecated Use {@link BluetoothGattCallback#onDescriptorRead(BluetoothGatt,
+ * BluetoothGattDescriptor, int, byte[])} as it is memory safe by providing the descriptor
+ * value at the time it was read.
*/
+ @Deprecated
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
}
/**
+ * Callback reporting the result of a descriptor read operation.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
+ * @param descriptor Descriptor that was read from the associated remote device.
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed
+ * successfully
+ * @param value the descriptor value at the time of the read operation
+ */
+ public void onDescriptorRead(@NonNull BluetoothGatt gatt,
+ @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) {
+ }
+
+ /**
* Callback indicating the result of a descriptor write operation.
*
- * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
+ * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
* @param descriptor Descriptor that was writte to the associated remote device.
- * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
- * operation succeeds.
+ * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the
+ * operation succeeds.
*/
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 8a7d4ba..c5e986e 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -451,8 +451,8 @@
* Set the write type for this characteristic
*
* <p>Setting the write type of a characteristic determines how the
- * {@link BluetoothGatt#writeCharacteristic} function write this
- * characteristic.
+ * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function
+ * write this characteristic.
*
* @param writeType The write type to for this characteristic. Can be one of: {@link
* #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}.
@@ -504,7 +504,10 @@
* operation or if a characteristic update notification has been received.
*
* @return Cached value of the characteristic
+ *
+ * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} instead
*/
+ @Deprecated
public byte[] getValue() {
return mValue;
}
@@ -521,7 +524,11 @@
* @param formatType The format type used to interpret the characteristic value.
* @param offset Offset at which the integer value can be found.
* @return Cached value of the characteristic or null of offset exceeds value size.
+ *
+ * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
+ * the characteristic value
*/
+ @Deprecated
public Integer getIntValue(int formatType, int offset) {
if ((offset + getTypeLen(formatType)) > mValue.length) return null;
@@ -558,7 +565,11 @@
* @param offset Offset at which the float value can be found.
* @return Cached value of the characteristic at a given offset or null if the requested offset
* exceeds the value size.
+ *
+ * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
+ * the characteristic value
*/
+ @Deprecated
public Float getFloatValue(int formatType, int offset) {
if ((offset + getTypeLen(formatType)) > mValue.length) return null;
@@ -580,7 +591,11 @@
*
* @param offset Offset at which the string value can be found.
* @return Cached value of the characteristic
+ *
+ * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get
+ * the characteristic value
*/
+ @Deprecated
public String getStringValue(int offset) {
if (mValue == null || offset > mValue.length) return null;
byte[] strBytes = new byte[mValue.length - offset];
@@ -599,7 +614,11 @@
* @param value New value for this characteristic
* @return true if the locally stored value has been set, false if the requested value could not
* be stored locally.
+ *
+ * @deprecated Pass the characteristic value directly into
+ * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
*/
+ @Deprecated
public boolean setValue(byte[] value) {
mValue = value;
return true;
@@ -613,7 +632,11 @@
* @param formatType Integer format type used to transform the value parameter
* @param offset Offset at which the value should be placed
* @return true if the locally stored value has been set
+ *
+ * @deprecated Pass the characteristic value directly into
+ * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
*/
+ @Deprecated
public boolean setValue(int value, int formatType, int offset) {
int len = offset + getTypeLen(formatType);
if (mValue == null) mValue = new byte[len];
@@ -660,7 +683,11 @@
* @param formatType Float format type used to transform the value parameter
* @param offset Offset at which the value should be placed
* @return true if the locally stored value has been set
+ *
+ * @deprecated Pass the characteristic value directly into
+ * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
*/
+ @Deprecated
public boolean setValue(int mantissa, int exponent, int formatType, int offset) {
int len = offset + getTypeLen(formatType);
if (mValue == null) mValue = new byte[len];
@@ -697,7 +724,11 @@
*
* @param value New value for this characteristic
* @return true if the locally stored value has been set
+ *
+ * @deprecated Pass the characteristic value directly into
+ * {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)}
*/
+ @Deprecated
public boolean setValue(String value) {
mValue = value.getBytes();
return true;
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index ed5ea08..a35d5b9 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -260,7 +260,10 @@
* operation.
*
* @return Cached value of the descriptor
+ *
+ * @deprecated Use {@link BluetoothGatt#readDescriptor(BluetoothGattDescriptor)} instead
*/
+ @Deprecated
public byte[] getValue() {
return mValue;
}
@@ -276,7 +279,11 @@
* @param value New value for this descriptor
* @return true if the locally stored value has been set, false if the requested value could not
* be stored locally.
+ *
+ * @deprecated Pass the descriptor value directly into
+ * {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])}
*/
+ @Deprecated
public boolean setValue(byte[] value) {
mValue = value;
return true;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 83108d2..a5a2470 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -817,7 +817,7 @@
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public Bundle getCurrentAgEvents(BluetoothDevice device) {
- if (DBG) log("getCurrentCalls()");
+ if (DBG) log("getCurrentAgEvents()");
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index 3e46c49..ca01784 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -79,6 +79,33 @@
public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
/**
+ * Error code indicating that the caller does not have the
+ * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission
+ */
+ public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8;
+
+ /**
+ * Error code indicating that the profile service is not bound. You can bind a profile service
+ * by calling {@link BluetoothAdapter#getProfileProxy}
+ */
+ public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9;
+
+ /**
+ * Error code indicating that the feature is not supported.
+ */
+ public static final int ERROR_FEATURE_NOT_SUPPORTED = 10;
+
+ /**
+ * A GATT writeCharacteristic request is not permitted on the remote device.
+ */
+ public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101;
+
+ /**
+ * A GATT writeCharacteristic request is issued to a busy remote device.
+ */
+ public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102;
+
+ /**
* If another application has already requested {@link OobData} then another fetch will be
* disallowed until the callback is removed.
*
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 74506da..ee24084 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -777,8 +777,8 @@
}
/**
- * Examine the given template and normalize if it refers to a "merged"
- * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
* for key purposes, and expand the template to match all other merged
* subscribers.
* <p>
@@ -793,8 +793,8 @@
}
/**
- * Examine the given template and normalize if it refers to a "merged"
- * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
* for key purposes, and expand the template to match all other merged
* subscribers.
*
@@ -806,7 +806,12 @@
* A, but also matches B.
*/
public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
- if (!template.isMatchRuleMobile()) return template;
+ // Now there are several types of network which uses SubscriberId to store network
+ // information. For instances:
+ // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
+ // The TYPE_CARRIER means that the network associate to specific carrier network.
+
+ if (template.mSubscriberId == null) return template;
for (String[] merged : mergedList) {
if (ArrayUtils.contains(merged, template.mSubscriberId)) {
diff --git a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
index 09f5283..be57372 100644
--- a/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
+++ b/core/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtils.java
@@ -79,6 +79,7 @@
IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH);
IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_MOBIKE);
IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_FORCE_PORT_4500);
+ IKE_OPTIONS.add(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT);
}
/** Serializes an IkeSessionParams to a PersistableBundle. */
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 2a344f6..ad3de25 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -103,7 +103,7 @@
* are unparcelled, mParcelledData willbe set to null.
*/
@UnsupportedAppUsage
- Parcel mParcelledData = null;
+ volatile Parcel mParcelledData = null;
/**
* Whether {@link #mParcelledData} was generated by native code or not.
@@ -182,13 +182,56 @@
* @param b a Bundle to be copied.
*/
BaseBundle(BaseBundle b) {
- copyInternal(b, false);
+ this(b, /* deep */ false);
}
/**
- * Special constructor that does not initialize the bundle.
+ * Constructs a {@link BaseBundle} containing a copy of {@code from}.
+ *
+ * @param from The bundle to be copied.
+ * @param deep Whether is a deep or shallow copy.
+ *
+ * @hide
*/
- BaseBundle(boolean doInit) {
+ BaseBundle(BaseBundle from, boolean deep) {
+ synchronized (from) {
+ mClassLoader = from.mClassLoader;
+
+ if (from.mMap != null) {
+ if (!deep) {
+ mMap = new ArrayMap<>(from.mMap);
+ } else {
+ final ArrayMap<String, Object> fromMap = from.mMap;
+ final int n = fromMap.size();
+ mMap = new ArrayMap<>(n);
+ for (int i = 0; i < n; i++) {
+ mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
+ }
+ }
+ } else {
+ mMap = null;
+ }
+
+ final Parcel parcelledData;
+ if (from.mParcelledData != null) {
+ if (from.isEmptyParcel()) {
+ parcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
+ mParcelledByNative = false;
+ } else {
+ parcelledData = Parcel.obtain();
+ parcelledData.appendFrom(from.mParcelledData, 0,
+ from.mParcelledData.dataSize());
+ parcelledData.setDataPosition(0);
+ mParcelledByNative = from.mParcelledByNative;
+ }
+ } else {
+ parcelledData = null;
+ mParcelledByNative = false;
+ }
+
+ // Keep as last statement to ensure visibility of other fields
+ mParcelledData = parcelledData;
+ }
}
/**
@@ -323,8 +366,8 @@
} else {
mMap.erase();
}
- mParcelledData = null;
mParcelledByNative = false;
+ mParcelledData = null;
return;
}
@@ -358,8 +401,8 @@
if (recycleParcel) {
recycleParcel(parcelledData);
}
- mParcelledData = null;
mParcelledByNative = false;
+ mParcelledData = null;
}
if (DEBUG) {
Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
@@ -501,44 +544,7 @@
mMap.clear();
}
- void copyInternal(BaseBundle from, boolean deep) {
- synchronized (from) {
- if (from.mParcelledData != null) {
- if (from.isEmptyParcel()) {
- mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
- mParcelledByNative = false;
- } else {
- mParcelledData = Parcel.obtain();
- mParcelledData.appendFrom(from.mParcelledData, 0,
- from.mParcelledData.dataSize());
- mParcelledData.setDataPosition(0);
- mParcelledByNative = from.mParcelledByNative;
- }
- } else {
- mParcelledData = null;
- mParcelledByNative = false;
- }
-
- if (from.mMap != null) {
- if (!deep) {
- mMap = new ArrayMap<>(from.mMap);
- } else {
- final ArrayMap<String, Object> fromMap = from.mMap;
- final int N = fromMap.size();
- mMap = new ArrayMap<>(N);
- for (int i = 0; i < N; i++) {
- mMap.append(fromMap.keyAt(i), deepCopyValue(fromMap.valueAt(i)));
- }
- }
- } else {
- mMap = null;
- }
-
- mClassLoader = from.mClassLoader;
- }
- }
-
- Object deepCopyValue(Object value) {
+ private Object deepCopyValue(Object value) {
if (value == null) {
return null;
}
@@ -570,7 +576,7 @@
return value;
}
- ArrayList deepcopyArrayList(ArrayList from) {
+ private ArrayList deepcopyArrayList(ArrayList from) {
final int N = from.size();
ArrayList out = new ArrayList(N);
for (int i=0; i<N; i++) {
@@ -1717,9 +1723,9 @@
if (length < 0) {
throw new RuntimeException("Bad length in parcel: " + length);
} else if (length == 0) {
+ mParcelledByNative = false;
// Empty Bundle or end of data.
mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
- mParcelledByNative = false;
return;
} else if (length % 4 != 0) {
throw new IllegalStateException("Bundle length is not aligned by 4: " + length);
@@ -1757,8 +1763,8 @@
+ ": " + length + " bundle bytes starting at " + offset);
p.setDataPosition(0);
- mParcelledData = p;
mParcelledByNative = isNativeBundle;
+ mParcelledData = p;
}
/** {@hide} */
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index b677b69..b069fb3 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -53,7 +53,7 @@
*
* <p>Most developers will not implement this class directly, instead using the
* <a href="{@docRoot}guide/components/aidl.html">aidl</a> tool to describe the desired
- * interface, having it generate the appropriate Binder subclass. You can,
+ * interface, having it generate the appropriate Binder subclass. You can,
* however, derive directly from Binder to implement your own custom RPC
* protocol or simply instantiate a raw Binder object directly to use as a
* token that can be shared across processes.
@@ -63,17 +63,17 @@
* To use this correctly, you must be doing so within the context of a top-level
* application component (a {@link android.app.Service}, {@link android.app.Activity},
* or {@link android.content.ContentProvider}) that lets the system know your process
- * should remain running.</p>
+ * should remain running.
*
* <p>You must keep in mind the situations in which your process
* could go away, and thus require that you later re-create a new Binder and re-attach
- * it when the process starts again. For example, if you are using this within an
+ * it when the process starts again. For example, if you are using this within an
* {@link android.app.Activity}, your activity's process may be killed any time the
* activity is not started; if the activity is later re-created you will need to
* create a new Binder and hand it back to the correct place again; you need to be
* aware that your process may be started for another reason (for example to receive
* a broadcast) that will not involve re-creating the activity and thus run its code
- * to create a new Binder.</p>
+ * to create a new Binder.
*
* @see IBinder
*/
@@ -94,14 +94,15 @@
/**
* Value to represents that a calling work source is not set.
*
- * This constatnt needs to be kept in sync with IPCThreadState::kUnsetWorkSource.
+ * <p>This constant needs to be kept in sync with IPCThreadState::kUnsetWorkSource.
*
* @hide
*/
public static final int UNSET_WORKSOURCE = -1;
/**
- * Control whether dump() calls are allowed.
+ * Control whether {@link #dump(FileDescriptor, PrintWriter, String[]) dump()}
+ * calls are allowed.
*/
private static volatile String sDumpDisabled = null;
@@ -188,7 +189,7 @@
sObserver = observer;
}
- /** {@hide} */
+ /** @hide */
static volatile boolean sWarnOnBlocking = false;
/**
@@ -207,8 +208,8 @@
/**
* Allow blocking calls on the given interface, overriding the requested
* value of {@link #setWarnOnBlocking(boolean)}.
- * <p>
- * This should only be rarely called when you are <em>absolutely sure</em>
+ *
+ * <p>This should only be rarely called when you are <em>absolutely sure</em>
* the remote interface is a built-in system component that can never be
* upgraded. In particular, this <em>must never</em> be called for
* interfaces hosted by package that could be upgraded or replaced,
@@ -258,7 +259,9 @@
ThreadLocal.withInitial(() -> sWarnOnBlocking);
/**
- * Allow blocking calls for the current thread. See {@link #allowBlocking}.
+ * Allow blocking calls for the current thread.
+ *
+ * @see {@link #allowBlocking}.
*
* @hide
*/
@@ -267,7 +270,9 @@
}
/**
- * Reset the current thread to the default blocking behavior. See {@link #defaultBlocking}.
+ * Reset the current thread to the default blocking behavior.
+ *
+ * @see {@link #defaultBlocking}.
*
* @hide
*/
@@ -286,10 +291,10 @@
/**
* Return the ID of the process that sent you the current transaction
- * that is being processed. This pid can be used with higher-level
+ * that is being processed. This PID can be used with higher-level
* system services to determine its identity and check permissions.
* If the current thread is not currently executing an incoming transaction,
- * then its own pid is returned.
+ * then its own PID is returned.
*
* Warning: oneway transactions do not receive PID.
*/
@@ -297,11 +302,11 @@
public static final native int getCallingPid();
/**
- * Return the Linux uid assigned to the process that sent you the
- * current transaction that is being processed. This uid can be used with
+ * Return the Linux UID assigned to the process that sent you the
+ * current transaction that is being processed. This UID can be used with
* higher-level system services to determine its identity and check
- * permissions. If the current thread is not currently executing an
- * incoming transaction, then its own uid is returned.
+ * permissions. If the current thread is not currently executing an
+ * incoming transaction, then its own UID is returned.
*/
@CriticalNative
public static final native int getCallingUid();
@@ -316,11 +321,11 @@
public static final native boolean isDirectlyHandlingTransaction();
/**
- * Return the Linux uid assigned to the process that sent the transaction
+ * Return the Linux UID assigned to the process that sent the transaction
* currently being processed.
*
* @throws IllegalStateException if the current thread is not currently
- * executing an incoming transaction.
+ * executing an incoming transaction.
*/
public static final int getCallingUidOrThrow() {
if (!isDirectlyHandlingTransaction()) {
@@ -332,18 +337,20 @@
/**
* Return the UserHandle assigned to the process that sent you the
- * current transaction that is being processed. This is the user
- * of the caller. It is distinct from {@link #getCallingUid()} in that a
+ * current transaction that is being processed. This is the user
+ * of the caller. It is distinct from {@link #getCallingUid()} in that a
* particular user will have multiple distinct apps running under it each
- * with their own uid. If the current thread is not currently executing an
+ * with their own UID. If the current thread is not currently executing an
* incoming transaction, then its own UserHandle is returned.
+ *
+ * @see UserHandle
*/
public static final @NonNull UserHandle getCallingUserHandle() {
return UserHandle.of(UserHandle.getUserId(getCallingUid()));
}
/**
- * Reset the identity of the incoming IPC on the current thread. This can
+ * Reset the identity of the incoming IPC on the current thread. This can
* be useful if, while handling an incoming call, you will be calling
* on interfaces of other objects that may be local to your process and
* need to do permission checks on the calls coming into them (so they
@@ -376,10 +383,10 @@
/**
* Convenience method for running the provided action enclosed in
- * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}
+ * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}.
*
- * Any exception thrown by the given action will be caught and rethrown after the call to
- * {@link #restoreCallingIdentity}
+ * <p>Any exception thrown by the given action will be caught and
+ * rethrown after the call to {@link #restoreCallingIdentity}.
*
* @hide
*/
@@ -400,10 +407,10 @@
/**
* Convenience method for running the provided action enclosed in
- * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result
+ * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result.
*
- * Any exception thrown by the given action will be caught and rethrown after the call to
- * {@link #restoreCallingIdentity}
+ * <p>Any exception thrown by the given action will be caught and rethrown after
+ * the call to {@link #restoreCallingIdentity}.
*
* @hide
*/
@@ -428,12 +435,13 @@
*
* <p>The StrictMode settings are kept in two places: a Java-level
* threadlocal for libcore/Dalvik, and a native threadlocal (set
- * here) for propagation via Binder calls. This is a little
+ * here) for propagation via Binder calls. This is a little
* unfortunate, but necessary to break otherwise more unfortunate
* dependencies either of Dalvik on Android, or Android
* native-only code on Dalvik.
*
* @see StrictMode
+ *
* @hide
*/
@CriticalNative
@@ -443,6 +451,7 @@
* Gets the current native thread-local StrictMode policy mask.
*
* @see #setThreadStrictModePolicy
+ *
* @hide
*/
@CriticalNative
@@ -459,7 +468,7 @@
* reasons, we only support one UID. This UID represents the original user responsible for the
* binder calls.
*
- * <p>{@link Binder#restoreCallingWorkSource(long)} must always be called after setting the
+ * <p>{@link #restoreCallingWorkSource(long)} must always be called after setting the
* worksource.
*
* <p>A typical use case would be
@@ -477,16 +486,16 @@
*
* @param workSource The original UID responsible for the binder call.
* @return token to restore original work source.
- **/
+ */
@CriticalNative
public static final native long setCallingWorkSourceUid(int workSource);
/**
* Returns the work source set by the caller.
*
- * Unlike {@link Binder#getCallingUid()}, this result of this method cannot be trusted. The
+ * <p>Unlike {@link #getCallingUid()}, this result of this method cannot be trusted. The
* caller can set the value to whatever they want. Only use this value if you trust the calling
- * uid.
+ * UID.
*
* @return The original UID responsible for the binder transaction.
*/
@@ -499,7 +508,7 @@
* <p>The work source will be propagated for future outgoing binder transactions
* executed on this thread.
*
- * <p>{@link Binder#restoreCallingWorkSource(long)} must always be called after clearing the
+ * <p>{@link #restoreCallingWorkSource(long)} must always be called after clearing the
* worksource.
*
* <p>A typical use case would be
@@ -513,13 +522,13 @@
* </pre>
*
* @return token to restore original work source.
- **/
+ */
@CriticalNative
public static final native long clearCallingWorkSource();
/**
* Restores the work source on this thread using a token returned by
- * {@link #setCallingWorkSourceUid(int) or {@link clearCallingWorkSource()}.
+ * {@link #setCallingWorkSourceUid(int)} or {@link #clearCallingWorkSource()}.
*
* <p>A typical use case would be
* <pre>
@@ -530,7 +539,7 @@
* Binder.restoreCallingWorkSource(token);
* }
* </pre>
- **/
+ */
@CriticalNative
public static final native void restoreCallingWorkSource(long token);
@@ -553,7 +562,7 @@
* Use a VINTF-stability binder w/o VINTF requirements. Should be called
* on a binder before it is sent out of process.
*
- * This must be called before the object is sent to another process.
+ * <p>This must be called before the object is sent to another process.
*
* @hide
*/
@@ -561,7 +570,7 @@
/**
* Flush any Binder commands pending in the current thread to the kernel
- * driver. This can be
+ * driver. This can be
* useful to call before performing an operation that may block for a long
* time, to ensure that any pending object references have been released
* in order to prevent the process from holding on to objects longer than
@@ -570,7 +579,7 @@
public static final native void flushPendingCommands();
/**
- * Add the calling thread to the IPC thread pool. This function does
+ * Add the calling thread to the IPC thread pool. This function does
* not return until the current process is exiting.
*/
public static final void joinThreadPool() {
@@ -579,6 +588,7 @@
/**
* Returns true if the specified interface is a proxy.
+ *
* @hide
*/
public static final boolean isProxy(IInterface iface) {
@@ -588,6 +598,7 @@
/**
* Call blocks until the number of executing binder threads is less
* than the maximum number of binder threads allowed for this process.
+ *
* @hide
*/
public static final native void blockUntilThreadAvailable();
@@ -595,7 +606,7 @@
/**
* Default constructor just initializes the object.
*
- * If you're creating a Binder token (a Binder object without an attached interface),
+ * <p>If you're creating a Binder token (a Binder object without an attached interface),
* you should use {@link #Binder(String)} instead.
*/
public Binder() {
@@ -605,7 +616,7 @@
/**
* Constructor for creating a raw Binder object (token) along with a descriptor.
*
- * The descriptor of binder objects usually specifies the interface they are implementing.
+ * <p>The descriptor of binder objects usually specifies the interface they are implementing.
* In case of binder tokens, no interface is implemented, and the descriptor can be used
* as a sort of tag to help identify the binder token. This will help identify remote
* references to these objects more easily when debugging.
@@ -614,7 +625,7 @@
* Instead of creating multiple tokens with the same descriptor, consider adding a suffix to
* help identify them.
*/
- public Binder(@Nullable String descriptor) {
+ public Binder(@Nullable String descriptor) {
mObject = getNativeBBinderHolder();
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
@@ -631,9 +642,9 @@
/**
* Convenience method for associating a specific interface with the Binder.
- * After calling, queryLocalInterface() will be implemented for you
- * to return the given owner IInterface when the corresponding
- * descriptor is requested.
+ * After calling, {@link #queryLocalInterface(String) queryLocalInterface()}
+ * will be implemented for you to return the given owner IInterface when
+ * the corresponding descriptor is requested.
*/
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
@@ -666,8 +677,8 @@
}
/**
- * Use information supplied to attachInterface() to return the
- * associated IInterface if it matches the requested
+ * Use information supplied to {@link #attachInterface attachInterface()}
+ * to return the associated {@link IInterface} if it matches the requested
* descriptor.
*/
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
@@ -678,14 +689,15 @@
}
/**
- * Control disabling of dump calls in this process. This is used by the system
+ * Control disabling of dump calls in this process. This is used by the system
* process watchdog to disable incoming dump calls while it has detecting the system
- * is hung and is reporting that back to the activity controller. This is to
+ * is hung and is reporting that back to the activity controller. This is to
* prevent the controller from getting hung up on bug reports at this point.
- * @hide
*
* @param msg The message to show instead of the dump; if null, dumps are
* re-enabled.
+ *
+ * @hide
*/
public static void setDumpDisabled(String msg) {
sDumpDisabled = msg;
@@ -694,7 +706,8 @@
/**
* Listener to be notified about each proxy-side binder call.
*
- * See {@link setProxyTransactListener}.
+ * @see {@link #setProxyTransactListener}.
+ *
* @hide
*/
@SystemApi
@@ -702,7 +715,8 @@
/**
* Called before onTransact.
*
- * @return an object that will be passed back to #onTransactEnded (or null).
+ * @return an object that will be passed back to {@link #onTransactEnded} (or null).,
+ *
* @hide
*/
@Nullable
@@ -713,15 +727,15 @@
/**
* Called before onTransact.
*
- * @return an object that will be passed back to #onTransactEnded (or null).
+ * @return an object that will be passed back to {@link #onTransactEnded} (or null).
*/
@Nullable
Object onTransactStarted(@NonNull IBinder binder, int transactionCode);
/**
- * Called after onTranact (even when an exception is thrown).
+ * Called after onTransact (even when an exception is thrown).
*
- * @param session The object return by #onTransactStarted.
+ * @param session The object return by {@link #onTransactStarted}.
*/
void onTransactEnded(@Nullable Object session);
}
@@ -732,16 +746,17 @@
* <li>By default, this listener will propagate the worksource if the outgoing call happens on
* the same thread as the incoming binder call.
* <li>Custom attribution can be done by calling {@link ThreadLocalWorkSource#setUid(int)}.
+ *
* @hide
*/
public static class PropagateWorkSourceTransactListener implements ProxyTransactListener {
@Override
public Object onTransactStarted(IBinder binder, int transactionCode) {
- // Note that {@link Binder#getCallingUid()} is already set to the UID of the current
- // process when this method is called.
- //
- // We use ThreadLocalWorkSource instead. It also allows feature owners to set
- // {@link ThreadLocalWorkSource#set(int) manually to attribute resources to a UID.
+ // Note that {@link #getCallingUid()} is already set to the UID of the current
+ // process when this method is called.
+ //
+ // We use {@link ThreadLocalWorkSource} instead. It also allows feature owners to set
+ // {@link ThreadLocalWorkSource#set(int)} manually to attribute resources to a UID.
int uid = ThreadLocalWorkSource.getUid();
if (uid != ThreadLocalWorkSource.UID_NONE) {
return Binder.setCallingWorkSourceUid(uid);
@@ -770,6 +785,7 @@
* <li>The listener is called on the critical path of the binder transaction so be careful about
* performance.
* <li>Never execute another binder transaction inside the listener.
+ *
* @hide
*/
@SystemApi
@@ -778,7 +794,7 @@
}
/**
- * Default implementation is a stub that returns false. You will want
+ * Default implementation is a stub that returns false. You will want
* to override this to do the appropriate unmarshalling of transactions.
*
* <p>If you want to call this, call transact().
@@ -786,15 +802,14 @@
* <p>Implementations that are returning a result should generally use
* {@link Parcel#writeNoException() Parcel.writeNoException} and
* {@link Parcel#writeException(Exception) Parcel.writeException} to propagate
- * exceptions back to the caller.</p>
+ * exceptions back to the caller.
*
- * @param code The action to perform. This should
- * be a number between {@link #FIRST_CALL_TRANSACTION} and
- * {@link #LAST_CALL_TRANSACTION}.
+ * @param code The action to perform. This should be a number between
+ * {@link #FIRST_CALL_TRANSACTION} and {@link #LAST_CALL_TRANSACTION}.
* @param data Marshalled data being received from the caller.
* @param reply If the caller is expecting a result back, it should be marshalled
* in to here.
- * @param flags Additional operation flags. Either 0 for a normal
+ * @param flags Additional operation flags. Either 0 for a normal
* RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
*
* @return Return true on a successful call; returning false is generally used to
@@ -856,10 +871,12 @@
* Resolves a transaction code to a human readable name.
*
* <p>Default implementation is a stub that returns null.
+ *
* <p>AIDL generated code will return the original method name.
*
* @param transactionCode The code to resolve.
* @return A human readable name.
+ *
* @hide
*/
public @Nullable String getTransactionName(int transactionCode) {
@@ -925,7 +942,7 @@
* Print the object's state into the given stream.
*
* @param fd The raw file descriptor that the dump is being sent to.
- * @param fout The file to which you should dump your state. This will be
+ * @param fout The file to which you should dump your state. This will be
* closed for you after you return.
* @param args additional arguments to the dump request.
*/
@@ -941,6 +958,7 @@
* @param callback Callback through which to interact with the invoking shell.
* @param resultReceiver Called when the command has finished executing, with the result code.
* @throws RemoteException
+ *
* @hide
*/
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@@ -958,7 +976,8 @@
*
* <p class="caution">Note: no permission checking is done before calling this method; you must
* apply any security checks as appropriate for the command being executed.
- * Consider using {@link ShellCommand} to help in the implementation.</p>
+ * Consider using {@link ShellCommand} to help in the implementation.
+ *
* @hide
*/
public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@@ -1013,7 +1032,7 @@
* System services can implement this method to implement ADB shell commands.
*
* <p>A system binder service can implement it to handle shell commands on ADB. For example,
- * the Job Scheduler service implements it to handle <code>adb shell cmd jobscheduler</code>.
+ * the Job Scheduler service implements it to handle {@code adb shell cmd jobscheduler}.
*
* <p>Commands are only executable by ADB shell; i.e. only {@link Process#SHELL_UID} and
* {@link Process#ROOT_UID} can call them.
@@ -1022,8 +1041,8 @@
* @param out standard output
* @param err standard error
* @param args arguments passed to the command. Can be empty. The first argument is typically
- * a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
- * @return the status code returned from the <code>cmd</code> command.
+ * a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
+ * @return the status code returned from the {@code cmd} command.
*
* @hide
*/
@@ -1051,7 +1070,7 @@
public final native void setExtension(@Nullable IBinder extension);
/**
- * Default implementation rewinds the parcels and calls onTransact. On
+ * Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
@@ -1083,7 +1102,7 @@
static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
- // Trying to send > 800k, this is way too much
+ // Trying to send > 800k, this is way too much.
StringBuilder sb = new StringBuilder();
sb.append(msg);
sb.append(": on ");
@@ -1107,7 +1126,7 @@
private static native long getNativeBBinderHolder();
/**
- * By default, we use the calling uid since we can always trust it.
+ * By default, we use the calling UID since we can always trust it.
*/
private static volatile BinderInternal.WorkSourceProvider sWorkSourceProvider =
(x) -> Binder.getCallingUid();
@@ -1122,6 +1141,7 @@
* <li>The callback is called on the critical path of the binder transaction so be careful about
* performance.
* <li>Never execute another binder transaction inside the callback.
+ *
* @hide
*/
public static void setWorkSourceProvider(BinderInternal.WorkSourceProvider workSourceProvider) {
@@ -1131,12 +1151,12 @@
sWorkSourceProvider = workSourceProvider;
}
- // Entry point from android_util_Binder.cpp's onTransact
+ // Entry point from android_util_Binder.cpp's onTransact.
@UnsupportedAppUsage
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
// At that point, the parcel request headers haven't been parsed so we do not know what
- // WorkSource the caller has set. Use calling uid as the default.
+ // {@link WorkSource} the caller has set. Use calling UID as the default.
final int callingUid = Binder.getCallingUid();
final long origWorkSource = ThreadLocalWorkSource.setUid(callingUid);
try {
@@ -1154,17 +1174,18 @@
observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null;
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
- // theoretically, we should call transact, which will call onTransact,
+ // Theoretically, we should call transact, which will call onTransact,
// but all that does is rewind it, and we just got these from an IPC,
// so we'll just call it directly.
boolean res;
// Log any exceptions as warnings, don't silently suppress them.
- // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
+ // If the call was {@link IBinder#FLAG_ONEWAY} then these exceptions
+ // disappear into the ether.
final boolean tracingEnabled = Binder.isTracingEnabled();
try {
final BinderCallHeavyHitterWatcher heavyHitterWatcher = sHeavyHitterWatcher;
if (heavyHitterWatcher != null) {
- // Notify the heavy hitter watcher, if it's enabled
+ // Notify the heavy hitter watcher, if it's enabled.
heavyHitterWatcher.onTransaction(callingUid, getClass(), code);
}
if (tracingEnabled) {
@@ -1197,7 +1218,7 @@
Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
}
} else {
- // Clear the parcel before writing the exception
+ // Clear the parcel before writing the exception.
reply.setDataSize(0);
reply.setDataPosition(0);
reply.writeException(e);
@@ -1209,7 +1230,7 @@
}
if (observer != null) {
// The parcel RPC headers have been called during onTransact so we can now access
- // the worksource uid from the parcel.
+ // the worksource UID from the parcel.
final int workSourceUid = sWorkSourceProvider.resolveWorkSourceUid(
data.readCallingWorkSourceUid());
observer.callEnded(callSession, data.dataSize(), reply.dataSize(), workSourceUid);
@@ -1220,9 +1241,9 @@
data.recycle();
// Just in case -- we are done with the IPC, so there should be no more strict
- // mode violations that have gathered for this thread. Either they have been
+ // mode violations that have gathered for this thread. Either they have been
// parceled and are now in transport off to the caller, or we are returning back
- // to the main transaction loop to wait for another incoming transaction. Either
+ // to the main transaction loop to wait for another incoming transaction. Either
// way, strict mode begone!
StrictMode.clearGatheredViolations();
return res;
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 92eb7a5..b2bbfd6 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -102,6 +102,18 @@
}
/**
+ * Constructs a {@link Bundle} containing a copy of {@code from}.
+ *
+ * @param from The bundle to be copied.
+ * @param deep Whether is a deep or shallow copy.
+ *
+ * @hide
+ */
+ Bundle(Bundle from, boolean deep) {
+ super(from, deep);
+ }
+
+ /**
* If {@link #mParcelledData} is not null, copy the HAS FDS bit from it because it's fast.
* Otherwise (if {@link #mParcelledData} is already null), leave {@link #FLAG_HAS_FDS_KNOWN}
* unset, because scanning a map is slower. We'll do it lazily in
@@ -167,13 +179,6 @@
}
/**
- * Constructs a Bundle without initializing it.
- */
- Bundle(boolean doInit) {
- super(doInit);
- }
-
- /**
* Make a Bundle for a single key/value pair.
*
* @hide
@@ -260,9 +265,7 @@
* are referenced as-is and not copied in any way.
*/
public Bundle deepCopy() {
- Bundle b = new Bundle(false);
- b.copyInternal(this, true);
- return b;
+ return new Bundle(this, /* deep */ true);
}
/**
@@ -324,28 +327,10 @@
*/
public boolean hasFileDescriptors() {
if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
- boolean fdFound = false; // keep going until we find one or run out of data
-
- if (mParcelledData != null) {
- if (mParcelledData.hasFileDescriptors()) {
- fdFound = true;
- }
- } else {
- // It's been unparcelled, so we need to walk the map
- for (int i=mMap.size()-1; i>=0; i--) {
- Object obj = mMap.valueAt(i);
- if (Parcel.hasFileDescriptors(obj)) {
- fdFound = true;
- break;
- }
- }
- }
-
- if (fdFound) {
- mFlags |= FLAG_HAS_FDS;
- } else {
- mFlags &= ~FLAG_HAS_FDS;
- }
+ Parcel p = mParcelledData;
+ mFlags = (Parcel.hasFileDescriptors((p != null) ? p : mMap))
+ ? mFlags | FLAG_HAS_FDS
+ : mFlags & ~FLAG_HAS_FDS;
mFlags |= FLAG_HAS_FDS_KNOWN;
}
return (mFlags & FLAG_HAS_FDS) != 0;
diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl
index d83d94a..15e3ce2 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -16,6 +16,8 @@
package android.os;
+import android.content.ComponentName;
+
/**
* Binder interface to query SystemConfig in the system server.
* {@hide}
@@ -44,5 +46,5 @@
/**
* @see SystemConfigManager#getEnabledComponentOverrides
*/
- List<String> getEnabledComponentOverrides(String packageName);
+ List<ComponentName> getEnabledComponentOverrides(String packageName);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 1468d9f..d1e6716 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -381,6 +381,8 @@
private static native void nativeUnmarshall(
long nativePtr, byte[] data, int offset, int length);
private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
+ private static native boolean nativeCompareDataInRange(
+ long ptrA, int offsetA, long ptrB, int offsetB, int length);
private static native void nativeAppendFrom(
long thisNativePtr, long otherNativePtr, int offset, int length);
@CriticalNative
@@ -678,11 +680,16 @@
}
/** @hide */
- public final int compareData(Parcel other) {
+ public int compareData(Parcel other) {
return nativeCompareData(mNativePtr, other.mNativePtr);
}
/** @hide */
+ public static boolean compareData(Parcel a, int offsetA, Parcel b, int offsetB, int length) {
+ return nativeCompareDataInRange(a.mNativePtr, offsetA, b.mNativePtr, offsetB, length);
+ }
+
+ /** @hide */
public final void setClassCookie(Class clz, Object cookie) {
if (mClassCookies == null) {
mClassCookies = new ArrayMap<>();
@@ -740,57 +747,70 @@
}
/**
- * Check if the object used in {@link #readValue(ClassLoader)} / {@link #writeValue(Object)}
- * has file descriptors.
+ * Check if the object has file descriptors.
+ *
+ * <p>Objects supported are {@link Parcel} and objects that can be passed to {@link
+ * #writeValue(Object)}}
*
* <p>For most cases, it will use the self-reported {@link Parcelable#describeContents()} method
* for that.
*
- * @throws IllegalArgumentException if you provide any object not supported by above methods.
- * Most notably, if you pass {@link Parcel}, this method will throw, for that check
- * {@link Parcel#hasFileDescriptors()}
+ * @throws IllegalArgumentException if you provide any object not supported by above methods
+ * (including if the unsupported object is inside a nested container).
*
* @hide
*/
public static boolean hasFileDescriptors(Object value) {
- if (value instanceof LazyValue) {
- return ((LazyValue) value).hasFileDescriptors();
- } else if (value instanceof Parcelable) {
- if ((((Parcelable) value).describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+ if (value instanceof Parcel) {
+ Parcel parcel = (Parcel) value;
+ if (parcel.hasFileDescriptors()) {
return true;
}
- } else if (value instanceof Parcelable[]) {
- Parcelable[] array = (Parcelable[]) value;
- for (int n = array.length - 1; n >= 0; n--) {
- Parcelable p = array[n];
- if (p != null && ((p.describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
+ } else if (value instanceof LazyValue) {
+ LazyValue lazy = (LazyValue) value;
+ if (lazy.hasFileDescriptors()) {
+ return true;
+ }
+ } else if (value instanceof Parcelable) {
+ Parcelable parcelable = (Parcelable) value;
+ if ((parcelable.describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
+ return true;
+ }
+ } else if (value instanceof ArrayMap<?, ?>) {
+ ArrayMap<?, ?> map = (ArrayMap<?, ?>) value;
+ for (int i = 0, n = map.size(); i < n; i++) {
+ if (hasFileDescriptors(map.keyAt(i))
+ || hasFileDescriptors(map.valueAt(i))) {
+ return true;
+ }
+ }
+ } else if (value instanceof Map<?, ?>) {
+ Map<?, ?> map = (Map<?, ?>) value;
+ for (Map.Entry<?, ?> entry : map.entrySet()) {
+ if (hasFileDescriptors(entry.getKey())
+ || hasFileDescriptors(entry.getValue())) {
+ return true;
+ }
+ }
+ } else if (value instanceof List<?>) {
+ List<?> list = (List<?>) value;
+ for (int i = 0, n = list.size(); i < n; i++) {
+ if (hasFileDescriptors(list.get(i))) {
return true;
}
}
} else if (value instanceof SparseArray<?>) {
SparseArray<?> array = (SparseArray<?>) value;
- for (int n = array.size() - 1; n >= 0; n--) {
- Object object = array.valueAt(n);
- if (object instanceof Parcelable) {
- Parcelable p = (Parcelable) object;
- if (p != null && (p.describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) {
- return true;
- }
+ for (int i = 0, n = array.size(); i < n; i++) {
+ if (hasFileDescriptors(array.valueAt(i))) {
+ return true;
}
}
- } else if (value instanceof ArrayList<?>) {
- ArrayList<?> array = (ArrayList<?>) value;
- for (int n = array.size() - 1; n >= 0; n--) {
- Object object = array.get(n);
- if (object instanceof Parcelable) {
- Parcelable p = (Parcelable) object;
- if (p != null && ((p.describeContents()
- & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) {
- return true;
- }
+ } else if (value instanceof Object[]) {
+ Object[] array = (Object[]) value;
+ for (int i = 0, n = array.length; i < n; i++) {
+ if (hasFileDescriptors(array[i])) {
+ return true;
}
}
} else {
@@ -2441,9 +2461,9 @@
writeByteArray(baos.toByteArray());
} catch (IOException ioe) {
- throw new RuntimeException("Parcelable encountered " +
- "IOException writing serializable object (name = " + name +
- ")", ioe);
+ throw new BadParcelableException("Parcelable encountered "
+ + "IOException writing serializable object (name = "
+ + name + ")", ioe);
}
}
@@ -3609,7 +3629,6 @@
private final int mType;
@Nullable private final ClassLoader mLoader;
@Nullable private Object mObject;
- @Nullable private volatile Parcel mValueParcel;
/**
* This goes from non-null to null once. Always check the nullability of this object before
@@ -3707,7 +3726,7 @@
return false;
}
// Finally we compare the payload.
- return getValueParcel(source).compareData(value.getValueParcel(otherSource)) == 0;
+ return Parcel.compareData(source, mPosition, otherSource, value.mPosition, mLength);
}
@Override
@@ -3715,17 +3734,6 @@
// Accessing mSource first to provide memory barrier for mObject
return Objects.hash(mSource == null, mObject, mLoader, mType, mLength);
}
-
- /** This extracts the parcel section responsible for the object and returns it. */
- private Parcel getValueParcel(Parcel source) {
- Parcel parcel = mValueParcel;
- if (parcel == null) {
- parcel = Parcel.obtain();
- parcel.appendFrom(source, mPosition, mLength);
- mValueParcel = parcel;
- }
- return parcel;
- }
}
/**
@@ -3823,7 +3831,7 @@
break;
case VAL_SERIALIZABLE:
- object = readSerializable(loader);
+ object = readSerializableInternal(loader, clazz);
break;
case VAL_PARCELABLEARRAY:
@@ -4149,12 +4157,37 @@
* wasn't found in the parcel.
*/
@Nullable
- public final Serializable readSerializable() {
- return readSerializable(null);
+ public Serializable readSerializable() {
+ return readSerializableInternal(/* loader */ null, /* clazz */ null);
}
+ /**
+ * Same as {@link #readSerializable()} but accepts {@code loader} parameter
+ * as the primary classLoader for resolving the Serializable class; and {@code clazz} parameter
+ * as the required type.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children class or there there was an error
+ * deserializing the object.
+ */
@Nullable
- private final Serializable readSerializable(@Nullable final ClassLoader loader) {
+ public <T extends Serializable> T readSerializable(@Nullable ClassLoader loader,
+ @NonNull Class<T> clazz) {
+ Objects.requireNonNull(clazz);
+ return readSerializableInternal(loader, clazz);
+ }
+
+ /**
+ * @param clazz The type of the serializable expected or {@code null} for performing no checks
+ */
+ @Nullable
+ private <T> T readSerializableInternal(@Nullable final ClassLoader loader,
+ @Nullable Class<T> clazz) {
+ if (clazz != null && !Serializable.class.isAssignableFrom(clazz)) {
+ throw new BadParcelableException("About to unparcel a serializable object "
+ + " but class required " + clazz.getName() + " is not Serializable");
+ }
+
String name = readString();
if (name == null) {
// For some reason we were unable to read the name of the Serializable (either there
@@ -4163,9 +4196,20 @@
return null;
}
- byte[] serializedData = createByteArray();
- ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
try {
+ if (clazz != null && loader != null) {
+ // If custom classloader is provided, resolve the type of serializable using the
+ // name, then check the type before deserialization. As in this case we can resolve
+ // the class the same way as ObjectInputStream, using the provided classloader.
+ Class<?> cl = Class.forName(name, false, loader);
+ if (!clazz.isAssignableFrom(cl)) {
+ throw new BadParcelableException("Serializable object "
+ + cl.getName() + " is not a subclass of required class "
+ + clazz.getName() + " provided in the parameter");
+ }
+ }
+ byte[] serializedData = createByteArray();
+ ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
ObjectInputStream ois = new ObjectInputStream(bais) {
@Override
protected Class<?> resolveClass(ObjectStreamClass osClass)
@@ -4173,22 +4217,31 @@
// try the custom classloader if provided
if (loader != null) {
Class<?> c = Class.forName(osClass.getName(), false, loader);
- if (c != null) {
- return c;
- }
+ return Objects.requireNonNull(c);
}
return super.resolveClass(osClass);
}
};
- return (Serializable) ois.readObject();
+ T object = (T) ois.readObject();
+ if (clazz != null && loader == null) {
+ // If custom classloader is not provided, check the type of the serializable using
+ // the deserialized object, as we cannot resolve the class the same way as
+ // ObjectInputStream.
+ if (!clazz.isAssignableFrom(object.getClass())) {
+ throw new BadParcelableException("Serializable object "
+ + object.getClass().getName() + " is not a subclass of required class "
+ + clazz.getName() + " provided in the parameter");
+ }
+ }
+ return object;
} catch (IOException ioe) {
- throw new RuntimeException("Parcelable encountered " +
- "IOException reading a Serializable object (name = " + name +
- ")", ioe);
+ throw new BadParcelableException("Parcelable encountered "
+ + "IOException reading a Serializable object (name = "
+ + name + ")", ioe);
} catch (ClassNotFoundException cnfe) {
- throw new RuntimeException("Parcelable encountered " +
- "ClassNotFoundException reading a Serializable object (name = "
- + name + ")", cnfe);
+ throw new BadParcelableException("Parcelable encountered "
+ + "ClassNotFoundException reading a Serializable object (name = "
+ + name + ")", cnfe);
}
}
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 7b55e710..f4edcb1 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -156,10 +156,15 @@
}
/**
- * Constructs a PersistableBundle without initializing it.
+ * Constructs a {@link PersistableBundle} containing a copy of {@code from}.
+ *
+ * @param from The bundle to be copied.
+ * @param deep Whether is a deep or shallow copy.
+ *
+ * @hide
*/
- PersistableBundle(boolean doInit) {
- super(doInit);
+ PersistableBundle(PersistableBundle from, boolean deep) {
+ super(from, deep);
}
/**
@@ -190,9 +195,7 @@
* are referenced as-is and not copied in any way.
*/
public PersistableBundle deepCopy() {
- PersistableBundle b = new PersistableBundle(false);
- b.copyInternal(this, true);
- return b;
+ return new PersistableBundle(this, /* deep */ true);
}
/**
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index a6316df..cde2063 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -17,10 +17,10 @@
import android.Manifest;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.content.ComponentName;
import android.content.Context;
import android.util.ArraySet;
import android.util.Log;
@@ -138,9 +138,9 @@
* @return The enabled component
* {@hide}
*/
- @SystemApi
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
- public List<String> getEnabledComponentOverrides(@NonNull String packageName) {
+ public List<ComponentName> getEnabledComponentOverrides(@NonNull String packageName) {
try {
return mInterface.getEnabledComponentOverrides(packageName);
} catch (RemoteException e) {
diff --git a/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
new file mode 100644
index 0000000..cb521c8
--- /dev/null
+++ b/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
@@ -0,0 +1,8 @@
+ewol@google.com
+hackbod@google.com
+jsharkey@google.com
+narayan@google.com
+patb@google.com
+svetoslavganov@google.com
+yamasani@google.com
+zhanghai@google.com
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 25e3a4f..8ac5c03 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -181,6 +181,22 @@
public static final String NAMESPACE_CONNECTIVITY = "connectivity";
/**
+ * Namespace for CaptivePortalLogin module.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_CAPTIVEPORTALLOGIN = "captive_portal_login";
+
+ /**
+ * Namespace for Tethering module.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_TETHERING = "tethering";
+
+ /**
* Namespace for content capture feature used by on-device machine intelligence
* to provide suggestions in a privacy-safe manner.
*
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index d39b56d..5b9d69c 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -191,20 +191,6 @@
public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100;
/**
- * Listen for changes of the network signal strengths (cellular) always reported from modem,
- * even in some situations such as the screen of the device is off.
- *
- * @see #onSignalStrengthsChanged
- *
- * @hide
- * @deprecated Use TelephonyManager#setSignalStrengthUpdateRequest
- * instead.
- */
- @Deprecated
- @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
- public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 0x00000200;
-
- /**
* Listen for changes to observed cell info.
*
* Listening to this event requires the {@link Manifest.permission#READ_PHONE_STATE} and
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index bedad73..cb1cff9 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1041,10 +1041,6 @@
eventList.add(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED);
}
- if ((eventMask & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
- eventList.add(TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED);
- }
-
if ((eventMask & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
eventList.add(TelephonyCallback.EVENT_CELL_INFO_CHANGED);
}
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index 5ec882c..475caa5 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -63,6 +63,8 @@
public int argi4;
public int argi5;
public int argi6;
+ public long argl1;
+ public long argl2;
private SomeArgs() {
/* do nothing - reduce visibility */
@@ -129,5 +131,7 @@
argi4 = 0;
argi5 = 0;
argi6 = 0;
+ argl1 = 0;
+ argl2 = 0;
}
}
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index be9aaaf..0d530f6 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -604,6 +604,25 @@
return thisParcel->compareData(*otherParcel);
}
+static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
+ jint thisOffset, jlong otherNativePtr,
+ jint otherOffset, jint length) {
+ Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
+ LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
+
+ Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
+ LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
+
+ int result;
+ status_t err =
+ thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ return JNI_FALSE;
+ }
+ return (result == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
jlong otherNativePtr, jint offset, jint length)
{
@@ -841,6 +860,7 @@
{"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
{"nativeUnmarshall", "(J[BII)V", (void*)android_os_Parcel_unmarshall},
{"nativeCompareData", "(JJ)I", (void*)android_os_Parcel_compareData},
+ {"nativeCompareDataInRange", "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
{"nativeAppendFrom", "(JJII)V", (void*)android_os_Parcel_appendFrom},
// @CriticalNative
{"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index fa1e9d4..a62ddd0 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -351,6 +351,7 @@
optional bool translucent = 30;
optional bool pip_auto_enter_enabled = 31;
optional bool in_size_compat_mode = 32;
+ optional float min_aspect_ratio = 33;
}
/* represents WindowToken */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1418dbe..d727a55 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -252,6 +252,11 @@
android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
<protected-broadcast
android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONF_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.action.TETHERING_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
@@ -2394,7 +2399,7 @@
<permission android:name="android.permission.READ_ACTIVE_EMERGENCY_SESSION"
android:protectionLevel="signature" />
- <!-- Allows listen permission to always reported signal strength.
+ <!-- Allows listen permission to always reported system signal strength.
@hide Used internally. -->
<permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH"
android:protectionLevel="signature" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7db2fe9..8496a47 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5054,4 +5054,7 @@
<!-- the number of the max cached processes in the system. -->
<integer name="config_customizedMaxCachedProcesses">32</integer>
+
+ <!-- Whether this device should support taking app snapshots on closure -->
+ <bool name="config_disableTaskSnapshots">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1c44526..d06dafe 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4403,7 +4403,7 @@
<java-symbol type="string" name="view_and_control_notification_title" />
<java-symbol type="string" name="view_and_control_notification_content" />
<java-symbol type="array" name="config_accessibility_allowed_install_source" />
-
+
<!-- Translation -->
<java-symbol type="string" name="ui_translation_accessibility_translated_text" />
<java-symbol type="string" name="ui_translation_accessibility_translation_finished" />
@@ -4430,4 +4430,7 @@
<java-symbol type="array" name="config_sharedLibrariesLoadedAfterApp" />
<java-symbol type="integer" name="config_customizedMaxCachedProcesses" />
+
+ <java-symbol type="bool" name="config_disableTaskSnapshots" />
+
</resources>
diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java
index ddd0070..09f4840 100644
--- a/core/tests/coretests/src/android/os/BundleTest.java
+++ b/core/tests/coretests/src/android/os/BundleTest.java
@@ -273,16 +273,21 @@
Parcelable p1 = new CustomParcelable(13, "Tiramisu");
Parcelable p2 = new CustomParcelable(13, "Tiramisu");
Bundle a = new Bundle();
- a.putParcelable("key", p1);
+ a.putParcelable("key1", p1);
a.readFromParcel(getParcelledBundle(a));
a.setClassLoader(getClass().getClassLoader());
Bundle b = new Bundle();
- b.putParcelable("key", p2);
+ // Adding extra element so that the position of the elements of interest in their respective
+ // source parcels are different so we can cover that case of Parcel.compareData(). We'll
+ // remove the element later so the map is equal.
+ b.putString("key0", "string");
+ b.putParcelable("key1", p2);
b.readFromParcel(getParcelledBundle(b));
b.setClassLoader(getClass().getClassLoader());
- // 2 lazy values with identical parcels inside
a.isEmpty();
b.isEmpty();
+ b.remove("key0");
+ // 2 lazy values with identical parcels inside
assertTrue(Bundle.kindofEquals(a, b));
}
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index dcb3e2f..fdd278b 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -17,6 +17,9 @@
package android.os;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
@@ -110,4 +113,130 @@
assertEquals(string, p.readString16());
}
}
+
+ @Test
+ public void testCompareDataInRange_whenSameData() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(13);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenSameDataWithBinder() {
+ Binder binder = new Binder();
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(13);
+ pA.writeStrongBinder(binder);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeStrongBinder(binder);
+ pB.writeString("Tiramisu");
+
+ assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenDifferentData() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(13);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ int iB = pB.dataPosition();
+ pB.writeString("Prefix");
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertFalse(Parcel.compareData(pA, iA, pB, iB, length));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenLimitOutOfBounds_throws() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+ pB.writeInt(-1);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA + length, pB, iB, 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA, pB, pB.dataSize(), 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA, pB, iB, length + 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA + length + 1, pB, iB, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Parcel.compareData(pA, iA, pB, iB + pB.dataSize() + 1, 0));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenLengthZero() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ int length = pA.dataPosition() - iA;
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertTrue(Parcel.compareData(pA, 0, pB, iB, 0));
+ assertTrue(Parcel.compareData(pA, iA + length, pB, iB, 0));
+ assertTrue(Parcel.compareData(pA, iA, pB, pB.dataSize(), 0));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenNegativeLength_throws() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, iA, pB, iB, -1));
+ }
+
+ @Test
+ public void testCompareDataInRange_whenNegativeOffset_throws() {
+ Parcel pA = Parcel.obtain();
+ int iA = pA.dataPosition();
+ pA.writeInt(12);
+ pA.writeString("Tiramisu");
+ Parcel pB = Parcel.obtain();
+ pB.writeString("Prefix");
+ int iB = pB.dataPosition();
+ pB.writeInt(13);
+ pB.writeString("Tiramisu");
+
+ assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0));
+ assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0));
+ }
}
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index c3b1cd74..b61ae12 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -1075,6 +1076,53 @@
ProcessInitializer.sInstance.setContext(context);
}
+ /**
+ * Returns true if HardwareRender will produce output.
+ *
+ * This value is global to the process and affects all uses of HardwareRenderer,
+ * including
+ * those created by the system such as those used by the View tree when using hardware
+ * accelerated rendering.
+ *
+ * Default is true in all production environments, but may be false in testing-focused
+ * emulators or if {@link #setDrawingEnabled(boolean)} is used.
+ *
+ * Backported from android T.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static boolean isDrawingEnabled() {
+ return nIsDrawingEnabled();
+ }
+
+ /**
+ * Toggles whether or not HardwareRenderer will produce drawing output globally in the current
+ * process.
+ *
+ * This applies to all HardwareRenderer instances, including those created by the platform such
+ * as those used by the system for hardware accelerated View rendering.
+ *
+ * The capability to disable drawing output is intended for test environments, primarily
+ * headless ones. By setting this to false, tests that launch activities or interact with Views
+ * can be quicker with less RAM usage by skipping the final step of View drawing. All View
+ * lifecycle events will occur as normal, only the final step of rendering on the GPU to the
+ * display will be skipped.
+ *
+ * This can be toggled on and off at will, so screenshot tests can also run in this same
+ * environment by toggling drawing back on and forcing a frame to be drawn such as by calling
+ * view#invalidate(). Once drawn and the screenshot captured, this can then be turned back off.
+ *
+ * Backported from android T.
+ *
+ * @hide
+ */
+ // TODO: Add link to androidx's Screenshot library for help with this
+ @UnsupportedAppUsage
+ public static void setDrawingEnabled(boolean drawingEnabled) {
+ nSetDrawingEnabled(drawingEnabled);
+ }
+
private static final class DestroyContextRunnable implements Runnable {
private final long mNativeInstance;
@@ -1393,4 +1441,8 @@
private static native void nInitDisplayInfo(int width, int height, float refreshRate,
int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos);
+
+ private static native void nSetDrawingEnabled(boolean drawingEnabled);
+
+ private static native boolean nIsDrawingEnabled();
}
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index b8fa55a..c804418 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -88,6 +88,8 @@
StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI;
+DrawingEnabled Properties::drawingEnabled = DrawingEnabled::NotInitialized;
+
bool Properties::load() {
bool prevDebugLayersUpdates = debugLayersUpdates;
bool prevDebugOverdraw = debugOverdraw;
@@ -141,6 +143,9 @@
enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, false);
+ // call isDrawingEnabled to force loading of the property
+ isDrawingEnabled();
+
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}
@@ -210,5 +215,19 @@
sRenderPipelineType = type;
}
+void Properties::setDrawingEnabled(bool newDrawingEnabled) {
+ drawingEnabled = newDrawingEnabled ? DrawingEnabled::On : DrawingEnabled::Off;
+ enableRTAnimations = newDrawingEnabled;
+}
+
+bool Properties::isDrawingEnabled() {
+ if (drawingEnabled == DrawingEnabled::NotInitialized) {
+ bool drawingEnabledProp = base::GetBoolProperty(PROPERTY_DRAWING_ENABLED, true);
+ drawingEnabled = drawingEnabledProp ? DrawingEnabled::On : DrawingEnabled::Off;
+ enableRTAnimations = drawingEnabledProp;
+ }
+ return drawingEnabled == DrawingEnabled::On;
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 7df6e2c..7f9782b 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -187,6 +187,12 @@
*/
#define PROPERTY_WEBVIEW_OVERLAYS_ENABLED "debug.hwui.webview_overlays_enabled"
+/**
+ * Property for globally GL drawing state. Can be overridden per process with
+ * setDrawingEnabled.
+ */
+#define PROPERTY_DRAWING_ENABLED "debug.hwui.drawing_enabled"
+
///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
@@ -208,6 +214,8 @@
UniformScale // Uniform scale stretch everywhere
};
+enum class DrawingEnabled { NotInitialized, On, Off };
+
/**
* Renderthread-only singleton which manages several static rendering properties. Most of these
* are driven by system properties which are queried once at initialization, and again if init()
@@ -301,6 +309,11 @@
stretchEffectBehavior = behavior;
}
+ // Represents if drawing is enabled. Should only be Off in headless testing environments
+ static DrawingEnabled drawingEnabled;
+ static bool isDrawingEnabled();
+ static void setDrawingEnabled(bool enable);
+
private:
static StretchEffectBehavior stretchEffectBehavior;
static ProfileType sProfileType;
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 54367b8..9e56584 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -817,6 +817,14 @@
DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
}
+static void android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv*, jclass, jboolean enabled) {
+ Properties::setDrawingEnabled(enabled);
+}
+
+static jboolean android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv*, jclass) {
+ return Properties::isDrawingEnabled();
+}
+
// ----------------------------------------------------------------------------
// HardwareRendererObserver
// ----------------------------------------------------------------------------
@@ -953,6 +961,9 @@
{"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
{"isWebViewOverlaysEnabled", "()Z",
(void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
+ {"nSetDrawingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDrawingEnabled},
+ {"nIsDrawingEnabled", "()Z", (void*)android_view_ThreadedRenderer_isDrawingEnabled},
+
};
static JavaVM* mJvm = nullptr;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2f3a509..bb0b135 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -256,7 +256,7 @@
}
void CanvasContext::allocateBuffers() {
- if (mNativeSurface) {
+ if (mNativeSurface && Properties::isDrawingEnabled()) {
ANativeWindow_tryAllocateBuffers(mNativeSurface->getNativeWindow());
}
}
@@ -480,7 +480,8 @@
SkRect dirty;
mDamageAccumulator.finish(&dirty);
- if (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw()) {
+ if (!Properties::isDrawingEnabled() ||
+ (dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw())) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
if (auto grContext = getGrContext()) {
// Submit to ensure that any texture uploads complete and Skia can
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6dbfcc3..2fed468 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -90,9 +90,17 @@
* and false otherwise (e.g. cache limits have been exceeded).
*/
bool pinImages(std::vector<SkImage*>& mutableImages) {
+ if (!Properties::isDrawingEnabled()) {
+ return true;
+ }
return mRenderPipeline->pinImages(mutableImages);
}
- bool pinImages(LsaVector<sk_sp<Bitmap>>& images) { return mRenderPipeline->pinImages(images); }
+ bool pinImages(LsaVector<sk_sp<Bitmap>>& images) {
+ if (!Properties::isDrawingEnabled()) {
+ return true;
+ }
+ return mRenderPipeline->pinImages(images);
+ }
/**
* Unpin any image that had be previously pinned to the GPU cache
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ed8cdb9..cf7039b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3255,6 +3255,54 @@
}
/**
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setHfpEnabled(boolean enable) {
+ AudioSystem.setParameters("hfp_enable=" + enable);
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setHfpVolume(int volume) {
+ AudioSystem.setParameters("hfp_volume=" + volume);
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setHfpSamplingRate(int rate) {
+ AudioSystem.setParameters("hfp_set_sampling_rate=" + rate);
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setBluetoothHeadsetProperties(@NonNull String name, boolean hasNrecEnabled,
+ boolean hasWbsEnabled) {
+ AudioSystem.setParameters("bt_headset_name=" + name
+ + ";bt_headset_nrec=" + (hasNrecEnabled ? "on" : "off")
+ + ";bt_wbs=" + (hasWbsEnabled ? "on" : "off"));
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
+ public void setA2dpSuspended(boolean enable) {
+ AudioSystem.setParameters("A2dpSuspended=" + enable);
+ }
+
+ /**
* Gets a variable number of parameter values from audio hardware.
*
* @param keys list of parameters
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 8b91536..de31a7f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -60,10 +60,10 @@
with {@link MediaExtractor}, {@link MediaSync}, {@link MediaMuxer}, {@link MediaCrypto},
{@link MediaDrm}, {@link Image}, {@link Surface}, and {@link AudioTrack}.)
<p>
- <center><object style="width: 540px; height: 205px;" type="image/svg+xml"
- data="../../../images/media/mediacodec_buffers.svg"><img
- src="../../../images/media/mediacodec_buffers.png" style="width: 540px; height: 205px"
- alt="MediaCodec buffer flow diagram"></object></center>
+ <center>
+ <img src="../../../images/media/mediacodec_buffers.svg" style="width: 540px; height: 205px"
+ alt="MediaCodec buffer flow diagram">
+ </center>
<p>
In broad terms, a codec processes input data to generate output data. It processes data
asynchronously and uses a set of input and output buffers. At a simplistic level, you request
@@ -268,10 +268,10 @@
Uninitialized, Configured and Error, whereas the Executing state conceptually progresses through
three sub-states: Flushed, Running and End-of-Stream.
<p>
- <center><object style="width: 516px; height: 353px;" type="image/svg+xml"
- data="../../../images/media/mediacodec_states.svg"><img
- src="../../../images/media/mediacodec_states.png" style="width: 519px; height: 356px"
- alt="MediaCodec state diagram"></object></center>
+ <center>
+ <img src="../../../images/media/mediacodec_states.svg" style="width: 519px; height: 356px"
+ alt="MediaCodec state diagram">
+ </center>
<p>
When you create a codec using one of the factory methods, the codec is in the Uninitialized
state. First, you need to configure it via {@link #configure configure(…)}, which brings
@@ -513,10 +513,10 @@
Similarly, upon an initial call to {@code start} the codec will move directly to the Running
sub-state and start passing available input buffers via the callback.
<p>
- <center><object style="width: 516px; height: 353px;" type="image/svg+xml"
- data="../../../images/media/mediacodec_async_states.svg"><img
- src="../../../images/media/mediacodec_async_states.png" style="width: 516px; height: 353px"
- alt="MediaCodec state diagram for asynchronous operation"></object></center>
+ <center>
+ <img src="../../../images/media/mediacodec_async_states.svg" style="width: 516px; height: 353px"
+ alt="MediaCodec state diagram for asynchronous operation">
+ </center>
<p>
MediaCodec is typically used like this in asynchronous mode:
<pre class=prettyprint>
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 86ed50b..72ee00f 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -102,6 +102,13 @@
mState = AudioPlaybackConfiguration.PLAYER_STATE_IDLE;
};
+ /** @hide */
+ public int getPlayerIId() {
+ synchronized (mLock) {
+ return mPlayerIId;
+ }
+ }
+
/**
* Call from derived class when instantiation / initialization is successful
*/
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2636ab2..8dcdc98 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -953,7 +953,7 @@
Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
android::content::AttributionSourceState attributionSource;
attributionSource.readFromParcel(parcel);
- sp<MediaPlayer> mp = new MediaPlayer(attributionSource);
+ sp<MediaPlayer> mp = sp<MediaPlayer>::make(attributionSource);
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
diff --git a/mms/OWNERS b/mms/OWNERS
index 7f05a2a..f56845e 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -3,16 +3,15 @@
tgunn@google.com
breadley@google.com
rgreenwalt@google.com
-amitmahajan@google.com
fionaxu@google.com
jackyu@google.com
jminjie@google.com
satk@google.com
shuoq@google.com
-nazaninb@google.com
sarahchin@google.com
xiaotonj@google.com
huiwang@google.com
jayachandranc@google.com
chinmayd@google.com
amruthr@google.com
+sasindran@google.com
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index 0d23f05..b9de5a3 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -2,17 +2,16 @@
tgunn@google.com
breadley@google.com
rgreenwalt@google.com
-amitmahajan@google.com
fionaxu@google.com
jackyu@google.com
jminjie@google.com
satk@google.com
shuoq@google.com
-nazaninb@google.com
sarahchin@google.com
xiaotonj@google.com
huiwang@google.com
jayachandranc@google.com
chinmayd@google.com
amruthr@google.com
+sasindran@google.com
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c1a0a9a..b4cafd8 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -93,9 +93,9 @@
final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
setTitle(Html.fromHtml(getString(
R.string.confirmation_title,
- getCallingAppName(),
- profileName,
- selectedDevice.getDisplayName()), 0));
+ Html.escapeHtml(getCallingAppName()),
+ Html.escapeHtml(selectedDevice.getDisplayName())), 0));
+
mPairButton = findViewById(R.id.button_pair);
mPairButton.setOnClickListener(v -> onDeviceConfirmed(getService().mSelectedDevice));
getService().mSelectedDevice = selectedDevice;
@@ -108,8 +108,8 @@
mPairButton = findViewById(R.id.button_pair);
mPairButton.setVisibility(View.GONE);
setTitle(Html.fromHtml(getString(R.string.chooser_title,
- profileName,
- getCallingAppName()), 0));
+ Html.escapeHtml(profileName),
+ Html.escapeHtml(getCallingAppName())), 0));
mDeviceListView = findViewById(R.id.device_list);
mDevicesAdapter = new DevicesAdapter();
mDeviceListView.setAdapter(mDevicesAdapter);
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS b/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
index 5b2e1e3..e3e28cb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/OWNERS
@@ -1,6 +1,3 @@
-# Default reviewers for this and subdirectories.
-takaoka@google.com
-yukawa@google.com
-wilsonwu@google.com
+# Bug component: 34867
-# Emergency approvers in case the above are not available
\ No newline at end of file
+include platform/frameworks/base:/services/core/java/com/android/server/inputmethod/OWNERS
\ No newline at end of file
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 54fb647..76b0b38 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -641,6 +641,15 @@
</intent-filter>
</receiver>
+ <receiver
+ android:name=".ProfcollectUploadReceiver"
+ android:exported="true"
+ android:permission="android.permission.TRIGGER_SHELL_PROFCOLLECT_UPLOAD" >
+ <intent-filter>
+ <action android:name="com.android.shell.action.PROFCOLLECT_UPLOAD" />
+ </intent-filter>
+ </receiver>
+
<service
android:name=".BugreportProgressService"
android:exported="false"/>
diff --git a/packages/Shell/res/xml/file_provider_paths.xml b/packages/Shell/res/xml/file_provider_paths.xml
index 225c757..85d7dd3 100644
--- a/packages/Shell/res/xml/file_provider_paths.xml
+++ b/packages/Shell/res/xml/file_provider_paths.xml
@@ -1,3 +1,4 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="bugreports" path="bugreports/" />
+ <root-path name="profcollect" path="/data/misc/profcollectd/report/" />
</paths>
diff --git a/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java b/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java
new file mode 100644
index 0000000..d2da724
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/ProfcollectUploadReceiver.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.shell;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.util.Log;
+
+import androidx.core.content.FileProvider;
+
+import com.android.internal.R;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * A proxy service that relays report upload requests to the uploader app, while translating
+ * the path to the report to a content URI owned by this service.
+ */
+public final class ProfcollectUploadReceiver extends BroadcastReceiver {
+ private static final String AUTHORITY = "com.android.shell";
+ private static final String PROFCOLLECT_DATA_ROOT = "/data/misc/profcollectd/report/";
+
+ private static final String LOG_TAG = "ProfcollectUploadReceiver";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(LOG_TAG, "Received upload intent");
+
+ String uploaderPkg = getUploaderPackageName(context);
+ String uploaderAction = getUploaderActionName(context);
+
+ try {
+ ApplicationInfo info = context.getPackageManager().getApplicationInfo(uploaderPkg,
+ 0);
+ if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ Log.e(LOG_TAG, "The profcollect uploader app " + uploaderPkg
+ + " must be a system application");
+ return;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOG_TAG, "Cannot find profcollect uploader app " + uploaderPkg);
+ return;
+ }
+
+ String filename = intent.getStringExtra("filename");
+ File reportFile = new File(PROFCOLLECT_DATA_ROOT + filename);
+ Uri reportUri = FileProvider.getUriForFile(context, AUTHORITY, reportFile);
+ Intent uploadIntent =
+ new Intent(uploaderAction)
+ .setPackage(uploaderPkg)
+ .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
+ .putExtra("EXTRA_PACKAGE_NAME", context.getPackageName())
+ .setData(reportUri)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ List<ResolveInfo> receivers =
+ context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
+ if (receivers == null || receivers.isEmpty()) {
+ Log.e(LOG_TAG, "No one to receive upload intent, abort upload.");
+ return;
+ }
+
+ context.grantUriPermission(uploaderPkg, reportUri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ context.sendBroadcast(uploadIntent);
+ }
+
+ private String getUploaderPackageName(Context context) {
+ return context.getResources().getString(
+ R.string.config_defaultProfcollectReportUploaderApp);
+ }
+
+ private String getUploaderActionName(Context context) {
+ return context.getResources().getString(
+ R.string.config_defaultProfcollectReportUploaderAction);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index 89786ee..a617850 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -139,7 +139,7 @@
+ " with ducking", e);
}
player.start();
- if (DEBUG) { Log.d(mTag, "player.start"); }
+ if (DEBUG) { Log.d(mTag, "player.start piid:" + player.getPlayerIId()); }
} catch (Exception e) {
if (player != null) {
player.release();
@@ -155,7 +155,13 @@
mPlayer = player;
}
if (mp != null) {
- if (DEBUG) { Log.d(mTag, "mPlayer.release"); }
+ if (DEBUG) {
+ Log.d(mTag, "mPlayer.pause+release piid:" + player.getPlayerIId());
+ }
+ mp.pause();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ie) { }
mp.release();
}
this.notify();
@@ -244,6 +250,10 @@
try {
mp.stop();
} catch (Exception e) { }
+ if (DEBUG) {
+ Log.i(mTag, "About to release MediaPlayer piid:"
+ + mp.getPlayerIId() + " due to notif cancelled");
+ }
mp.release();
synchronized(mQueueAudioFocusLock) {
if (mAudioManagerWithAudioFocus != null) {
@@ -284,7 +294,7 @@
public void onCompletion(MediaPlayer mp) {
synchronized(mQueueAudioFocusLock) {
if (mAudioManagerWithAudioFocus != null) {
- if (DEBUG) Log.d(mTag, "onCompletion() abandonning AudioFocus");
+ if (DEBUG) Log.d(mTag, "onCompletion() abandoning AudioFocus");
mAudioManagerWithAudioFocus.abandonAudioFocus(null);
mAudioManagerWithAudioFocus = null;
} else {
@@ -310,6 +320,10 @@
}
}
if (mp != null) {
+ if (DEBUG) {
+ Log.i("NotificationPlayer", "About to release MediaPlayer piid:"
+ + mp.getPlayerIId() + " due to onCompletion");
+ }
mp.release();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 541ee2c..4a75810 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -51,6 +51,7 @@
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -95,6 +96,7 @@
private final UiEventLogger mUiEventLogger;
private final InstanceIdSequence mInstanceIdSequence;
private final CustomTileStatePersister mCustomTileStatePersister;
+ private final FeatureFlags mFeatureFlags;
private final List<Callback> mCallbacks = new ArrayList<>();
private AutoTileManager mAutoTiles;
@@ -122,7 +124,8 @@
UiEventLogger uiEventLogger,
UserTracker userTracker,
SecureSettings secureSettings,
- CustomTileStatePersister customTileStatePersister
+ CustomTileStatePersister customTileStatePersister,
+ FeatureFlags featureFlags
) {
mIconController = iconController;
mContext = context;
@@ -144,6 +147,7 @@
mUserTracker = userTracker;
mSecureSettings = secureSettings;
mCustomTileStatePersister = customTileStatePersister;
+ mFeatureFlags = featureFlags;
mainHandler.post(() -> {
// This is technically a hack to avoid circular dependency of
@@ -265,7 +269,7 @@
if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {
newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);
}
- final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
+ final List<String> tileSpecs = loadTileSpecs(mContext, newValue, mFeatureFlags);
int currentUser = mUserTracker.getUserId();
if (currentUser != mCurrentUser) {
mUserContext = mUserTracker.getUserContext();
@@ -334,7 +338,7 @@
if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {
// If we didn't manage to create any tiles, set it to empty (default)
Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");
- changeTiles(currentSpecs, loadTileSpecs(mContext, ""));
+ changeTiles(currentSpecs, loadTileSpecs(mContext, "", mFeatureFlags));
} else {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onTilesChanged();
@@ -389,7 +393,7 @@
private void changeTileSpecs(Predicate<List<String>> changeFunction) {
final String setting = mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser);
- final List<String> tileSpecs = loadTileSpecs(mContext, setting);
+ final List<String> tileSpecs = loadTileSpecs(mContext, setting, mFeatureFlags);
if (changeFunction.test(tileSpecs)) {
saveTilesToSettings(tileSpecs);
}
@@ -478,7 +482,8 @@
throw new RuntimeException("Default factory didn't create view for " + tile.getTileSpec());
}
- protected static List<String> loadTileSpecs(Context context, String tileList) {
+ protected static List<String> loadTileSpecs(
+ Context context, String tileList, FeatureFlags featureFlags) {
final Resources res = context.getResources();
if (TextUtils.isEmpty(tileList)) {
@@ -511,6 +516,21 @@
}
}
}
+ if (featureFlags.isProviderModelSettingEnabled()) {
+ if (!tiles.contains("internet")) {
+ if (tiles.contains("wifi")) {
+ // Replace the WiFi with Internet, and remove the Cell
+ tiles.set(tiles.indexOf("wifi"), "internet");
+ tiles.remove("cell");
+ } else if (tiles.contains("cell")) {
+ // Replace the Cell with Internet
+ tiles.set(tiles.indexOf("cell"), "internet");
+ }
+ } else {
+ tiles.remove("wifi");
+ tiles.remove("cell");
+ }
+ }
return tiles;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 3c2f35b..f2832b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -41,6 +41,7 @@
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.util.leak.GarbageMonitor;
import java.util.ArrayList;
@@ -62,6 +63,7 @@
private final Executor mBgExecutor;
private final Context mContext;
private final UserTracker mUserTracker;
+ private final FeatureFlags mFeatureFlags;
private TileStateListener mListener;
private boolean mFinished;
@@ -71,12 +73,14 @@
Context context,
UserTracker userTracker,
@Main Executor mainExecutor,
- @Background Executor bgExecutor
+ @Background Executor bgExecutor,
+ FeatureFlags featureFlags
) {
mContext = context;
mMainExecutor = mainExecutor;
mBgExecutor = bgExecutor;
mUserTracker = userTracker;
+ mFeatureFlags = featureFlags;
}
public void setListener(TileStateListener listener) {
@@ -117,6 +121,10 @@
}
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
+ if (mFeatureFlags.isProviderModelSettingEnabled()) {
+ possibleTiles.remove("cell");
+ possibleTiles.remove("wifi");
+ }
for (String spec : possibleTiles) {
// Only add current and stock tiles that can be created from QSFactoryImpl.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 86c90c7..9eb95c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification.row;
-import android.annotation.ColorInt;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -28,15 +27,12 @@
import com.android.systemui.statusbar.notification.stack.ViewState;
public class FooterView extends StackScrollerDecorView {
- private final int mClearAllTopPadding;
private FooterViewButton mDismissButton;
private FooterViewButton mManageButton;
private boolean mShowHistory;
public FooterView(Context context, AttributeSet attrs) {
super(context, attrs);
- mClearAllTopPadding = context.getResources().getDimensionPixelSize(
- R.dimen.clear_all_padding_top);
}
@Override
@@ -55,11 +51,6 @@
mManageButton = findViewById(R.id.manage_text);
}
- public void setTextColor(@ColorInt int color) {
- mManageButton.setTextColor(color);
- mDismissButton.setTextColor(color);
- }
-
public void setManageButtonClickListener(OnClickListener listener) {
mManageButton.setOnClickListener(listener);
}
@@ -95,21 +86,25 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- int textColor = getResources().getColor(R.color.notif_pill_text);
- Resources.Theme theme = getContext().getTheme();
- mDismissButton.setBackground(
- getResources().getDrawable(R.drawable.notif_footer_btn_background, theme));
- mDismissButton.setTextColor(textColor);
- mManageButton.setBackground(
- getResources().getDrawable(R.drawable.notif_footer_btn_background, theme));
- mManageButton = findViewById(R.id.manage_text);
+ updateColors();
mDismissButton.setText(R.string.clear_all_notifications_text);
- mManageButton.setTextColor(textColor);
mDismissButton.setContentDescription(
mContext.getString(R.string.accessibility_clear_all));
showHistory(mShowHistory);
}
+ /**
+ * Update the text and background colors for the current color palette and night mode setting.
+ */
+ public void updateColors() {
+ Resources.Theme theme = mContext.getTheme();
+ int textColor = getResources().getColor(R.color.notif_pill_text, theme);
+ mDismissButton.setBackground(theme.getDrawable(R.drawable.notif_footer_btn_background));
+ mDismissButton.setTextColor(textColor);
+ mManageButton.setBackground(theme.getDrawable(R.drawable.notif_footer_btn_background));
+ mManageButton.setTextColor(textColor);
+ }
+
@Override
public ExpandableViewState createExpandableViewState() {
return new FooterViewState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 289c32f..0660daa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4231,7 +4231,7 @@
final @ColorInt int textColor =
Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
mSectionsManager.setHeaderForegroundColor(textColor);
- mFooterView.setTextColor(textColor);
+ mFooterView.updateColors();
mEmptyShadeView.setTextColor(textColor);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 3ee3e55..7f89b26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -139,7 +139,7 @@
() -> mock(AutoTileManager.class), mock(DumpManager.class),
mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
- mock(SecureSettings.class), mock(CustomTileStatePersister.class));
+ mock(SecureSettings.class), mock(CustomTileStatePersister.class), mFeatureFlags);
qs.setHost(host);
qs.setListening(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 9e97f80..4cbad5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -63,6 +63,7 @@
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -124,6 +125,8 @@
private SecureSettings mSecureSettings;
@Mock
private CustomTileStatePersister mCustomTileStatePersister;
+ @Mock
+ private FeatureFlags mFeatureFlags;
private Handler mHandler;
private TestableLooper mLooper;
@@ -137,9 +140,9 @@
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger, mUserTracker,
- mSecureSettings, mCustomTileStatePersister);
+ mSecureSettings, mCustomTileStatePersister, mFeatureFlags);
setUpTileFactory();
-
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
when(mSecureSettings.getStringForUser(eq(QSTileHost.TILES_SETTING), anyInt()))
.thenReturn("");
}
@@ -169,13 +172,13 @@
@Test
public void testLoadTileSpecs_emptySetting() {
- List<String> tiles = QSTileHost.loadTileSpecs(mContext, "");
+ List<String> tiles = QSTileHost.loadTileSpecs(mContext, "", mFeatureFlags);
assertFalse(tiles.isEmpty());
}
@Test
public void testLoadTileSpecs_nullSetting() {
- List<String> tiles = QSTileHost.loadTileSpecs(mContext, null);
+ List<String> tiles = QSTileHost.loadTileSpecs(mContext, null, mFeatureFlags);
assertFalse(tiles.isEmpty());
}
@@ -189,6 +192,55 @@
}
@Test
+ public void testRemoveWifiAndCellularWithoutInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2");
+
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testRemoveWifiAndCellularWithInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2, internet");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testRemoveWifiWithoutInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, wifi, spec2");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testRemoveCellWithInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, spec2, cell, internet");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testNoWifiNoCellularNoInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ }
+
+ @Test
public void testSpecWithInvalidDoesNotUseDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec2");
@@ -321,7 +373,7 @@
@Test
public void testLoadTileSpec_repeated() {
- List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2");
+ List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2", mFeatureFlags);
assertEquals(2, specs.size());
assertEquals("spec1", specs.get(0));
@@ -332,7 +384,7 @@
public void testLoadTileSpec_repeatedInDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1,spec1");
- List<String> specs = QSTileHost.loadTileSpecs(mContext, "default");
+ List<String> specs = QSTileHost.loadTileSpecs(mContext, "default", mFeatureFlags);
// Remove spurious tiles, like dbg:mem
specs.removeIf(spec -> !"spec1".equals(spec));
@@ -343,7 +395,7 @@
public void testLoadTileSpec_repeatedDefaultAndSetting() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1");
- List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1");
+ List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1", mFeatureFlags);
// Remove spurious tiles, like dbg:mem
specs.removeIf(spec -> !"spec1".equals(spec));
@@ -371,11 +423,12 @@
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger,
UiEventLogger uiEventLogger, UserTracker userTracker,
- SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister) {
+ SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister,
+ FeatureFlags featureFlags) {
super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
tunerService, autoTiles, dumpManager, broadcastDispatcher,
Optional.of(statusBar), qsLogger, uiEventLogger, userTracker, secureSettings,
- customTileStatePersister);
+ customTileStatePersister, featureFlags);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 4efcc5c..c5b6709 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -58,6 +58,7 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -108,6 +109,8 @@
private PackageManager mPackageManager;
@Mock
private UserTracker mUserTracker;
+ @Mock
+ private FeatureFlags mFeatureFlags;
@Captor
private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
@@ -133,12 +136,12 @@
}
}
).when(mQSTileHost).createTile(anyString());
-
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
FakeSystemClock clock = new FakeSystemClock();
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
mTileQueryHelper = new TileQueryHelper(
- mContext, mUserTracker, mMainExecutor, mBgExecutor);
+ mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
mTileQueryHelper.setListener(mListener);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 2b18404..01fa222 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -48,6 +48,7 @@
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -98,6 +99,8 @@
private UserTracker mUserTracker;
@Mock
private SecureSettings mSecureSettings;
+ @Mock
+ private FeatureFlags mFeatureFlags;
@Before
public void setUp() throws Exception {
@@ -119,7 +122,8 @@
mUiEventLogger,
mUserTracker,
mSecureSettings,
- mock(CustomTileStatePersister.class));
+ mock(CustomTileStatePersister.class),
+ mFeatureFlags);
mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher,
mUserTracker);
}
diff --git a/rs/jni/Android.bp b/rs/jni/Android.bp
new file mode 100644
index 0000000..9a6fa8e
--- /dev/null
+++ b/rs/jni/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2021 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+cc_library_shared {
+ name: "librs_jni",
+
+ srcs: ["android_renderscript_RenderScript.cpp"],
+
+ shared_libs: [
+ "libandroid",
+ "libandroid_runtime",
+ "libandroidfw",
+ "libRS",
+ "libcutils",
+ "libhwui",
+ "liblog",
+ "libutils",
+ "libui",
+ "libgui",
+ "libjnigraphics",
+ ],
+
+ header_libs: [
+ "jni_headers",
+ "libbase_headers",
+ ],
+
+ include_dirs: ["frameworks/rs"],
+
+ cflags: [
+ "-Wno-unused-parameter",
+ "-Wunused",
+ "-Wunreachable-code",
+ "-Wno-deprecated-declarations",
+ ],
+}
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
deleted file mode 100644
index 0caba42..0000000
--- a/rs/jni/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- android_renderscript_RenderScript.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid \
- libandroid_runtime \
- libandroidfw \
- libRS \
- libcutils \
- libhwui \
- liblog \
- libutils \
- libui \
- libgui \
- libjnigraphics
-
-LOCAL_HEADER_LIBRARIES := \
- jni_headers \
- libbase_headers
-
-LOCAL_C_INCLUDES += \
- frameworks/rs
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -Wno-deprecated-declarations
-
-LOCAL_MODULE:= librs_jni
-LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS:= notice
-LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE
-LOCAL_MODULE_TAGS := optional
-LOCAL_REQUIRED_MODULES := libRS
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index d6ee951..aeb8143 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -58,13 +58,13 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.Range;
-import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
@@ -1056,9 +1056,9 @@
public void systemReady() {
if (isNetdAlive()) {
- Slog.d(TAG, "IpSecService is ready");
+ Log.d(TAG, "IpSecService is ready");
} else {
- Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
+ Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
}
}
@@ -1332,7 +1332,7 @@
final INetd netd = mSrvConfig.getNetdInstance();
netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
NetdUtils.setInterfaceUp(netd, intfName);
});
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 3ea0ce1..c7e9068 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -59,9 +59,6 @@
import android.net.RouteInfo;
import android.net.TetherStatsParcel;
import android.net.UidRangeParcel;
-import android.net.shared.NetdUtils;
-import android.net.shared.RouteUtils;
-import android.net.shared.RouteUtils.ModifyOperation;
import android.net.util.NetdService;
import android.os.BatteryStats;
import android.os.Binder;
@@ -88,6 +85,8 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.HexDump;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.NetdUtils;
+import com.android.net.module.util.NetdUtils.ModifyOperation;
import com.google.android.collect.Maps;
@@ -831,13 +830,13 @@
@Override
public void addRoute(int netId, RouteInfo route) {
NetworkStack.checkNetworkStackPermission(mContext);
- RouteUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
+ NetdUtils.modifyRoute(mNetdService, ModifyOperation.ADD, netId, route);
}
@Override
public void removeRoute(int netId, RouteInfo route) {
NetworkStack.checkNetworkStackPermission(mContext);
- RouteUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
+ NetdUtils.modifyRoute(mNetdService, ModifyOperation.REMOVE, netId, route);
}
private ArrayList<String> readRouteList(String filename) {
@@ -1785,7 +1784,7 @@
public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
// modifyInterfaceInNetwork already check calling permission.
- RouteUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
+ NetdUtils.addRoutesToLocalNetwork(mNetdService, iface, routes);
}
@Override
@@ -1796,7 +1795,7 @@
@Override
public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
NetworkStack.checkNetworkStackPermission(mContext);
- return RouteUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
+ return NetdUtils.removeRoutesFromLocalNetwork(mNetdService, routes);
}
@Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 43bd9e7..c742708 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1164,17 +1164,6 @@
remove(r.binder);
}
}
- if (events.contains(
- TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
- updateReportSignalStrengthDecision(r.subId);
- try {
- if (mSignalStrength[r.phoneId] != null) {
- r.callback.onSignalStrengthsChanged(mSignalStrength[r.phoneId]);
- }
- } catch (RemoteException ex) {
- remove(r.binder);
- }
- }
if (validateEventAndUserLocked(
r, TelephonyCallback.EVENT_CELL_INFO_CHANGED)) {
try {
@@ -1353,27 +1342,6 @@
}
}
- private void updateReportSignalStrengthDecision(int subscriptionId) {
- synchronized (mRecords) {
- TelephonyManager telephonyManager = (TelephonyManager) mContext
- .getSystemService(Context.TELEPHONY_SERVICE);
- for (Record r : mRecords) {
- // If any of the system clients wants to always listen to signal strength,
- // we need to set it on.
- if (r.matchTelephonyCallbackEvent(
- TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
- telephonyManager.createForSubscriptionId(subscriptionId)
- .setAlwaysReportSignalStrength(true);
- return;
- }
- }
- // If none of the system clients wants to always listen to signal strength,
- // we need to set it off.
- telephonyManager.createForSubscriptionId(subscriptionId)
- .setAlwaysReportSignalStrength(false);
- }
- }
-
private String getCallIncomingNumber(Record record, int phoneId) {
// Only reveal the incoming number if the record has read call log permission.
return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : "";
@@ -1457,14 +1425,6 @@
}
mRecords.remove(i);
-
- // Every time a client that is registrating to always receive the signal
- // strength is removed from registry records, we need to check if
- // the signal strength decision needs to update on its slot.
- if (r.matchTelephonyCallbackEvent(
- TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
- updateReportSignalStrengthDecision(r.subId);
- }
return;
}
}
@@ -1696,10 +1656,8 @@
log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " ss=" + signalStrength);
}
- if ((r.matchTelephonyCallbackEvent(
+ if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)
- || r.matchTelephonyCallbackEvent(
- TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))
&& idMatch(r, subId, phoneId)) {
try {
if (DBG) {
@@ -3119,11 +3077,6 @@
android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
}
- if ((events.contains(TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null);
- }
-
if (isPrivilegedPhoneStatePermissionRequired(events)) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
@@ -3284,9 +3237,7 @@
}
}
- if (events.contains(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)
- || events.contains(
- TelephonyCallback.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
+ if (events.contains(TelephonyCallback.EVENT_SIGNAL_STRENGTHS_CHANGED)) {
try {
if (mSignalStrength[phoneId] != null) {
SignalStrength signalStrength = mSignalStrength[phoneId];
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 731f7fe..ab2147d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1834,6 +1834,11 @@
+ ", skipping since the account already exists");
return false;
}
+ if (accounts.accountsDb.findAllDeAccounts().size() > 100) {
+ Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
+ + ", skipping since more than 50 accounts on device exist");
+ return false;
+ }
long accountId = accounts.accountsDb.insertCeAccount(account, password);
if (accountId < 0) {
Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString()
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 243a336b..bf4ef48 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -126,6 +126,7 @@
import libcore.io.IoUtils;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -195,6 +196,7 @@
private final Context mContext;
private final ConnectivityManager mConnectivityManager;
+ private final AppOpsManager mAppOpsManager;
// The context is for specific user which is created from mUserId
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
@@ -407,6 +409,46 @@
public boolean isInterfacePresent(final Vpn vpn, final String iface) {
return vpn.jniCheck(iface) != 0;
}
+
+ /**
+ * @see ParcelFileDescriptor#adoptFd(int)
+ */
+ public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) {
+ return ParcelFileDescriptor.adoptFd(jniCreate(vpn, mtu));
+ }
+
+ /**
+ * Call native method to create the VPN interface and return the FileDescriptor of /dev/tun.
+ */
+ public int jniCreate(Vpn vpn, int mtu) {
+ return vpn.jniCreate(mtu);
+ }
+
+ /**
+ * Call native method to get the interface name of VPN.
+ */
+ public String jniGetName(Vpn vpn, int fd) {
+ return vpn.jniGetName(fd);
+ }
+
+ /**
+ * Call native method to set the VPN addresses and return the number of addresses.
+ */
+ public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) {
+ return vpn.jniSetAddresses(interfaze, addresses);
+ }
+
+ /**
+ * @see IoUtils#setBlocking(FileDescriptor, boolean)
+ */
+ public void setBlocking(FileDescriptor fd, boolean blocking) {
+ try {
+ IoUtils.setBlocking(fd, blocking);
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "Cannot set tunnel's fd as blocking=" + blocking, e);
+ }
+ }
}
public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
@@ -431,6 +473,7 @@
mVpnProfileStore = vpnProfileStore;
mContext = context;
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mDeps = deps;
mNms = netService;
@@ -826,7 +869,6 @@
VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage);
if (profile != null) {
startVpnProfilePrivileged(profile, alwaysOnPackage);
-
// If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was
// correctly parsed, and the VPN has started running in a different thread. The only
// other possibility is that the above call threw an exception, which will be
@@ -974,9 +1016,15 @@
} catch (Exception e) {
// ignore
}
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null);
mContext.unbindService(mConnection);
cleanupVpnStateLocked();
} else if (mVpnRunner != null) {
+ if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null);
+ }
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
}
@@ -1041,10 +1089,8 @@
return false;
}
- final AppOpsManager appOpMgr =
- (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
for (final String appOpStr : toChange) {
- appOpMgr.setMode(
+ mAppOpsManager.setMode(
appOpStr,
uid,
packageName,
@@ -1366,9 +1412,9 @@
Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids();
// Configure the interface. Abort if any of these steps fails.
- ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
+ final ParcelFileDescriptor tun = mDeps.adoptFd(this, config.mtu);
try {
- String interfaze = jniGetName(tun.getFd());
+ final String interfaze = mDeps.jniGetName(this, tun.getFd());
// TEMP use the old jni calls until there is support for netd address setting
StringBuilder builder = new StringBuilder();
@@ -1376,7 +1422,7 @@
builder.append(" ");
builder.append(address);
}
- if (jniSetAddresses(interfaze, builder.toString()) < 1) {
+ if (mDeps.jniSetAddresses(this, interfaze, builder.toString()) < 1) {
throw new IllegalArgumentException("At least one address must be specified");
}
Connection connection = new Connection();
@@ -1422,11 +1468,11 @@
jniReset(oldInterface);
}
- try {
- IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
- } catch (IOException e) {
- throw new IllegalStateException(
- "Cannot set tunnel's fd as blocking=" + config.blocking, e);
+ mDeps.setBlocking(tun.getFileDescriptor(), config.blocking);
+ // Record that the VPN connection is established by an app which uses VpnService API.
+ if (oldNetworkAgent != mNetworkAgent) {
+ mAppOpsManager.startOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null, null);
}
} catch (RuntimeException e) {
IoUtils.closeQuietly(tun);
@@ -1781,9 +1827,17 @@
synchronized (Vpn.this) {
if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
if (mConnection != null) {
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage,
+ null);
mContext.unbindService(mConnection);
cleanupVpnStateLocked();
} else if (mVpnRunner != null) {
+ if (!VpnConfig.LEGACY_VPN.equals(mPackage)) {
+ mAppOpsManager.finishOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage,
+ null);
+ }
// cleanupVpnStateLocked() is called from mVpnRunner.exit()
mVpnRunner.exit();
}
@@ -3254,8 +3308,7 @@
*
* @param packageName the package name of the app provisioning this profile
*/
- public synchronized void startVpnProfile(
- @NonNull String packageName) {
+ public synchronized void startVpnProfile(@NonNull String packageName) {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
@@ -3318,6 +3371,13 @@
Log.d(TAG, "Unknown VPN profile type: " + profile.type);
break;
}
+
+ // Record that the VPN connection is established by an app which uses VpnManager API.
+ if (!VpnConfig.LEGACY_VPN.equals(packageName)) {
+ mAppOpsManager.startOp(
+ AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null,
+ null);
+ }
} catch (GeneralSecurityException e) {
// Reset mConfig
mConfig = null;
diff --git a/services/core/java/com/android/server/health/OWNERS b/services/core/java/com/android/server/health/OWNERS
new file mode 100644
index 0000000..81522fc
--- /dev/null
+++ b/services/core/java/com/android/server/health/OWNERS
@@ -0,0 +1 @@
+file:platform/hardware/interfaces:/health/aidl/OWNERS
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index dc95533..3e52f5e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2582,14 +2582,12 @@
}
if (mCurToken != null) {
- try {
- if (DEBUG) {
- Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
- + mCurTokenDisplayId);
- }
- mIWindowManager.removeWindowToken(mCurToken, mCurTokenDisplayId);
- } catch (RemoteException e) {
+ if (DEBUG) {
+ Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
+ + mCurTokenDisplayId);
}
+ mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */,
+ false /* animateExit */, mCurTokenDisplayId);
// Set IME window status as invisible when unbind current method.
mImeWindowVis = 0;
mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS
index c09ade9..00cd700 100644
--- a/services/core/java/com/android/server/inputmethod/OWNERS
+++ b/services/core/java/com/android/server/inputmethod/OWNERS
@@ -5,3 +5,4 @@
tarandeep@google.com
lumark@google.com
roosa@google.com
+wilsonwu@google.com
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 3019439..5643873 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -215,7 +215,7 @@
private static final DefaultCrossProfileIntentFilter RECOGNIZE_SPEECH =
new DefaultCrossProfileIntentFilter.Builder(
DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
- /* flags= */0,
+ /* flags= */ ONLY_IF_NO_MATCH_FOUND,
/* letsPersonalDataIntoProfile= */ false)
.addAction(ACTION_RECOGNIZE_SPEECH)
.addCategory(Intent.CATEGORY_DEFAULT)
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index c2c35b7..08a7215 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -1255,6 +1255,9 @@
info.diskImagePath = ai.modulePath;
info.versionCode = ai.versionCode;
info.versionName = ai.versionName;
+ info.hasBootClassPathJars = ai.hasBootClassPathJars;
+ info.hasDex2OatBootClassPathJars = ai.hasDex2OatBootClassPathJars;
+ info.hasSystemServerClassPathJars = ai.hasSystemServerClassPathJars;
return info;
}
}
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index 8c1a90c..fc0ee23 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -1,7 +1,3 @@
include platform/frameworks/base:/core/java/android/permission/OWNERS
-per-file DefaultPermissionGrantPolicy.java = hackbod@android.com
-per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com
-per-file DefaultPermissionGrantPolicy.java = toddke@google.com
-per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
-per-file DefaultPermissionGrantPolicy.java = patb@google.com
+per-file DefaultPermissionGrantPolicy.java = file:platform/frameworks/base:/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index cda4806..94e551a 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -480,9 +480,10 @@
r.append("DUP:");
r.append(permissionInfo.name);
}
- if (permission.isRuntime() && (ownerChanged || wasNonRuntime)) {
- // If this is a runtime permission and the owner has changed, or this wasn't a runtime
- // permission, then permission state should be cleaned up
+ if ((permission.isInternal() && ownerChanged)
+ || (permission.isRuntime() && (ownerChanged || wasNonRuntime))) {
+ // If this is an internal/runtime permission and the owner has changed, or this wasn't a
+ // runtime permission, then permission state should be cleaned up.
permission.mDefinitionChanged = true;
}
if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 1133faa..7b12709 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1643,7 +1643,8 @@
isRolePermission = permission.isRole();
}
final boolean mayRevokeRolePermission = isRolePermission
- && mayManageRolePermission(callingUid);
+ // Allow ourselves to revoke role permissions due to definition changes.
+ && (callingUid == Process.myUid() || mayManageRolePermission(callingUid));
final boolean isRuntimePermission;
synchronized (mLock) {
@@ -2321,11 +2322,13 @@
for (int permNum = 0; permNum < numPermissions; permNum++) {
final String permName = permissionsToRevoke.get(permNum);
+ final boolean isInternalPermission;
synchronized (mLock) {
final Permission bp = mRegistry.getPermission(permName);
- if (bp == null || !bp.isRuntime()) {
+ if (bp == null || !(bp.isInternal() || bp.isRuntime())) {
continue;
}
+ isInternalPermission = bp.isInternal();
}
mPackageManagerInt.forEachPackage(pkg -> {
final String packageName = pkg.getPackageName();
@@ -2345,12 +2348,18 @@
if (permissionState == PackageManager.PERMISSION_GRANTED
&& (flags & flagMask) == 0) {
final int uid = UserHandle.getUid(userId, appId);
- EventLog.writeEvent(0x534e4554, "154505240", uid,
- "Revoking permission " + permName + " from package "
- + packageName + " due to definition change");
- EventLog.writeEvent(0x534e4554, "168319670", uid,
- "Revoking permission " + permName + " from package "
- + packageName + " due to definition change");
+ if (isInternalPermission) {
+ EventLog.writeEvent(0x534e4554, "195338390", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ } else {
+ EventLog.writeEvent(0x534e4554, "154505240", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ EventLog.writeEvent(0x534e4554, "168319670", uid,
+ "Revoking permission " + permName + " from package "
+ + packageName + " due to definition change");
+ }
Slog.e(TAG, "Revoking permission " + permName + " from package "
+ packageName + " due to definition change");
try {
diff --git a/services/core/java/com/android/server/security/OWNERS b/services/core/java/com/android/server/security/OWNERS
index 41070f3..5c2d5ba 100644
--- a/services/core/java/com/android/server/security/OWNERS
+++ b/services/core/java/com/android/server/security/OWNERS
@@ -1,4 +1,4 @@
# Bug component: 36824
-per-file AttestationVerificationService.java = file:/core/java/android/security/attestationverification/OWNERS
+per-file *AttestationVerification* = file:/core/java/android/security/attestationverification/OWNERS
per-file FileIntegrityService.java = victorhsieh@google.com
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 36a854e..2894708 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -2304,10 +2304,9 @@
public void requestChannelBrowsable(Uri channelUri, int userId)
throws RemoteException {
final String callingPackageName = getCallingPackageName();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, "requestChannelBrowsable");
final long identity = Binder.clearCallingIdentity();
- final int callingUid = Binder.getCallingUid();
- final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
- userId, "requestChannelBrowsable");
try {
Intent intent = new Intent(TvContract.ACTION_CHANNEL_BROWSABLE_REQUESTED);
List<ResolveInfo> list = getContext().getPackageManager()
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 7dec4e7..239a916 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -1663,8 +1663,6 @@
} /* validationStatusCallback */);
agent.register();
- agent.setUnderlyingNetworks(
- mUnderlying == null ? null : Collections.singletonList(mUnderlying.network));
agent.markConnected();
return agent;
@@ -2039,6 +2037,7 @@
"Unknown transport type or missing TransportInfo/NetworkSpecifier for"
+ " non-null underlying network");
}
+ builder.setUnderlyingNetworks(List.of(underlying.network));
} else {
Slog.wtf(
TAG,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 308df2f..d1f2177 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -140,6 +140,7 @@
import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.ActivityRecordProto.MIN_ASPECT_RATIO;
import static com.android.server.wm.ActivityRecordProto.NAME;
import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
@@ -656,6 +657,12 @@
boolean mLastImeShown;
/**
+ * When set to true, the IME insets will be frozen until the next app becomes IME input target.
+ * @see InsetsPolicy#adjustVisibilityForIme
+ */
+ boolean mImeInsetsFrozenUntilStartInput;
+
+ /**
* A flag to determine if this AR is in the process of closing or entering PIP. This is needed
* to help AR know that the app is in the process of closing but hasn't yet started closing on
* the WM side.
@@ -1343,13 +1350,7 @@
}
final Task rootTask = getRootTask();
- // If we reparent, make sure to remove ourselves from the old animation registry.
- if (mAnimatingActivityRegistry != null) {
- mAnimatingActivityRegistry.notifyFinished(this);
- }
- mAnimatingActivityRegistry = rootTask != null
- ? rootTask.getAnimatingActivityRegistry()
- : null;
+ updateAnimatingActivityRegistry();
if (task == mLastParentBeforePip) {
// Activity's reparented back from pip, clear the links once established
@@ -1363,6 +1364,7 @@
}
if (newTask != null && isState(RESUMED)) {
newTask.setResumedActivity(this, "onParentChanged");
+ mImeInsetsFrozenUntilStartInput = false;
}
if (rootTask != null && rootTask.topRunningActivity() == this) {
@@ -1373,6 +1375,20 @@
}
}
+ void updateAnimatingActivityRegistry() {
+ final Task rootTask = getRootTask();
+ final AnimatingActivityRegistry registry = rootTask != null
+ ? rootTask.getAnimatingActivityRegistry()
+ : null;
+
+ // If we reparent, make sure to remove ourselves from the old animation registry.
+ if (mAnimatingActivityRegistry != null && mAnimatingActivityRegistry != registry) {
+ mAnimatingActivityRegistry.notifyFinished(this);
+ }
+
+ mAnimatingActivityRegistry = registry;
+ }
+
/**
* Sets {@link #mLastParentBeforePip} to the current parent Task, it's caller's job to ensure
* {@link #getTask()} is set before this is called.
@@ -4759,6 +4775,7 @@
&& imeInputTarget.getWindow().mActivityRecord == this
&& mDisplayContent.mInputMethodWindow != null
&& mDisplayContent.mInputMethodWindow.isVisible();
+ mImeInsetsFrozenUntilStartInput = true;
}
final DisplayContent displayContent = getDisplayContent();
@@ -5877,6 +5894,14 @@
// closing activity having to wait until idle timeout to be stopped or destroyed if the
// next activity won't report idle (e.g. repeated view animation).
mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded();
+
+ // If the activity is visible, but no windows are eligible to start input, unfreeze
+ // to avoid permanently frozen IME insets.
+ if (mImeInsetsFrozenUntilStartInput && getWindow(
+ win -> WindowManager.LayoutParams.mayUseInputMethod(win.mAttrs.flags))
+ == null) {
+ mImeInsetsFrozenUntilStartInput = false;
+ }
}
}
@@ -7792,6 +7817,13 @@
}
}
+ @Override
+ void onResize() {
+ // Reset freezing IME insets flag when the activity resized.
+ mImeInsetsFrozenUntilStartInput = false;
+ super.onResize();
+ }
+
/** Returns true if the configuration is compatible with this activity. */
boolean isConfigurationCompatible(Configuration config) {
final int orientation = getRequestedOrientation();
@@ -8641,6 +8673,7 @@
}
proto.write(PIP_AUTO_ENTER_ENABLED, pictureInPictureArgs.isAutoEnterEnabled());
proto.write(IN_SIZE_COMPAT_MODE, inSizeCompatMode());
+ proto.write(MIN_ASPECT_RATIO, info.getMinAspectRatio());
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index dbc1116..9335846 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1165,10 +1165,10 @@
}
}
- WindowToken removeWindowToken(IBinder binder) {
+ WindowToken removeWindowToken(IBinder binder, boolean animateExit) {
final WindowToken token = mTokenMap.remove(binder);
if (token != null && token.asActivityRecord() == null) {
- token.setExiting();
+ token.setExiting(animateExit);
}
return token;
}
@@ -1252,7 +1252,7 @@
}
void removeAppToken(IBinder binder) {
- final WindowToken token = removeWindowToken(binder);
+ final WindowToken token = removeWindowToken(binder, true /* animateExit */);
if (token == null) {
Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
return;
@@ -3971,6 +3971,9 @@
void updateImeInputAndControlTarget(WindowState target) {
if (mImeInputTarget != target) {
ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
+ if (target != null && target.mActivityRecord != null) {
+ target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
+ }
setImeInputTarget(target);
updateImeControlTarget();
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index f2f1926..a8e1c1c 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -211,7 +211,7 @@
InsetsState getInsetsForWindow(WindowState target) {
final InsetsState originalState = mStateController.getInsetsForWindow(target);
final InsetsState state = adjustVisibilityForTransientTypes(originalState);
- return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
+ return adjustVisibilityForIme(target, state, state == originalState);
}
/**
@@ -241,16 +241,37 @@
return state;
}
- // Navigation bar insets is always visible to IME.
- private static InsetsState adjustVisibilityForIme(InsetsState originalState,
+ private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
boolean copyState) {
- final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
- if (originalNavSource != null && !originalNavSource.isVisible()) {
- final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
- final InsetsSource navSource = new InsetsSource(originalNavSource);
- navSource.setVisible(true);
- state.addSource(navSource);
- return state;
+ if (w.mIsImWindow) {
+ // Navigation bar insets is always visible to IME.
+ final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
+ if (originalNavSource != null && !originalNavSource.isVisible()) {
+ final InsetsState state = copyState ? new InsetsState(originalState)
+ : originalState;
+ final InsetsSource navSource = new InsetsSource(originalNavSource);
+ navSource.setVisible(true);
+ state.addSource(navSource);
+ return state;
+ }
+ } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
+ // During switching tasks with gestural navigation, if the IME is attached to
+ // one app window on that time, even the next app window is behind the IME window,
+ // conceptually the window should not receive the IME insets if the next window is
+ // not eligible IME requester and ready to show IME on top of it.
+ final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
+ final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
+
+ if (shouldImeAttachedToApp && originalImeSource != null) {
+ final boolean imeVisibility =
+ w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME);
+ final InsetsState state = copyState ? new InsetsState(originalState)
+ : originalState;
+ final InsetsSource imeSource = new InsetsSource(originalImeSource);
+ imeSource.setVisible(imeVisibility);
+ state.addSource(imeSource);
+ return state;
+ }
}
return originalState;
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index fe1020c..a7216da 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -190,8 +190,7 @@
if (keyguardChanged) {
// Irrelevant to AOD.
- dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */,
- false /* turningScreenOn */);
+ dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */);
mKeyguardGoingAway = false;
if (keyguardShowing) {
mDismissalRequested = false;
@@ -385,6 +384,8 @@
mService.continueWindowLayout();
}
}
+ dismissMultiWindowModeForTaskIfNeeded(topActivity != null
+ ? topActivity.getRootTask() : null);
}
/**
@@ -410,21 +411,6 @@
}
}
- /**
- * Called when somebody wants to turn screen on.
- */
- private void handleTurnScreenOn(int displayId) {
- if (displayId != DEFAULT_DISPLAY) {
- return;
- }
-
- mTaskSupervisor.wakeUp("handleTurnScreenOn");
- if (mKeyguardShowing && canDismissKeyguard()) {
- mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
- mDismissalRequested = true;
- }
- }
-
boolean isDisplayOccluded(int displayId) {
return getDisplayState(displayId).mOccluded;
}
@@ -438,11 +424,9 @@
}
private void dismissMultiWindowModeForTaskIfNeeded(
- @Nullable Task currentTaskControllingOcclusion, boolean turningScreenOn) {
- // If turningScreenOn is true, it means that the visibility state has changed from
- // currentTaskControllingOcclusion and we should update windowing mode.
+ @Nullable Task currentTaskControllingOcclusion) {
// TODO(b/113840485): Handle docked stack for individual display.
- if (!turningScreenOn && (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY))) {
+ if (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY)) {
return;
}
@@ -581,26 +565,17 @@
&& controller.mWindowManager.isKeyguardSecure(
controller.mService.getCurrentUserId());
- boolean occludingChange = false;
- boolean turningScreenOn = false;
if (mTopTurnScreenOnActivity != lastTurnScreenOnActivity
&& mTopTurnScreenOnActivity != null
&& !mService.mWindowManager.mPowerManager.isInteractive()
- && (mRequestDismissKeyguard || occludedByActivity
- || controller.canDismissKeyguard())) {
- turningScreenOn = true;
- controller.handleTurnScreenOn(mDisplayId);
+ && (mRequestDismissKeyguard || occludedByActivity)) {
+ controller.mTaskSupervisor.wakeUp("handleTurnScreenOn");
mTopTurnScreenOnActivity.setCurrentLaunchCanTurnScreenOn(false);
}
if (lastOccluded != mOccluded) {
- occludingChange = true;
controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
}
-
- if (occludingChange || turningScreenOn) {
- controller.dismissMultiWindowModeForTaskIfNeeded(task, turningScreenOn);
- }
}
/**
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 516be55..9634855 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1464,6 +1464,9 @@
adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
mRootWindowContainer.updateUIDsPresentOnDisplay();
+
+ // Ensure all animations are finished at same time in split-screen mode.
+ forAllActivities(ActivityRecord::updateAnimatingActivityRegistry);
}
void cleanUpActivityReferences(ActivityRecord r) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index e743710..a518222 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -118,6 +118,11 @@
*/
private final boolean mIsRunningOnWear;
+ /**
+ * Flag indicating if device configuration has disabled app snapshots.
+ */
+ private final boolean mConfigDisableTaskSnapshots;
+
TaskSnapshotController(WindowManagerService service) {
mService = service;
mPersister = new TaskSnapshotPersister(mService, Environment::getDataSystemCeDirectory);
@@ -131,6 +136,8 @@
PackageManager.FEATURE_WATCH);
mHighResTaskSnapshotScale = mService.mContext.getResources().getFloat(
com.android.internal.R.dimen.config_highResTaskSnapshotScale);
+ mConfigDisableTaskSnapshots = mService.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_disableTaskSnapshots);
}
void systemReady() {
@@ -488,7 +495,8 @@
}
boolean shouldDisableSnapshots() {
- return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT;
+ return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT
+ || mConfigDisableTaskSnapshots;
}
/**
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 194f48f..b54e8b7 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -66,8 +66,8 @@
}
@Override
- void setExiting() {
- super.setExiting();
+ void setExiting(boolean animateExit) {
+ super.setExiting(animateExit);
mDisplayContent.mWallpaperController.removeWallpaperToken(this);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 47087cf..4fac05c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -445,8 +445,21 @@
* @param removeWindows Whether to also remove the windows associated with the token.
* @param displayId The display to remove the token from.
*/
+ public final void removeWindowToken(android.os.IBinder token, boolean removeWindows,
+ int displayId) {
+ removeWindowToken(token, removeWindows, true /* animateExit */, displayId);
+ }
+
+ /**
+ * Removes a window token.
+ *
+ * @param token The toke to remove.
+ * @param removeWindows Whether to also remove the windows associated with the token.
+ * @param animateExit Whether to play the windows exit animation after the token removal.
+ * @param displayId The display to remove the token from.
+ */
public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows,
- int displayId);
+ boolean animateExit, int displayId);
/**
* Registers a listener to be notified about app transition events.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1ec9187..9caef70 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2816,6 +2816,31 @@
}
+ void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
+ int displayId) {
+ synchronized (mGlobalLock) {
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+
+ if (dc == null) {
+ ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
+ + " for non-exiting displayId=%d", binder, displayId);
+ return;
+ }
+ final WindowToken token = dc.removeWindowToken(binder, animateExit);
+ if (token == null) {
+ ProtoLog.w(WM_ERROR,
+ "removeWindowToken: Attempted to remove non-existing token: %s",
+ binder);
+ return;
+ }
+
+ if (removeWindows) {
+ token.removeAllWindowsIfPossible();
+ }
+ dc.getInputMonitor().updateInputWindowsLw(true /* force */);
+ }
+ }
+
@Override
public void removeWindowToken(IBinder binder, int displayId) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeWindowToken()")) {
@@ -2823,23 +2848,7 @@
}
final long origId = Binder.clearCallingIdentity();
try {
- synchronized (mGlobalLock) {
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
-
- if (dc == null) {
- ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
- + " for non-exiting displayId=%d", binder, displayId);
- return;
- }
- final WindowToken token = dc.removeWindowToken(binder);
- if (token == null) {
- ProtoLog.w(WM_ERROR,
- "removeWindowToken: Attempted to remove non-existing token: %s",
- binder);
- return;
- }
- dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
- }
+ removeWindowToken(binder, false /* removeWindows */, true /* animateExit */, displayId);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -7536,28 +7545,10 @@
}
@Override
- public void removeWindowToken(IBinder binder, boolean removeWindows, int displayId) {
- synchronized (mGlobalLock) {
- if (removeWindows) {
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc == null) {
- ProtoLog.w(WM_ERROR, "removeWindowToken: Attempted to remove token: %s"
- + " for non-exiting displayId=%d", binder, displayId);
- return;
- }
-
- final WindowToken token = dc.removeWindowToken(binder);
- if (token == null) {
- ProtoLog.w(WM_ERROR,
- "removeWindowToken: Attempted to remove non-existing token: %s",
- binder);
- return;
- }
-
- token.removeAllWindowsIfPossible();
- }
- WindowManagerService.this.removeWindowToken(binder, displayId);
- }
+ public void removeWindowToken(IBinder binder, boolean removeWindows, boolean animateExit,
+ int displayId) {
+ WindowManagerService.this.removeWindowToken(binder, removeWindows, animateExit,
+ displayId);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c3fc995..5e042ef 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2180,11 +2180,18 @@
}
}
- boolean onSetAppExiting() {
+ boolean onSetAppExiting(boolean animateExit) {
final DisplayContent displayContent = getDisplayContent();
boolean changed = false;
- if (isVisibleNow()) {
+ if (!animateExit) {
+ // Hide the window permanently if no window exist animation is performed, so we can
+ // avoid the window surface becoming visible again unexpectedly during the next
+ // relayout.
+ mPermanentlyHidden = true;
+ hide(false /* doAnimation */, false /* requestAnim */);
+ }
+ if (isVisibleNow() && animateExit) {
mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
if (mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onWindowTransition(this, TRANSIT_EXIT);
@@ -2197,7 +2204,7 @@
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState c = mChildren.get(i);
- changed |= c.onSetAppExiting();
+ changed |= c.onSetAppExiting(animateExit);
}
return changed;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index fbfa400..3cbc67c 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -24,6 +24,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -232,7 +233,7 @@
}
}
- void setExiting() {
+ void setExiting(boolean animateExit) {
if (isEmpty()) {
super.removeImmediately();
return;
@@ -247,11 +248,12 @@
final int count = mChildren.size();
boolean changed = false;
- final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
+ final boolean delayed = isAnimating(TRANSITION | PARENTS)
+ || (isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION) && animateExit);
for (int i = 0; i < count; i++) {
final WindowState win = mChildren.get(i);
- changed |= win.onSetAppExiting();
+ changed |= win.onSetAppExiting(animateExit);
}
final ActivityRecord app = asActivityRecord();
@@ -353,7 +355,7 @@
@Override
void removeImmediately() {
if (mDisplayContent != null) {
- mDisplayContent.removeWindowToken(token);
+ mDisplayContent.removeWindowToken(token, true /* animateExit */);
}
// Needs to occur after the token is removed from the display above to avoid attempt at
// duplicate removal of this window container from it's parent.
diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java
index 3a9b2dc..cb52e5f 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -19,6 +19,7 @@
import static java.util.stream.Collectors.toMap;
import android.Manifest;
+import android.content.ComponentName;
import android.content.Context;
import android.os.ISystemConfig;
import android.util.ArrayMap;
@@ -87,14 +88,14 @@
}
@Override
- public List<String> getEnabledComponentOverrides(String packageName) {
+ public List<ComponentName> getEnabledComponentOverrides(String packageName) {
ArrayMap<String, Boolean> systemComponents = SystemConfig.getInstance()
.getComponentsEnabledStates(packageName);
- List<String> enabledComponent = new ArrayList<>();
+ List<ComponentName> enabledComponent = new ArrayList<>();
if (systemComponents != null) {
for (Map.Entry<String, Boolean> entry : systemComponents.entrySet()) {
if (Boolean.TRUE.equals(entry.getValue())) {
- enabledComponent.add(entry.getKey());
+ enabledComponent.add(new ComponentName(packageName, entry.getKey()));
}
}
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 09a831e..0c3f1dd 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -41,6 +41,7 @@
sdk_version: "module_current",
min_sdk_version: "30",
libs: [
+ "framework-annotations-lib",
"unsupportedappusage",
"framework-wifi-util-lib",
"framework-connectivity",
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index fdf23d3..4fb801e 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -23,7 +23,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
@@ -32,8 +31,6 @@
import android.os.SystemProperties;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.Log;
@@ -45,9 +42,6 @@
import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
import com.android.server.wm.ActivityTaskManagerInternal;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -306,79 +300,27 @@
return;
}
- if (!getUploaderEnabledConfig(getContext())) {
- return;
- }
-
+ Context context = getContext();
new Thread(() -> {
try {
- Context context = getContext();
- final String uploaderPkg = getUploaderPackageName(context);
- final String uploaderAction = getUploaderActionName(context);
- String reportUuid = mIProfcollect.report();
+ // Prepare profile report
+ String reportName = mIProfcollect.report() + ".zip";
- final int profileId = getBBProfileId();
- String reportDir = "/data/user/" + profileId
- + "/com.google.android.apps.internal.betterbug/cache/";
- String reportPath = reportDir + reportUuid + ".zip";
-
- if (!Files.exists(Paths.get(reportDir))) {
- Log.i(LOG_TAG, "Destination directory does not exist, abort upload.");
+ if (!context.getResources().getBoolean(
+ R.bool.config_profcollectReportUploaderEnabled)) {
+ Log.i(LOG_TAG, "Upload is not enabled.");
return;
}
- Intent uploadIntent =
- new Intent(uploaderAction)
- .setPackage(uploaderPkg)
- .putExtra("EXTRA_DESTINATION", "PROFCOLLECT")
- .putExtra("EXTRA_PACKAGE_NAME", getContext().getPackageName())
- .putExtra("EXTRA_PROFILE_PATH", reportPath)
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-
- List<ResolveInfo> receivers =
- context.getPackageManager().queryBroadcastReceivers(uploadIntent, 0);
- if (receivers == null || receivers.isEmpty()) {
- Log.i(LOG_TAG, "No one to receive upload intent, abort upload.");
- return;
- }
- mIProfcollect.copy_report_to_bb(profileId, reportUuid);
- context.sendBroadcast(uploadIntent);
- mIProfcollect.delete_report(reportUuid);
+ // Upload the report
+ Intent intent = new Intent()
+ .setPackage("com.android.shell")
+ .setAction("com.android.shell.action.PROFCOLLECT_UPLOAD")
+ .putExtra("filename", reportName);
+ context.sendBroadcast(intent);
} catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage());
}
}).start();
}
-
- /**
- * Get BetterBug's profile ID. It is the work profile ID, if it exists. Otherwise the system
- * user ID.
- *
- * @return BetterBug's profile ID.
- */
- private int getBBProfileId() {
- UserManager userManager = UserManager.get(getContext());
- int[] profiles = userManager.getProfileIds(UserHandle.USER_SYSTEM, false);
- for (int p : profiles) {
- if (userManager.getUserInfo(p).isManagedProfile()) {
- return p;
- }
- }
- return UserHandle.USER_SYSTEM;
- }
-
- private boolean getUploaderEnabledConfig(Context context) {
- return context.getResources().getBoolean(
- R.bool.config_profcollectReportUploaderEnabled);
- }
-
- private String getUploaderPackageName(Context context) {
- return context.getResources().getString(
- R.string.config_defaultProfcollectReportUploaderApp);
- }
-
- private String getUploaderActionName(Context context) {
- return context.getResources().getString(
- R.string.config_defaultProfcollectReportUploaderAction);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/health/OWNERS b/services/tests/servicestests/src/com/android/server/health/OWNERS
new file mode 100644
index 0000000..81522fc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/health/OWNERS
@@ -0,0 +1 @@
+file:platform/hardware/interfaces:/health/aidl/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
index b4fbf5f..184ea52 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
@@ -110,18 +110,20 @@
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
- t.setVisibility(leash, true /* visible */).apply();
+ t.show(leash).apply();
}
int cookieIndex = -1;
if (trampoline.equals(taskInfo.baseActivity)) {
cookieIndex = 0;
} else if (main.equals(taskInfo.baseActivity)) {
cookieIndex = 1;
- mainLatch.countDown();
}
if (cookieIndex >= 0) {
appearedCookies[cookieIndex] = taskInfo.launchCookies.isEmpty()
? null : taskInfo.launchCookies.get(0);
+ if (cookieIndex == 1) {
+ mainLatch.countDown();
+ }
}
}
};
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 293e862a..6f04f17 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -39,6 +39,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -2816,6 +2817,73 @@
assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
}
+ @Test
+ public void testImeInsetsFrozenFlag_resetWhenReparented() {
+ final ActivityRecord activity = createActivityWithTask();
+ final WindowState app = createWindow(null, TYPE_APPLICATION, activity, "app");
+ final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
+ final Task newTask = new TaskBuilder(mSupervisor).build();
+ makeWindowVisible(app, imeWindow);
+ mDisplayContent.mInputMethodWindow = imeWindow;
+ mDisplayContent.setImeLayeringTarget(app);
+ mDisplayContent.setImeInputTarget(app);
+
+ // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
+ app.mActivityRecord.commitVisibility(false, false);
+ assertTrue(app.mActivityRecord.mLastImeShown);
+ assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+ // Expect IME insets frozen state will reset when the activity is reparent to the new task.
+ activity.setState(RESUMED, "test");
+ activity.reparent(newTask, 0 /* top */, "test");
+ assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+ }
+
+ @UseTestDisplay(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testImeInsetsFrozenFlag_resetWhenResized() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ makeWindowVisibleAndDrawn(app, mImeWindow);
+ mDisplayContent.setImeLayeringTarget(app);
+ mDisplayContent.setImeInputTarget(app);
+
+ // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
+ app.mActivityRecord.commitVisibility(false, false);
+ assertTrue(app.mActivityRecord.mLastImeShown);
+ assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+ // Expect IME insets frozen state will reset when the activity is reparent to the new task.
+ app.mActivityRecord.onResize();
+ assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+ }
+
+ @UseTestDisplay(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ makeWindowVisibleAndDrawn(app, mImeWindow);
+ mDisplayContent.setImeLayeringTarget(app);
+ mDisplayContent.setImeInputTarget(app);
+
+ // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
+ app.mActivityRecord.commitVisibility(false, false);
+ app.mActivityRecord.onWindowsGone();
+
+ assertTrue(app.mActivityRecord.mLastImeShown);
+ assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+ // Expect IME insets frozen state will reset when the activity has no IME focusable window.
+ app.mActivityRecord.forAllWindowsUnchecked(w -> {
+ w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
+ return true;
+ }, true);
+
+ app.mActivityRecord.commitVisibility(true, false);
+ app.mActivityRecord.onWindowsVisible();
+
+ assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+ }
+
private void assertHasStartingWindow(ActivityRecord atoken) {
assertNotNull(atoken.mStartingSurface);
assertNotNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index a8e1753..8e7ba4bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -258,6 +258,7 @@
final ActivityManagerInternal amInternal = mAmService.mInternal;
spyOn(amInternal);
doNothing().when(amInternal).trimApplications();
+ doNothing().when(amInternal).scheduleAppGcs();
doNothing().when(amInternal).updateCpuStats();
doNothing().when(amInternal).updateOomAdj();
doNothing().when(amInternal).updateBatteryStats(any(), anyInt(), anyInt(), anyBoolean());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 92b670e..d88ac25 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -891,6 +891,40 @@
assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
}
+ @Test
+ public void testAdjustImeInsetsVisibilityWhenSwitchingApps() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");
+ final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
+ spyOn(imeWindow);
+ doReturn(true).when(imeWindow).isVisible();
+ mDisplayContent.mInputMethodWindow = imeWindow;
+
+ final InsetsStateController controller = mDisplayContent.getInsetsStateController();
+ controller.getImeSourceProvider().setWindow(imeWindow, null, null);
+
+ // Simulate app requests IME with updating all windows Insets State when IME is above app.
+ mDisplayContent.setImeLayeringTarget(app);
+ mDisplayContent.setImeInputTarget(app);
+ assertTrue(mDisplayContent.shouldImeAttachedToApp());
+ controller.getImeSourceProvider().scheduleShowImePostLayout(app);
+ controller.getImeSourceProvider().getSource().setVisible(true);
+ controller.updateAboveInsetsState(imeWindow, false);
+
+ // Expect all app windows behind IME can receive IME insets visible.
+ assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+ assertTrue(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+
+ // Simulate app plays closing transition to app2.
+ app.mActivityRecord.commitVisibility(false, false);
+ assertTrue(app.mActivityRecord.mLastImeShown);
+ assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+ // Verify the IME insets is visible on app, but not for app2 during app task switching.
+ assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+ assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+ }
+
@UseTestDisplay(addWindows = { W_ACTIVITY })
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
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 d048f1842..589f913 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -24,6 +24,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -44,6 +45,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import java.util.function.BiFunction;
@@ -126,7 +128,7 @@
final WindowState window1 = createWindow(null, TYPE_TOAST, token, "window1");
final WindowState window2 = createWindow(null, TYPE_TOAST, token, "window2");
- mDisplayContent.removeWindowToken(token.token);
+ mDisplayContent.removeWindowToken(token.token, true /* animateExit */);
// Verify that the token is no longer mapped on the display
assertNull(mDisplayContent.getWindowToken(token.token));
// Verify that the token is still attached to its parent
@@ -261,4 +263,29 @@
assertNotNull(app.getFrozenInsetsState());
assertNull(mDisplayContent.mInputMethodWindow.getFrozenInsetsState());
}
+
+ @Test
+ public void testRemoveWindowToken_noAnimateExitWhenSet() {
+ final TestWindowToken token = createTestWindowToken(0, mDisplayContent);
+ final WindowState win = createWindow(null, TYPE_APPLICATION, token, "win");
+ makeWindowVisible(win);
+ assertTrue(win.isOnScreen());
+ spyOn(win);
+ spyOn(win.mWinAnimator);
+ spyOn(win.mToken);
+
+ // Invoking removeWindowToken with setting no window exit animation and not remove window
+ // immediately. verify the window will hide without applying exit animation.
+ mWm.removeWindowToken(win.mToken.token, false /* removeWindows */, false /* animateExit */,
+ mDisplayContent.mDisplayId);
+ verify(win).onSetAppExiting(Mockito.eq(false) /* animateExit */);
+ verify(win).hide(false /* doAnimation */, false /* requestAnim */);
+ assertFalse(win.isOnScreen());
+ verify(win.mWinAnimator, Mockito.never()).applyAnimationLocked(TRANSIT_EXIT, false);
+ assertTrue(win.mToken.hasChild());
+
+ // Even though the window is being removed afterwards, it won't apply exit animation.
+ win.removeIfPossible();
+ verify(win.mWinAnimator, Mockito.never()).applyAnimationLocked(TRANSIT_EXIT, false);
+ }
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 7f24c36..1579aaf 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -765,6 +765,8 @@
// send a sticky broadcast containing USB accessory handshake information
Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_HANDSHAKE)
+ .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+ | Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(UsbManager.EXTRA_ACCESSORY_UEVENT_TIME,
mAccessoryConnectionStartTime)
.putExtra(UsbManager.EXTRA_ACCESSORY_STRING_COUNT,
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 4df8a4b..4016ba7 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -1,6 +1,5 @@
set noparent
-amitmahajan@google.com
breadley@google.com
fionaxu@google.com
jackyu@google.com
@@ -8,10 +7,10 @@
tgunn@google.com
jminjie@google.com
shuoq@google.com
-nazaninb@google.com
sarahchin@google.com
xiaotonj@google.com
huiwang@google.com
jayachandranc@google.com
chinmayd@google.com
amruthr@google.com
+sasindran@google.com
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 73e6c76..d11c667 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1879,6 +1879,20 @@
"lte_plus_threshold_bandwidth_khz_int";
/**
+ * The combined channel bandwidth threshold (non-inclusive) in KHz required to display the
+ * NR advanced (i.e. 5G+) data icon. It is 0 by default, meaning minimum bandwidth check is
+ * not enabled. Other factors like bands or frequency can also determine whether the NR
+ * advanced data icon is shown or not.
+ *
+ * @see #KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY
+ * @see #KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT
+ *
+ * @hide
+ */
+ public static final String KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT =
+ "nr_advanced_threshold_bandwidth_khz_int";
+
+ /**
* The string is used to filter redundant string from PLMN Network Name that's supplied by
* specific carrier.
*
@@ -3543,6 +3557,17 @@
"nr_advanced_capable_pco_id_int";
/**
+ * Enabled NR advanced (i.e. 5G+) icon while roaming. The default value is {@code true}, meaming
+ * the same NR advanced logic used for home network will be used for roaming network as well.
+ * Set this to {@code false} will disable NR advanced icon while the device is roaming,
+ * regardless meeting NR advanced criteria or not.
+ *
+ * @hide
+ */
+ public static final String KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL =
+ "enable_nr_advanced_for_roaming_bool";
+
+ /**
* This configuration allows the framework to use user data communication to detect Idle state,
* and this is used on the 5G icon.
*
@@ -5560,6 +5585,7 @@
sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
+ sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0);
sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA});
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
@@ -5655,6 +5681,7 @@
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
sDefaults.putIntArray(KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY, new int[0]);
sDefaults.putInt(KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT, 0);
+ sDefaults.putBoolean(KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL, true);
sDefaults.putBoolean(KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, false);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index d250088..95448c7 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -242,6 +242,11 @@
}
/**
+ * The physical cell ID which differentiates cells using the same radio channel.
+ *
+ * In GERAN, this value is the BSIC. The range is [0-63].
+ * Reference: 3GPP TS 3.03 section 4.2.2.
+ *
* In UTRAN, this value is primary scrambling code. The range is [0, 511].
* Reference: 3GPP TS 25.213 section 5.2.2.
*
diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
index 41e24dd..2ff4ac5 100644
--- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
+++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
@@ -17,6 +17,8 @@
package android.telephony;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
@@ -66,10 +68,15 @@
private final IBinder mLiveToken;
private SignalStrengthUpdateRequest(
- @NonNull List<SignalThresholdInfo> signalThresholdInfos,
+ @Nullable List<SignalThresholdInfo> signalThresholdInfos,
boolean isReportingRequestedWhileIdle,
boolean isSystemThresholdReportingRequestedWhileIdle) {
- validate(signalThresholdInfos);
+ // System app (like Bluetooth) can specify the request to report system thresholds while
+ // device is idle (with permission protection). In this case, the request doesn't need to
+ // provide a non-empty list of SignalThresholdInfo which is only asked for public apps.
+ if (!isSystemThresholdReportingRequestedWhileIdle) {
+ validate(signalThresholdInfos);
+ }
mSignalThresholdInfos = signalThresholdInfos;
mIsReportingRequestedWhileIdle = isReportingRequestedWhileIdle;
@@ -128,13 +135,15 @@
/**
* Set the builder object if require reporting on the system thresholds when device is idle.
*
- * This can only used by the system caller.
+ * <p>This can only used by the system caller. Requires permission
+ * {@link android.Manifest.permission#LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH}.
*
* @param isSystemThresholdReportingRequestedWhileIdle true if request reporting on the
* system thresholds when device is idle
* @return the builder to facilitate the chaining
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
public @NonNull Builder setSystemThresholdReportingRequestedWhileIdle(
boolean isSystemThresholdReportingRequestedWhileIdle) {
mIsSystemThresholdReportingRequestedWhileIdle =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a1bed29..122f96d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -12425,26 +12425,6 @@
}
/**
- * Enable or disable signal strength changes from radio will always be reported in any
- * condition (e.g. screen is off). This is only allowed for System caller.
- *
- * @param isEnabled {@code true} for enabling; {@code false} for disabling.
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public void setAlwaysReportSignalStrength(boolean isEnabled) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.setAlwaysReportSignalStrength(getSubId(), isEnabled);
- }
- } catch (RemoteException ex) {
- Log.e(TAG, "setAlwaysReportSignalStrength RemoteException", ex);
- ex.rethrowAsRuntimeException();
- }
- }
-
- /**
* Get the most recently available signal strength information.
*
* Get the most recent SignalStrength information reported by the modem. Due
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index be1502a..1ef04be 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -147,7 +147,12 @@
}
// Possible values for authentication types.
- /** No authentication type. */
+ /**
+ * Authentication type is unknown.
+ * @hide
+ */
+ public static final int AUTH_TYPE_UNKNOWN = -1;
+ /** Authentication is not required. */
public static final int AUTH_TYPE_NONE = 0;
/** Authentication type for PAP. */
public static final int AUTH_TYPE_PAP = 1;
@@ -357,6 +362,7 @@
/** @hide */
@IntDef(prefix = { "AUTH_TYPE_" }, value = {
+ AUTH_TYPE_UNKNOWN,
AUTH_TYPE_NONE,
AUTH_TYPE_PAP,
AUTH_TYPE_CHAP,
@@ -498,7 +504,8 @@
private final String mOperatorNumeric;
private final int mProtocol;
private final int mRoamingProtocol;
- private final int mMtu;
+ private final int mMtuV4;
+ private final int mMtuV6;
private final boolean mCarrierEnabled;
@@ -522,13 +529,25 @@
private final int mSkip464Xlat;
/**
- * Returns the MTU size of the mobile interface to which the APN connected.
+ * Returns the MTU size of the IPv4 mobile interface to which the APN connected. Note this value
+ * is used only if MTU size is not provided in {@link DataCallResponse}.
*
* @return the MTU size of the APN
* @hide
*/
- public int getMtu() {
- return mMtu;
+ public int getMtuV4() {
+ return mMtuV4;
+ }
+
+ /**
+ * Returns the MTU size of the IPv6 mobile interface to which the APN connected. Note this value
+ * is used only if MTU size is not provided in {@link DataCallResponse}.
+ *
+ * @return the MTU size of the APN
+ * @hide
+ */
+ public int getMtuV6() {
+ return mMtuV6;
}
/**
@@ -879,13 +898,18 @@
this.mMmsProxyPort = builder.mMmsProxyPort;
this.mUser = builder.mUser;
this.mPassword = builder.mPassword;
- this.mAuthType = builder.mAuthType;
+ this.mAuthType = (builder.mAuthType != AUTH_TYPE_UNKNOWN)
+ ? builder.mAuthType
+ : TextUtils.isEmpty(builder.mUser)
+ ? AUTH_TYPE_NONE
+ : AUTH_TYPE_PAP_OR_CHAP;
this.mApnTypeBitmask = builder.mApnTypeBitmask;
this.mId = builder.mId;
this.mOperatorNumeric = builder.mOperatorNumeric;
this.mProtocol = builder.mProtocol;
this.mRoamingProtocol = builder.mRoamingProtocol;
- this.mMtu = builder.mMtu;
+ this.mMtuV4 = builder.mMtuV4;
+ this.mMtuV6 = builder.mMtuV6;
this.mCarrierEnabled = builder.mCarrierEnabled;
this.mNetworkTypeBitmask = builder.mNetworkTypeBitmask;
this.mProfileId = builder.mProfileId;
@@ -903,66 +927,6 @@
/**
* @hide
*/
- public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
- String apnName, String proxyAddress, int proxyPort, Uri mmsc,
- String mmsProxyAddress, int mmsProxyPort, String user, String password,
- int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
- boolean carrierEnabled, int networkTypeBitmask, int profileId,
- boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime, int mtu,
- int mvnoType, String mvnoMatchData, int apnSetId, int carrierId, int skip464xlat) {
- return new Builder()
- .setId(id)
- .setOperatorNumeric(operatorNumeric)
- .setEntryName(entryName)
- .setApnName(apnName)
- .setProxyAddress(proxyAddress)
- .setProxyPort(proxyPort)
- .setMmsc(mmsc)
- .setMmsProxyAddress(mmsProxyAddress)
- .setMmsProxyPort(mmsProxyPort)
- .setUser(user)
- .setPassword(password)
- .setAuthType(authType)
- .setApnTypeBitmask(mApnTypeBitmask)
- .setProtocol(protocol)
- .setRoamingProtocol(roamingProtocol)
- .setCarrierEnabled(carrierEnabled)
- .setNetworkTypeBitmask(networkTypeBitmask)
- .setProfileId(profileId)
- .setModemCognitive(modemCognitive)
- .setMaxConns(maxConns)
- .setWaitTime(waitTime)
- .setMaxConnsTime(maxConnsTime)
- .setMtu(mtu)
- .setMvnoType(mvnoType)
- .setMvnoMatchData(mvnoMatchData)
- .setApnSetId(apnSetId)
- .setCarrierId(carrierId)
- .setSkip464Xlat(skip464xlat)
- .buildWithoutCheck();
- }
-
- /**
- * @hide
- */
- public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
- String apnName, String proxyAddress, int proxyPort, Uri mmsc,
- String mmsProxyAddress, int mmsProxyPort, String user, String password,
- int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
- boolean carrierEnabled, int networkTypeBitmask, int profileId, boolean modemCognitive,
- int maxConns, int waitTime, int maxConnsTime, int mtu, int mvnoType,
- String mvnoMatchData) {
- return makeApnSetting(id, operatorNumeric, entryName, apnName, proxyAddress, proxyPort,
- mmsc, mmsProxyAddress, mmsProxyPort, user, password, authType, mApnTypeBitmask,
- protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, profileId,
- modemCognitive, maxConns, waitTime, maxConnsTime, mtu, mvnoType, mvnoMatchData,
- Carriers.NO_APN_SET_ID, TelephonyManager.UNKNOWN_CARRIER_ID,
- Carriers.SKIP_464XLAT_DEFAULT);
- }
-
- /**
- * @hide
- */
public static ApnSetting makeApnSetting(Cursor cursor) {
final int apnTypesBitmask = getApnTypesBitmaskFromString(
cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
@@ -975,272 +939,99 @@
ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
}
- return makeApnSetting(
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
- cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
- portFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
- UriFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
- cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
- portFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
- apnTypesBitmask,
- getProtocolIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
- getProtocolIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.ROAMING_PROTOCOL))),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.CARRIER_ENABLED)) == 1,
- networkTypeBitmask,
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MODEM_PERSIST)) == 1,
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNECTIONS)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME_RETRY)),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
- getMvnoTypeIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_TYPE))),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_MATCH_DATA)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)));
+ return new Builder()
+ .setId(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)))
+ .setOperatorNumeric(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)))
+ .setEntryName(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)))
+ .setApnName(cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)))
+ .setProxyAddress(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)))
+ .setProxyPort(portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))))
+ .setMmsc(UriFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))))
+ .setMmsProxyAddress(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)))
+ .setMmsProxyPort(portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))))
+ .setUser(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)))
+ .setPassword(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)))
+ .setAuthType(cursor.getInt(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)))
+ .setApnTypeBitmask(apnTypesBitmask)
+ .setProtocol(getProtocolIntFromString(
+ cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))))
+ .setRoamingProtocol(getProtocolIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL))))
+ .setCarrierEnabled(cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.CARRIER_ENABLED)) == 1)
+ .setNetworkTypeBitmask(networkTypeBitmask)
+ .setProfileId(cursor.getInt(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)))
+ .setModemCognitive(cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MODEM_PERSIST)) == 1)
+ .setMaxConns(cursor.getInt(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNECTIONS)))
+ .setWaitTime(cursor.getInt(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME_RETRY)))
+ .setMaxConnsTime(cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS)))
+ .setMtuV4(cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)))
+ .setMtuV6(UNSET_MTU) // TODO: Add corresponding support in telephony provider
+ .setMvnoType(getMvnoTypeIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE))))
+ .setMvnoMatchData(cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_MATCH_DATA)))
+ .setApnSetId(cursor.getInt(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)))
+ .setCarrierId(cursor.getInt(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)))
+ .setSkip464Xlat(cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)))
+ .buildWithoutCheck();
}
/**
* @hide
*/
public static ApnSetting makeApnSetting(ApnSetting apn) {
- return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
- apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
- apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
- apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
- apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
- apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId,
- apn.mCarrierId, apn.mSkip464Xlat);
- }
-
- /**
- * Creates an ApnSetting object from a string.
- *
- * @param data the string to read.
- *
- * The string must be in one of two formats (newlines added for clarity,
- * spaces are optional):
- *
- * v1 format:
- * <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...],
- *
- * v2 format:
- * [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
- *
- * v3 format:
- * [ApnSettingV3] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
- * <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
- * <mvnoType>, <mvnoMatchData>
- *
- * v4 format:
- * [ApnSettingV4] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
- * <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
- * <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>
- *
- * v5 format:
- * [ApnSettingV5] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
- * <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
- * <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>
- *
- * v6 format:
- * [ApnSettingV6] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
- * <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
- * <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>
- *
- * v7 format:
- * [ApnSettingV7] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
- * <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
- * <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
- * <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
- * <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>, <skip464xlat>
- *
- * Note that the strings generated by {@link #toString()} do not contain the username
- * and password and thus cannot be read by this method.
- *
- * This method may return {@code null} if the input string is invalid.
- *
- * @hide
- */
- public static ApnSetting fromString(String data) {
- if (data == null) return null;
-
- int version;
- // matches() operates on the whole string, so append .* to the regex.
- if (data.matches(V7_FORMAT_REGEX + ".*")) {
- version = 7;
- data = data.replaceFirst(V7_FORMAT_REGEX, "");
- } else if (data.matches(V6_FORMAT_REGEX + ".*")) {
- version = 6;
- data = data.replaceFirst(V6_FORMAT_REGEX, "");
- } else if (data.matches(V5_FORMAT_REGEX + ".*")) {
- version = 5;
- data = data.replaceFirst(V5_FORMAT_REGEX, "");
- } else if (data.matches(V4_FORMAT_REGEX + ".*")) {
- version = 4;
- data = data.replaceFirst(V4_FORMAT_REGEX, "");
- } else if (data.matches(V3_FORMAT_REGEX + ".*")) {
- version = 3;
- data = data.replaceFirst(V3_FORMAT_REGEX, "");
- } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
- version = 2;
- data = data.replaceFirst(V2_FORMAT_REGEX, "");
- } else {
- version = 1;
- }
-
- String[] a = data.split("\\s*,\\s*", -1);
- if (a.length < 14) {
- return null;
- }
-
- int authType;
- try {
- authType = Integer.parseInt(a[12]);
- } catch (NumberFormatException e) {
- authType = 0;
- }
-
- String[] typeArray;
- String protocol, roamingProtocol;
- boolean carrierEnabled;
- int bearerBitmask = 0;
- int networkTypeBitmask = 0;
- int profileId = 0;
- boolean modemCognitive = false;
- int maxConns = 0;
- int waitTime = 0;
- int maxConnsTime = 0;
- int mtu = UNSET_MTU;
- String mvnoType = "";
- String mvnoMatchData = "";
- int apnSetId = Carriers.NO_APN_SET_ID;
- int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
- int skip464xlat = Carriers.SKIP_464XLAT_DEFAULT;
- if (version == 1) {
- typeArray = new String[a.length - 13];
- System.arraycopy(a, 13, typeArray, 0, a.length - 13);
- protocol = PROTOCOL_INT_MAP.get(PROTOCOL_IP);
- roamingProtocol = PROTOCOL_INT_MAP.get(PROTOCOL_IP);
- carrierEnabled = true;
- } else {
- if (a.length < 18) {
- return null;
- }
- typeArray = a[13].split("\\s*\\|\\s*");
- protocol = a[14];
- roamingProtocol = a[15];
- carrierEnabled = Boolean.parseBoolean(a[16]);
-
- bearerBitmask = ServiceState.getBitmaskFromString(a[17]);
-
- if (a.length > 22) {
- modemCognitive = Boolean.parseBoolean(a[19]);
- try {
- profileId = Integer.parseInt(a[18]);
- maxConns = Integer.parseInt(a[20]);
- waitTime = Integer.parseInt(a[21]);
- maxConnsTime = Integer.parseInt(a[22]);
- } catch (NumberFormatException e) {
- }
- }
- if (a.length > 23) {
- try {
- mtu = Integer.parseInt(a[23]);
- } catch (NumberFormatException e) {
- }
- }
- if (a.length > 25) {
- mvnoType = a[24];
- mvnoMatchData = a[25];
- }
- if (a.length > 26) {
- networkTypeBitmask = ServiceState.getBitmaskFromString(a[26]);
- }
- if (a.length > 27) {
- apnSetId = Integer.parseInt(a[27]);
- }
- if (a.length > 28) {
- carrierId = Integer.parseInt(a[28]);
- }
- if (a.length > 29) {
- try {
- skip464xlat = Integer.parseInt(a[29]);
- } catch (NumberFormatException e) {
- }
- }
- }
-
- // If both bearerBitmask and networkTypeBitmask were specified, bearerBitmask would be
- // ignored.
- if (networkTypeBitmask == 0) {
- networkTypeBitmask =
- ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
- }
- return makeApnSetting(-1, a[10] + a[11], a[0], a[1], a[2],
- portFromString(a[3]), UriFromString(a[7]), a[8],
- portFromString(a[9]), a[4], a[5], authType,
- getApnTypesBitmaskFromString(TextUtils.join(",", typeArray)),
- getProtocolIntFromString(protocol), getProtocolIntFromString(roamingProtocol),
- carrierEnabled, networkTypeBitmask, profileId, modemCognitive, maxConns, waitTime,
- maxConnsTime, mtu, getMvnoTypeIntFromString(mvnoType), mvnoMatchData, apnSetId,
- carrierId, skip464xlat);
- }
-
- /**
- * Creates an array of ApnSetting objects from a string.
- *
- * @param data the string to read.
- *
- * Builds on top of the same format used by fromString, but allows for multiple entries
- * separated by ";".
- *
- * @hide
- */
- public static List<ApnSetting> arrayFromString(String data) {
- List<ApnSetting> retVal = new ArrayList<ApnSetting>();
- if (TextUtils.isEmpty(data)) {
- return retVal;
- }
- String[] apnStrings = data.split("\\s*;\\s*");
- for (String apnString : apnStrings) {
- ApnSetting apn = fromString(apnString);
- if (apn != null) {
- retVal.add(apn);
- }
- }
- return retVal;
+ return new Builder()
+ .setId(apn.mId)
+ .setOperatorNumeric(apn.mOperatorNumeric)
+ .setEntryName(apn.mEntryName)
+ .setApnName(apn.mApnName)
+ .setProxyAddress(apn.mProxyAddress)
+ .setProxyPort(apn.mProxyPort)
+ .setMmsc(apn.mMmsc)
+ .setMmsProxyAddress(apn.mMmsProxyAddress)
+ .setMmsProxyPort(apn.mMmsProxyPort)
+ .setUser(apn.mUser)
+ .setPassword(apn.mPassword)
+ .setAuthType(apn.mAuthType)
+ .setApnTypeBitmask(apn.mApnTypeBitmask)
+ .setProtocol(apn.mProtocol)
+ .setRoamingProtocol(apn.mRoamingProtocol)
+ .setCarrierEnabled(apn.mCarrierEnabled)
+ .setNetworkTypeBitmask(apn.mNetworkTypeBitmask)
+ .setProfileId(apn.mProfileId)
+ .setModemCognitive(apn.mPersistent)
+ .setMaxConns(apn.mMaxConns)
+ .setWaitTime(apn.mWaitTime)
+ .setMaxConnsTime(apn.mMaxConnsTime)
+ .setMtuV4(apn.mMtuV4)
+ .setMtuV6(apn.mMtuV6)
+ .setMvnoType(apn.mMvnoType)
+ .setMvnoMatchData(apn.mMvnoMatchData)
+ .setApnSetId(apn.mApnSetId)
+ .setCarrierId(apn.mCarrierId)
+ .setSkip464Xlat(apn.mSkip464Xlat)
+ .buildWithoutCheck();
}
/**
@@ -1251,7 +1042,7 @@
*/
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("[ApnSettingV7] ")
+ sb.append("[ApnSetting] ")
.append(mEntryName)
.append(", ").append(mId)
.append(", ").append(mOperatorNumeric)
@@ -1272,7 +1063,8 @@
sb.append(", ").append(mMaxConns);
sb.append(", ").append(mWaitTime);
sb.append(", ").append(mMaxConnsTime);
- sb.append(", ").append(mMtu);
+ sb.append(", ").append(mMtuV4);
+ sb.append(", ").append(mMtuV6);
sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType));
sb.append(", ").append(mMvnoMatchData);
sb.append(", ").append(mPermanentFailed);
@@ -1343,9 +1135,9 @@
public int hashCode() {
return Objects.hash(mApnName, mProxyAddress, mProxyPort, mMmsc, mMmsProxyAddress,
mMmsProxyPort, mUser, mPassword, mAuthType, mApnTypeBitmask, mId, mOperatorNumeric,
- mProtocol, mRoamingProtocol, mMtu, mCarrierEnabled, mNetworkTypeBitmask, mProfileId,
- mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType, mMvnoMatchData,
- mApnSetId, mCarrierId, mSkip464Xlat);
+ mProtocol, mRoamingProtocol, mMtuV4, mMtuV6, mCarrierEnabled, mNetworkTypeBitmask,
+ mProfileId, mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType,
+ mMvnoMatchData, mApnSetId, mCarrierId, mSkip464Xlat);
}
@Override
@@ -1357,33 +1149,34 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mId, other.mId)
- && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
- && Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxyAddress, other.mProxyAddress)
- && Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
- && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
- && Objects.equals(mProxyPort, other.mProxyPort)
- && Objects.equals(mUser, other.mUser)
- && Objects.equals(mPassword, other.mPassword)
- && Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
- && Objects.equals(mProtocol, other.mProtocol)
- && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(mProfileId, other.mProfileId)
- && Objects.equals(mPersistent, other.mPersistent)
- && Objects.equals(mMaxConns, other.mMaxConns)
- && Objects.equals(mWaitTime, other.mWaitTime)
- && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
- && Objects.equals(mMtu, other.mMtu)
- && Objects.equals(mMvnoType, other.mMvnoType)
- && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
- && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId)
- && Objects.equals(mCarrierId, other.mCarrierId)
- && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+ && Objects.equals(mId, other.mId)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort, other.mProxyPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+ && Objects.equals(mProtocol, other.mProtocol)
+ && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mPersistent, other.mPersistent)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtuV4, other.mMtuV4)
+ && Objects.equals(mMtuV6, other.mMtuV6)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(mApnSetId, other.mApnSetId)
+ && Objects.equals(mCarrierId, other.mCarrierId)
+ && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
}
/**
@@ -1406,31 +1199,32 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
- && Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxyAddress, other.mProxyAddress)
- && Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
- && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
- && Objects.equals(mProxyPort, other.mProxyPort)
- && Objects.equals(mUser, other.mUser)
- && Objects.equals(mPassword, other.mPassword)
- && Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
- && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
- && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
- && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(mProfileId, other.mProfileId)
- && Objects.equals(mPersistent, other.mPersistent)
- && Objects.equals(mMaxConns, other.mMaxConns)
- && Objects.equals(mWaitTime, other.mWaitTime)
- && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
- && Objects.equals(mMtu, other.mMtu)
- && Objects.equals(mMvnoType, other.mMvnoType)
- && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
- && Objects.equals(mApnSetId, other.mApnSetId)
- && Objects.equals(mCarrierId, other.mCarrierId)
- && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort, other.mProxyPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+ && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
+ && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mPersistent, other.mPersistent)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtuV4, other.mMtuV4)
+ && Objects.equals(mMtuV6, other.mMtuV6)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(mApnSetId, other.mApnSetId)
+ && Objects.equals(mCarrierId, other.mCarrierId)
+ && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
}
/**
@@ -1732,7 +1526,7 @@
dest.writeString(mApnName);
dest.writeString(mProxyAddress);
dest.writeInt(mProxyPort);
- dest.writeValue(mMmsc);
+ dest.writeParcelable(mMmsc, flags);
dest.writeString(mMmsProxyAddress);
dest.writeInt(mMmsProxyPort);
dest.writeString(mUser);
@@ -1742,40 +1536,53 @@
dest.writeInt(mProtocol);
dest.writeInt(mRoamingProtocol);
dest.writeBoolean(mCarrierEnabled);
- dest.writeInt(mMvnoType);
dest.writeInt(mNetworkTypeBitmask);
+ dest.writeInt(mProfileId);
+ dest.writeBoolean(mPersistent);
+ dest.writeInt(mMaxConns);
+ dest.writeInt(mWaitTime);
+ dest.writeInt(mMaxConnsTime);
+ dest.writeInt(mMtuV4);
+ dest.writeInt(mMtuV6);
+ dest.writeInt(mMvnoType);
+ dest.writeString(mMvnoMatchData);
dest.writeInt(mApnSetId);
dest.writeInt(mCarrierId);
dest.writeInt(mSkip464Xlat);
}
private static ApnSetting readFromParcel(Parcel in) {
- final int id = in.readInt();
- final String operatorNumeric = in.readString();
- final String entryName = in.readString();
- final String apnName = in.readString();
- final String proxy = in.readString();
- final int port = in.readInt();
- final Uri mmsc = (Uri) in.readValue(Uri.class.getClassLoader());
- final String mmsProxy = in.readString();
- final int mmsPort = in.readInt();
- final String user = in.readString();
- final String password = in.readString();
- final int authType = in.readInt();
- final int apnTypesBitmask = in.readInt();
- final int protocol = in.readInt();
- final int roamingProtocol = in.readInt();
- final boolean carrierEnabled = in.readBoolean();
- final int mvnoType = in.readInt();
- final int networkTypeBitmask = in.readInt();
- final int apnSetId = in.readInt();
- final int carrierId = in.readInt();
- final int skip464xlat = in.readInt();
-
- return makeApnSetting(id, operatorNumeric, entryName, apnName,
- proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
- protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
- 0, 0, 0, 0, mvnoType, null, apnSetId, carrierId, skip464xlat);
+ return new Builder()
+ .setId(in.readInt())
+ .setOperatorNumeric(in.readString())
+ .setEntryName(in.readString())
+ .setApnName(in.readString())
+ .setProxyAddress(in.readString())
+ .setProxyPort(in.readInt())
+ .setMmsc(in.readParcelable(Uri.class.getClassLoader()))
+ .setMmsProxyAddress(in.readString())
+ .setMmsProxyPort(in.readInt())
+ .setUser(in.readString())
+ .setPassword(in.readString())
+ .setAuthType(in.readInt())
+ .setApnTypeBitmask(in.readInt())
+ .setProtocol(in.readInt())
+ .setRoamingProtocol(in.readInt())
+ .setCarrierEnabled(in.readBoolean())
+ .setNetworkTypeBitmask(in.readInt())
+ .setProfileId(in.readInt())
+ .setModemCognitive(in.readBoolean())
+ .setMaxConns(in.readInt())
+ .setWaitTime(in.readInt())
+ .setMaxConnsTime(in.readInt())
+ .setMtuV4(in.readInt())
+ .setMtuV6(in.readInt())
+ .setMvnoType(in.readInt())
+ .setMvnoMatchData(in.readString())
+ .setApnSetId(in.readInt())
+ .setCarrierId(in.readInt())
+ .setSkip464Xlat(in.readInt())
+ .buildWithoutCheck();
}
public static final @android.annotation.NonNull Parcelable.Creator<ApnSetting> CREATOR =
@@ -1834,13 +1641,14 @@
private int mMmsProxyPort = UNSPECIFIED_INT;
private String mUser;
private String mPassword;
- private int mAuthType;
+ private int mAuthType = AUTH_TYPE_UNKNOWN;
private int mApnTypeBitmask;
private int mId;
private String mOperatorNumeric;
private int mProtocol = UNSPECIFIED_INT;
private int mRoamingProtocol = UNSPECIFIED_INT;
- private int mMtu;
+ private int mMtuV4;
+ private int mMtuV6;
private int mNetworkTypeBitmask;
private boolean mCarrierEnabled;
private int mProfileId;
@@ -1863,20 +1671,34 @@
* Sets the unique database id for this entry.
*
* @param id the unique database id to set for this entry
+ * @hide
*/
- private Builder setId(int id) {
+ public Builder setId(int id) {
this.mId = id;
return this;
}
/**
- * Set the MTU size of the mobile interface to which the APN connected.
+ * Set the MTU size of the IPv4 mobile interface to which the APN connected. Note this value
+ * is used only if MTU size is not provided in {@link DataCallResponse}.
*
- * @param mtu the MTU size to set for the APN
+ * @param mtuV4 the MTU size to set for the APN
* @hide
*/
- public Builder setMtu(int mtu) {
- this.mMtu = mtu;
+ public Builder setMtuV4(int mtuV4) {
+ this.mMtuV4 = mtuV4;
+ return this;
+ }
+
+ /**
+ * Set the MTU size of the IPv6 mobile interface to which the APN connected. Note this value
+ * is used only if MTU size is not provided in {@link DataCallResponse}.
+ *
+ * @param mtuV6 the MTU size to set for the APN
+ * @hide
+ */
+ public Builder setMtuV6(int mtuV6) {
+ this.mMtuV6 = mtuV6;
return this;
}
@@ -2237,7 +2059,8 @@
| TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
| TYPE_XCAP | TYPE_VSIM | TYPE_BIP | TYPE_ENTERPRISE)) == 0
|| TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
- return null;
+ throw new IllegalArgumentException("mApName=" + mApnName + ", mEntryName="
+ + mEntryName + ", mApnTypeBitmask=" + mApnTypeBitmask);
}
return new ApnSetting(this);
}
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index f2a1249..93903d2 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -25,13 +25,11 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.ApnType;
+import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
import android.telephony.data.ApnSetting.AuthType;
import android.text.TextUtils;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.util.TelephonyUtils;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -62,152 +60,141 @@
/** 3GPP2 type data profile */
public static final int TYPE_3GPP2 = 2;
- private final int mProfileId;
+ private final @Type int mType;
- private final String mApn;
+ private final @Nullable ApnSetting mApnSetting;
- @ProtocolType
- private final int mProtocolType;
-
- @AuthType
- private final int mAuthType;
-
- private final String mUserName;
-
- private final String mPassword;
-
- @Type
- private final int mType;
-
- private final int mMaxConnectionsTime;
-
- private final int mMaxConnections;
-
- private final int mWaitTime;
-
- private final boolean mEnabled;
-
- @ApnType
- private final int mSupportedApnTypesBitmask;
-
- @ProtocolType
- private final int mRoamingProtocolType;
-
- @NetworkTypeBitMask
- private final int mBearerBitmask;
-
- private final int mMtuV4;
-
- private final int mMtuV6;
-
- private final boolean mPersistent;
+ private final @Nullable TrafficDescriptor mTrafficDescriptor;
private final boolean mPreferred;
- /** @hide */
- private DataProfile(int profileId, String apn, @ProtocolType int protocolType, int authType,
- String userName, String password, int type, int maxConnectionsTime,
- int maxConnections, int waitTime, boolean enabled,
- @ApnType int supportedApnTypesBitmask, @ProtocolType int roamingProtocolType,
- @NetworkTypeBitMask int bearerBitmask, int mtuV4, int mtuV6, boolean persistent,
- boolean preferred) {
- this.mProfileId = profileId;
- this.mApn = apn;
- this.mProtocolType = protocolType;
- if (authType == -1) {
- authType = TextUtils.isEmpty(userName) ? RILConstants.SETUP_DATA_AUTH_NONE
- : RILConstants.SETUP_DATA_AUTH_PAP_CHAP;
+ private DataProfile(@NonNull Builder builder) {
+ mApnSetting = builder.mApnSetting;
+ mTrafficDescriptor = builder.mTrafficDescriptor;
+ mPreferred = builder.mPreferred;
+
+ if (builder.mType != -1) {
+ mType = builder.mType;
+ } else if (mApnSetting != null) {
+ int networkTypes = mApnSetting.getNetworkTypeBitmask();
+
+ if (networkTypes == 0) {
+ mType = DataProfile.TYPE_COMMON;
+ } else if ((networkTypes & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP2)
+ == networkTypes) {
+ mType = DataProfile.TYPE_3GPP2;
+ } else if ((networkTypes & TelephonyManager.NETWORK_STANDARDS_FAMILY_BITMASK_3GPP)
+ == networkTypes) {
+ mType = DataProfile.TYPE_3GPP;
+ } else {
+ mType = DataProfile.TYPE_COMMON;
+ }
+ } else {
+ mType = DataProfile.TYPE_COMMON;
}
- this.mAuthType = authType;
- this.mUserName = userName;
- this.mPassword = password;
- this.mType = type;
- this.mMaxConnectionsTime = maxConnectionsTime;
- this.mMaxConnections = maxConnections;
- this.mWaitTime = waitTime;
- this.mEnabled = enabled;
- this.mSupportedApnTypesBitmask = supportedApnTypesBitmask;
- this.mRoamingProtocolType = roamingProtocolType;
- this.mBearerBitmask = bearerBitmask;
- this.mMtuV4 = mtuV4;
- this.mMtuV6 = mtuV6;
- this.mPersistent = persistent;
- this.mPreferred = preferred;
}
private DataProfile(Parcel source) {
- mProfileId = source.readInt();
- mApn = source.readString();
- mProtocolType = source.readInt();
- mAuthType = source.readInt();
- mUserName = source.readString();
- mPassword = source.readString();
mType = source.readInt();
- mMaxConnectionsTime = source.readInt();
- mMaxConnections = source.readInt();
- mWaitTime = source.readInt();
- mEnabled = source.readBoolean();
- mSupportedApnTypesBitmask = source.readInt();
- mRoamingProtocolType = source.readInt();
- mBearerBitmask = source.readInt();
- mMtuV4 = source.readInt();
- mMtuV6 = source.readInt();
- mPersistent = source.readBoolean();
+ mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader());
+ mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader());
mPreferred = source.readBoolean();
}
/**
* @return Id of the data profile.
*/
- public int getProfileId() { return mProfileId; }
+ public int getProfileId() {
+ if (mApnSetting != null) {
+ return mApnSetting.getProfileId();
+ }
+ return 0;
+ }
/**
* @return The APN (Access Point Name) to establish data connection. This is a string
* specifically defined by the carrier.
*/
@NonNull
- public String getApn() { return mApn; }
+ public String getApn() {
+ if (mApnSetting != null) {
+ return TextUtils.emptyIfNull(mApnSetting.getApnName());
+ }
+ return "";
+ }
/**
* @return The connection protocol defined in 3GPP TS 27.007 section 10.1.1.
*/
- public @ProtocolType int getProtocolType() { return mProtocolType; }
+ public @ProtocolType int getProtocolType() {
+ if (mApnSetting != null) {
+ return mApnSetting.getProtocol();
+ }
+ return ApnSetting.PROTOCOL_IP;
+ }
/**
* @return The authentication protocol used for this PDP context.
*/
- public @AuthType int getAuthType() { return mAuthType; }
+ public @AuthType int getAuthType() {
+ if (mApnSetting != null) {
+ return mApnSetting.getAuthType();
+ }
+ return ApnSetting.AUTH_TYPE_NONE;
+ }
/**
* @return The username for APN. Can be null.
*/
@Nullable
- public String getUserName() { return mUserName; }
+ public String getUserName() {
+ if (mApnSetting != null) {
+ return mApnSetting.getUser();
+ }
+ return null;
+ }
/**
* @return The password for APN. Can be null.
*/
@Nullable
- public String getPassword() { return mPassword; }
+ public String getPassword() {
+ if (mApnSetting != null) {
+ return mApnSetting.getPassword();
+ }
+ return null;
+ }
/**
* @return The profile type.
*/
- public @Type int getType() { return mType; }
+ public @Type int getType() {
+ return mType;
+ }
/**
* @return The period in seconds to limit the maximum connections.
*
* @hide
*/
- public int getMaxConnectionsTime() { return mMaxConnectionsTime; }
+ public int getMaxConnectionsTime() {
+ if (mApnSetting != null) {
+ return mApnSetting.getMaxConnsTime();
+ }
+ return 0;
+ }
/**
* @return The maximum connections allowed.
*
* @hide
*/
- public int getMaxConnections() { return mMaxConnections; }
+ public int getMaxConnections() {
+ if (mApnSetting != null) {
+ return mApnSetting.getMaxConns();
+ }
+ return 0;
+ }
/**
* @return The required wait time in seconds after a successful UE initiated disconnect of a
@@ -216,57 +203,117 @@
*
* @hide
*/
- public int getWaitTime() { return mWaitTime; }
+ public int getWaitTime() {
+ if (mApnSetting != null) {
+ return mApnSetting.getWaitTime();
+ }
+ return 0;
+ }
/**
* @return True if the profile is enabled.
*/
- public boolean isEnabled() { return mEnabled; }
+ public boolean isEnabled() {
+ if (mApnSetting != null) {
+ return mApnSetting.isEnabled();
+ }
+ return false;
+ }
/**
* @return The supported APN types bitmask.
*/
- public @ApnType int getSupportedApnTypesBitmask() { return mSupportedApnTypesBitmask; }
+ public @ApnType int getSupportedApnTypesBitmask() {
+ if (mApnSetting != null) {
+ return mApnSetting.getApnTypeBitmask();
+ }
+ return ApnSetting.TYPE_NONE;
+ }
/**
* @return The connection protocol on roaming network defined in 3GPP TS 27.007 section 10.1.1.
*/
- public @ProtocolType int getRoamingProtocolType() { return mRoamingProtocolType; }
+ public @ProtocolType int getRoamingProtocolType() {
+ if (mApnSetting != null) {
+ return mApnSetting.getRoamingProtocol();
+ }
+ return ApnSetting.PROTOCOL_IP;
+ }
/**
* @return The bearer bitmask indicating the applicable networks for this data profile.
*/
- public @NetworkTypeBitMask int getBearerBitmask() { return mBearerBitmask; }
+ public @NetworkTypeBitMask int getBearerBitmask() {
+ if (mApnSetting != null) {
+ return mApnSetting.getNetworkTypeBitmask();
+ }
+ return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
+ }
/**
* @return The maximum transmission unit (MTU) size in bytes.
* @deprecated use {@link #getMtuV4} or {@link #getMtuV6} instead.
*/
@Deprecated
- public int getMtu() { return mMtuV4; }
+ public int getMtu() {
+ return getMtuV4();
+ }
/**
* This replaces the deprecated method getMtu.
* @return The maximum transmission unit (MTU) size in bytes, for IPv4.
*/
- public int getMtuV4() { return mMtuV4; }
+ public int getMtuV4() {
+ if (mApnSetting != null) {
+ return mApnSetting.getMtuV4();
+ }
+ return 0;
+ }
/**
* @return The maximum transmission unit (MTU) size in bytes, for IPv6.
*/
- public int getMtuV6() { return mMtuV6; }
+ public int getMtuV6() {
+ if (mApnSetting != null) {
+ return mApnSetting.getMtuV6();
+ }
+ return 0;
+ }
/**
* @return {@code true} if modem must persist this data profile.
*/
- public boolean isPersistent() { return mPersistent; }
+ public boolean isPersistent() {
+ if (mApnSetting != null) {
+ return mApnSetting.isPersistent();
+ }
+ return false;
+ }
/**
* @return {@code true} if this data profile was used to bring up the last default
* (i.e internet) data connection successfully, or the one chosen by the user in Settings'
* APN editor. For one carrier there can be only one profiled preferred.
*/
- public boolean isPreferred() { return mPreferred; }
+ public boolean isPreferred() {
+ return mPreferred;
+ }
+
+ /**
+ * @return The APN setting
+ * @hide TODO: Remove before T is released.
+ */
+ public @Nullable ApnSetting getApnSetting() {
+ return mApnSetting;
+ }
+
+ /**
+ * @return The traffic descriptor
+ * @hide TODO: Remove before T is released.
+ */
+ public @Nullable TrafficDescriptor getTrafficDescriptor() {
+ return mTrafficDescriptor;
+ }
@Override
public int describeContents() {
@@ -276,34 +323,15 @@
@NonNull
@Override
public String toString() {
- return "DataProfile=" + mProfileId + "/" + mProtocolType + "/" + mAuthType
- + "/" + (TelephonyUtils.IS_USER ? "***/***/***" :
- (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
- + mMaxConnectionsTime + "/" + mMaxConnections + "/"
- + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmask + "/"
- + mRoamingProtocolType + "/" + mBearerBitmask + "/" + mMtuV4 + "/" + mMtuV6 + "/"
- + mPersistent + "/" + mPreferred;
+ return "DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
+ + mPreferred;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mProfileId);
- dest.writeString(mApn);
- dest.writeInt(mProtocolType);
- dest.writeInt(mAuthType);
- dest.writeString(mUserName);
- dest.writeString(mPassword);
dest.writeInt(mType);
- dest.writeInt(mMaxConnectionsTime);
- dest.writeInt(mMaxConnections);
- dest.writeInt(mWaitTime);
- dest.writeBoolean(mEnabled);
- dest.writeInt(mSupportedApnTypesBitmask);
- dest.writeInt(mRoamingProtocolType);
- dest.writeInt(mBearerBitmask);
- dest.writeInt(mMtuV4);
- dest.writeInt(mMtuV6);
- dest.writeBoolean(mPersistent);
+ dest.writeParcelable(mApnSetting, flags);
+ dest.writeParcelable(mTrafficDescriptor, flags);
dest.writeBoolean(mPreferred);
}
@@ -321,36 +349,18 @@
};
@Override
- public boolean equals(@Nullable Object o) {
+ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DataProfile that = (DataProfile) o;
- return mProfileId == that.mProfileId
- && mProtocolType == that.mProtocolType
- && mAuthType == that.mAuthType
- && mType == that.mType
- && mMaxConnectionsTime == that.mMaxConnectionsTime
- && mMaxConnections == that.mMaxConnections
- && mWaitTime == that.mWaitTime
- && mEnabled == that.mEnabled
- && mSupportedApnTypesBitmask == that.mSupportedApnTypesBitmask
- && mRoamingProtocolType == that.mRoamingProtocolType
- && mBearerBitmask == that.mBearerBitmask
- && mMtuV4 == that.mMtuV4
- && mMtuV6 == that.mMtuV6
- && mPersistent == that.mPersistent
- && mPreferred == that.mPreferred
- && Objects.equals(mApn, that.mApn)
- && Objects.equals(mUserName, that.mUserName)
- && Objects.equals(mPassword, that.mPassword);
+ return mType == that.mType
+ && Objects.equals(mApnSetting, that.mApnSetting)
+ && Objects.equals(mTrafficDescriptor, that.mTrafficDescriptor);
}
@Override
public int hashCode() {
- return Objects.hash(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword, mType,
- mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
- mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
- mPersistent, mPreferred);
+ return Objects.hash(mType, mApnSetting, mTrafficDescriptor);
}
/**
@@ -383,13 +393,7 @@
private String mPassword;
@Type
- private int mType;
-
- private int mMaxConnectionsTime;
-
- private int mMaxConnections;
-
- private int mWaitTime;
+ private int mType = -1;
private boolean mEnabled;
@@ -410,6 +414,10 @@
private boolean mPreferred;
+ private ApnSetting mApnSetting;
+
+ private TrafficDescriptor mTrafficDescriptor;
+
/**
* Default constructor for Builder.
*/
@@ -496,48 +504,6 @@
}
/**
- * Set the period in seconds to limit the maximum connections.
- *
- * @param maxConnectionsTime The profile type
- * @return The same instance of the builder.
- *
- * @hide
- */
- public @NonNull Builder setMaxConnectionsTime(int maxConnectionsTime) {
- mMaxConnectionsTime = maxConnectionsTime;
- return this;
- }
-
- /**
- * Set the maximum connections allowed.
- *
- * @param maxConnections The maximum connections allowed.
- * @return The same instance of the builder.
- *
- * @hide
- */
- public @NonNull Builder setMaxConnections(int maxConnections) {
- mMaxConnections = maxConnections;
- return this;
- }
-
- /**
- * Set the period in seconds to limit the maximum connections.
- *
- * @param waitTime The required wait time in seconds after a successful UE initiated
- * disconnect of a given PDN connection before the device can send a new PDN connection
- * request for that given PDN.
- *
- * @return The same instance of the builder.
- *
- * @hide
- */
- public @NonNull Builder setWaitTime(int waitTime) {
- mWaitTime = waitTime;
- return this;
- }
-
- /**
* Enable the data profile
*
* @param isEnabled {@code true} to enable the data profile, otherwise disable.
@@ -587,8 +553,9 @@
*
* @param mtu The maximum transmission unit (MTU) size in bytes.
* @return The same instance of the builder.
- * @deprecated use {@link #setMtuV4} or {@link #setMtuV6} instead.
+ * @deprecated use {@link #setApnSetting(ApnSetting)} instead.
*/
+ @Deprecated
public @NonNull Builder setMtu(int mtu) {
mMtuV4 = mMtuV6 = mtu;
return this;
@@ -631,7 +598,7 @@
}
/**
- * Set data profile as persistent/non-persistent
+ * Set data profile as persistent/non-persistent.
*
* @param isPersistent {@code true} if this data profile was used to bring up the last
* default (i.e internet) data connection successfully.
@@ -643,15 +610,63 @@
}
/**
+ * Set APN setting.
+ *
+ * @param apnSetting APN setting
+ * @return The same instance of the builder
+ *
+ * @hide // TODO: Remove before T is released.
+ */
+ public @NonNull Builder setApnSetting(@NonNull ApnSetting apnSetting) {
+ mApnSetting = apnSetting;
+ return this;
+ }
+
+ /**
+ * Set traffic descriptor.
+ *
+ * @param trafficDescriptor Traffic descriptor
+ * @return The same instance of the builder
+ *
+ * @hide // TODO: Remove before T is released.
+ */
+ public @NonNull Builder setTrafficDescriptor(@NonNull TrafficDescriptor trafficDescriptor) {
+ mTrafficDescriptor = trafficDescriptor;
+ return this;
+ }
+
+ /**
* Build the DataProfile object
*
* @return The data profile object
*/
public @NonNull DataProfile build() {
- return new DataProfile(mProfileId, mApn, mProtocolType, mAuthType, mUserName, mPassword,
- mType, mMaxConnectionsTime, mMaxConnections, mWaitTime, mEnabled,
- mSupportedApnTypesBitmask, mRoamingProtocolType, mBearerBitmask, mMtuV4, mMtuV6,
- mPersistent, mPreferred);
+ if (mApnSetting == null && mApn != null) {
+ // This is for backwards compatibility.
+ mApnSetting = new ApnSetting.Builder()
+ .setEntryName(mApn)
+ .setApnName(mApn)
+ .setApnTypeBitmask(mSupportedApnTypesBitmask)
+ .setAuthType(mAuthType)
+ .setCarrierEnabled(mEnabled)
+ .setModemCognitive(mPersistent)
+ .setMtuV4(mMtuV4)
+ .setMtuV6(mMtuV6)
+ .setNetworkTypeBitmask(mBearerBitmask)
+ .setProfileId(mProfileId)
+ .setPassword(mPassword)
+ .setProtocol(mProtocolType)
+ .setRoamingProtocol(mRoamingProtocolType)
+ .setUser(mUserName)
+ .build();
+ }
+
+ if (mApnSetting == null && mTrafficDescriptor == null) {
+ throw new IllegalArgumentException("APN setting and traffic descriptor can't be "
+ + "both null.");
+ }
+
+ return new DataProfile(this);
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 63732b5..232a5d8 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1002,11 +1002,6 @@
boolean isManualNetworkSelectionAllowed(int subId);
/**
- * Enable or disable always reporting signal strength changes from radio.
- */
- void setAlwaysReportSignalStrength(int subId, boolean isEnable);
-
- /**
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
* @param callingPackage The package making the call.
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 7a564fc..a5852b5 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -31,6 +31,7 @@
],
test_suites: ["general-tests"],
java_resources: [
+ ":apex.apexd_test_classpath",
":com.android.apex.apkrollback.test_v2",
":StagedInstallTestApexV2",
":StagedInstallTestApexV2_WrongSha",
@@ -54,6 +55,7 @@
"cts-install-lib-host",
],
data: [
+ ":apex.apexd_test",
":com.android.apex.apkrollback.test_v1",
":StagedInstallTestApexV2",
":StagedInstallTestApexV2_WrongSha",
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index c610641..f0ab63e 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -74,6 +74,11 @@
"ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
"com.android.apex.cts.shim.v2.apex");
+ private static final String TEST_APEX_PACKAGE_NAME = "com.android.apex.test_package";
+ private static final TestApp TEST_APEX_CLASSPATH = new TestApp("TestApex",
+ TEST_APEX_PACKAGE_NAME, 1, /*isApex=*/true,
+ "apex.apexd_test_classpath.apex");
+
private File mTestStateFile = new File(
InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
"stagedinstall_state");
@@ -439,11 +444,13 @@
StagedApexInfo result = getPackageManagerNative().getStagedApexInfo("not found");
assertThat(result).isNull();
// Stage an apex
- int sessionId = Install.single(APEX_V2).setStaged().commit();
+ int sessionId = Install.single(TEST_APEX_CLASSPATH).setStaged().commit();
waitForSessionReady(sessionId);
// Query proper module name
- result = getPackageManagerNative().getStagedApexInfo(SHIM_APEX_PACKAGE_NAME);
- assertThat(result.moduleName).isEqualTo(SHIM_APEX_PACKAGE_NAME);
+ result = getPackageManagerNative().getStagedApexInfo(TEST_APEX_PACKAGE_NAME);
+ assertThat(result.moduleName).isEqualTo(TEST_APEX_PACKAGE_NAME);
+ assertThat(result.hasBootClassPathJars).isTrue();
+ assertThat(result.hasSystemServerClassPathJars).isTrue();
InstallUtils.openPackageInstallerSession(sessionId).abandon();
}
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 3102103..cd00783 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -61,6 +61,7 @@
private static final String APEX_WRONG_SHA = "com.android.apex.cts.shim.v2_wrong_sha.apex";
private static final String APK_A = "TestAppAv1.apk";
private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
+ private static final String APEXD_TEST_APEX = "apex.apexd_test.apex";
private static final String TEST_VENDOR_APEX_ALLOW_LIST =
"/vendor/etc/sysconfig/test-vendor-apex-allow-list.xml";
@@ -480,16 +481,29 @@
@Test
public void testGetStagedModuleNames() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
runPhase("testGetStagedModuleNames");
}
@Test
+ @LargeTest
public void testGetStagedApexInfo() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
+ pushTestApex(APEXD_TEST_APEX);
+ getDevice().reboot();
+
runPhase("testGetStagedApexInfo");
}
@Test
public void testStagedApexObserver() throws Exception {
+ assumeTrue("Device does not support updating APEX",
+ mHostUtils.isApexUpdateSupported());
+
runPhase("testStagedApexObserver");
}
diff --git a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
index f385113..3b201f9 100644
--- a/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
+++ b/tests/vcn/java/android/net/vcn/persistablebundleutils/IkeSessionParamsUtilsTest.java
@@ -135,11 +135,12 @@
}
@Test
- public void testEncodeRecodeParamsWithIkeOptions() throws Exception {
+ public void testEncodeDecodeParamsWithIkeOptions() throws Exception {
final IkeSessionParams params =
createBuilderMinimum()
.addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
.addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
+ .addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT)
.build();
verifyPersistableBundleEncodeDecodeIsLossless(params);
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index c9a8947a..937f9dc 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -297,8 +297,6 @@
any(),
any());
verify(mNetworkAgent).register();
- verify(mNetworkAgent)
- .setUnderlyingNetworks(eq(singletonList(TEST_UNDERLYING_NETWORK_RECORD_1.network)));
verify(mNetworkAgent).markConnected();
verify(mIpSecSvc)
@@ -313,6 +311,7 @@
final NetworkCapabilities nc = ncCaptor.getValue();
assertTrue(nc.hasTransport(TRANSPORT_CELLULAR));
assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+ assertEquals(List.of(TEST_UNDERLYING_NETWORK_RECORD_1.network), nc.getUnderlyingNetworks());
for (int cap : mConfig.getAllExposedCapabilities()) {
assertTrue(nc.hasCapability(cap));
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index a700171..5253c3e 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -61,6 +61,7 @@
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -116,8 +117,9 @@
capBuilder.setLinkUpstreamBandwidthKbps(TEST_UPSTREAM_BANDWIDTH);
capBuilder.setLinkDownstreamBandwidthKbps(TEST_DOWNSTREAM_BANDWIDTH);
capBuilder.setAdministratorUids(new int[] {TEST_UID});
+ final Network underlyingNetwork = mock(Network.class, CALLS_REAL_METHODS);
UnderlyingNetworkRecord record = new UnderlyingNetworkRecord(
- mock(Network.class, CALLS_REAL_METHODS),
+ underlyingNetwork,
capBuilder.build(), new LinkProperties(), false);
final NetworkCapabilities vcnCaps =
VcnGatewayConnection.buildNetworkCapabilities(
@@ -128,6 +130,7 @@
assertTrue(vcnCaps.hasTransport(TRANSPORT_CELLULAR));
assertTrue(vcnCaps.hasCapability(NET_CAPABILITY_NOT_METERED));
assertTrue(vcnCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+ assertTrue(vcnCaps.getUnderlyingNetworks().equals(List.of(underlyingNetwork)));
for (int cap : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
if (cap == NET_CAPABILITY_INTERNET || cap == NET_CAPABILITY_DUN) {