Merge "Make StubVolumes visible for read"
diff --git a/apex/media/framework/java/android/media/MediaTranscodingManager.java b/apex/media/framework/java/android/media/MediaTranscodingManager.java
index 93d58d0..1a84929 100644
--- a/apex/media/framework/java/android/media/MediaTranscodingManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodingManager.java
@@ -952,6 +952,8 @@
*
* @return the video track format to be used if transcoding should be performed,
* and null otherwise.
+ * @throws IllegalArgumentException if the hinted source video format contains invalid
+ * parameters.
*/
@Nullable
public MediaFormat resolveVideoFormat() {
@@ -962,20 +964,19 @@
MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint);
videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
- int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH);
- int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT);
+ int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH, -1);
+ int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT, -1);
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException(
"Source Width and height must be larger than 0");
}
- float frameRate = 30.0f; // default to 30fps.
- if (mSrcVideoFormatHint.containsKey(MediaFormat.KEY_FRAME_RATE)) {
- frameRate = mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE);
- if (frameRate <= 0) {
- throw new IllegalArgumentException(
- "frameRate must be larger than 0");
- }
+ float frameRate =
+ mSrcVideoFormatHint.getNumber(MediaFormat.KEY_FRAME_RATE, 30.0)
+ .floatValue();
+ if (frameRate <= 0) {
+ throw new IllegalArgumentException(
+ "frameRate must be larger than 0");
}
int bitrate = getAVCBitrate(width, height, frameRate);
diff --git a/core/api/current.txt b/core/api/current.txt
index a70a0a9..9922615 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9252,7 +9252,8 @@
method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
@@ -31513,6 +31514,7 @@
method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
+ method @NonNull public <T> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader, @NonNull Class<T>);
method @Nullable public android.os.PersistableBundle readPersistableBundle();
method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
method @Deprecated @Nullable public java.io.Serializable readSerializable();
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 3e799de..08e0178 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.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;
@@ -26,6 +28,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;
@@ -709,33 +713,85 @@
* notification
* @return true, if the notification has been triggered successfully
* @throws IllegalArgumentException
+ *
+ * @deprecated Use {@link BluetoothGattServer#notifyCharacteristicChanged(BluetoothDevice,
+ * BluetoothGattCharacteristic, boolean, byte[])} as this is not memory safe.
*/
+ @Deprecated
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean notifyCharacteristicChanged(BluetoothDevice device,
BluetoothGattCharacteristic characteristic, boolean confirm) {
+ return notifyCharacteristicChanged(device, characteristic, confirm,
+ characteristic.getValue()) == BluetoothStatusCodes.SUCCESS;
+ }
+
+ /** @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 NotifyCharacteristicReturnValues{}
+
+ /**
+ * Send a notification or indication that a local characteristic has been
+ * updated.
+ *
+ * <p>A notification or indication is sent to the remote device to signal
+ * that the characteristic has been updated. This function should be invoked
+ * for every client that requests notifications/indications by writing
+ * to the "Client Configuration" descriptor for the given characteristic.
+ *
+ * @param device the remote device to receive the notification/indication
+ * @param characteristic the local characteristic that has been updated
+ * @param confirm {@code true} to request confirmation from the client (indication) or
+ * {@code false} to send a notification
+ * @param value the characteristic value
+ * @return whether the notification has been triggered successfully
+ * @throws IllegalArgumentException if the characteristic value or service is null
+ */
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @NotifyCharacteristicReturnValues
+ public int notifyCharacteristicChanged(@NonNull BluetoothDevice device,
+ @NonNull BluetoothGattCharacteristic characteristic, boolean confirm,
+ @NonNull byte[] value) {
if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
- if (mService == null || mServerIf == 0) return false;
+ if (mService == null || mServerIf == 0) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+ if (characteristic == null) {
+ throw new IllegalArgumentException("characteristic must not be null");
+ }
+ if (device == null) {
+ throw new IllegalArgumentException("device must not be null");
+ }
BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
-
- if (characteristic.getValue() == null) {
- throw new IllegalArgumentException("Chracteristic value is empty. Use "
- + "BluetoothGattCharacteristic#setvalue to update");
+ if (service == null) {
+ throw new IllegalArgumentException("Characteristic must have a non-null service");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException("Characteristic value must not be null");
}
try {
- mService.sendNotification(mServerIf, device.getAddress(),
+ return mService.sendNotification(mServerIf, device.getAddress(),
characteristic.getInstanceId(), confirm,
- characteristic.getValue(), mAttributionSource);
+ value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
-
- return true;
}
/**
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 1655b62..db5b751 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -18,7 +18,6 @@
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.LocalSocket;
@@ -266,7 +265,7 @@
throw new IOException("bt socket acept failed");
}
- as.mPfd = new ParcelFileDescriptor(fds[0]);
+ as.mPfd = ParcelFileDescriptor.dup(fds[0]);
as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
as.mSocketIS = as.mSocket.getInputStream();
as.mSocketOS = as.mSocket.getOutputStream();
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 2b4e4a1..95f13b5 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -6,3 +6,7 @@
# Sensors framework
per-file *Sensor*,*Trigger* = file:platform/frameworks/native:/services/sensorservice/OWNERS
+
+# Buffers
+per-file HardwareBuffer* = file:/graphics/java/android/graphics/OWNERS
+per-file DataSpace* = file:/graphics/java/android/graphics/OWNERS
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index ee24084..c906a13 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -70,9 +70,17 @@
private static final String TAG = "NetworkTemplate";
/**
+ * Initial Version of the backup serializer.
+ */
+ public static final int BACKUP_VERSION_1_INIT = 1;
+ /**
+ * Version of the backup serializer that added carrier template support.
+ */
+ public static final int BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE = 2;
+ /**
* Current Version of the Backup Serializer.
*/
- private static final int BACKUP_VERSION = 1;
+ private static final int BACKUP_VERSION = BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE;
public static final int MATCH_MOBILE = 1;
public static final int MATCH_WIFI = 4;
@@ -285,6 +293,10 @@
private final int mRoaming;
private final int mDefaultNetwork;
private final int mSubType;
+ /**
+ * The subscriber Id match rule defines how the template should match networks with
+ * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
+ */
private final int mSubscriberIdMatchRule;
// Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
@@ -348,7 +360,7 @@
mSubscriberIdMatchRule = subscriberIdMatchRule;
checkValidSubscriberIdMatchRule();
if (!isKnownMatchRule(matchRule)) {
- Log.e(TAG, "Unknown network template rule " + matchRule
+ throw new IllegalArgumentException("Unknown network template rule " + matchRule
+ " will not match any identity.");
}
}
@@ -842,11 +854,17 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos);
+ if (!isPersistable()) {
+ Log.wtf(TAG, "Trying to backup non-persistable template: " + this);
+ }
+
out.writeInt(BACKUP_VERSION);
out.writeInt(mMatchRule);
BackupUtils.writeString(out, mSubscriberId);
BackupUtils.writeString(out, mNetworkId);
+ out.writeInt(mMetered);
+ out.writeInt(mSubscriberIdMatchRule);
return baos.toByteArray();
}
@@ -854,7 +872,7 @@
public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
throws IOException, BackupUtils.BadVersionException {
int version = in.readInt();
- if (version < 1 || version > BACKUP_VERSION) {
+ if (version < BACKUP_VERSION_1_INIT || version > BACKUP_VERSION) {
throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
}
@@ -862,11 +880,27 @@
String subscriberId = BackupUtils.readString(in);
String networkId = BackupUtils.readString(in);
- if (!isKnownMatchRule(matchRule)) {
- throw new BackupUtils.BadVersionException(
- "Restored network template contains unknown match rule " + matchRule);
+ final int metered;
+ final int subscriberIdMatchRule;
+ if (version >= BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE) {
+ metered = in.readInt();
+ subscriberIdMatchRule = in.readInt();
+ } else {
+ // For backward compatibility, fill the missing filters from match rules.
+ metered = (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD
+ || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL;
+ subscriberIdMatchRule = SUBSCRIBER_ID_MATCH_RULE_EXACT;
}
- return new NetworkTemplate(matchRule, subscriberId, networkId);
+ try {
+ return new NetworkTemplate(matchRule,
+ subscriberId, new String[] { subscriberId },
+ networkId, metered, NetworkStats.ROAMING_ALL,
+ NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL,
+ NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule);
+ } catch (IllegalArgumentException e) {
+ throw new BackupUtils.BadVersionException(
+ "Restored network template contains unknown match rule " + matchRule, e);
+ }
}
}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 92861fb..1e424d1 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -1,18 +1,6 @@
# Haptics
-per-file CombinedVibrationEffect.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file CombinedVibrationEffect.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file ExternalVibration.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file ExternalVibration.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file IExternalVibrationController.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file IExternalVibratorService.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file IVibratorManagerService.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file NullVibrator.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file SystemVibrator.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file SystemVibratorManager.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibrationEffect.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibrationEffect.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file Vibrator.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibratorManager.java = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file *Vibration* = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file *Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
# PowerManager
per-file IPowerManager.aidl = michaelwr@google.com, santoscordon@google.com
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 7bdb6b9..afd0ff7 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -3650,22 +3650,47 @@
@NonNull
public final <T extends Parcelable> List<T> readParcelableList(@NonNull List<T> list,
@Nullable ClassLoader cl) {
- final int N = readInt();
- if (N == -1) {
+ return readParcelableListInternal(list, cl, /*clazz*/ null);
+ }
+
+ /**
+ * Same as {@link #readParcelableList(List, ClassLoader)} but accepts {@code clazz} parameter as
+ * the type required for each item.
+ *
+ * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
+ * is not an instance of that class or any of its children classes or there was an error
+ * trying to instantiate an element.
+ */
+ @NonNull
+ public <T> List<T> readParcelableList(@NonNull List<T> list,
+ @Nullable ClassLoader cl, @NonNull Class<T> clazz) {
+ Objects.requireNonNull(list);
+ Objects.requireNonNull(clazz);
+ return readParcelableListInternal(list, cl, clazz);
+ }
+
+ /**
+ * @param clazz The type of the object expected or {@code null} for performing no checks.
+ */
+ @NonNull
+ private <T> List<T> readParcelableListInternal(@NonNull List<T> list,
+ @Nullable ClassLoader cl, @Nullable Class<T> clazz) {
+ final int n = readInt();
+ if (n == -1) {
list.clear();
return list;
}
- final int M = list.size();
+ final int m = list.size();
int i = 0;
- for (; i < M && i < N; i++) {
- list.set(i, (T) readParcelable(cl));
+ for (; i < m && i < n; i++) {
+ list.set(i, (T) readParcelableInternal(cl, clazz));
}
- for (; i<N; i++) {
- list.add((T) readParcelable(cl));
+ for (; i < n; i++) {
+ list.add((T) readParcelableInternal(cl, clazz));
}
- for (; i<M; i++) {
- list.remove(N);
+ for (; i < m; i++) {
+ list.remove(n);
}
return list;
}
diff --git a/core/java/android/os/vibrator/OWNERS b/core/java/android/os/vibrator/OWNERS
new file mode 100644
index 0000000..b54d6bf
--- /dev/null
+++ b/core/java/android/os/vibrator/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
\ No newline at end of file
diff --git a/core/java/android/util/BackupUtils.java b/core/java/android/util/BackupUtils.java
index 474ceda..4fcb13c 100644
--- a/core/java/android/util/BackupUtils.java
+++ b/core/java/android/util/BackupUtils.java
@@ -37,6 +37,10 @@
public BadVersionException(String message) {
super(message);
}
+
+ public BadVersionException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
}
public static String readString(DataInputStream in) throws IOException {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 92d5a47..6d4b8c5 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -724,9 +724,6 @@
DataOutputStream usapOutputStream = null;
ZygoteArguments args = null;
- // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
- blockSigTerm();
-
LocalSocket sessionSocket = null;
if (argBuffer == null) {
// Read arguments from usapPoolSocket instead.
@@ -742,6 +739,10 @@
ZygoteCommandBuffer tmpArgBuffer = null;
try {
sessionSocket = usapPoolSocket.accept();
+ // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
+ // This is safe from a race condition because the pool is only flushed after
+ // the SystemServer changes its internal state to stop using the USAP pool.
+ blockSigTerm();
usapOutputStream =
new DataOutputStream(sessionSocket.getOutputStream());
@@ -759,9 +760,10 @@
unblockSigTerm();
IoUtils.closeQuietly(sessionSocket);
IoUtils.closeQuietly(tmpArgBuffer);
- blockSigTerm();
}
} else {
+ // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
+ blockSigTerm();
try {
args = ZygoteArguments.getInstance(argBuffer);
} catch (Exception ex) {
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 1616c03..54e19db 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -163,6 +163,14 @@
* {@link android.graphics.BitmapFactory#decodeByteArray BitmapFactory#decodeByteArray}.
* </td>
* </tr>
+ * <tr>
+ * <td>{@link android.graphics.ImageFormat#YCBCR_P010 YCBCR_P010}</td>
+ * <td>1</td>
+ * <td>P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
+ * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
+ * little-endian value, with the lower 6 bits set to zero.
+ * </td>
+ * </tr>
* </table>
*
* @see android.graphics.ImageFormat
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index de31a7f..72dd2bd 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -5107,7 +5107,6 @@
public MediaImage(
@NonNull ByteBuffer buffer, @NonNull ByteBuffer info, boolean readOnly,
long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) {
- mFormat = ImageFormat.YUV_420_888;
mTimestamp = timestamp;
mIsImageValid = true;
mIsReadOnly = buffer.isReadOnly();
@@ -5120,6 +5119,11 @@
mBufferContext = 0;
+ int cbPlaneOffset = -1;
+ int crPlaneOffset = -1;
+ int planeOffsetInc = -1;
+ int pixelStride = -1;
+
// read media-info. See MediaImage2
if (info.remaining() == 104) {
int type = info.getInt();
@@ -5137,14 +5141,27 @@
"unsupported size: " + mWidth + "x" + mHeight);
}
int bitDepth = info.getInt();
- if (bitDepth != 8) {
+ if (bitDepth != 8 && bitDepth != 10) {
throw new UnsupportedOperationException("unsupported bit depth: " + bitDepth);
}
int bitDepthAllocated = info.getInt();
- if (bitDepthAllocated != 8) {
+ if (bitDepthAllocated != 8 && bitDepthAllocated != 16) {
throw new UnsupportedOperationException(
"unsupported allocated bit depth: " + bitDepthAllocated);
}
+ if (bitDepth == 8 && bitDepthAllocated == 8) {
+ mFormat = ImageFormat.YUV_420_888;
+ planeOffsetInc = 1;
+ pixelStride = 2;
+ } else if (bitDepth == 10 && bitDepthAllocated == 16) {
+ mFormat = ImageFormat.YCBCR_P010;
+ planeOffsetInc = 2;
+ pixelStride = 4;
+ } else {
+ throw new UnsupportedOperationException("couldn't infer ImageFormat"
+ + " bitDepth: " + bitDepth + " bitDepthAllocated: " + bitDepthAllocated);
+ }
+
mPlanes = new MediaPlane[numPlanes];
for (int ix = 0; ix < numPlanes; ix++) {
int planeOffset = info.getInt();
@@ -5166,12 +5183,31 @@
buffer.limit(buffer.position() + Utils.divUp(bitDepth, 8)
+ (mHeight / vert - 1) * rowInc + (mWidth / horiz - 1) * colInc);
mPlanes[ix] = new MediaPlane(buffer.slice(), rowInc, colInc);
+ if ((mFormat == ImageFormat.YUV_420_888 || mFormat == ImageFormat.YCBCR_P010)
+ && ix == 1) {
+ cbPlaneOffset = planeOffset;
+ } else if ((mFormat == ImageFormat.YUV_420_888
+ || mFormat == ImageFormat.YCBCR_P010) && ix == 2) {
+ crPlaneOffset = planeOffset;
+ }
}
} else {
throw new UnsupportedOperationException(
"unsupported info length: " + info.remaining());
}
+ // Validate chroma semiplanerness.
+ if (mFormat == ImageFormat.YCBCR_P010) {
+ if (crPlaneOffset != cbPlaneOffset + planeOffsetInc) {
+ throw new UnsupportedOperationException("Invalid plane offsets"
+ + " cbPlaneOffset: " + cbPlaneOffset + " crPlaneOffset: " + crPlaneOffset);
+ }
+ if (mPlanes[1].getPixelStride() != pixelStride
+ || mPlanes[2].getPixelStride() != pixelStride) {
+ throw new UnsupportedOperationException("Invalid pixelStride");
+ }
+ }
+
if (cropRect == null) {
cropRect = new Rect(0, 0, mWidth, mHeight);
}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
index ae63462..0c8e431 100644
--- a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
@@ -41,5 +41,5 @@
interface ISecureElementService {
String[] getReaders();
android.se.omapi.ISecureElementReader getReader(in String reader);
- boolean[] isNFCEventAllowed(in String reader, in byte[] aid, in String[] packageNames);
+ boolean[] isNfcEventAllowed(in String reader, in byte[] aid, in String[] packageNames, in int userId);
}
diff --git a/omapi/aidl/android/se/omapi/ISecureElementService.aidl b/omapi/aidl/android/se/omapi/ISecureElementService.aidl
index 61ae481..13707ec 100644
--- a/omapi/aidl/android/se/omapi/ISecureElementService.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementService.aidl
@@ -52,7 +52,7 @@
* Checks if the application defined by the package name is allowed to
* receive NFC transaction events for the defined AID.
*/
- boolean[] isNFCEventAllowed(in String reader, in byte[] aid,
- in String[] packageNames);
+ boolean[] isNfcEventAllowed(in String reader, in byte[] aid,
+ in String[] packageNames, in int userId);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 021ba224..ddee433 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -21,7 +21,6 @@
import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
-import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -191,7 +190,7 @@
void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) {
if (BluetoothUtils.D) {
Log.d(TAG, "onProfileStateChanged: profile " + profile + ", device "
- + mDevice.getAlias() + ", newProfileState " + newProfileState);
+ + mDevice.getAnonymizedAddress() + ", newProfileState " + newProfileState);
}
if (mLocalAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF)
{
@@ -741,7 +740,7 @@
}
if (BluetoothUtils.D) {
- Log.d(TAG, "updating profiles for " + mDevice.getAlias());
+ Log.d(TAG, "updating profiles for " + mDevice.getAnonymizedAddress());
BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString());
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 7d75b73..0aa50bd 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -407,7 +407,7 @@
@Override
public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {
synchronized (mLock) {
- if (mSecurityPolicy.canPerformGestures(this)) {
+ if (mServiceInterface != null && mSecurityPolicy.canPerformGestures(this)) {
MotionEventInjector motionEventInjector =
mSystemSupport.getMotionEventInjectorForDisplayLocked(displayId);
if (motionEventInjector != null
diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING
index 90246f8..5a6c6a5 100644
--- a/services/core/java/com/android/server/audio/TEST_MAPPING
+++ b/services/core/java/com/android/server/audio/TEST_MAPPING
@@ -1,13 +1,13 @@
{
"presubmit-large": [
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaAudioTestCases",
"options": [
{
- "include-filter": "android.media.cts.AudioManagerTest"
+ "include-filter": "android.media.audio.cts.AudioManagerTest"
},
{
- "include-filter": "android.media.cts.AudioFocusTest"
+ "include-filter": "android.media.audio.cts.AudioFocusTest"
}
]
}
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index df1eb6d..d17dbde 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -322,8 +322,11 @@
gateway = InetAddresses.parseNumericAddress(in.readUTF());
}
// If the destination is a default IPv4 route, use the gateway
- // address unless already set.
- if (dest.getAddress() instanceof Inet4Address
+ // address unless already set. If there is no destination, assume
+ // it is default route and use the gateway address in all cases.
+ if (dest == null) {
+ gatewayAddress = gateway;
+ } else if (dest.getAddress() instanceof Inet4Address
&& dest.getPrefixLength() == 0 && gatewayAddress == null) {
gatewayAddress = gateway;
} else {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 654b17f..b45d87f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -39,6 +39,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.RingBuffer;
import com.android.server.am.ProcessList;
+import com.android.server.net.NetworkPolicyManagerService.UidBlockedState;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@@ -72,16 +73,6 @@
private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
private static final int EVENT_APP_IDLE_WL_CHANGED = 14;
- static final int NTWK_BLOCKED_POWER = 0;
- static final int NTWK_ALLOWED_NON_METERED = 1;
- static final int NTWK_BLOCKED_DENYLIST = 2;
- static final int NTWK_ALLOWED_ALLOWLIST = 3;
- static final int NTWK_ALLOWED_TMP_ALLOWLIST = 4;
- static final int NTWK_BLOCKED_BG_RESTRICT = 5;
- static final int NTWK_ALLOWED_DEFAULT = 6;
- static final int NTWK_ALLOWED_SYSTEM = 7;
- static final int NTWK_BLOCKED_RESTRICTED_MODE = 8;
-
private final LogBuffer mNetworkBlockedBuffer = new LogBuffer(MAX_NETWORK_BLOCKED_LOG_SIZE);
private final LogBuffer mUidStateChangeBuffer = new LogBuffer(MAX_LOG_SIZE);
private final LogBuffer mEventsBuffer = new LogBuffer(MAX_LOG_SIZE);
@@ -90,12 +81,13 @@
private final Object mLock = new Object();
- void networkBlocked(int uid, int reason) {
+ void networkBlocked(int uid, UidBlockedState uidBlockedState) {
synchronized (mLock) {
if (LOGD || uid == mDebugUid) {
- Slog.d(TAG, uid + " is " + getBlockedReason(reason));
+ Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString());
}
- mNetworkBlockedBuffer.networkBlocked(uid, reason);
+ mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
+ uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
}
}
@@ -269,29 +261,6 @@
}
}
- private static String getBlockedReason(int reason) {
- switch (reason) {
- case NTWK_BLOCKED_POWER:
- return "blocked by power restrictions";
- case NTWK_ALLOWED_NON_METERED:
- return "allowed on unmetered network";
- case NTWK_BLOCKED_DENYLIST:
- return "denylisted on metered network";
- case NTWK_ALLOWED_ALLOWLIST:
- return "allowlisted on metered network";
- case NTWK_ALLOWED_TMP_ALLOWLIST:
- return "temporary allowlisted on metered network";
- case NTWK_BLOCKED_BG_RESTRICT:
- return "blocked when background is restricted";
- case NTWK_ALLOWED_DEFAULT:
- return "allowed by default";
- case NTWK_BLOCKED_RESTRICTED_MODE:
- return "blocked by restricted networking mode";
- default:
- return String.valueOf(reason);
- }
- }
-
private static String getPolicyChangedLog(int uid, int oldPolicy, int newPolicy) {
return "Policy for " + uid + " changed from "
+ NetworkPolicyManager.uidPoliciesToString(oldPolicy) + " to "
@@ -402,14 +371,17 @@
data.timeStamp = System.currentTimeMillis();
}
- public void networkBlocked(int uid, int reason) {
+ public void networkBlocked(int uid, int blockedReasons, int allowedReasons,
+ int effectiveBlockedReasons) {
final Data data = getNextSlot();
if (data == null) return;
data.reset();
data.type = EVENT_NETWORK_BLOCKED;
data.ifield1 = uid;
- data.ifield2 = reason;
+ data.ifield2 = blockedReasons;
+ data.ifield3 = allowedReasons;
+ data.ifield4 = effectiveBlockedReasons;
data.timeStamp = System.currentTimeMillis();
}
@@ -554,7 +526,8 @@
case EVENT_TYPE_GENERIC:
return data.sfield1;
case EVENT_NETWORK_BLOCKED:
- return data.ifield1 + "-" + getBlockedReason(data.ifield2);
+ return data.ifield1 + "-" + UidBlockedState.toString(
+ data.ifield2, data.ifield3, data.ifield4);
case EVENT_UID_STATE_CHANGED:
return data.ifield1 + ":" + ProcessList.makeProcStateString(data.ifield2)
+ ":" + ActivityManager.getCapabilitiesSummary(data.ifield3)
@@ -593,17 +566,18 @@
}
}
- public final static class Data {
- int type;
- long timeStamp;
+ private static final class Data {
+ public int type;
+ public long timeStamp;
- int ifield1;
- int ifield2;
- int ifield3;
- long lfield1;
- boolean bfield1;
- boolean bfield2;
- String sfield1;
+ public int ifield1;
+ public int ifield2;
+ public int ifield3;
+ public int ifield4;
+ public long lfield1;
+ public boolean bfield1;
+ public boolean bfield2;
+ public String sfield1;
public void reset(){
sfield1 = null;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 20687c6..5de5fd3 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -79,14 +79,10 @@
import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
-import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
-import static android.net.NetworkPolicyManager.MASK_RESTRICTED_MODE_NETWORKS;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -135,15 +131,6 @@
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_ALLOWLIST;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_DEFAULT;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_NON_METERED;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_SYSTEM;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_TMP_ALLOWLIST;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BG_RESTRICT;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_DENYLIST;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_POWER;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_RESTRICTED_MODE;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -518,8 +505,6 @@
/** Defined UID policies. */
@GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidPolicy = new SparseIntArray();
- /** Currently derived rules for each UID. */
- @GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidRules = new SparseIntArray();
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
@@ -598,6 +583,10 @@
@GuardedBy("mUidRulesFirstLock")
private final SparseArray<UidBlockedState> mUidBlockedState = new SparseArray<>();
+ /** Objects used temporarily while computing the new blocked state for each uid. */
+ @GuardedBy("mUidRulesFirstLock")
+ private final SparseArray<UidBlockedState> mTmpUidBlockedState = new SparseArray<>();
+
/** Map from network ID to last observed meteredness state */
@GuardedBy("mNetworkPoliciesSecondLock")
private final SparseBooleanArray mNetworkMetered = new SparseBooleanArray();
@@ -3825,7 +3814,7 @@
final SparseBooleanArray knownUids = new SparseBooleanArray();
collectKeys(mUidState, knownUids);
- collectKeys(mUidRules, knownUids);
+ collectKeys(mUidBlockedState, knownUids);
fout.println("Status for all known UIDs:");
fout.increaseIndent();
@@ -3843,23 +3832,13 @@
fout.print(uidState.toString());
}
- final int uidRules = mUidRules.get(uid, RULE_NONE);
- fout.print(" rules=");
- fout.print(uidRulesToString(uidRules));
- fout.println();
- }
- fout.decreaseIndent();
-
- fout.println("Status for just UIDs with rules:");
- fout.increaseIndent();
- size = mUidRules.size();
- for (int i = 0; i < size; i++) {
- final int uid = mUidRules.keyAt(i);
- fout.print("UID=");
- fout.print(uid);
- final int uidRules = mUidRules.get(uid, RULE_NONE);
- fout.print(" rules=");
- fout.print(uidRulesToString(uidRules));
+ final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ if (uidBlockedState == null) {
+ fout.print(" blocked_state={null}");
+ } else {
+ fout.print(" blocked_state=");
+ fout.print(uidBlockedState.toString());
+ }
fout.println();
}
fout.decreaseIndent();
@@ -4010,22 +3989,17 @@
void updateRestrictedModeAllowlistUL() {
mUidFirewallRestrictedModeRules.clear();
forEachUid("updateRestrictedModeAllowlist", uid -> {
- final int oldUidRule = mUidRules.get(uid);
- final int newUidRule = getNewRestrictedModeUidRule(uid, oldUidRule);
- final boolean hasUidRuleChanged = oldUidRule != newUidRule;
- final int newFirewallRule = getRestrictedModeFirewallRule(newUidRule);
+ synchronized (mUidRulesFirstLock) {
+ final UidBlockedState uidBlockedState = updateBlockedReasonsForRestrictedModeUL(
+ uid);
+ final int newFirewallRule = getRestrictedModeFirewallRule(uidBlockedState);
- // setUidFirewallRulesUL will allowlist all uids that are passed to it, so only add
- // non-default rules.
- if (newFirewallRule != FIREWALL_RULE_DEFAULT) {
- mUidFirewallRestrictedModeRules.append(uid, newFirewallRule);
+ // setUidFirewallRulesUL will allowlist all uids that are passed to it, so only add
+ // non-default rules.
+ if (newFirewallRule != FIREWALL_RULE_DEFAULT) {
+ mUidFirewallRestrictedModeRules.append(uid, newFirewallRule);
+ }
}
-
- if (hasUidRuleChanged) {
- mUidRules.put(uid, newUidRule);
- mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRule).sendToTarget();
- }
- updateBlockedReasonsForRestrictedModeUL(uid);
});
if (mRestrictedNetworkingMode) {
// firewall rules only need to be set when this mode is being enabled.
@@ -4038,15 +4012,7 @@
@VisibleForTesting
@GuardedBy("mUidRulesFirstLock")
void updateRestrictedModeForUidUL(int uid) {
- final int oldUidRule = mUidRules.get(uid);
- final int newUidRule = getNewRestrictedModeUidRule(uid, oldUidRule);
- final boolean hasUidRuleChanged = oldUidRule != newUidRule;
-
- if (hasUidRuleChanged) {
- mUidRules.put(uid, newUidRule);
- mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRule).sendToTarget();
- }
- updateBlockedReasonsForRestrictedModeUL(uid);
+ final UidBlockedState uidBlockedState = updateBlockedReasonsForRestrictedModeUL(uid);
// if restricted networking mode is on, and the app has an access exemption, the uid rule
// will not change, but the firewall rule will have to be updated.
@@ -4054,16 +4020,14 @@
// Note: setUidFirewallRule also updates mUidFirewallRestrictedModeRules.
// In this case, default firewall rules can also be added.
setUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, uid,
- getRestrictedModeFirewallRule(newUidRule));
+ getRestrictedModeFirewallRule(uidBlockedState));
}
}
- private void updateBlockedReasonsForRestrictedModeUL(int uid) {
- UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
- if (uidBlockedState == null) {
- uidBlockedState = new UidBlockedState();
- mUidBlockedState.put(uid, uidBlockedState);
- }
+ @GuardedBy("mUidRulesFirstLock")
+ private UidBlockedState updateBlockedReasonsForRestrictedModeUL(int uid) {
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
if (mRestrictedNetworkingMode) {
uidBlockedState.blockedReasons |= BLOCKED_REASON_RESTRICTED_MODE;
@@ -4077,23 +4041,16 @@
}
uidBlockedState.updateEffectiveBlockedReasons();
if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
- mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
- uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons)
- .sendToTarget();
+ postBlockedReasonsChangedMsg(uid,
+ uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons);
+
+ postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules());
}
+ return uidBlockedState;
}
- private int getNewRestrictedModeUidRule(int uid, int oldUidRule) {
- int newRule = oldUidRule;
- newRule &= ~MASK_RESTRICTED_MODE_NETWORKS;
- if (mRestrictedNetworkingMode && !hasRestrictedModeAccess(uid)) {
- newRule |= RULE_REJECT_RESTRICTED_MODE;
- }
- return newRule;
- }
-
- private static int getRestrictedModeFirewallRule(int uidRule) {
- if ((uidRule & RULE_REJECT_RESTRICTED_MODE) != 0) {
+ private static int getRestrictedModeFirewallRule(UidBlockedState uidBlockedState) {
+ if ((uidBlockedState.effectiveBlockedReasons & BLOCKED_REASON_RESTRICTED_MODE) != 0) {
// rejected in restricted mode, this is the default behavior.
return FIREWALL_RULE_DEFAULT;
} else {
@@ -4301,16 +4258,12 @@
if (!isUidValidForDenylistRulesUL(uid)) {
continue;
}
- int oldRules = mUidRules.get(uid);
- if (enableChain) {
- // Chain wasn't enabled before and the other power-related
- // chains are allowlists, so we can clear the
- // MASK_ALL_NETWORKS part of the rules and re-inform listeners if
- // the effective rules result in blocking network access.
- oldRules &= MASK_METERED_NETWORKS;
- } else {
- // Skip if it had no restrictions to begin with
- if ((oldRules & MASK_ALL_NETWORKS) == 0) continue;
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
+ if (!enableChain && (uidBlockedState.blockedReasons & ~BLOCKED_METERED_REASON_MASK)
+ == BLOCKED_REASON_NONE) {
+ // Chain isn't enabled and the uid had no restrictions to begin with.
+ continue;
}
final boolean isUidIdle = !paroled && isUidIdle(uid);
if (isUidIdle && !mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid))
@@ -4320,13 +4273,7 @@
} else {
mUidFirewallStandbyRules.put(uid, FIREWALL_RULE_DEFAULT);
}
- final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules,
- isUidIdle);
- if (newUidRules == RULE_NONE) {
- mUidRules.delete(uid);
- } else {
- mUidRules.put(uid, newUidRules);
- }
+ updateRulesForPowerRestrictionsUL(uid, isUidIdle);
}
setUidFirewallRulesUL(FIREWALL_CHAIN_STANDBY, blockedUids,
enableChain ? CHAIN_TOGGLE_ENABLE : CHAIN_TOGGLE_DISABLE);
@@ -4544,6 +4491,7 @@
mInternetPermissionMap.put(uid, hasPermission);
return hasPermission;
} catch (RemoteException e) {
+ // ignored; service lives in system_server
}
return true;
}
@@ -4554,7 +4502,7 @@
@GuardedBy("mUidRulesFirstLock")
private void onUidDeletedUL(int uid) {
// First cleanup in-memory state synchronously...
- mUidRules.delete(uid);
+ mUidBlockedState.delete(uid);
mUidPolicy.delete(uid);
mUidFirewallStandbyRules.delete(uid);
mUidFirewallDozableRules.delete(uid);
@@ -4640,7 +4588,7 @@
* permission, since there is no need to change the {@code iptables} rule if the app does not
* have permission to use the internet.
*
- * <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
+ * <p>The {@link #mUidBlockedState} map is used to define the transition of states of an UID.
*
*/
private void updateRulesForDataUsageRestrictionsUL(int uid) {
@@ -4655,6 +4603,7 @@
}
}
+ @GuardedBy("mUidRulesFirstLock")
private void updateRulesForDataUsageRestrictionsULInner(int uid) {
if (!isUidValidForAllowlistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
@@ -4662,38 +4611,17 @@
}
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
- final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid);
- UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
- if (uidBlockedState == null) {
- uidBlockedState = new UidBlockedState();
- mUidBlockedState.put(uid, uidBlockedState);
- }
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
+ final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid(
+ mTmpUidBlockedState, uid);
+ previousUidBlockedState.copyFrom(uidBlockedState);
final boolean isDenied = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
final boolean isAllowed = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
- // copy oldUidRules and clear out METERED_NETWORKS rules.
- int newUidRules = oldUidRules & (~MASK_METERED_NETWORKS);
-
- // First step: define the new rule based on user restrictions and foreground state.
- if (isRestrictedByAdmin) {
- newUidRules |= RULE_REJECT_METERED;
- } else if (isForeground) {
- if (isDenied || (mRestrictBackground && !isAllowed)) {
- newUidRules |= RULE_TEMPORARY_ALLOW_METERED;
- } else if (isAllowed) {
- newUidRules |= RULE_ALLOW_METERED;
- }
- } else {
- if (isDenied) {
- newUidRules |= RULE_REJECT_METERED;
- } else if (mRestrictBackground && isAllowed) {
- newUidRules |= RULE_ALLOW_METERED;
- }
- }
-
int newBlockedReasons = BLOCKED_REASON_NONE;
int newAllowedReasons = ALLOWED_REASON_NONE;
newBlockedReasons |= (isRestrictedByAdmin ? BLOCKED_METERED_REASON_ADMIN_DISABLED : 0);
@@ -4704,16 +4632,48 @@
newAllowedReasons |= (isForeground ? ALLOWED_METERED_REASON_FOREGROUND : 0);
newAllowedReasons |= (isAllowed ? ALLOWED_METERED_REASON_USER_EXEMPTED : 0);
+ uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
+ & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
+ uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
+ & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
+ uidBlockedState.updateEffectiveBlockedReasons();
+ final int oldEffectiveBlockedReasons = previousUidBlockedState.effectiveBlockedReasons;
+ final int newEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) {
+ postBlockedReasonsChangedMsg(uid,
+ newEffectiveBlockedReasons, oldEffectiveBlockedReasons);
+
+ postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules());
+ }
+
+ // Note that the conditionals below are for avoiding unnecessary calls to netd.
+ // TODO: Measure the performance for doing a no-op call to netd so that we can
+ // remove the conditionals to simplify the logic below. We can also further reduce
+ // some calls to netd if they turn out to be costly.
+ final int denylistReasons = BLOCKED_METERED_REASON_ADMIN_DISABLED
+ | BLOCKED_METERED_REASON_USER_RESTRICTED;
+ if ((oldEffectiveBlockedReasons & denylistReasons) != BLOCKED_REASON_NONE
+ || (newEffectiveBlockedReasons & denylistReasons) != BLOCKED_REASON_NONE) {
+ setMeteredNetworkDenylist(uid,
+ (newEffectiveBlockedReasons & denylistReasons) != BLOCKED_REASON_NONE);
+ }
+ final int allowlistReasons = ALLOWED_METERED_REASON_FOREGROUND
+ | ALLOWED_METERED_REASON_USER_EXEMPTED;
+ final int oldAllowedReasons = previousUidBlockedState.allowedReasons;
+ if ((oldAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE
+ || (newAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE) {
+ setMeteredNetworkAllowlist(uid,
+ (newAllowedReasons & allowlistReasons) != ALLOWED_REASON_NONE);
+ }
+
if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
+ ": isForeground=" +isForeground
+ ", isDenied=" + isDenied
+ ", isAllowed=" + isAllowed
+ ", isRestrictedByAdmin=" + isRestrictedByAdmin
- + ", oldRule=" + uidRulesToString(oldUidRules & MASK_METERED_NETWORKS)
- + ", newRule=" + uidRulesToString(newUidRules & MASK_METERED_NETWORKS)
- + ", newUidRules=" + uidRulesToString(newUidRules)
- + ", oldUidRules=" + uidRulesToString(oldUidRules)
+ + ", oldBlockedState=" + previousUidBlockedState.toString()
+ + ", newBlockedState="
+ ", oldBlockedMeteredReasons=" + NetworkPolicyManager.blockedReasonsToString(
uidBlockedState.blockedReasons & BLOCKED_METERED_REASON_MASK)
+ ", oldBlockedMeteredEffectiveReasons="
@@ -4722,84 +4682,11 @@
+ ", oldAllowedMeteredReasons=" + NetworkPolicyManager.blockedReasonsToString(
uidBlockedState.allowedReasons & BLOCKED_METERED_REASON_MASK));
}
-
- if (newUidRules == RULE_NONE) {
- mUidRules.delete(uid);
- } else {
- mUidRules.put(uid, newUidRules);
- }
-
- // Second step: apply bw changes based on change of state.
- if (newUidRules != oldUidRules) {
- if (hasRule(newUidRules, RULE_TEMPORARY_ALLOW_METERED)) {
- // Temporarily allow foreground app, removing from denylist if necessary
- // (since bw_penalty_box prevails over bw_happy_box).
-
- setMeteredNetworkAllowlist(uid, true);
- // TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
- // but ideally it should be just:
- // setMeteredNetworkDenylist(uid, isDenied);
- if (isDenied) {
- setMeteredNetworkDenylist(uid, false);
- }
- } else if (hasRule(oldUidRules, RULE_TEMPORARY_ALLOW_METERED)) {
- // Remove temporary exemption from app that is not on foreground anymore.
-
- // TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
- // but ideally they should be just:
- // setMeteredNetworkAllowlist(uid, isAllowed);
- // setMeteredNetworkDenylist(uid, isDenied);
- if (!isAllowed) {
- setMeteredNetworkAllowlist(uid, false);
- }
- if (isDenied || isRestrictedByAdmin) {
- setMeteredNetworkDenylist(uid, true);
- }
- } else if (hasRule(newUidRules, RULE_REJECT_METERED)
- || hasRule(oldUidRules, RULE_REJECT_METERED)) {
- // Flip state because app was explicitly added or removed to denylist.
- setMeteredNetworkDenylist(uid, (isDenied || isRestrictedByAdmin));
- if (hasRule(oldUidRules, RULE_REJECT_METERED) && isAllowed) {
- // Since denial prevails over allowance, we need to handle the special case
- // where app is allowed and denied at the same time (although such
- // scenario should be blocked by the UI), then it is removed from the denylist.
- setMeteredNetworkAllowlist(uid, isAllowed);
- }
- } else if (hasRule(newUidRules, RULE_ALLOW_METERED)
- || hasRule(oldUidRules, RULE_ALLOW_METERED)) {
- // Flip state because app was explicitly added or removed to allowlist.
- setMeteredNetworkAllowlist(uid, isAllowed);
- } else {
- // All scenarios should have been covered above.
- Log.wtf(TAG, "Unexpected change of metered UID state for " + uid
- + ": foreground=" + isForeground
- + ", allowlisted=" + isAllowed
- + ", denylisted=" + isDenied
- + ", isRestrictedByAdmin=" + isRestrictedByAdmin
- + ", newRule=" + uidRulesToString(newUidRules)
- + ", oldRule=" + uidRulesToString(oldUidRules));
- }
-
- // Dispatch changed rule to existing listeners.
- mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
- }
-
- final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
- uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
- & ~BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
- uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
- & ~ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
- uidBlockedState.updateEffectiveBlockedReasons();
- if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
- mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
- uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons)
- .sendToTarget();
- }
}
/**
- * Updates the power-related part of the {@link #mUidRules} for a given map, and notify external
- * listeners in case of change.
+ * Updates the power-related part of the {@link #mUidBlockedState} for a given map, and
+ * notify external listeners in case of change.
* <p>
* There are 3 power-related rules that affects whether an app has background access on
* non-metered networks, and when the condition applies and the UID is not allowed for power
@@ -4810,23 +4697,15 @@
* <li>Battery Saver Mode is on: {@code fw_powersave} firewall chain.
* </ul>
* <p>
- * This method updates the power-related part of the {@link #mUidRules} for a given uid based on
- * these modes, the UID process state (foreground or not), and the UID allowlist state.
+ * This method updates the power-related part of the {@link #mUidBlockedState} for a given
+ * uid based on these modes, the UID process state (foreground or not), and the UID
+ * allowlist state.
* <p>
* <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
*/
@GuardedBy("mUidRulesFirstLock")
private void updateRulesForPowerRestrictionsUL(int uid) {
- final int oldUidRules = mUidRules.get(uid, RULE_NONE);
-
- final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules,
- isUidIdle(uid));
-
- if (newUidRules == RULE_NONE) {
- mUidRules.delete(uid);
- } else {
- mUidRules.put(uid, newUidRules);
- }
+ updateRulesForPowerRestrictionsUL(uid, isUidIdle(uid));
}
/**
@@ -4835,56 +4714,37 @@
* @param uid the uid of the app to update rules for
* @param oldUidRules the current rules for the uid, in order to determine if there's a change
* @param isUidIdle whether uid is idle or not
- *
- * @return the new computed rules for the uid
*/
@GuardedBy("mUidRulesFirstLock")
- private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean isUidIdle) {
+ private void updateRulesForPowerRestrictionsUL(int uid, boolean isUidIdle) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
- "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules + "/"
+ "updateRulesForPowerRestrictionsUL: " + uid + "/"
+ (isUidIdle ? "I" : "-"));
}
try {
- return updateRulesForPowerRestrictionsULInner(uid, oldUidRules, isUidIdle);
+ updateRulesForPowerRestrictionsULInner(uid, isUidIdle);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
@GuardedBy("mUidRulesFirstLock")
- private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules,
- boolean isUidIdle) {
+ private void updateRulesForPowerRestrictionsULInner(int uid, boolean isUidIdle) {
if (!isUidValidForDenylistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
- return RULE_NONE;
+ return;
}
- final boolean restrictMode = isUidIdle || mRestrictPower || mDeviceIdleMode;
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
- // Copy existing uid rules and clear ALL_NETWORK rules.
- int newUidRules = oldUidRules & (~MASK_ALL_NETWORKS);
-
- UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
- if (uidBlockedState == null) {
- uidBlockedState = new UidBlockedState();
- mUidBlockedState.put(uid, uidBlockedState);
- }
-
- // First step: define the new rule based on user restrictions and foreground state.
-
- // NOTE: if statements below could be inlined, but it's easier to understand the logic
- // by considering the foreground and non-foreground states.
- if (isForeground) {
- if (restrictMode) {
- newUidRules |= RULE_ALLOW_ALL;
- }
- } else if (restrictMode) {
- newUidRules |= isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
- }
+ final UidBlockedState uidBlockedState = getOrCreateUidBlockedStateForUid(
+ mUidBlockedState, uid);
+ final UidBlockedState previousUidBlockedState = getOrCreateUidBlockedStateForUid(
+ mTmpUidBlockedState, uid);
+ previousUidBlockedState.copyFrom(uidBlockedState);
int newBlockedReasons = BLOCKED_REASON_NONE;
int newAllowedReasons = ALLOWED_REASON_NONE;
@@ -4899,6 +4759,22 @@
? ALLOWED_REASON_POWER_SAVE_ALLOWLIST : 0);
newAllowedReasons |= (isWhitelistedFromPowerSaveExceptIdleUL(uid)
? ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST : 0);
+ newAllowedReasons |= (uidBlockedState.allowedReasons
+ & ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS);
+
+ uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
+ & BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
+ uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
+ & ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
+ uidBlockedState.updateEffectiveBlockedReasons();
+ if (previousUidBlockedState.effectiveBlockedReasons
+ != uidBlockedState.effectiveBlockedReasons) {
+ postBlockedReasonsChangedMsg(uid,
+ uidBlockedState.effectiveBlockedReasons,
+ previousUidBlockedState.effectiveBlockedReasons);
+
+ postUidRulesChangedMsg(uid, uidBlockedState.deriveUidRules());
+ }
if (LOGV) {
Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
@@ -4907,43 +4783,9 @@
+ ", mDeviceIdleMode: " + mDeviceIdleMode
+ ", isForeground=" + isForeground
+ ", isWhitelisted=" + isWhitelisted
- + ", oldRule=" + uidRulesToString(oldUidRules & MASK_ALL_NETWORKS)
- + ", newRule=" + uidRulesToString(newUidRules & MASK_ALL_NETWORKS)
- + ", newUidRules=" + uidRulesToString(newUidRules)
- + ", oldUidRules=" + uidRulesToString(oldUidRules));
+ + ", oldUidBlockedState=" + previousUidBlockedState.toString()
+ + ", newUidBlockedState=" + uidBlockedState.toString());
}
-
- // Second step: notify listeners if state changed.
- if (newUidRules != oldUidRules) {
- if ((newUidRules & MASK_ALL_NETWORKS) == RULE_NONE || hasRule(newUidRules,
- RULE_ALLOW_ALL)) {
- if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid);
- } else if (hasRule(newUidRules, RULE_REJECT_ALL)) {
- if (LOGV) Log.v(TAG, "Rejecting non-metered access for UID " + uid);
- } else {
- // All scenarios should have been covered above
- Log.wtf(TAG, "Unexpected change of non-metered UID state for " + uid
- + ": foreground=" + isForeground
- + ", whitelisted=" + isWhitelisted
- + ", newRule=" + uidRulesToString(newUidRules)
- + ", oldRule=" + uidRulesToString(oldUidRules));
- }
- mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
- }
-
- final int oldEffectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
- uidBlockedState.blockedReasons = (uidBlockedState.blockedReasons
- & BLOCKED_METERED_REASON_MASK) | newBlockedReasons;
- uidBlockedState.allowedReasons = (uidBlockedState.allowedReasons
- & ALLOWED_METERED_REASON_MASK) | newAllowedReasons;
- uidBlockedState.updateEffectiveBlockedReasons();
- if (oldEffectiveBlockedReasons != uidBlockedState.effectiveBlockedReasons) {
- mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
- uidBlockedState.effectiveBlockedReasons, oldEffectiveBlockedReasons)
- .sendToTarget();
- }
-
- return newUidRules;
}
private class NetPolicyAppIdleStateChangeListener extends AppIdleStateChangeListener {
@@ -4971,10 +4813,23 @@
}
}
+ private void postBlockedReasonsChangedMsg(int uid, int newEffectiveBlockedReasons,
+ int oldEffectiveBlockedReasons) {
+ mHandler.obtainMessage(MSG_BLOCKED_REASON_CHANGED, uid,
+ newEffectiveBlockedReasons, oldEffectiveBlockedReasons)
+ .sendToTarget();
+ }
+
+ private void postUidRulesChangedMsg(int uid, int uidRules) {
+ mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules)
+ .sendToTarget();
+ }
+
private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
try {
listener.onUidRulesChanged(uid, uidRules);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -4983,6 +4838,7 @@
try {
listener.onMeteredIfacesChanged(meteredIfaces);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -4991,6 +4847,7 @@
try {
listener.onRestrictBackgroundChanged(restrictBackground);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -4999,6 +4856,7 @@
try {
listener.onUidPoliciesChanged(uid, uidPolicies);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -5007,6 +4865,7 @@
try {
listener.onSubscriptionOverride(subId, overrideMask, overrideValue, networkTypes);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -5015,6 +4874,7 @@
try {
listener.onSubscriptionPlansChanged(subId, plans);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -5023,6 +4883,7 @@
try {
listener.onBlockedReasonChanged(uid, oldBlockedReasons, newBlockedReasons);
} catch (RemoteException ignored) {
+ // Ignore if there is an error sending the callback to the client.
}
}
@@ -5033,6 +4894,10 @@
case MSG_RULES_CHANGED: {
final int uid = msg.arg1;
final int uidRules = msg.arg2;
+ if (LOGV) {
+ Slog.v(TAG, "Dispatching rules=" + uidRulesToString(uidRules)
+ + " for uid=" + uid);
+ }
final int length = mListeners.beginBroadcast();
for (int i = 0; i < length; i++) {
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -5605,7 +5470,7 @@
}
}
- private static void collectKeys(SparseArray<UidState> source, SparseBooleanArray target) {
+ private static <T> void collectKeys(SparseArray<T> source, SparseBooleanArray target) {
final int size = source.size();
for (int i = 0; i < size; i++) {
target.put(source.keyAt(i), true);
@@ -5653,90 +5518,38 @@
final long startTime = mStatLogger.getTime();
mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
- final int uidRules;
- final boolean isBackgroundRestricted;
+ int blockedReasons;
synchronized (mUidRulesFirstLock) {
- uidRules = mUidRules.get(uid, RULE_NONE);
- isBackgroundRestricted = mRestrictBackground;
+ final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ blockedReasons = uidBlockedState == null
+ ? BLOCKED_REASON_NONE : uidBlockedState.effectiveBlockedReasons;
+ if (!isNetworkMetered) {
+ blockedReasons &= ~BLOCKED_METERED_REASON_MASK;
+ }
+ mLogger.networkBlocked(uid, uidBlockedState);
}
- final boolean ret = isUidNetworkingBlockedInternal(uid, uidRules, isNetworkMetered,
- isBackgroundRestricted, mLogger);
mStatLogger.logDurationStat(Stats.IS_UID_NETWORKING_BLOCKED, startTime);
- return ret;
+ return blockedReasons != BLOCKED_REASON_NONE;
}
@Override
public boolean isUidRestrictedOnMeteredNetworks(int uid) {
mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
- final int uidRules;
- final boolean isBackgroundRestricted;
synchronized (mUidRulesFirstLock) {
- uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
- isBackgroundRestricted = mRestrictBackground;
+ final UidBlockedState uidBlockedState = mUidBlockedState.get(uid);
+ int blockedReasons = uidBlockedState == null
+ ? BLOCKED_REASON_NONE : uidBlockedState.effectiveBlockedReasons;
+ blockedReasons &= BLOCKED_METERED_REASON_MASK;
+ return blockedReasons != BLOCKED_REASON_NONE;
}
- // TODO(b/177490332): The logic here might not be correct because it doesn't consider
- // RULE_REJECT_METERED condition. And it could be replaced by
- // isUidNetworkingBlockedInternal().
- return isBackgroundRestricted
- && !hasRule(uidRules, RULE_ALLOW_METERED)
- && !hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED);
}
private static boolean isSystem(int uid) {
return uid < Process.FIRST_APPLICATION_UID;
}
- static boolean isUidNetworkingBlockedInternal(int uid, int uidRules, boolean isNetworkMetered,
- boolean isBackgroundRestricted, @Nullable NetworkPolicyLogger logger) {
- final int reason;
- // Networks are never blocked for system components
- if (isSystem(uid)) {
- reason = NTWK_ALLOWED_SYSTEM;
- } else if (hasRule(uidRules, RULE_REJECT_RESTRICTED_MODE)) {
- reason = NTWK_BLOCKED_RESTRICTED_MODE;
- } else if (hasRule(uidRules, RULE_REJECT_ALL)) {
- reason = NTWK_BLOCKED_POWER;
- } else if (!isNetworkMetered) {
- reason = NTWK_ALLOWED_NON_METERED;
- } else if (hasRule(uidRules, RULE_REJECT_METERED)) {
- reason = NTWK_BLOCKED_DENYLIST;
- } else if (hasRule(uidRules, RULE_ALLOW_METERED)) {
- reason = NTWK_ALLOWED_ALLOWLIST;
- } else if (hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED)) {
- reason = NTWK_ALLOWED_TMP_ALLOWLIST;
- } else if (isBackgroundRestricted) {
- reason = NTWK_BLOCKED_BG_RESTRICT;
- } else {
- reason = NTWK_ALLOWED_DEFAULT;
- }
-
- final boolean blocked;
- switch(reason) {
- case NTWK_ALLOWED_DEFAULT:
- case NTWK_ALLOWED_NON_METERED:
- case NTWK_ALLOWED_TMP_ALLOWLIST:
- case NTWK_ALLOWED_ALLOWLIST:
- case NTWK_ALLOWED_SYSTEM:
- blocked = false;
- break;
- case NTWK_BLOCKED_RESTRICTED_MODE:
- case NTWK_BLOCKED_POWER:
- case NTWK_BLOCKED_DENYLIST:
- case NTWK_BLOCKED_BG_RESTRICT:
- blocked = true;
- break;
- default:
- throw new IllegalArgumentException();
- }
- if (logger != null) {
- logger.networkBlocked(uid, reason);
- }
-
- return blocked;
- }
-
private class NetworkPolicyManagerInternalImpl extends NetworkPolicyManagerInternal {
@Override
@@ -5945,6 +5758,16 @@
return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue;
}
+ private static UidBlockedState getOrCreateUidBlockedStateForUid(
+ SparseArray<UidBlockedState> uidBlockedStates, int uid) {
+ UidBlockedState uidBlockedState = uidBlockedStates.get(uid);
+ if (uidBlockedState == null) {
+ uidBlockedState = new UidBlockedState();
+ uidBlockedStates.put(uid, uidBlockedState);
+ }
+ return uidBlockedState;
+ }
+
@VisibleForTesting
static final class UidBlockedState {
public int blockedReasons;
@@ -6008,9 +5831,180 @@
}
return effectiveBlockedReasons;
}
+
+ @Override
+ public String toString() {
+ return toString(blockedReasons, allowedReasons, effectiveBlockedReasons);
+ }
+
+ public static String toString(int blockedReasons, int allowedReasons,
+ int effectiveBlockedReasons) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ sb.append("blocked=").append(blockedReasonsToString(blockedReasons)).append(",");
+ sb.append("allowed=").append(allowedReasonsToString(allowedReasons)).append(",");
+ sb.append("effective=").append(blockedReasonsToString(effectiveBlockedReasons));
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private static final int[] BLOCKED_REASONS = {
+ BLOCKED_REASON_BATTERY_SAVER,
+ BLOCKED_REASON_DOZE,
+ BLOCKED_REASON_APP_STANDBY,
+ BLOCKED_REASON_RESTRICTED_MODE,
+ BLOCKED_METERED_REASON_DATA_SAVER,
+ BLOCKED_METERED_REASON_USER_RESTRICTED,
+ BLOCKED_METERED_REASON_ADMIN_DISABLED,
+ };
+
+ private static final int[] ALLOWED_REASONS = {
+ ALLOWED_REASON_SYSTEM,
+ ALLOWED_REASON_FOREGROUND,
+ ALLOWED_REASON_POWER_SAVE_ALLOWLIST,
+ ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST,
+ ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS,
+ ALLOWED_METERED_REASON_USER_EXEMPTED,
+ ALLOWED_METERED_REASON_SYSTEM,
+ ALLOWED_METERED_REASON_FOREGROUND,
+ };
+
+ private static String blockedReasonToString(int blockedReason) {
+ switch (blockedReason) {
+ case BLOCKED_REASON_NONE:
+ return "NONE";
+ case BLOCKED_REASON_BATTERY_SAVER:
+ return "BATTERY_SAVER";
+ case BLOCKED_REASON_DOZE:
+ return "DOZE";
+ case BLOCKED_REASON_APP_STANDBY:
+ return "APP_STANDBY";
+ case BLOCKED_REASON_RESTRICTED_MODE:
+ return "RESTRICTED_MODE";
+ case BLOCKED_METERED_REASON_DATA_SAVER:
+ return "DATA_SAVER";
+ case BLOCKED_METERED_REASON_USER_RESTRICTED:
+ return "METERED_USER_RESTRICTED";
+ case BLOCKED_METERED_REASON_ADMIN_DISABLED:
+ return "METERED_ADMIN_DISABLED";
+ default:
+ Slog.wtfStack(TAG, "Unknown blockedReason: " + blockedReason);
+ return String.valueOf(blockedReason);
+ }
+ }
+
+ private static String allowedReasonToString(int allowedReason) {
+ switch (allowedReason) {
+ case ALLOWED_REASON_NONE:
+ return "NONE";
+ case ALLOWED_REASON_SYSTEM:
+ return "SYSTEM";
+ case ALLOWED_REASON_FOREGROUND:
+ return "FOREGROUND";
+ case ALLOWED_REASON_POWER_SAVE_ALLOWLIST:
+ return "POWER_SAVE_ALLOWLIST";
+ case ALLOWED_REASON_POWER_SAVE_EXCEPT_IDLE_ALLOWLIST:
+ return "POWER_SAVE_EXCEPT_IDLE_ALLOWLIST";
+ case ALLOWED_REASON_RESTRICTED_MODE_PERMISSIONS:
+ return "RESTRICTED_MODE_PERMISSIONS";
+ case ALLOWED_METERED_REASON_USER_EXEMPTED:
+ return "METERED_USER_EXEMPTED";
+ case ALLOWED_METERED_REASON_SYSTEM:
+ return "METERED_SYSTEM";
+ case ALLOWED_METERED_REASON_FOREGROUND:
+ return "METERED_FOREGROUND";
+ default:
+ Slog.wtfStack(TAG, "Unknown allowedReason: " + allowedReason);
+ return String.valueOf(allowedReason);
+ }
+ }
+
+ public static String blockedReasonsToString(int blockedReasons) {
+ if (blockedReasons == BLOCKED_REASON_NONE) {
+ return blockedReasonToString(BLOCKED_REASON_NONE);
+ }
+ final StringBuilder sb = new StringBuilder();
+ for (int reason : BLOCKED_REASONS) {
+ if ((blockedReasons & reason) != 0) {
+ sb.append(sb.length() == 0 ? "" : "|");
+ sb.append(blockedReasonToString(reason));
+ blockedReasons &= ~reason;
+ }
+ }
+ if (blockedReasons != 0) {
+ sb.append(sb.length() == 0 ? "" : "|");
+ sb.append(String.valueOf(blockedReasons));
+ Slog.wtfStack(TAG, "Unknown blockedReasons: " + blockedReasons);
+ }
+ return sb.toString();
+ }
+
+ public static String allowedReasonsToString(int allowedReasons) {
+ if (allowedReasons == ALLOWED_REASON_NONE) {
+ return allowedReasonToString(ALLOWED_REASON_NONE);
+ }
+ final StringBuilder sb = new StringBuilder();
+ for (int reason : ALLOWED_REASONS) {
+ if ((allowedReasons & reason) != 0) {
+ sb.append(sb.length() == 0 ? "" : "|");
+ sb.append(allowedReasonToString(reason));
+ allowedReasons &= ~reason;
+ }
+ }
+ if (allowedReasons != 0) {
+ sb.append(sb.length() == 0 ? "" : "|");
+ sb.append(String.valueOf(allowedReasons));
+ Slog.wtfStack(TAG, "Unknown allowedReasons: " + allowedReasons);
+ }
+ return sb.toString();
+ }
+
+ public void copyFrom(UidBlockedState uidBlockedState) {
+ blockedReasons = uidBlockedState.blockedReasons;
+ allowedReasons = uidBlockedState.allowedReasons;
+ effectiveBlockedReasons = uidBlockedState.effectiveBlockedReasons;
+ }
+
+ public int deriveUidRules() {
+ int uidRule = RULE_NONE;
+ if ((effectiveBlockedReasons & BLOCKED_REASON_RESTRICTED_MODE) != 0) {
+ uidRule |= RULE_REJECT_RESTRICTED_MODE;
+ }
+
+ int powerBlockedReasons = BLOCKED_REASON_APP_STANDBY
+ | BLOCKED_REASON_DOZE
+ | BLOCKED_REASON_BATTERY_SAVER;
+ if ((effectiveBlockedReasons & powerBlockedReasons) != 0) {
+ uidRule |= RULE_REJECT_ALL;
+ } else if ((blockedReasons & powerBlockedReasons) != 0) {
+ uidRule |= RULE_ALLOW_ALL;
+ }
+
+ // UidRule doesn't include RestrictBackground (DataSaver) state, so not including in
+ // metered blocked reasons below.
+ int meteredBlockedReasons = BLOCKED_METERED_REASON_ADMIN_DISABLED
+ | BLOCKED_METERED_REASON_USER_RESTRICTED;
+ if ((effectiveBlockedReasons & meteredBlockedReasons) != 0) {
+ uidRule |= RULE_REJECT_METERED;
+ } else if ((blockedReasons & BLOCKED_METERED_REASON_USER_RESTRICTED) != 0
+ && (allowedReasons & ALLOWED_METERED_REASON_FOREGROUND) != 0) {
+ uidRule |= RULE_TEMPORARY_ALLOW_METERED;
+ } else if ((blockedReasons & BLOCKED_METERED_REASON_DATA_SAVER) != 0) {
+ if ((allowedReasons & ALLOWED_METERED_REASON_USER_EXEMPTED) != 0) {
+ uidRule |= RULE_ALLOW_ALL;
+ } else if ((allowedReasons & ALLOWED_METERED_REASON_FOREGROUND) != 0) {
+ uidRule |= RULE_TEMPORARY_ALLOW_METERED;
+ }
+ }
+ if (LOGV) {
+ Slog.v(TAG, "uidBlockedState=" + this.toString()
+ + " -> uidRule=" + uidRulesToString(uidRule));
+ }
+ return uidRule;
+ }
}
- private class NotificationId {
+ private static class NotificationId {
private final String mTag;
private final int mId;
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index f4b72a1..c876d41 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -150,6 +150,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.BinderUtils;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
@@ -2097,14 +2098,18 @@
@Override
public void notifyAlertReached() throws RemoteException {
- mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
+ // This binder object can only have been obtained by a process that holds
+ // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
+ BinderUtils.withCleanCallingIdentity(() ->
+ mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
}
@Override
public void notifyWarningOrLimitReached() {
Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
- LocalServices.getService(NetworkPolicyManagerInternal.class)
- .onStatsProviderWarningOrLimitReached(mTag);
+ BinderUtils.withCleanCallingIdentity(() ->
+ LocalServices.getService(NetworkPolicyManagerInternal.class)
+ .onStatsProviderWarningOrLimitReached(mTag));
}
@Override
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 0bb6198..22320fd 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -27,9 +27,8 @@
java_sdk_library {
name: "android.test.mock",
-
- srcs: [
- ":android-test-mock-sources",
+ srcs: [":android-test-mock-sources"],
+ api_srcs: [
// Note: Below are NOT APIs of this library. We only take APIs under
// the android.test.mock package. They however provide private APIs that
// android.test.mock APIs references to. We need to have the classes in
@@ -44,15 +43,9 @@
"app-compat-annotations",
"unsupportedappusage",
],
-
api_packages: [
"android.test.mock",
],
- // Only include android.test.mock.* classes. Jarjar rules below removes
- // classes in other packages like android.content. In order to keep the
- // list up-to-date, permitted_packages ensures that the library contains
- // clases under android.test.mock after the jarjar rules are applied.
- jarjar_rules: "jarjar-rules.txt",
permitted_packages: [
"android.test.mock",
],
diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt
deleted file mode 100644
index 4420a44..0000000
--- a/test-mock/jarjar-rules.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-zap android.accounts.**
-zap android.app.**
-zap android.content.**
-zap android.database.**
-zap android.os.**
-zap android.util.**
-zap android.view.**