Merge "Revert "Move frameworks/base/Android.mk to build/tasks"" into main
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5713e9e..a4b16f8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8158,6 +8158,10 @@
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
+ <service android:name="com.android.system.virtualmachine.SecretkeeperJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
<service android:name="com.android.server.PruneInstantAppsJobService"
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 61e6a36..7d740ef 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -88,6 +88,9 @@
<!-- Colombia: 1-6 digits (not confirmed) -->
<shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739|85517|491289" />
+ <!-- Costa Rica -->
+ <shortcode country="cr" pattern="\\d{1,6}" free="466453" />
+
<!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
<shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
@@ -143,6 +146,9 @@
<!-- Greece: 5 digits (54xxx, 19yxx, x=0-9, y=0-5): http://www.cmtelecom.com/premium-sms/greece -->
<shortcode country="gr" pattern="\\d{5}" premium="54\\d{3}|19[0-5]\\d{2}" free="116\\d{3}|12115" />
+ <!-- Guatemala -->
+ <shortcode country="gt" pattern="\\d{1,6}" free="466453" />
+
<!-- Croatia -->
<shortcode country="hr" pattern="\\d{1,5}" free="13062" />
@@ -241,10 +247,10 @@
<shortcode country="ph" pattern="\\d{1,5}" free="2147|5495|5496" />
<!-- Pakistan -->
- <shortcode country="pk" pattern="\\d{1,5}" free="2057" />
+ <shortcode country="pk" pattern="\\d{1,5}" free="2057|9092" />
<!-- Palestine: 5 digits, known premium codes listed -->
- <shortcode country="ps" pattern="\\d{1,5}" free="37477" />
+ <shortcode country="ps" pattern="\\d{1,5}" free="37477|6681" />
<!-- Poland: 4-5 digits (not confirmed), known premium codes listed, plus EU -->
<shortcode country="pl" pattern="\\d{4,5}" premium="74240|79(?:10|866)|92525" free="116\\d{3}|8012|80921" />
@@ -324,4 +330,7 @@
<!-- South Africa -->
<shortcode country="za" pattern="\\d{1,5}" free="44136|30791|36056" />
+ <!-- Zimbabwe -->
+ <shortcode country="zw" pattern="\\d{1,5}" free="33679" />
+
</shortcodes>
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index 3f7f088..51100c0 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -29,11 +29,13 @@
import com.android.internal.util.Preconditions;
import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.NeverInline;
import libcore.util.NativeAllocationRegistry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Locale;
import java.util.Objects;
/**
@@ -83,6 +85,30 @@
return mChars;
}
+ private void rangeCheck(int start, int end) {
+ if (start < 0 || start > end || end > mChars.length) {
+ throwRangeError(start, end);
+ }
+ }
+
+ @NeverInline
+ private void throwRangeError(int start, int end) {
+ throw new IllegalArgumentException(String.format(Locale.US,
+ "start(%d) end(%d) length(%d) out of bounds", start, end, mChars.length));
+ }
+
+ private void offsetCheck(int offset) {
+ if (offset < 0 || offset >= mChars.length) {
+ throwOffsetError(offset);
+ }
+ }
+
+ @NeverInline
+ private void throwOffsetError(int offset) {
+ throw new IllegalArgumentException(String.format(Locale.US,
+ "offset (%d) length(%d) out of bounds", offset, mChars.length));
+ }
+
/**
* Returns the width of a given range.
*
@@ -91,12 +117,7 @@
*/
public @FloatRange(from = 0.0) @Px float getWidth(
@IntRange(from = 0) int start, @IntRange(from = 0) int end) {
- Preconditions.checkArgument(0 <= start && start <= mChars.length,
- "start(%d) must be 0 <= start <= %d", start, mChars.length);
- Preconditions.checkArgument(0 <= end && end <= mChars.length,
- "end(%d) must be 0 <= end <= %d", end, mChars.length);
- Preconditions.checkArgument(start <= end,
- "start(%d) is larger than end(%d)", start, end);
+ rangeCheck(start, end);
return nGetWidth(mNativePtr, start, end);
}
@@ -118,12 +139,7 @@
*/
public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
@NonNull Rect rect) {
- Preconditions.checkArgument(0 <= start && start <= mChars.length,
- "start(%d) must be 0 <= start <= %d", start, mChars.length);
- Preconditions.checkArgument(0 <= end && end <= mChars.length,
- "end(%d) must be 0 <= end <= %d", end, mChars.length);
- Preconditions.checkArgument(start <= end,
- "start(%d) is larger than end(%d)", start, end);
+ rangeCheck(start, end);
Preconditions.checkNotNull(rect);
nGetBounds(mNativePtr, mChars, start, end, rect);
}
@@ -137,12 +153,7 @@
*/
public void getFontMetricsInt(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
@NonNull Paint.FontMetricsInt outMetrics) {
- Preconditions.checkArgument(0 <= start && start <= mChars.length,
- "start(%d) must be 0 <= start <= %d", start, mChars.length);
- Preconditions.checkArgument(0 <= end && end <= mChars.length,
- "end(%d) must be 0 <= end <= %d", end, mChars.length);
- Preconditions.checkArgument(start <= end,
- "start(%d) is larger than end(%d)", start, end);
+ rangeCheck(start, end);
Objects.requireNonNull(outMetrics);
long packed = nGetExtent(mNativePtr, mChars, start, end);
@@ -158,8 +169,7 @@
* @param offset an offset of the character.
*/
public @FloatRange(from = 0.0f) @Px float getCharWidthAt(@IntRange(from = 0) int offset) {
- Preconditions.checkArgument(0 <= offset && offset < mChars.length,
- "offset(%d) is larger than text length %d" + offset, mChars.length);
+ offsetCheck(offset);
return nGetCharWidthAt(mNativePtr, offset);
}
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 2795cfe..f05ea9c 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -336,8 +336,9 @@
* This method must not be called when the Visualizer is enabled.
* @param size requested capture size
* @return {@link #SUCCESS} in case of success,
- * {@link #ERROR_BAD_VALUE} in case of failure.
- * @throws IllegalStateException
+ * {@link #ERROR_INVALID_OPERATION} if Visualizer effect enginer not enabled.
+ * @throws IllegalStateException if the effect is not in proper state.
+ * @throws IllegalArgumentException if the size parameter is invalid (out of supported range).
*/
public int setCaptureSize(int size)
throws IllegalStateException {
@@ -345,7 +346,13 @@
if (mState != STATE_INITIALIZED) {
throw(new IllegalStateException("setCaptureSize() called in wrong state: "+mState));
}
- return native_setCaptureSize(size);
+
+ int ret = native_setCaptureSize(size);
+ if (ret == ERROR_BAD_VALUE) {
+ throw(new IllegalArgumentException("setCaptureSize to " + size + " failed"));
+ }
+
+ return ret;
}
}
diff --git a/media/java/android/media/metrics/PlaybackSession.java b/media/java/android/media/metrics/PlaybackSession.java
index f8dd756..6223acf 100644
--- a/media/java/android/media/metrics/PlaybackSession.java
+++ b/media/java/android/media/metrics/PlaybackSession.java
@@ -24,7 +24,10 @@
import java.util.Objects;
/**
- * An instances of this class represents a session of media playback.
+ * An instance of this class represents a session of media playback used to report playback
+ * metrics and events.
+ *
+ * Create a new instance using {@link MediaMetricsManager#createPlaybackSession}.
*/
public final class PlaybackSession implements AutoCloseable {
private final @NonNull String mId;
@@ -80,6 +83,21 @@
mManager.reportTrackChangeEvent(mId, event);
}
+ /**
+ * A session ID is used to identify a unique playback and to tie together lower-level
+ * playback components.
+ *
+ * Associate this session with a {@link MediaCodec} by passing the ID into
+ * {@link MediaFormat} through {@link MediaFormat#LOG_SESSION_ID} when
+ * creating the {@link MediaCodec}.
+ *
+ * Associate this session with an {@link AudioTrack} by calling
+ * {@link AudioTrack#setLogSessionId}.
+ *
+ * Associate this session with {@link MediaDrm} and {@link MediaCrypto} by calling
+ * {@link MediaDrm#getPlaybackComponent} and then calling
+ * {@link PlaybackComponent#setLogSessionId}.
+ */
public @NonNull LogSessionId getSessionId() {
return mLogSessionId;
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 8396005..0fc80dd 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2895,6 +2895,10 @@
jint offset,
jint size,
std::shared_ptr<C2Buffer> *buffer) {
+ if ((offset + size) > context->capacity()) {
+ ALOGW("extractBufferFromContext: offset + size provided exceed capacity");
+ return;
+ }
*buffer = context->toC2Buffer(offset, size);
if (*buffer == nullptr) {
if (!context->mMemory) {
@@ -2995,18 +2999,15 @@
"MediaCodec.LinearBlock#obtain method to obtain a compatible buffer.");
return;
}
- sp<CryptoInfosWrapper> cryptoInfos = new CryptoInfosWrapper{decltype(cryptoInfos->value)()};
- jint sampleSize = 0;
+ sp<CryptoInfosWrapper> cryptoInfos = nullptr;
+ jint sampleSize = totalSize;
if (cryptoInfoArray != nullptr) {
+ cryptoInfos = new CryptoInfosWrapper{decltype(cryptoInfos->value)()};
extractCryptoInfosFromObjectArray(env,
&sampleSize,
&cryptoInfos->value,
cryptoInfoArray,
&errorDetailMsg);
- } else {
- sampleSize = totalSize;
- std::unique_ptr<CodecCryptoInfo> cryptoInfo{new MediaCodecCryptoInfo(totalSize)};
- cryptoInfos->value.push_back(std::move(cryptoInfo));
}
if (env->ExceptionCheck()) {
// Creation of cryptoInfo failed. Let the exception bubble up.
diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp
index 09c45ea..9ae5c99 100644
--- a/media/jni/audioeffect/Visualizer.cpp
+++ b/media/jni/audioeffect/Visualizer.cpp
@@ -25,7 +25,6 @@
#include <limits.h>
#include <audio_utils/fixedfft.h>
-#include <cutils/bitops.h>
#include <utils/Thread.h>
#include <android/content/AttributionSourceState.h>
@@ -59,8 +58,8 @@
status_t status = AudioEffect::set(
SL_IID_VISUALIZATION, nullptr, priority, cbf, user, sessionId, io, device, probe);
if (status == NO_ERROR || status == ALREADY_EXISTS) {
- initCaptureSize();
- initSampleRate();
+ status = initCaptureSize();
+ if (status == NO_ERROR) initSampleRate();
}
return status;
}
@@ -152,9 +151,8 @@
status_t Visualizer::setCaptureSize(uint32_t size)
{
- if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
- size < VISUALIZER_CAPTURE_SIZE_MIN ||
- popcount(size) != 1) {
+ if (!isCaptureSizeValid(size)) {
+ ALOGE("%s with invalid capture size %u from HAL", __func__, size);
return BAD_VALUE;
}
@@ -172,7 +170,7 @@
*((int32_t *)p->data + 1)= size;
status_t status = setParameter(p);
- ALOGV("setCaptureSize size %d status %d p->status %d", size, status, p->status);
+ ALOGV("setCaptureSize size %u status %d p->status %d", size, status, p->status);
if (status == NO_ERROR) {
status = p->status;
@@ -257,8 +255,8 @@
if ((type != MEASUREMENT_MODE_PEAK_RMS)
// for peak+RMS measurement, the results are 2 int32_t values
|| (number != 2)) {
- ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d",
- number);
+ ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %u",
+ number);
return BAD_VALUE;
}
@@ -390,7 +388,7 @@
}
}
-uint32_t Visualizer::initCaptureSize()
+status_t Visualizer::initCaptureSize()
{
uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
effect_param_t *p = (effect_param_t *)buf32;
@@ -405,14 +403,20 @@
}
uint32_t size = 0;
- if (status == NO_ERROR) {
- size = *((int32_t *)p->data + 1);
+ if (status != NO_ERROR) {
+ ALOGE("%s getParameter failed status %d", __func__, status);
+ return status;
}
+
+ size = *((int32_t *)p->data + 1);
+ if (!isCaptureSizeValid(size)) {
+ ALOGE("%s with invalid capture size %u from HAL", __func__, size);
+ return BAD_VALUE;
+ }
+
mCaptureSize = size;
-
- ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
-
- return size;
+ ALOGV("%s size %u status %d", __func__, mCaptureSize, status);
+ return NO_ERROR;
}
void Visualizer::initSampleRate()
diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h
index b38c01f..26d58d0 100644
--- a/media/jni/audioeffect/Visualizer.h
+++ b/media/jni/audioeffect/Visualizer.h
@@ -20,6 +20,8 @@
#include <media/AudioEffect.h>
#include <system/audio_effects/effect_visualizer.h>
#include <utils/Thread.h>
+#include <cstdint>
+#include <cutils/bitops.h>
#include "android/content/AttributionSourceState.h"
/**
@@ -170,8 +172,12 @@
status_t doFft(uint8_t *fft, uint8_t *waveform);
void periodicCapture();
- uint32_t initCaptureSize();
+ status_t initCaptureSize();
void initSampleRate();
+ static constexpr bool isCaptureSizeValid(uint32_t size) {
+ return size <= VISUALIZER_CAPTURE_SIZE_MAX && size >= VISUALIZER_CAPTURE_SIZE_MIN &&
+ popcount(size) == 1;
+ }
Mutex mCaptureLock;
uint32_t mCaptureRate = CAPTURE_RATE_DEF;
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index b6ba6a5..5320033 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -84,15 +84,6 @@
{
"name": "CtsVcnTestCases",
"file_patterns": ["VcnManagementService\\.java"]
- },
- {
- "name": "FrameworksNetTests",
- "options": [
- {
- "exclude-annotation": "com.android.testutils.SkipPresubmit"
- }
- ],
- "file_patterns": ["VpnManagerService\\.java"]
}
],
"presubmit-large": [
@@ -126,5 +117,10 @@
],
"file_patterns": ["VpnManagerService\\.java"]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksVpnTests"
+ }
]
}
diff --git a/services/core/java/com/android/server/connectivity/TEST_MAPPING b/services/core/java/com/android/server/connectivity/TEST_MAPPING
index 687d4b0..c2b1c77 100644
--- a/services/core/java/com/android/server/connectivity/TEST_MAPPING
+++ b/services/core/java/com/android/server/connectivity/TEST_MAPPING
@@ -7,7 +7,7 @@
"exclude-annotation": "com.android.testutils.SkipPresubmit"
}
],
- "file_patterns": ["Vpn\\.java", "VpnIkeV2Utils\\.java", "VpnProfileStore\\.java"]
+ "file_patterns": ["VpnIkeV2Utils\\.java", "VpnProfileStore\\.java"]
}
],
"presubmit-large": [
@@ -26,5 +26,10 @@
],
"file_patterns": ["Vpn\\.java", "VpnIkeV2Utils\\.java", "VpnProfileStore\\.java"]
}
+ ],
+ "postsubmit":[
+ {
+ "name":"FrameworksVpnTests"
+ }
]
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/net/TEST_MAPPING b/services/core/java/com/android/server/net/TEST_MAPPING
index e0376ed..8db5905 100644
--- a/services/core/java/com/android/server/net/TEST_MAPPING
+++ b/services/core/java/com/android/server/net/TEST_MAPPING
@@ -28,5 +28,10 @@
}
]
}
+ ],
+ "postsubmit":[
+ {
+ "name":"FrameworksVpnTests"
+ }
]
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 677a5d1..e2f8c50 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3194,12 +3194,7 @@
} else if (tagName.equals("verifier")) {
final String deviceIdentity = parser.getAttributeValue(null, "device");
- try {
- mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
- } catch (IllegalArgumentException e) {
- Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
- + e.getMessage());
- }
+ mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
} else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
// No longer used.
} else if (tagName.equals("keyset-settings")) {
@@ -3228,7 +3223,7 @@
}
str.close();
- } catch (IOException | XmlPullParserException e) {
+ } catch (IOException | XmlPullParserException | IllegalArgumentException e) {
// Remove corrupted file and retry.
atomicFile.failRead(str, e);
diff --git a/services/tests/VpnTests/java/android/net/Ikev2VpnProfileTest.java b/services/tests/VpnTests/java/android/net/Ikev2VpnProfileTest.java
new file mode 100644
index 0000000..e12e961f
--- /dev/null
+++ b/services/tests/VpnTests/java/android/net/Ikev2VpnProfileTest.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
+import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V6;
+import static android.net.cts.util.IkeSessionTestUtils.getTestIkeSessionParams;
+
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.net.ipsec.ike.IkeKeyIdIdentification;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.os.Build;
+import android.test.mock.MockContext;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.net.VpnProfile;
+import com.android.internal.org.bouncycastle.x509.X509V1CertificateGenerator;
+import com.android.net.module.util.ProxyUtils;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.security.auth.x500.X500Principal;
+
+/** Unit tests for {@link Ikev2VpnProfile.Builder}. */
+@SmallTest
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+public class Ikev2VpnProfileTest {
+ private static final String SERVER_ADDR_STRING = "1.2.3.4";
+ private static final String IDENTITY_STRING = "Identity";
+ private static final String USERNAME_STRING = "username";
+ private static final String PASSWORD_STRING = "pa55w0rd";
+ private static final String EXCL_LIST = "exclList";
+ private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
+ private static final int TEST_MTU = 1300;
+
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
+ private final MockContext mMockContext =
+ new MockContext() {
+ @Override
+ public String getOpPackageName() {
+ return "fooPackage";
+ }
+ };
+ private final ProxyInfo mProxy = ProxyInfo.buildDirectProxy(
+ SERVER_ADDR_STRING, -1, ProxyUtils.exclusionStringAsList(EXCL_LIST));
+
+ private X509Certificate mUserCert;
+ private X509Certificate mServerRootCa;
+ private PrivateKey mPrivateKey;
+
+ @Before
+ public void setUp() throws Exception {
+ mServerRootCa = generateRandomCertAndKeyPair().cert;
+
+ final CertificateAndKey userCertKey = generateRandomCertAndKeyPair();
+ mUserCert = userCertKey.cert;
+ mPrivateKey = userCertKey.key;
+ }
+
+ private Ikev2VpnProfile.Builder getBuilderWithDefaultOptions() {
+ final Ikev2VpnProfile.Builder builder =
+ new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING);
+
+ builder.setBypassable(true);
+ builder.setProxy(mProxy);
+ builder.setMaxMtu(TEST_MTU);
+ builder.setMetered(true);
+
+ return builder;
+ }
+
+ @Test
+ public void testBuildValidProfileWithOptions() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+ final Ikev2VpnProfile profile = builder.build();
+ assertNotNull(profile);
+
+ // Check non-auth parameters correctly stored
+ assertEquals(SERVER_ADDR_STRING, profile.getServerAddr());
+ assertEquals(IDENTITY_STRING, profile.getUserIdentity());
+ assertEquals(mProxy, profile.getProxyInfo());
+ assertTrue(profile.isBypassable());
+ assertTrue(profile.isMetered());
+ assertEquals(TEST_MTU, profile.getMaxMtu());
+ assertEquals(Ikev2VpnProfile.DEFAULT_ALGORITHMS, profile.getAllowedAlgorithms());
+ }
+
+ @Test
+ public void testBuildUsernamePasswordProfile() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+ final Ikev2VpnProfile profile = builder.build();
+ assertNotNull(profile);
+
+ assertEquals(USERNAME_STRING, profile.getUsername());
+ assertEquals(PASSWORD_STRING, profile.getPassword());
+ assertEquals(mServerRootCa, profile.getServerRootCaCert());
+
+ assertNull(profile.getPresharedKey());
+ assertNull(profile.getRsaPrivateKey());
+ assertNull(profile.getUserCert());
+ }
+
+ @Test
+ public void testBuildDigitalSignatureProfile() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final Ikev2VpnProfile profile = builder.build();
+ assertNotNull(profile);
+
+ assertEquals(profile.getUserCert(), mUserCert);
+ assertEquals(mPrivateKey, profile.getRsaPrivateKey());
+ assertEquals(profile.getServerRootCaCert(), mServerRootCa);
+
+ assertNull(profile.getPresharedKey());
+ assertNull(profile.getUsername());
+ assertNull(profile.getPassword());
+ }
+
+ @Test
+ public void testBuildPresharedKeyProfile() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthPsk(PSK_BYTES);
+ final Ikev2VpnProfile profile = builder.build();
+ assertNotNull(profile);
+
+ assertArrayEquals(PSK_BYTES, profile.getPresharedKey());
+
+ assertNull(profile.getServerRootCaCert());
+ assertNull(profile.getUsername());
+ assertNull(profile.getPassword());
+ assertNull(profile.getRsaPrivateKey());
+ assertNull(profile.getUserCert());
+ }
+
+ @Test
+ public void testBuildWithAllowedAlgorithmsAead() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ builder.setAuthPsk(PSK_BYTES);
+
+ List<String> allowedAlgorithms =
+ Arrays.asList(
+ IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+ IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305);
+ builder.setAllowedAlgorithms(allowedAlgorithms);
+
+ final Ikev2VpnProfile profile = builder.build();
+ assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms());
+ }
+
+ @Test
+ public void testBuildWithAllowedAlgorithmsNormal() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ builder.setAuthPsk(PSK_BYTES);
+
+ List<String> allowedAlgorithms =
+ Arrays.asList(
+ IpSecAlgorithm.AUTH_HMAC_SHA512,
+ IpSecAlgorithm.AUTH_AES_XCBC,
+ IpSecAlgorithm.AUTH_AES_CMAC,
+ IpSecAlgorithm.CRYPT_AES_CBC,
+ IpSecAlgorithm.CRYPT_AES_CTR);
+ builder.setAllowedAlgorithms(allowedAlgorithms);
+
+ final Ikev2VpnProfile profile = builder.build();
+ assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms());
+ }
+
+ @Test
+ public void testSetAllowedAlgorithmsEmptyList() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ try {
+ builder.setAllowedAlgorithms(new ArrayList<>());
+ fail("Expected exception due to no valid algorithm set");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testSetAllowedAlgorithmsInvalidList() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ List<String> allowedAlgorithms = new ArrayList<>();
+
+ try {
+ builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA256));
+ fail("Expected exception due to missing encryption");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.CRYPT_AES_CBC));
+ fail("Expected exception due to missing authentication");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testSetAllowedAlgorithmsInsecureAlgorithm() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ List<String> allowedAlgorithms = new ArrayList<>();
+
+ try {
+ builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_MD5));
+ fail("Expected exception due to insecure algorithm");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA1));
+ fail("Expected exception due to insecure algorithm");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testBuildNoAuthMethodSet() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ try {
+ builder.build();
+ fail("Expected exception due to lack of auth method");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+
+ // TODO: Refer to Build.VERSION_CODES.SC_V2 when it's available in AOSP and mainline branch
+ @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
+ @Test
+ public void testBuildExcludeLocalRoutesSet() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ builder.setAuthPsk(PSK_BYTES);
+ builder.setLocalRoutesExcluded(true);
+
+ final Ikev2VpnProfile profile = builder.build();
+ assertNotNull(profile);
+ assertTrue(profile.areLocalRoutesExcluded());
+
+ builder.setBypassable(false);
+ try {
+ builder.build();
+ fail("Expected exception because excludeLocalRoutes should be set only"
+ + " on the bypassable VPN");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
+ public void testBuildInvalidMtu() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ try {
+ builder.setMaxMtu(500);
+ fail("Expected exception due to too-small MTU");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ private void verifyVpnProfileCommon(VpnProfile profile) {
+ assertEquals(SERVER_ADDR_STRING, profile.server);
+ assertEquals(IDENTITY_STRING, profile.ipsecIdentifier);
+ assertEquals(mProxy, profile.proxy);
+ assertTrue(profile.isBypassable);
+ assertTrue(profile.isMetered);
+ assertEquals(TEST_MTU, profile.maxMtu);
+ }
+
+ @Test
+ public void testPskConvertToVpnProfile() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthPsk(PSK_BYTES);
+ final VpnProfile profile = builder.build().toVpnProfile();
+
+ verifyVpnProfileCommon(profile);
+ assertEquals(Ikev2VpnProfile.encodeForIpsecSecret(PSK_BYTES), profile.ipsecSecret);
+
+ // Check nothing else is set
+ assertEquals("", profile.username);
+ assertEquals("", profile.password);
+ assertEquals("", profile.ipsecUserCert);
+ assertEquals("", profile.ipsecCaCert);
+ }
+
+ @Test
+ public void testUsernamePasswordConvertToVpnProfile() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+ final VpnProfile profile = builder.build().toVpnProfile();
+
+ verifyVpnProfileCommon(profile);
+ assertEquals(USERNAME_STRING, profile.username);
+ assertEquals(PASSWORD_STRING, profile.password);
+ assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
+
+ // Check nothing else is set
+ assertEquals("", profile.ipsecUserCert);
+ assertEquals("", profile.ipsecSecret);
+ }
+
+ @Test
+ public void testRsaConvertToVpnProfile() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final VpnProfile profile = builder.build().toVpnProfile();
+
+ final String expectedSecret = Ikev2VpnProfile.PREFIX_INLINE
+ + Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded());
+ verifyVpnProfileCommon(profile);
+ assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert);
+ assertEquals(
+ expectedSecret,
+ profile.ipsecSecret);
+ assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
+
+ // Check nothing else is set
+ assertEquals("", profile.username);
+ assertEquals("", profile.password);
+ }
+
+ @Test
+ public void testPskFromVpnProfileDiscardsIrrelevantValues() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthPsk(PSK_BYTES);
+ final VpnProfile profile = builder.build().toVpnProfile();
+ profile.username = USERNAME_STRING;
+ profile.password = PASSWORD_STRING;
+ profile.ipsecCaCert = Ikev2VpnProfile.certificateToPemString(mServerRootCa);
+ profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
+
+ final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
+ assertNull(result.getUsername());
+ assertNull(result.getPassword());
+ assertNull(result.getUserCert());
+ assertNull(result.getRsaPrivateKey());
+ assertNull(result.getServerRootCaCert());
+ }
+
+ @Test
+ public void testUsernamePasswordFromVpnProfileDiscardsIrrelevantValues() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+ final VpnProfile profile = builder.build().toVpnProfile();
+ profile.ipsecSecret = new String(PSK_BYTES);
+ profile.ipsecUserCert = Ikev2VpnProfile.certificateToPemString(mUserCert);
+
+ final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
+ assertNull(result.getPresharedKey());
+ assertNull(result.getUserCert());
+ assertNull(result.getRsaPrivateKey());
+ }
+
+ @Test
+ public void testRsaFromVpnProfileDiscardsIrrelevantValues() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final VpnProfile profile = builder.build().toVpnProfile();
+ profile.username = USERNAME_STRING;
+ profile.password = PASSWORD_STRING;
+
+ final Ikev2VpnProfile result = Ikev2VpnProfile.fromVpnProfile(profile);
+ assertNull(result.getUsername());
+ assertNull(result.getPassword());
+ assertNull(result.getPresharedKey());
+ }
+
+ @Test
+ public void testPskConversionIsLossless() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthPsk(PSK_BYTES);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+ }
+
+ @Test
+ public void testUsernamePasswordConversionIsLossless() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+ }
+
+ @Test
+ public void testRsaConversionIsLossless() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+ }
+
+ @Test
+ public void testBuildWithIkeTunConnParamsConvertToVpnProfile() throws Exception {
+ // Special keyId that contains delimiter character of VpnProfile
+ final byte[] keyId = "foo\0bar".getBytes();
+ final IkeTunnelConnectionParams tunnelParams = new IkeTunnelConnectionParams(
+ getTestIkeSessionParams(true /* testIpv6 */, new IkeKeyIdIdentification(keyId)),
+ CHILD_PARAMS);
+ final Ikev2VpnProfile ikev2VpnProfile = new Ikev2VpnProfile.Builder(tunnelParams).build();
+ final VpnProfile vpnProfile = ikev2VpnProfile.toVpnProfile();
+
+ assertEquals(VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS, vpnProfile.type);
+
+ // Username, password, server, ipsecIdentifier, ipsecCaCert, ipsecSecret, ipsecUserCert and
+ // getAllowedAlgorithms should not be set if IkeTunnelConnectionParams is set.
+ assertEquals("", vpnProfile.server);
+ assertEquals("", vpnProfile.ipsecIdentifier);
+ assertEquals("", vpnProfile.username);
+ assertEquals("", vpnProfile.password);
+ assertEquals("", vpnProfile.ipsecCaCert);
+ assertEquals("", vpnProfile.ipsecSecret);
+ assertEquals("", vpnProfile.ipsecUserCert);
+ assertEquals(0, vpnProfile.getAllowedAlgorithms().size());
+
+ // IkeTunnelConnectionParams should stay the same.
+ assertEquals(tunnelParams, vpnProfile.ikeTunConnParams);
+
+ // Convert to disk-stable format and then back to Ikev2VpnProfile should be the same.
+ final VpnProfile decodedVpnProfile =
+ VpnProfile.decode(vpnProfile.key, vpnProfile.encode());
+ final Ikev2VpnProfile convertedIkev2VpnProfile =
+ Ikev2VpnProfile.fromVpnProfile(decodedVpnProfile);
+ assertEquals(ikev2VpnProfile, convertedIkev2VpnProfile);
+ }
+
+ @Test
+ public void testConversionIsLosslessWithIkeTunConnParams() throws Exception {
+ final IkeTunnelConnectionParams tunnelParams =
+ new IkeTunnelConnectionParams(IKE_PARAMS_V6, CHILD_PARAMS);
+ // Config authentication related fields is not required while building with
+ // IkeTunnelConnectionParams.
+ final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams).build();
+ assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+ }
+
+ @Test
+ public void testAutomaticNattAndIpVersionConversionIsLossless() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ builder.setAutomaticNattKeepaliveTimerEnabled(true);
+ builder.setAutomaticIpVersionSelectionEnabled(true);
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+ }
+
+ @Test
+ public void testAutomaticNattAndIpVersionDefaults() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(false, ikeProfile.isAutomaticNattKeepaliveTimerEnabled());
+ assertEquals(false, ikeProfile.isAutomaticIpVersionSelectionEnabled());
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ // Verify building without IkeTunnelConnectionParams
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ assertEquals(builder.build(), builder.build());
+
+ // Verify building with IkeTunnelConnectionParams
+ final IkeTunnelConnectionParams tunnelParams =
+ new IkeTunnelConnectionParams(IKE_PARAMS_V6, CHILD_PARAMS);
+ final IkeTunnelConnectionParams tunnelParams2 =
+ new IkeTunnelConnectionParams(IKE_PARAMS_V6, CHILD_PARAMS);
+ assertEquals(new Ikev2VpnProfile.Builder(tunnelParams).build(),
+ new Ikev2VpnProfile.Builder(tunnelParams2).build());
+ }
+
+ @Test
+ public void testBuildProfileWithNullProxy() throws Exception {
+ final Ikev2VpnProfile ikev2VpnProfile =
+ new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING)
+ .setAuthUsernamePassword(USERNAME_STRING, PASSWORD_STRING, mServerRootCa)
+ .build();
+
+ // ProxyInfo should be null for the profile without setting ProxyInfo.
+ assertNull(ikev2VpnProfile.getProxyInfo());
+
+ // ProxyInfo should stay null after performing toVpnProfile() and fromVpnProfile()
+ final VpnProfile vpnProfile = ikev2VpnProfile.toVpnProfile();
+ assertNull(vpnProfile.proxy);
+
+ final Ikev2VpnProfile convertedIkev2VpnProfile = Ikev2VpnProfile.fromVpnProfile(vpnProfile);
+ assertNull(convertedIkev2VpnProfile.getProxyInfo());
+ }
+
+ private static class CertificateAndKey {
+ public final X509Certificate cert;
+ public final PrivateKey key;
+
+ CertificateAndKey(X509Certificate cert, PrivateKey key) {
+ this.cert = cert;
+ this.key = key;
+ }
+ }
+
+ private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception {
+ final Date validityBeginDate =
+ new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L));
+ final Date validityEndDate =
+ new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L));
+
+ // Generate a keypair
+ final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(512);
+ final KeyPair keyPair = keyPairGenerator.generateKeyPair();
+
+ final X500Principal dnName = new X500Principal("CN=test.android.com");
+ final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
+ certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
+ certGen.setSubjectDN(dnName);
+ certGen.setIssuerDN(dnName);
+ certGen.setNotBefore(validityBeginDate);
+ certGen.setNotAfter(validityEndDate);
+ certGen.setPublicKey(keyPair.getPublic());
+ certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
+
+ final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL");
+ return new CertificateAndKey(cert, keyPair.getPrivate());
+ }
+}
diff --git a/services/tests/VpnTests/java/android/net/VpnManagerTest.java b/services/tests/VpnTests/java/android/net/VpnManagerTest.java
new file mode 100644
index 0000000..365b4d1
--- /dev/null
+++ b/services/tests/VpnTests/java/android/net/VpnManagerTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.test.mock.MockContext;
+import android.util.SparseArray;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.net.VpnProfile;
+import com.android.internal.util.MessageUtils;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link VpnManager}. */
+@SmallTest
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+public class VpnManagerTest {
+
+ private static final String PKG_NAME = "fooPackage";
+
+ private static final String SESSION_NAME_STRING = "testSession";
+ private static final String SERVER_ADDR_STRING = "1.2.3.4";
+ private static final String IDENTITY_STRING = "Identity";
+ private static final byte[] PSK_BYTES = "preSharedKey".getBytes();
+
+ private IVpnManager mMockService;
+ private VpnManager mVpnManager;
+ private final MockContext mMockContext =
+ new MockContext() {
+ @Override
+ public String getOpPackageName() {
+ return PKG_NAME;
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ assumeFalse("Skipping test because watches don't support VPN",
+ InstrumentationRegistry.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_WATCH));
+ mMockService = mock(IVpnManager.class);
+ mVpnManager = new VpnManager(mMockContext, mMockService);
+ }
+
+ @Test
+ public void testProvisionVpnProfilePreconsented() throws Exception {
+ final PlatformVpnProfile profile = getPlatformVpnProfile();
+ when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME)))
+ .thenReturn(true);
+
+ // Expect there to be no intent returned, as consent has already been granted.
+ assertNull(mVpnManager.provisionVpnProfile(profile));
+ verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME));
+ }
+
+ @Test
+ public void testProvisionVpnProfileNeedsConsent() throws Exception {
+ final PlatformVpnProfile profile = getPlatformVpnProfile();
+ when(mMockService.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME)))
+ .thenReturn(false);
+
+ // Expect intent to be returned, as consent has not already been granted.
+ final Intent intent = mVpnManager.provisionVpnProfile(profile);
+ assertNotNull(intent);
+
+ final ComponentName expectedComponentName =
+ ComponentName.unflattenFromString(
+ "com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog");
+ assertEquals(expectedComponentName, intent.getComponent());
+ verify(mMockService).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME));
+ }
+
+ @Test
+ public void testDeleteProvisionedVpnProfile() throws Exception {
+ mVpnManager.deleteProvisionedVpnProfile();
+ verify(mMockService).deleteVpnProfile(eq(PKG_NAME));
+ }
+
+ @Test
+ public void testStartProvisionedVpnProfile() throws Exception {
+ mVpnManager.startProvisionedVpnProfile();
+ verify(mMockService).startVpnProfile(eq(PKG_NAME));
+ }
+
+ @Test
+ public void testStopProvisionedVpnProfile() throws Exception {
+ mVpnManager.stopProvisionedVpnProfile();
+ verify(mMockService).stopVpnProfile(eq(PKG_NAME));
+ }
+
+ private Ikev2VpnProfile getPlatformVpnProfile() throws Exception {
+ return new Ikev2VpnProfile.Builder(SERVER_ADDR_STRING, IDENTITY_STRING)
+ .setBypassable(true)
+ .setMaxMtu(1300)
+ .setMetered(true)
+ .setAuthPsk(PSK_BYTES)
+ .build();
+ }
+
+ @Test
+ public void testVpnTypesEqual() throws Exception {
+ SparseArray<String> vmVpnTypes = MessageUtils.findMessageNames(
+ new Class[] { VpnManager.class }, new String[]{ "TYPE_VPN_" });
+ SparseArray<String> nativeVpnType = MessageUtils.findMessageNames(
+ new Class[] { NativeVpnType.class }, new String[]{ "" });
+
+ // TYPE_VPN_NONE = -1 is only defined in VpnManager.
+ assertEquals(vmVpnTypes.size() - 1, nativeVpnType.size());
+ for (int i = VpnManager.TYPE_VPN_SERVICE; i < vmVpnTypes.size(); i++) {
+ assertEquals(vmVpnTypes.get(i), "TYPE_VPN_" + nativeVpnType.get(i));
+ }
+ }
+}
diff --git a/services/tests/VpnTests/java/com/android/internal/net/VpnProfileTest.java b/services/tests/VpnTests/java/com/android/internal/net/VpnProfileTest.java
new file mode 100644
index 0000000..acae7d2
--- /dev/null
+++ b/services/tests/VpnTests/java/com/android/internal/net/VpnProfileTest.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
+import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V4;
+
+import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
+import static com.android.testutils.ParcelUtils.assertParcelSane;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.net.IpSecAlgorithm;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.os.Build;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/** Unit tests for {@link VpnProfile}. */
+@SmallTest
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+public class VpnProfileTest {
+ private static final String DUMMY_PROFILE_KEY = "Test";
+
+ private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
+ private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
+ private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
+ private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26;
+ private static final int ENCODED_INDEX_IKE_TUN_CONN_PARAMS = 27;
+ private static final int ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED = 28;
+ private static final int ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED = 29;
+
+ @Test
+ public void testDefaults() throws Exception {
+ final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY);
+
+ assertEquals(DUMMY_PROFILE_KEY, p.key);
+ assertEquals("", p.name);
+ assertEquals(VpnProfile.TYPE_PPTP, p.type);
+ assertEquals("", p.server);
+ assertEquals("", p.username);
+ assertEquals("", p.password);
+ assertEquals("", p.dnsServers);
+ assertEquals("", p.searchDomains);
+ assertEquals("", p.routes);
+ assertTrue(p.mppe);
+ assertEquals("", p.l2tpSecret);
+ assertEquals("", p.ipsecIdentifier);
+ assertEquals("", p.ipsecSecret);
+ assertEquals("", p.ipsecUserCert);
+ assertEquals("", p.ipsecCaCert);
+ assertEquals("", p.ipsecServerCert);
+ assertEquals(null, p.proxy);
+ assertTrue(p.getAllowedAlgorithms() != null && p.getAllowedAlgorithms().isEmpty());
+ assertFalse(p.isBypassable);
+ assertFalse(p.isMetered);
+ assertEquals(1360, p.maxMtu);
+ assertFalse(p.areAuthParamsInline);
+ assertFalse(p.isRestrictedToTestNetworks);
+ assertFalse(p.excludeLocalRoutes);
+ assertFalse(p.requiresInternetValidation);
+ assertFalse(p.automaticNattKeepaliveTimerEnabled);
+ assertFalse(p.automaticIpVersionSelectionEnabled);
+ }
+
+ private VpnProfile getSampleIkev2Profile(String key) {
+ final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
+ false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
+ null /* ikeTunConnParams */, true /* mAutomaticNattKeepaliveTimerEnabled */,
+ true /* automaticIpVersionSelectionEnabled */);
+
+ p.name = "foo";
+ p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
+ p.server = "bar";
+ p.username = "baz";
+ p.password = "qux";
+ p.dnsServers = "8.8.8.8";
+ p.searchDomains = "";
+ p.routes = "0.0.0.0/0";
+ p.mppe = false;
+ p.l2tpSecret = "";
+ p.ipsecIdentifier = "quux";
+ p.ipsecSecret = "quuz";
+ p.ipsecUserCert = "corge";
+ p.ipsecCaCert = "grault";
+ p.ipsecServerCert = "garply";
+ p.proxy = null;
+ p.setAllowedAlgorithms(
+ Arrays.asList(
+ IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+ IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305,
+ IpSecAlgorithm.AUTH_HMAC_SHA512,
+ IpSecAlgorithm.CRYPT_AES_CBC));
+ p.isBypassable = true;
+ p.isMetered = true;
+ p.maxMtu = 1350;
+ p.areAuthParamsInline = true;
+
+ // Not saved, but also not compared.
+ p.saveLogin = true;
+
+ return p;
+ }
+
+ private VpnProfile getSampleIkev2ProfileWithIkeTunConnParams(String key) {
+ final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
+ false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
+ new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS),
+ true /* mAutomaticNattKeepaliveTimerEnabled */,
+ true /* automaticIpVersionSelectionEnabled */);
+
+ p.name = "foo";
+ p.server = "bar";
+ p.dnsServers = "8.8.8.8";
+ p.searchDomains = "";
+ p.routes = "0.0.0.0/0";
+ p.mppe = false;
+ p.proxy = null;
+ p.setAllowedAlgorithms(
+ Arrays.asList(
+ IpSecAlgorithm.AUTH_CRYPT_AES_GCM,
+ IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305,
+ IpSecAlgorithm.AUTH_HMAC_SHA512,
+ IpSecAlgorithm.CRYPT_AES_CBC));
+ p.isBypassable = true;
+ p.isMetered = true;
+ p.maxMtu = 1350;
+ p.areAuthParamsInline = true;
+
+ // Not saved, but also not compared.
+ p.saveLogin = true;
+
+ return p;
+ }
+
+ @Test
+ public void testEquals() {
+ assertEquals(
+ getSampleIkev2Profile(DUMMY_PROFILE_KEY), getSampleIkev2Profile(DUMMY_PROFILE_KEY));
+
+ final VpnProfile modified = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+ modified.maxMtu--;
+ assertNotEquals(getSampleIkev2Profile(DUMMY_PROFILE_KEY), modified);
+ }
+
+ @Test
+ public void testParcelUnparcel() {
+ if (isAtLeastU()) {
+ // automaticNattKeepaliveTimerEnabled, automaticIpVersionSelectionEnabled added in U.
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 28);
+ assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 28);
+ } else if (isAtLeastT()) {
+ // excludeLocalRoutes, requiresPlatformValidation were added in T.
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 26);
+ assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 26);
+ } else {
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
+ }
+ }
+
+ @Test
+ public void testEncodeDecodeWithIkeTunConnParams() {
+ final VpnProfile profile = getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY);
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
+ assertEquals(profile, decoded);
+ }
+
+ @Test
+ public void testEncodeDecode() {
+ final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
+ assertEquals(profile, decoded);
+ }
+
+ @Test
+ public void testEncodeDecodeTooManyValues() {
+ final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+ final byte[] tooManyValues =
+ (new String(profile.encode()) + VpnProfile.VALUE_DELIMITER + "invalid").getBytes();
+
+ assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues));
+ }
+
+ private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) {
+ // Sort to ensure when we remove, we can do it from greatest first.
+ Arrays.sort(missingIndices);
+
+ final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode());
+ final List<String> parts =
+ new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER)));
+
+ // Remove from back first to ensure indexing is consistent.
+ for (int i = missingIndices.length - 1; i >= 0; i--) {
+ parts.remove(missingIndices[i]);
+ }
+
+ return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0]));
+ }
+
+ @Test
+ public void testEncodeDecodeInvalidNumberOfValues() {
+ final String tooFewValues =
+ getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_AUTH_PARAMS_INLINE,
+ ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION,
+ ENCODED_INDEX_IKE_TUN_CONN_PARAMS,
+ ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED,
+ ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED
+ /* missingIndices */);
+
+ assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
+ }
+
+ private String getEncodedDecodedIkev2ProfileWithtooFewValues() {
+ return getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION,
+ ENCODED_INDEX_IKE_TUN_CONN_PARAMS,
+ ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED,
+ ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED /* missingIndices */);
+ }
+
+ @Test
+ public void testEncodeDecodeMissingIsRestrictedToTestNetworks() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without isRestrictedToTestNetworks defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.isRestrictedToTestNetworks);
+ }
+
+ @Test
+ public void testEncodeDecodeMissingExcludeLocalRoutes() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without excludeLocalRoutes defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.excludeLocalRoutes);
+ }
+
+ @Test
+ public void testEncodeDecodeMissingRequiresValidation() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without requiresValidation defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.requiresInternetValidation);
+ }
+
+ @Test
+ public void testEncodeDecodeMissingAutomaticNattKeepaliveTimerEnabled() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without automaticNattKeepaliveTimerEnabled defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.automaticNattKeepaliveTimerEnabled);
+ }
+
+ @Test
+ public void testEncodeDecodeMissingAutomaticIpVersionSelectionEnabled() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without automaticIpVersionSelectionEnabled defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.automaticIpVersionSelectionEnabled);
+ }
+
+ @Test
+ public void testEncodeDecodeLoginsNotSaved() {
+ final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+ profile.saveLogin = false;
+
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, profile.encode());
+ assertNotEquals(profile, decoded);
+
+ // Add the username/password back, everything else must be equal.
+ decoded.username = profile.username;
+ decoded.password = profile.password;
+ assertEquals(profile, decoded);
+ }
+
+ @Test
+ public void testClone() {
+ final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
+ final VpnProfile clone = profile.clone();
+ assertEquals(profile, clone);
+ assertNotSame(profile, clone);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java b/services/tests/VpnTests/java/com/android/server/net/LockdownVpnTrackerTest.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/net/LockdownVpnTrackerTest.java
rename to services/tests/VpnTests/java/com/android/server/net/LockdownVpnTrackerTest.java
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
new file mode 100644
index 0000000..e94b8ad
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "RollbackPackageHealthObserverTests",
+
+ srcs: [
+ "*.java",
+ ],
+
+ static_libs: [
+ "androidx.test.runner",
+ "mockito-target-extended-minus-junit4",
+ "services.core",
+ "truth",
+ "flag-junit",
+ ],
+
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ "android.test.runner",
+ ],
+
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidManifest.xml b/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidManifest.xml
new file mode 100644
index 0000000..c52dbde
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.rollback">
+
+ <uses-sdk android:targetSdkVersion="35" />
+
+ <application android:testOnly="true"
+ android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.rollback"
+ android:label="Frameworks Rollback Package Health Observer test" />
+</manifest>
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml b/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml
new file mode 100644
index 0000000..635183c
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Runs Rollback Package Health Observer Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="RollbackPackageHealthObserverTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="RollbackPackageHealthObserverTests" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.server.rollback" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING b/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
index e42bdad..6ac56bf 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/TEST_MAPPING
@@ -1,7 +1,7 @@
{
"postsubmit": [
{
- "name": "FrameworksMockingServicesTests",
+ "name": "RollbackPackageHealthObserverTests",
"options": [
{
"include-filter": "com.android.server.rollback"
diff --git a/tests/graphics/HwAccelerationTest/jni/native-lib.cpp b/tests/graphics/HwAccelerationTest/jni/native-lib.cpp
index 407d4bf..2977c21 100644
--- a/tests/graphics/HwAccelerationTest/jni/native-lib.cpp
+++ b/tests/graphics/HwAccelerationTest/jni/native-lib.cpp
@@ -30,7 +30,7 @@
void setBuffer(AHardwareBuffer* buffer) {
ASurfaceTransaction* transaction = ASurfaceTransaction_create();
- ASurfaceTransaction_setBuffer(transaction, surfaceControl, buffer);
+ ASurfaceTransaction_setBuffer(transaction, surfaceControl, buffer, -1);
ASurfaceTransaction_setVisibility(transaction, surfaceControl,
ASURFACE_TRANSACTION_VISIBILITY_SHOW);
ASurfaceTransaction_apply(transaction);