summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java71
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/os/Debug.java2
-rw-r--r--core/java/android/util/CharsetUtils.java24
-rw-r--r--core/java/android/util/TEST_MAPPING28
-rw-r--r--core/java/android/view/View.java4
-rw-r--r--core/java/com/android/internal/util/BinaryXmlPullParser.java13
-rw-r--r--core/java/com/android/internal/util/BinaryXmlSerializer.java15
-rw-r--r--core/java/com/android/internal/util/FastDataInput.java102
-rw-r--r--core/java/com/android/internal/util/FastDataOutput.java114
-rw-r--r--core/java/com/android/internal/util/ModifiedUtf8.java110
-rw-r--r--core/java/com/android/internal/util/TEST_MAPPING17
-rw-r--r--core/jni/TEST_MAPPING16
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp11
-rw-r--r--core/tests/coretests/src/android/util/XmlTest.java2
-rw-r--r--core/tests/coretests/src/com/android/internal/util/FastDataTest.java93
-rw-r--r--graphics/java/android/graphics/Bitmap.java2
-rw-r--r--libs/incident/libincident.map.txt20
-rw-r--r--packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java4
-rw-r--r--packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java4
-rw-r--r--packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java19
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java16
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java2
-rw-r--r--rs/OWNERS7
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java14
-rw-r--r--services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java16
-rw-r--r--telephony/common/android/telephony/LocationAccessPolicy.java25
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthNr.java16
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java10
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java5
32 files changed, 653 insertions, 140 deletions
diff --git a/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java b/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java
index 2700fff4cba1..76656bd67afa 100644
--- a/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java
+++ b/apct-tests/perftests/core/src/com/android/internal/util/FastDataPerfTest.java
@@ -52,21 +52,45 @@ public class FastDataPerfTest {
while (state.keepRunning()) {
os.reset();
final BufferedOutputStream bos = new BufferedOutputStream(os, BUFFER_SIZE);
- final DataOutput out = new DataOutputStream(bos);
- doWrite(out);
- bos.flush();
+ final DataOutputStream out = new DataOutputStream(bos);
+ try {
+ doWrite(out);
+ out.flush();
+ } finally {
+ out.close();
+ }
}
}
@Test
- public void timeWrite_Local() throws IOException {
+ public void timeWrite_LocalUsing4ByteSequences() throws IOException {
final ByteArrayOutputStream os = new ByteArrayOutputStream(OUTPUT_SIZE);
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
os.reset();
- final FastDataOutput out = new FastDataOutput(os, BUFFER_SIZE);
- doWrite(out);
- out.flush();
+ final FastDataOutput out = FastDataOutput.obtainUsing4ByteSequences(os);
+ try {
+ doWrite(out);
+ out.flush();
+ } finally {
+ out.release();
+ }
+ }
+ }
+
+ @Test
+ public void timeWrite_LocalUsing3ByteSequences() throws IOException {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream(OUTPUT_SIZE);
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ os.reset();
+ final FastDataOutput out = FastDataOutput.obtainUsing3ByteSequences(os);
+ try {
+ doWrite(out);
+ out.flush();
+ } finally {
+ out.release();
+ }
}
}
@@ -77,19 +101,42 @@ public class FastDataPerfTest {
while (state.keepRunning()) {
is.reset();
final BufferedInputStream bis = new BufferedInputStream(is, BUFFER_SIZE);
- final DataInput in = new DataInputStream(bis);
- doRead(in);
+ final DataInputStream in = new DataInputStream(bis);
+ try {
+ doRead(in);
+ } finally {
+ in.close();
+ }
+ }
+ }
+
+ @Test
+ public void timeRead_LocalUsing4ByteSequences() throws Exception {
+ final ByteArrayInputStream is = new ByteArrayInputStream(doWrite());
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ is.reset();
+ final FastDataInput in = FastDataInput.obtainUsing4ByteSequences(is);
+ try {
+ doRead(in);
+ } finally {
+ in.release();
+ }
}
}
@Test
- public void timeRead_Local() throws Exception {
+ public void timeRead_LocalUsing3ByteSequences() throws Exception {
final ByteArrayInputStream is = new ByteArrayInputStream(doWrite());
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
is.reset();
- final DataInput in = new FastDataInput(is, BUFFER_SIZE);
- doRead(in);
+ final FastDataInput in = FastDataInput.obtainUsing3ByteSequences(is);
+ try {
+ doRead(in);
+ } finally {
+ in.release();
+ }
}
}
diff --git a/core/api/current.txt b/core/api/current.txt
index dc1949693802..e513bba57f9f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29758,7 +29758,7 @@ package android.os {
method @Deprecated public static void changeDebugPort(int);
method public static void dumpHprofData(String) throws java.io.IOException;
method public static boolean dumpService(String, java.io.FileDescriptor, String[]);
- method public static void enableEmulatorTraceOutput();
+ method @Deprecated public static void enableEmulatorTraceOutput();
method public static int getBinderDeathObjectCount();
method public static int getBinderLocalObjectCount();
method public static int getBinderProxyObjectCount();
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index b4930fa931eb..399f11b0f2a7 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1155,6 +1155,8 @@ public final class Debug
* consequences.
*
* To temporarily enable tracing, use {@link #startNativeTracing()}.
+ *
+ * @deprecated Please use other tracing method in this class.
*/
public static void enableEmulatorTraceOutput() {
Log.w(TAG, "Unimplemented");
diff --git a/core/java/android/util/CharsetUtils.java b/core/java/android/util/CharsetUtils.java
index fa146675b8d1..3b08c3b6d52f 100644
--- a/core/java/android/util/CharsetUtils.java
+++ b/core/java/android/util/CharsetUtils.java
@@ -26,6 +26,12 @@ import dalvik.annotation.optimization.FastNative;
* <p>
* These methods purposefully accept only non-movable byte array addresses to
* avoid extra JNI overhead.
+ * <p>
+ * Callers are cautioned that there is a long-standing ART bug that emits
+ * non-standard 4-byte sequences, as described by {@code kUtfUse4ByteSequence}
+ * in {@code art/runtime/jni/jni_internal.cc}. If precise modified UTF-8
+ * encoding is required, use {@link com.android.internal.util.ModifiedUtf8}
+ * instead.
*
* @hide
*/
@@ -33,6 +39,12 @@ public class CharsetUtils {
/**
* Attempt to encode the given string as modified UTF-8 into the destination
* byte array without making any new allocations.
+ * <p>
+ * Callers are cautioned that there is a long-standing ART bug that emits
+ * non-standard 4-byte sequences, as described by
+ * {@code kUtfUse4ByteSequence} in {@code art/runtime/jni/jni_internal.cc}.
+ * If precise modified UTF-8 encoding is required, use
+ * {@link com.android.internal.util.ModifiedUtf8} instead.
*
* @param src string value to be encoded
* @param dest destination byte array to encode into
@@ -50,6 +62,12 @@ public class CharsetUtils {
/**
* Attempt to encode the given string as modified UTF-8 into the destination
* byte array without making any new allocations.
+ * <p>
+ * Callers are cautioned that there is a long-standing ART bug that emits
+ * non-standard 4-byte sequences, as described by
+ * {@code kUtfUse4ByteSequence} in {@code art/runtime/jni/jni_internal.cc}.
+ * If precise modified UTF-8 encoding is required, use
+ * {@link com.android.internal.util.ModifiedUtf8} instead.
*
* @param src string value to be encoded
* @param srcLen exact length of string to be encoded
@@ -66,6 +84,12 @@ public class CharsetUtils {
/**
* Attempt to decode a modified UTF-8 string from the source byte array.
+ * <p>
+ * Callers are cautioned that there is a long-standing ART bug that emits
+ * non-standard 4-byte sequences, as described by
+ * {@code kUtfUse4ByteSequence} in {@code art/runtime/jni/jni_internal.cc}.
+ * If precise modified UTF-8 encoding is required, use
+ * {@link com.android.internal.util.ModifiedUtf8} instead.
*
* @param src source byte array to decode from
* @param srcOff offset into source where decoding should begin
diff --git a/core/java/android/util/TEST_MAPPING b/core/java/android/util/TEST_MAPPING
new file mode 100644
index 000000000000..0ae1c1593366
--- /dev/null
+++ b/core/java/android/util/TEST_MAPPING
@@ -0,0 +1,28 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.util.CharsetUtilsTest"
+ },
+ {
+ "include-filter": "com.android.internal.util.FastDataTest"
+ }
+ ],
+ "file_patterns": ["CharsetUtils|FastData"]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.util.XmlTest"
+ },
+ {
+ "include-filter": "android.util.BinaryXmlTest"
+ }
+ ],
+ "file_patterns": ["Xml"]
+ }
+ ]
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ffa577a47c88..271d7ba9cdd3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12810,6 +12810,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Set if view is a heading for a section of content for accessibility purposes.
+ * <p>
+ * Users of some accessibility services can choose to navigate between headings
+ * instead of between paragraphs, words, etc. Apps that provide headings on
+ * sections of text can help the text navigation experience.
*
* @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
*
diff --git a/core/java/com/android/internal/util/BinaryXmlPullParser.java b/core/java/com/android/internal/util/BinaryXmlPullParser.java
index 57552f301bd6..d3abac9f8877 100644
--- a/core/java/com/android/internal/util/BinaryXmlPullParser.java
+++ b/core/java/com/android/internal/util/BinaryXmlPullParser.java
@@ -73,12 +73,6 @@ import java.util.Objects;
* </ul>
*/
public final class BinaryXmlPullParser implements TypedXmlPullParser {
- /**
- * Default buffer size, which matches {@code FastXmlSerializer}. This should
- * be kept in sync with {@link BinaryXmlPullParser}.
- */
- private static final int BUFFER_SIZE = 32_768;
-
private FastDataInput mIn;
private int mCurrentToken = START_DOCUMENT;
@@ -100,7 +94,12 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser {
throw new UnsupportedOperationException();
}
- mIn = new FastDataInput(is, BUFFER_SIZE);
+ if (mIn != null) {
+ mIn.release();
+ mIn = null;
+ }
+
+ mIn = FastDataInput.obtainUsing4ByteSequences(is);
mCurrentToken = START_DOCUMENT;
mCurrentDepth = 0;
diff --git a/core/java/com/android/internal/util/BinaryXmlSerializer.java b/core/java/com/android/internal/util/BinaryXmlSerializer.java
index 9df4bdb157c8..485430a43768 100644
--- a/core/java/com/android/internal/util/BinaryXmlSerializer.java
+++ b/core/java/com/android/internal/util/BinaryXmlSerializer.java
@@ -91,12 +91,6 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
static final int TYPE_BOOLEAN_TRUE = 12 << 4;
static final int TYPE_BOOLEAN_FALSE = 13 << 4;
- /**
- * Default buffer size, which matches {@code FastXmlSerializer}. This should
- * be kept in sync with {@link BinaryXmlPullParser}.
- */
- private static final int BUFFER_SIZE = 32_768;
-
private FastDataOutput mOut;
/**
@@ -124,7 +118,7 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
throw new UnsupportedOperationException();
}
- mOut = new FastDataOutput(os, BUFFER_SIZE);
+ mOut = FastDataOutput.obtainUsing4ByteSequences(os);
mOut.write(PROTOCOL_MAGIC_VERSION_0);
mTagCount = 0;
@@ -138,7 +132,9 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
@Override
public void flush() throws IOException {
- mOut.flush();
+ if (mOut != null) {
+ mOut.flush();
+ }
}
@Override
@@ -157,6 +153,9 @@ public final class BinaryXmlSerializer implements TypedXmlSerializer {
public void endDocument() throws IOException {
mOut.writeByte(END_DOCUMENT | TYPE_NULL);
flush();
+
+ mOut.release();
+ mOut = null;
}
@Override
diff --git a/core/java/com/android/internal/util/FastDataInput.java b/core/java/com/android/internal/util/FastDataInput.java
index f8d241b5ede0..5117034815fc 100644
--- a/core/java/com/android/internal/util/FastDataInput.java
+++ b/core/java/com/android/internal/util/FastDataInput.java
@@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Optimized implementation of {@link DataInput} which buffers data in memory
@@ -41,13 +42,18 @@ import java.util.Objects;
public class FastDataInput implements DataInput, Closeable {
private static final int MAX_UNSIGNED_SHORT = 65_535;
+ private static final int DEFAULT_BUFFER_SIZE = 32_768;
+
+ private static AtomicReference<FastDataInput> sInCache = new AtomicReference<>();
+
private final VMRuntime mRuntime;
- private final InputStream mIn;
private final byte[] mBuffer;
private final long mBufferPtr;
private final int mBufferCap;
+ private final boolean mUse4ByteSequence;
+ private InputStream mIn;
private int mBufferPos;
private int mBufferLim;
@@ -57,7 +63,18 @@ public class FastDataInput implements DataInput, Closeable {
private int mStringRefCount = 0;
private String[] mStringRefs = new String[32];
+ /**
+ * @deprecated callers must specify {@code use4ByteSequence} so they make a
+ * clear choice about working around a long-standing ART bug, as
+ * described by the {@code kUtfUse4ByteSequence} comments in
+ * {@code art/runtime/jni/jni_internal.cc}.
+ */
+ @Deprecated
public FastDataInput(@NonNull InputStream in, int bufferSize) {
+ this(in, bufferSize, true /* use4ByteSequence */);
+ }
+
+ public FastDataInput(@NonNull InputStream in, int bufferSize, boolean use4ByteSequence) {
mRuntime = VMRuntime.getRuntime();
mIn = Objects.requireNonNull(in);
if (bufferSize < 8) {
@@ -67,6 +84,64 @@ public class FastDataInput implements DataInput, Closeable {
mBuffer = (byte[]) mRuntime.newNonMovableArray(byte.class, bufferSize);
mBufferPtr = mRuntime.addressOf(mBuffer);
mBufferCap = mBuffer.length;
+ mUse4ByteSequence = use4ByteSequence;
+ }
+
+ /**
+ * Obtain a {@link FastDataInput} configured with the given
+ * {@link InputStream} and which encodes large code-points using 3-byte
+ * sequences.
+ * <p>
+ * This <em>is</em> compatible with the {@link DataInput} API contract,
+ * which specifies that large code-points must be encoded with 3-byte
+ * sequences.
+ */
+ public static FastDataInput obtainUsing3ByteSequences(@NonNull InputStream in) {
+ return new FastDataInput(in, DEFAULT_BUFFER_SIZE, false /* use4ByteSequence */);
+ }
+
+ /**
+ * Obtain a {@link FastDataInput} configured with the given
+ * {@link InputStream} and which decodes large code-points using 4-byte
+ * sequences.
+ * <p>
+ * This <em>is not</em> compatible with the {@link DataInput} API contract,
+ * which specifies that large code-points must be encoded with 3-byte
+ * sequences.
+ */
+ public static FastDataInput obtainUsing4ByteSequences(@NonNull InputStream in) {
+ FastDataInput instance = sInCache.getAndSet(null);
+ if (instance != null) {
+ instance.setInput(in);
+ return instance;
+ }
+ return new FastDataInput(in, DEFAULT_BUFFER_SIZE, true /* use4ByteSequence */);
+ }
+
+ /**
+ * Release a {@link FastDataInput} to potentially be recycled. You must not
+ * interact with the object after releasing it.
+ */
+ public void release() {
+ mIn = null;
+ mBufferPos = 0;
+ mBufferLim = 0;
+ mStringRefCount = 0;
+
+ if (mBufferCap == DEFAULT_BUFFER_SIZE && mUse4ByteSequence) {
+ // Try to return to the cache.
+ sInCache.compareAndSet(null, this);
+ }
+ }
+
+ /**
+ * Re-initializes the object for the new input.
+ */
+ private void setInput(@NonNull InputStream in) {
+ mIn = Objects.requireNonNull(in);
+ mBufferPos = 0;
+ mBufferLim = 0;
+ mStringRefCount = 0;
}
private void fill(int need) throws IOException {
@@ -90,6 +165,7 @@ public class FastDataInput implements DataInput, Closeable {
@Override
public void close() throws IOException {
mIn.close();
+ release();
}
@Override
@@ -126,6 +202,14 @@ public class FastDataInput implements DataInput, Closeable {
@Override
public String readUTF() throws IOException {
+ if (mUse4ByteSequence) {
+ return readUTFUsing4ByteSequences();
+ } else {
+ return readUTFUsing3ByteSequences();
+ }
+ }
+
+ private String readUTFUsing4ByteSequences() throws IOException {
// Attempt to read directly from buffer space if there's enough room,
// otherwise fall back to chunking into place
final int len = readUnsignedShort();
@@ -141,6 +225,22 @@ public class FastDataInput implements DataInput, Closeable {
}
}
+ private String readUTFUsing3ByteSequences() throws IOException {
+ // Attempt to read directly from buffer space if there's enough room,
+ // otherwise fall back to chunking into place
+ final int len = readUnsignedShort();
+ if (mBufferCap > len) {
+ if (mBufferLim - mBufferPos < len) fill(len);
+ final String res = ModifiedUtf8.decode(mBuffer, new char[len], mBufferPos, len);
+ mBufferPos += len;
+ return res;
+ } else {
+ final byte[] tmp = (byte[]) mRuntime.newNonMovableArray(byte.class, len + 1);
+ readFully(tmp, 0, len);
+ return ModifiedUtf8.decode(tmp, new char[len], 0, len);
+ }
+ }
+
/**
* Read a {@link String} value with the additional signal that the given
* value is a candidate for being canonicalized, similar to
diff --git a/core/java/com/android/internal/util/FastDataOutput.java b/core/java/com/android/internal/util/FastDataOutput.java
index cf5b2966d889..c9e8f8f08229 100644
--- a/core/java/com/android/internal/util/FastDataOutput.java
+++ b/core/java/com/android/internal/util/FastDataOutput.java
@@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Optimized implementation of {@link DataOutput} which buffers data in memory
@@ -41,23 +42,38 @@ import java.util.Objects;
public class FastDataOutput implements DataOutput, Flushable, Closeable {
private static final int MAX_UNSIGNED_SHORT = 65_535;
+ private static final int DEFAULT_BUFFER_SIZE = 32_768;
+
+ private static AtomicReference<FastDataOutput> sOutCache = new AtomicReference<>();
+
private final VMRuntime mRuntime;
- private final OutputStream mOut;
private final byte[] mBuffer;
private final long mBufferPtr;
private final int mBufferCap;
+ private final boolean mUse4ByteSequence;
+ private OutputStream mOut;
private int mBufferPos;
/**
* Values that have been "interned" by {@link #writeInternedUTF(String)}.
*/
- private HashMap<String, Short> mStringRefs = new HashMap<>();
+ private final HashMap<String, Short> mStringRefs = new HashMap<>();
+ /**
+ * @deprecated callers must specify {@code use4ByteSequence} so they make a
+ * clear choice about working around a long-standing ART bug, as
+ * described by the {@code kUtfUse4ByteSequence} comments in
+ * {@code art/runtime/jni/jni_internal.cc}.
+ */
+ @Deprecated
public FastDataOutput(@NonNull OutputStream out, int bufferSize) {
+ this(out, bufferSize, true /* use4ByteSequence */);
+ }
+
+ public FastDataOutput(@NonNull OutputStream out, int bufferSize, boolean use4ByteSequence) {
mRuntime = VMRuntime.getRuntime();
- mOut = Objects.requireNonNull(out);
if (bufferSize < 8) {
throw new IllegalArgumentException();
}
@@ -65,6 +81,68 @@ public class FastDataOutput implements DataOutput, Flushable, Closeable {
mBuffer = (byte[]) mRuntime.newNonMovableArray(byte.class, bufferSize);
mBufferPtr = mRuntime.addressOf(mBuffer);
mBufferCap = mBuffer.length;
+ mUse4ByteSequence = use4ByteSequence;
+
+ setOutput(out);
+ }
+
+ /**
+ * Obtain a {@link FastDataOutput} configured with the given
+ * {@link OutputStream} and which encodes large code-points using 3-byte
+ * sequences.
+ * <p>
+ * This <em>is</em> compatible with the {@link DataOutput} API contract,
+ * which specifies that large code-points must be encoded with 3-byte
+ * sequences.
+ */
+ public static FastDataOutput obtainUsing3ByteSequences(@NonNull OutputStream out) {
+ return new FastDataOutput(out, DEFAULT_BUFFER_SIZE, false /* use4ByteSequence */);
+ }
+
+ /**
+ * Obtain a {@link FastDataOutput} configured with the given
+ * {@link OutputStream} and which encodes large code-points using 4-byte
+ * sequences.
+ * <p>
+ * This <em>is not</em> compatible with the {@link DataOutput} API contract,
+ * which specifies that large code-points must be encoded with 3-byte
+ * sequences.
+ */
+ public static FastDataOutput obtainUsing4ByteSequences(@NonNull OutputStream out) {
+ FastDataOutput instance = sOutCache.getAndSet(null);
+ if (instance != null) {
+ instance.setOutput(out);
+ return instance;
+ }
+ return new FastDataOutput(out, DEFAULT_BUFFER_SIZE, true /* use4ByteSequence */);
+ }
+
+ /**
+ * Release a {@link FastDataOutput} to potentially be recycled. You must not
+ * interact with the object after releasing it.
+ */
+ public void release() {
+ if (mBufferPos > 0) {
+ throw new IllegalStateException("Lingering data, call flush() before releasing.");
+ }
+
+ mOut = null;
+ mBufferPos = 0;
+ mStringRefs.clear();
+
+ if (mBufferCap == DEFAULT_BUFFER_SIZE && mUse4ByteSequence) {
+ // Try to return to the cache.
+ sOutCache.compareAndSet(null, this);
+ }
+ }
+
+ /**
+ * Re-initializes the object for the new output.
+ */
+ private void setOutput(@NonNull OutputStream out) {
+ mOut = Objects.requireNonNull(out);
+ mBufferPos = 0;
+ mStringRefs.clear();
}
private void drain() throws IOException {
@@ -83,6 +161,7 @@ public class FastDataOutput implements DataOutput, Flushable, Closeable {
@Override
public void close() throws IOException {
mOut.close();
+ release();
}
@Override
@@ -109,6 +188,14 @@ public class FastDataOutput implements DataOutput, Flushable, Closeable {
@Override
public void writeUTF(String s) throws IOException {
+ if (mUse4ByteSequence) {
+ writeUTFUsing4ByteSequences(s);
+ } else {
+ writeUTFUsing3ByteSequences(s);
+ }
+ }
+
+ private void writeUTFUsing4ByteSequences(String s) throws IOException {
// Attempt to write directly to buffer space if there's enough room,
// otherwise fall back to chunking into place
if (mBufferCap - mBufferPos < 2 + s.length()) drain();
@@ -136,6 +223,27 @@ public class FastDataOutput implements DataOutput, Flushable, Closeable {
}
}
+ private void writeUTFUsing3ByteSequences(String s) throws IOException {
+ final int len = (int) ModifiedUtf8.countBytes(s, false);
+ if (len > MAX_UNSIGNED_SHORT) {
+ throw new IOException("Modified UTF-8 length too large: " + len);
+ }
+
+ // Attempt to write directly to buffer space if there's enough room,
+ // otherwise fall back to chunking into place
+ if (mBufferCap >= 2 + len) {
+ if (mBufferCap - mBufferPos < 2 + len) drain();
+ writeShort(len);
+ ModifiedUtf8.encode(mBuffer, mBufferPos, s);
+ mBufferPos += len;
+ } else {
+ final byte[] tmp = (byte[]) mRuntime.newNonMovableArray(byte.class, len + 1);
+ ModifiedUtf8.encode(tmp, 0, s);
+ writeShort(len);
+ write(tmp, 0, len);
+ }
+ }
+
/**
* Write a {@link String} value with the additional signal that the given
* value is a candidate for being canonicalized, similar to
diff --git a/core/java/com/android/internal/util/ModifiedUtf8.java b/core/java/com/android/internal/util/ModifiedUtf8.java
new file mode 100644
index 000000000000..a144c0034dd2
--- /dev/null
+++ b/core/java/com/android/internal/util/ModifiedUtf8.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.io.UTFDataFormatException;
+
+public class ModifiedUtf8 {
+ /**
+ * Decodes a byte array containing <i>modified UTF-8</i> bytes into a string.
+ *
+ * <p>Note that although this method decodes the (supposedly impossible) zero byte to U+0000,
+ * that's what the RI does too.
+ */
+ public static String decode(byte[] in, char[] out, int offset, int utfSize)
+ throws UTFDataFormatException {
+ int count = 0, s = 0, a;
+ while (count < utfSize) {
+ if ((out[s] = (char) in[offset + count++]) < '\u0080') {
+ s++;
+ } else if (((a = out[s]) & 0xe0) == 0xc0) {
+ if (count >= utfSize) {
+ throw new UTFDataFormatException("bad second byte at " + count);
+ }
+ int b = in[offset + count++];
+ if ((b & 0xC0) != 0x80) {
+ throw new UTFDataFormatException("bad second byte at " + (count - 1));
+ }
+ out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+ } else if ((a & 0xf0) == 0xe0) {
+ if (count + 1 >= utfSize) {
+ throw new UTFDataFormatException("bad third byte at " + (count + 1));
+ }
+ int b = in[offset + count++];
+ int c = in[offset + count++];
+ if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
+ throw new UTFDataFormatException("bad second or third byte at " + (count - 2));
+ }
+ out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+ } else {
+ throw new UTFDataFormatException("bad byte at " + (count - 1));
+ }
+ }
+ return new String(out, 0, s);
+ }
+
+ /**
+ * Returns the number of bytes the modified UTF-8 representation of 's' would take. Note
+ * that this is just the space for the bytes representing the characters, not the length
+ * which precedes those bytes, because different callers represent the length differently,
+ * as two, four, or even eight bytes. If {@code shortLength} is true, we'll throw an
+ * exception if the string is too long for its length to be represented by a short.
+ */
+ public static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {
+ long result = 0;
+ final int length = s.length();
+ for (int i = 0; i < length; ++i) {
+ char ch = s.charAt(i);
+ if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+ ++result;
+ } else if (ch <= 2047) {
+ result += 2;
+ } else {
+ result += 3;
+ }
+ if (shortLength && result > 65535) {
+ throw new UTFDataFormatException("String more than 65535 UTF bytes long");
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Encodes the <i>modified UTF-8</i> bytes corresponding to string {@code s} into the
+ * byte array {@code dst}, starting at the given {@code offset}.
+ */
+ public static void encode(byte[] dst, int offset, String s) {
+ final int length = s.length();
+ for (int i = 0; i < length; i++) {
+ char ch = s.charAt(i);
+ if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+ dst[offset++] = (byte) ch;
+ } else if (ch <= 2047) {
+ dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6)));
+ dst[offset++] = (byte) (0x80 | (0x3f & ch));
+ } else {
+ dst[offset++] = (byte) (0xe0 | (0x0f & (ch >> 12)));
+ dst[offset++] = (byte) (0x80 | (0x3f & (ch >> 6)));
+ dst[offset++] = (byte) (0x80 | (0x3f & ch));
+ }
+ }
+ }
+
+ private ModifiedUtf8() {
+ }
+}
diff --git a/core/java/com/android/internal/util/TEST_MAPPING b/core/java/com/android/internal/util/TEST_MAPPING
index 5881c5198617..41d59bbeb801 100644
--- a/core/java/com/android/internal/util/TEST_MAPPING
+++ b/core/java/com/android/internal/util/TEST_MAPPING
@@ -1,7 +1,20 @@
{
"presubmit": [
{
- "name": "ScreenshotHelperTests"
+ "name": "ScreenshotHelperTests",
+ "file_patterns": ["ScreenshotHelper"]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.util.XmlTest"
+ },
+ {
+ "include-filter": "android.util.BinaryXmlTest"
+ }
+ ],
+ "file_patterns": ["Xml"]
}
]
-} \ No newline at end of file
+}
diff --git a/core/jni/TEST_MAPPING b/core/jni/TEST_MAPPING
new file mode 100644
index 000000000000..004c30ee5113
--- /dev/null
+++ b/core/jni/TEST_MAPPING
@@ -0,0 +1,16 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.util.CharsetUtilsTest"
+ },
+ {
+ "include-filter": "com.android.internal.util.FastDataTest"
+ }
+ ],
+ "file_patterns": ["CharsetUtils|FastData"]
+ }
+ ]
+}
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index ef6fd7dd6829..be82879c8411 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -36,7 +36,6 @@
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <linux/fs.h>
#include <memory>
@@ -254,16 +253,6 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
return INSTALL_FAILED_CONTAINER_ERROR;
}
- // If a filesystem like f2fs supports per-file compression, set the compression bit before data
- // writes
- unsigned int flags;
- if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
- ALOGE("Failed to call FS_IOC_GETFLAGS on %s: %s\n", localTmpFileName, strerror(errno));
- } else if ((flags & FS_COMPR_FL) == 0) {
- flags |= FS_COMPR_FL;
- ioctl(fd, FS_IOC_SETFLAGS, &flags);
- }
-
if (!zipFile->uncompressEntry(zipEntry, fd)) {
ALOGE("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
close(fd);
diff --git a/core/tests/coretests/src/android/util/XmlTest.java b/core/tests/coretests/src/android/util/XmlTest.java
index 4e10ea926966..1cd4d139b229 100644
--- a/core/tests/coretests/src/android/util/XmlTest.java
+++ b/core/tests/coretests/src/android/util/XmlTest.java
@@ -224,7 +224,7 @@ public class XmlTest {
doVerifyRead(in);
}
- private static final String TEST_STRING = "com.example";
+ private static final String TEST_STRING = "com☃example😀typical☃package😀name";
private static final String TEST_STRING_EMPTY = "";
private static final byte[] TEST_BYTES = new byte[] { 0, 1, 2, 3, 4, 3, 2, 1, 0 };
private static final byte[] TEST_BYTES_EMPTY = new byte[0];
diff --git a/core/tests/coretests/src/com/android/internal/util/FastDataTest.java b/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
index 81fb39fed026..04dfd6ee30e2 100644
--- a/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
@@ -23,10 +23,13 @@ import static org.junit.Assert.fail;
import android.annotation.NonNull;
import android.util.ExceptionUtils;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
+import libcore.util.HexEncoding;
+import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -38,22 +41,34 @@ import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Collection;
import java.util.function.Consumer;
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class FastDataTest {
+ private final boolean use4ByteSequence;
+
private static final String TEST_SHORT_STRING = "a";
- private static final String TEST_LONG_STRING = "com☃example☃typical☃package☃name";
+ private static final String TEST_LONG_STRING = "com☃example😀typical☃package😀name";
private static final byte[] TEST_BYTES = TEST_LONG_STRING.getBytes(StandardCharsets.UTF_16LE);
+ @Parameters(name = "use4ByteSequence={0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] { {true}, {false} });
+ }
+
+ public FastDataTest(boolean use4ByteSequence) {
+ this.use4ByteSequence = use4ByteSequence;
+ }
+
@Test
public void testEndOfFile_Int() throws Exception {
try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
- new byte[] { 1 }), 1000)) {
+ new byte[] { 1 }), 1000, use4ByteSequence)) {
assertThrows(EOFException.class, () -> in.readInt());
}
try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
- new byte[] { 1, 1, 1, 1 }), 1000)) {
+ new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
assertEquals(1, in.readByte());
assertThrows(EOFException.class, () -> in.readInt());
}
@@ -62,11 +77,11 @@ public class FastDataTest {
@Test
public void testEndOfFile_String() throws Exception {
try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
- new byte[] { 1 }), 1000)) {
+ new byte[] { 1 }), 1000, use4ByteSequence)) {
assertThrows(EOFException.class, () -> in.readUTF());
}
try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
- new byte[] { 1, 1, 1, 1 }), 1000)) {
+ new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
assertThrows(EOFException.class, () -> in.readUTF());
}
}
@@ -74,12 +89,12 @@ public class FastDataTest {
@Test
public void testEndOfFile_Bytes_Small() throws Exception {
try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
- new byte[] { 1, 1, 1, 1 }), 1000)) {
+ new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
final byte[] tmp = new byte[10];
assertThrows(EOFException.class, () -> in.readFully(tmp));
}
try (FastDataInput in = new FastDataInput(new ByteArrayInputStream(
- new byte[] { 1, 1, 1, 1 }), 1000)) {
+ new byte[] { 1, 1, 1, 1 }), 1000, use4ByteSequence)) {
final byte[] tmp = new byte[10_000];
assertThrows(EOFException.class, () -> in.readFully(tmp));
}
@@ -88,7 +103,8 @@ public class FastDataTest {
@Test
public void testUTF_Bounds() throws Exception {
final char[] buf = new char[65_534];
- try (FastDataOutput out = new FastDataOutput(new ByteArrayOutputStream(), BOUNCE_SIZE)) {
+ try (FastDataOutput out = new FastDataOutput(new ByteArrayOutputStream(),
+ BOUNCE_SIZE, use4ByteSequence)) {
// Writing simple string will fit fine
Arrays.fill(buf, '!');
final String simple = new String(buf);
@@ -100,11 +116,15 @@ public class FastDataTest {
final String complex = new String(buf);
assertThrows(IOException.class, () -> out.writeUTF(complex));
assertThrows(IOException.class, () -> out.writeInternedUTF(complex));
+
+ out.flush();
}
}
@Test
public void testTranscode() throws Exception {
+ Assume.assumeFalse(use4ByteSequence);
+
// Verify that upstream data can be read by fast
{
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
@@ -113,20 +133,22 @@ public class FastDataTest {
out.flush();
final FastDataInput in = new FastDataInput(
- new ByteArrayInputStream(outStream.toByteArray()), BOUNCE_SIZE);
- doTransodeRead(in);
+ new ByteArrayInputStream(outStream.toByteArray()),
+ BOUNCE_SIZE, use4ByteSequence);
+ doTranscodeRead(in);
}
// Verify that fast data can be read by upstream
{
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- final FastDataOutput out = new FastDataOutput(outStream, BOUNCE_SIZE);
+ final FastDataOutput out = new FastDataOutput(outStream,
+ BOUNCE_SIZE, use4ByteSequence);
doTranscodeWrite(out);
out.flush();
final DataInputStream in = new DataInputStream(
new ByteArrayInputStream(outStream.toByteArray()));
- doTransodeRead(in);
+ doTranscodeRead(in);
}
}
@@ -144,7 +166,7 @@ public class FastDataTest {
out.writeDouble(32d);
}
- private static void doTransodeRead(DataInput in) throws IOException {
+ private static void doTranscodeRead(DataInput in) throws IOException {
assertEquals(true, in.readBoolean());
assertEquals(false, in.readBoolean());
assertEquals(1, in.readByte());
@@ -225,10 +247,12 @@ public class FastDataTest {
doBounce((out) -> {
out.writeUTF("");
out.writeUTF("☃");
+ out.writeUTF("😀");
out.writeUTF("example");
}, (in) -> {
assertEquals("", in.readUTF());
assertEquals("☃", in.readUTF());
+ assertEquals("😀", in.readUTF());
assertEquals("example", in.readUTF());
});
}
@@ -263,6 +287,35 @@ public class FastDataTest {
}, 1);
}
+ /**
+ * Verify that we encode every valid code-point identically to RI when
+ * running in 3-byte mode.
+ */
+ @Test
+ public void testBounce_UTF_Exhaustive() throws Exception {
+ Assume.assumeFalse(use4ByteSequence);
+
+ final ByteArrayOutputStream slowStream = new ByteArrayOutputStream();
+ final DataOutput slowData = new DataOutputStream(slowStream);
+
+ final ByteArrayOutputStream fastStream = new ByteArrayOutputStream();
+ final FastDataOutput fastData = FastDataOutput.obtainUsing3ByteSequences(fastStream);
+
+ for (int cp = Character.MIN_CODE_POINT; cp < Character.MAX_CODE_POINT; cp++) {
+ if (Character.isValidCodePoint(cp)) {
+ final String cpString = new String(Character.toChars(cp));
+ slowStream.reset();
+ slowData.writeUTF(cpString);
+ fastStream.reset();
+ fastData.writeUTF(cpString);
+ fastData.flush();
+ assertEquals("Bad encoding for code-point " + Integer.toHexString(cp),
+ HexEncoding.encodeToString(slowStream.toByteArray()),
+ HexEncoding.encodeToString(fastStream.toByteArray()));
+ }
+ }
+ }
+
@Test
public void testBounce_InternedUTF() throws Exception {
doBounce((out) -> {
@@ -355,22 +408,24 @@ public class FastDataTest {
* Verify that some common data can be written and read back, effectively
* "bouncing" it through a serialized representation.
*/
- private static void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
+ private void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
@NonNull ThrowingConsumer<FastDataInput> in) throws Exception {
doBounce(out, in, BOUNCE_REPEAT);
}
- private static void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
+ private void doBounce(@NonNull ThrowingConsumer<FastDataOutput> out,
@NonNull ThrowingConsumer<FastDataInput> in, int count) throws Exception {
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- final FastDataOutput outData = new FastDataOutput(outStream, BOUNCE_SIZE);
+ final FastDataOutput outData = new FastDataOutput(outStream,
+ BOUNCE_SIZE, use4ByteSequence);
for (int i = 0; i < count; i++) {
out.accept(outData);
}
outData.flush();
final ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
- final FastDataInput inData = new FastDataInput(inStream, BOUNCE_SIZE);
+ final FastDataInput inData = new FastDataInput(inStream,
+ BOUNCE_SIZE, use4ByteSequence);
for (int i = 0; i < count; i++) {
in.accept(inData);
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 055e5ad17def..ad089b63a7c1 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -519,7 +519,7 @@ public final class Bitmap implements Parcelable {
ARGB_8888 (5),
/**
- * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
+ * Each pixel is stored on 8 bytes. Each channel (RGB and alpha
* for translucency) is stored as a
* {@link android.util.Half half-precision floating point value}.
*
diff --git a/libs/incident/libincident.map.txt b/libs/incident/libincident.map.txt
index f157763f1a03..f75cceaf59fa 100644
--- a/libs/incident/libincident.map.txt
+++ b/libs/incident/libincident.map.txt
@@ -1,15 +1,15 @@
LIBINCIDENT {
global:
- AIncidentReportArgs_init; # apex # introduced=30
- AIncidentReportArgs_clone; # apex # introduced=30
- AIncidentReportArgs_delete; # apex # introduced=30
- AIncidentReportArgs_setAll; # apex # introduced=30
- AIncidentReportArgs_setPrivacyPolicy; # apex # introduced=30
- AIncidentReportArgs_addSection; # apex # introduced=30
- AIncidentReportArgs_setReceiverPackage; # apex # introduced=30
- AIncidentReportArgs_setReceiverClass; # apex # introduced=30
- AIncidentReportArgs_addHeader; # apex # introduced=30
- AIncidentReportArgs_takeReport; # apex # introduced=30
+ AIncidentReportArgs_init; # systemapi # introduced=30
+ AIncidentReportArgs_clone; # systemapi # introduced=30
+ AIncidentReportArgs_delete; # systemapi # introduced=30
+ AIncidentReportArgs_setAll; # systemapi # introduced=30
+ AIncidentReportArgs_setPrivacyPolicy; # systemapi # introduced=30
+ AIncidentReportArgs_addSection; # systemapi # introduced=30
+ AIncidentReportArgs_setReceiverPackage; # systemapi # introduced=30
+ AIncidentReportArgs_setReceiverClass; # systemapi # introduced=30
+ AIncidentReportArgs_addHeader; # systemapi # introduced=30
+ AIncidentReportArgs_takeReport; # systemapi # introduced=30
local:
*;
};
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java
index f6914efd6d83..23d6e34db4f1 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedBackupTaskTest.java
@@ -22,8 +22,8 @@ import static com.android.server.backup.encryption.protos.nano.ChunksMetadataPro
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java
index 096b2da10c98..bfc5d0dca3ff 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupTaskTest.java
@@ -18,9 +18,9 @@ package com.android.server.backup.encryption.tasks;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
index fa4fef50ac1a..222b88221ba2 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedKvBackupTaskTest.java
@@ -19,8 +19,8 @@ package com.android.server.backup.encryption.tasks;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;
@@ -41,13 +41,6 @@ import com.android.server.backup.encryption.protos.nano.KeyValueListingProto;
import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
import com.android.server.backup.testing.CryptoTestUtils;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.crypto.SecretKey;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -59,6 +52,14 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.crypto.SecretKey;
+
+
@RunWith(RobolectricTestRunner.class)
public class EncryptedKvBackupTaskTest {
private static final boolean INCREMENTAL = true;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
index 5efce4da970f..30bbc2a3a864 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
@@ -21,9 +21,10 @@ import static android.os.UserHandle.MU_ENABLED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index 95f7ef41b10b..508dffc2fa21 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -18,7 +18,7 @@ package com.android.settingslib.net;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
index d6c8816ecc58..c190d0731a40 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
@@ -22,7 +22,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.Activity;
@@ -141,7 +141,7 @@ public class EditUserInfoControllerTest {
dialog.show();
dialog.cancel();
- verifyZeroInteractions(successCallback);
+ verifyNoInteractions(successCallback);
verify(cancelCallback, times(1))
.run();
}
@@ -157,7 +157,7 @@ public class EditUserInfoControllerTest {
dialog.show();
dialog.getButton(Dialog.BUTTON_NEGATIVE).performClick();
- verifyZeroInteractions(successCallback);
+ verifyNoInteractions(successCallback);
verify(cancelCallback, times(1))
.run();
}
@@ -178,7 +178,7 @@ public class EditUserInfoControllerTest {
verify(successCallback, times(1))
.accept("test", oldUserIcon);
- verifyZeroInteractions(cancelCallback);
+ verifyNoInteractions(cancelCallback);
}
@Test
@@ -196,7 +196,7 @@ public class EditUserInfoControllerTest {
verify(successCallback, times(1))
.accept("test", null);
- verifyZeroInteractions(cancelCallback);
+ verifyNoInteractions(cancelCallback);
}
@Test
@@ -217,7 +217,7 @@ public class EditUserInfoControllerTest {
verify(successCallback, times(1))
.accept(expectedNewName, mCurrentIcon);
- verifyZeroInteractions(cancelCallback);
+ verifyNoInteractions(cancelCallback);
}
@Test
@@ -236,7 +236,7 @@ public class EditUserInfoControllerTest {
verify(successCallback, times(1))
.accept("test", newPhoto);
- verifyZeroInteractions(cancelCallback);
+ verifyNoInteractions(cancelCallback);
}
@Test
@@ -255,7 +255,7 @@ public class EditUserInfoControllerTest {
verify(successCallback, times(1))
.accept("test", newPhoto);
- verifyZeroInteractions(cancelCallback);
+ verifyNoInteractions(cancelCallback);
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
index 0b3495def21f..ca0aa0d7b900 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/UpdatableListPreferenceDialogFragmentTest.java
@@ -56,7 +56,7 @@ public class UpdatableListPreferenceDialogFragmentTest {
mUpdatableListPrefDlgFragment = spy(UpdatableListPreferenceDialogFragment
.newInstance(KEY, MetricsProto.MetricsEvent.DIALOG_SWITCH_A2DP_DEVICES));
- mEntries = spy(new ArrayList<>());
+ mEntries = new ArrayList<>();
mUpdatableListPrefDlgFragment.setEntries(mEntries);
mUpdatableListPrefDlgFragment
.setMetricsCategory(mUpdatableListPrefDlgFragment.getArguments());
diff --git a/rs/OWNERS b/rs/OWNERS
index 61853d3d40cf..fd03660d2d81 100644
--- a/rs/OWNERS
+++ b/rs/OWNERS
@@ -1,5 +1,2 @@
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-miaowang@google.com
-yangni@google.com
+# Bug component: 43047
+include platform/frameworks/rs:/RS_OWNERS # RenderScript team
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c3fc8e0a7535..774fe5bc862c 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1095,7 +1095,7 @@ public class Vpn {
// Except for Settings and VpnDialogs, the caller should be matched one of oldPackage or
// newPackage. Otherwise, non VPN owner might get the VPN always-on status of the VPN owner.
// See b/191382886.
- if (mContext.checkCallingOrSelfPermission(CONTROL_VPN) != PERMISSION_GRANTED) {
+ if (!hasControlVpnPermission()) {
if (oldPackage != null) {
verifyCallingUidAndPackage(oldPackage);
}
@@ -2045,6 +2045,10 @@ public class Vpn {
"Unauthorized Caller");
}
+ private boolean hasControlVpnPermission() {
+ return mContext.checkCallingOrSelfPermission(CONTROL_VPN) == PERMISSION_GRANTED;
+ }
+
private class Connection implements ServiceConnection {
private IBinder mService;
@@ -3337,7 +3341,7 @@ public class Vpn {
// TODO(b/230548427): Remove SDK check once VPN related stuff are
// decoupled from ConnectivityServiceTest.
- if (SdkLevel.isAtLeastT() && category != null) {
+ if (SdkLevel.isAtLeastT() && category != null && isVpnApp(mPackage)) {
sendEventToVpnManagerApp(category, errorClass, errorCode,
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
mActiveNetwork,
@@ -3846,8 +3850,10 @@ public class Vpn {
Binder.restoreCallingIdentity(token);
}
- // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop.
- // This mirrors the prepareAndAuthorize that is used by VpnService.
+ // If package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop.
+ if (hasControlVpnPermission()) {
+ setPackageAuthorization(packageName, VpnManager.TYPE_VPN_PLATFORM);
+ }
// Return whether the app is already pre-consented
return isVpnProfilePreConsented(mContext, packageName);
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 7d17109af7d3..edcf357cd233 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -43,23 +43,23 @@ import static com.android.server.backup.testing.Utils.transferStreamedData;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.intThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.intThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import static org.robolectric.shadow.api.Shadow.extract;
@@ -2185,7 +2185,7 @@ public class KeyValueBackupTaskTest {
task.waitCancel();
reset(transportMock.transport);
taskFinished.block();
- verifyZeroInteractions(transportMock.transport);
+ verifyNoInteractions(transportMock.transport);
}
@Test
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index 9dfb0cc289ee..d4b6c91eb7a0 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -316,9 +316,11 @@ public final class LocationAccessPolicy {
return LocationPermissionResult.ALLOWED;
}
- // Check the system-wide requirements. If the location main switch is off or
- // the app's profile isn't in foreground, return a soft denial.
- if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid)) {
+ // Check the system-wide requirements. If the location main switch is off and the caller is
+ // not in the allowlist of apps that always have loation access or the app's profile
+ // isn't in the foreground, return a soft denial.
+ if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid,
+ query.callingPackage)) {
return LocationPermissionResult.DENIED_SOFT;
}
@@ -344,15 +346,16 @@ public final class LocationAccessPolicy {
return LocationPermissionResult.ALLOWED;
}
-
private static boolean checkManifestPermission(Context context, int pid, int uid,
String permissionToCheck) {
return context.checkPermission(permissionToCheck, pid, uid)
== PackageManager.PERMISSION_GRANTED;
}
- private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid) {
- if (!isLocationModeEnabled(context, UserHandle.getUserHandleForUid(uid).getIdentifier())) {
+ private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid,
+ @NonNull String callingPackage) {
+ if (!isLocationModeEnabled(context, UserHandle.getUserHandleForUid(uid).getIdentifier())
+ && !isLocationBypassAllowed(context, callingPackage)) {
if (DBG) Log.w(TAG, "Location disabled, failed, (" + uid + ")");
return false;
}
@@ -373,6 +376,16 @@ public final class LocationAccessPolicy {
return locationManager.isLocationEnabledForUser(UserHandle.of(userId));
}
+ private static boolean isLocationBypassAllowed(@NonNull Context context,
+ @NonNull String callingPackage) {
+ for (String bypassPackage : getLocationBypassPackages(context)) {
+ if (callingPackage.equals(bypassPackage)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* @return An array of packages that are always allowed to access location.
*/
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 417fd4904599..a22e43e07d34 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -49,7 +49,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
private static final String TAG = "CellSignalStrengthNr";
// Lifted from Default carrier configs and max range of SSRSRP
- // Boundaries: [-140 dB, -44 dB]
+ // Boundaries: [-156 dB, -31 dB]
private int[] mSsRsrpThresholds = new int[] {
-110, /* SIGNAL_STRENGTH_POOR */
-90, /* SIGNAL_STRENGTH_MODERATE */
@@ -173,14 +173,14 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
*/
public CellSignalStrengthNr(int csiRsrp, int csiRsrq, int csiSinr, int csiCqiTableIndex,
List<Byte> csiCqiReport, int ssRsrp, int ssRsrq, int ssSinr) {
- mCsiRsrp = inRangeOrUnavailable(csiRsrp, -140, -44);
+ mCsiRsrp = inRangeOrUnavailable(csiRsrp, -156, -31);
mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3);
mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23);
mCsiCqiTableIndex = inRangeOrUnavailable(csiCqiTableIndex, 1, 3);
mCsiCqiReport = csiCqiReport.stream()
- .map(cqi -> new Integer(inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 0, 15)))
+ .map(cqi -> inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 0, 15))
.collect(Collectors.toList());
- mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44);
+ mSsRsrp = inRangeOrUnavailable(ssRsrp, -156, -31);
mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20);
mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40);
updateLevel(null, null);
@@ -212,8 +212,8 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
}
/**
- * Reference: 3GPP TS 38.215.
- * Range: -140 dBm to -44 dBm.
+ * Reference: 3GPP TS 38.133 10.1.6.1.
+ * Range: -156 dBm to -31 dBm.
* @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
* value.
*/
@@ -242,8 +242,8 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
}
/**
- * Reference: 3GPP TS 38.215.
- * Range: -140 dBm to -44 dBm.
+ * Reference: 3GPP TS 38.133 10.1.6.1.
+ * Range: -156 dBm to -31 dBm.
* @return CSI reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
* value.
*/
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d2858eca8171..f25498022087 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3040,8 +3040,9 @@ public class SubscriptionManager {
* @param callback Callback will be triggered once it succeeds or failed.
* Pass null if don't care about the result.
*
+ * @throws IllegalStateException when subscription manager service is not available.
+ * @throws SecurityException when clients do not have MODIFY_PHONE_STATE permission.
* @hide
- *
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -3051,7 +3052,9 @@ public class SubscriptionManager {
if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
try {
ISub iSub = TelephonyManager.getSubscriptionService();
- if (iSub == null) return;
+ if (iSub == null) {
+ throw new IllegalStateException("subscription manager service is null.");
+ }
ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@Override
@@ -3071,7 +3074,8 @@ public class SubscriptionManager {
};
iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
} catch (RemoteException ex) {
- // ignore it
+ loge("setPreferredDataSubscriptionId RemoteException=" + ex);
+ ex.rethrowFromSystemServer();
}
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a710e38538ce..7fc8871e89c8 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1134,10 +1134,7 @@ public class ApnSetting implements Parcelable {
return false;
}
// DEFAULT can handle HIPRI.
- if (hasApnType(type)) {
- return true;
- }
- return false;
+ return hasApnType(type);
}
// Check whether the types of two APN same (even only one type of each APN is same).