diff options
35 files changed, 831 insertions, 113 deletions
diff --git a/apex/blobstore/OWNERS b/apex/blobstore/OWNERS index 8e04399196e2..a53bbeaa8601 100644 --- a/apex/blobstore/OWNERS +++ b/apex/blobstore/OWNERS @@ -1,4 +1,2 @@ -set noparent - sudheersai@google.com yamasani@google.com diff --git a/config/preloaded-classes b/config/preloaded-classes index d56fc7720c89..29f6055ec6a5 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -11759,7 +11759,6 @@ libcore.util.XmlObjectFactory libcore.util.ZoneInfo$CheckedArithmeticException libcore.util.ZoneInfo$WallTime libcore.util.ZoneInfo -org.apache.harmony.dalvik.NativeTestTarget org.apache.harmony.dalvik.ddmc.Chunk org.apache.harmony.dalvik.ddmc.ChunkHandler org.apache.harmony.dalvik.ddmc.DdmServer diff --git a/core/api/current.txt b/core/api/current.txt index 1ef98be04ecf..87fc6361983a 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -57317,6 +57317,7 @@ package java.lang { method public int getModifiers(); method @NonNull public String getName(); method @Nullable public Package getPackage(); + method @NonNull public String getPackageName(); method @Nullable public java.security.ProtectionDomain getProtectionDomain(); method @Nullable public java.net.URL getResource(@NonNull String); method @Nullable public java.io.InputStream getResourceAsStream(@NonNull String); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index b982dd745672..3b3170f6f278 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1577,6 +1577,7 @@ package android.bluetooth { field @NonNull public static final android.os.ParcelUuid HOGP; field @NonNull public static final android.os.ParcelUuid HSP; field @NonNull public static final android.os.ParcelUuid HSP_AG; + field @NonNull public static final android.os.ParcelUuid LE_AUDIO; field @NonNull public static final android.os.ParcelUuid MAP; field @NonNull public static final android.os.ParcelUuid MAS; field @NonNull public static final android.os.ParcelUuid MNS; diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index e274af1b5c5d..56c482471003 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -153,7 +153,12 @@ public final class BluetoothUuid { @SystemApi public static final ParcelUuid HEARING_AID = ParcelUuid.fromString("0000FDF0-0000-1000-8000-00805f9b34fb"); - + /** Placeholder until specification is released + * @hide */ + @NonNull + @SystemApi + public static final ParcelUuid LE_AUDIO = + ParcelUuid.fromString("EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE"); /** @hide */ @NonNull @SystemApi diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index df1f1b21eba3..e77b163743fe 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -249,6 +249,7 @@ public class GraphicsEnvironment { } if (appInfo == null) { Log.w(TAG, "Debug layer app '" + packageName + "' not installed"); + return ""; } final String abi = chooseAbi(appInfo); diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java index 33bc121d8555..93b5fd4cd4b6 100644 --- a/core/java/android/uwb/AngleMeasurement.java +++ b/core/java/android/uwb/AngleMeasurement.java @@ -17,6 +17,7 @@ package android.uwb; import android.annotation.FloatRange; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; @@ -109,7 +110,7 @@ public final class AngleMeasurement implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeDouble(mRadians); dest.writeDouble(mErrorRadians); dest.writeDouble(mConfidenceLevel); @@ -146,6 +147,7 @@ public final class AngleMeasurement implements Parcelable { * @param radians angle in radians * @throws IllegalArgumentException if angle exceeds allowed limits of [-Math.PI, +Math.PI] */ + @NonNull public Builder setRadians(double radians) { if (radians < -Math.PI || radians > Math.PI) { throw new IllegalArgumentException("Invalid radians: " + radians); @@ -160,6 +162,7 @@ public final class AngleMeasurement implements Parcelable { * @param errorRadians error of the angle in radians * @throws IllegalArgumentException if the error exceeds the allowed limits of [0, +Math.PI] */ + @NonNull public Builder setErrorRadians(double errorRadians) { if (errorRadians < 0.0 || errorRadians > Math.PI) { throw new IllegalArgumentException( @@ -175,6 +178,7 @@ public final class AngleMeasurement implements Parcelable { * @param confidenceLevel level of confidence of the angle measurement * @throws IllegalArgumentException if the error exceeds the allowed limits of [0.0, 1.0] */ + @NonNull public Builder setConfidenceLevel(double confidenceLevel) { if (confidenceLevel < 0.0 || confidenceLevel > 1.0) { throw new IllegalArgumentException( @@ -189,6 +193,7 @@ public final class AngleMeasurement implements Parcelable { * * @throws IllegalStateException if angle, error, or confidence values are missing */ + @NonNull public AngleMeasurement build() { if (Double.isNaN(mRadians)) { throw new IllegalStateException("Angle is not set"); diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java index cd5af691ed51..20a1c7aa72d0 100644 --- a/core/java/android/uwb/AngleOfArrivalMeasurement.java +++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java @@ -53,7 +53,7 @@ public final class AngleOfArrivalMeasurement implements Parcelable { * @return the azimuth {@link AngleMeasurement} */ @NonNull - public AngleMeasurement getAzimuth() { + public AngleMeasurement getAzimuthAngleMeasurement() { return mAzimuthAngleMeasurement; } @@ -70,7 +70,7 @@ public final class AngleOfArrivalMeasurement implements Parcelable { * @return altitude {@link AngleMeasurement} or null when this is not available */ @Nullable - public AngleMeasurement getAltitude() { + public AngleMeasurement getAltitudeAngleMeasurement() { return mAltitudeAngleMeasurement; } @@ -85,8 +85,8 @@ public final class AngleOfArrivalMeasurement implements Parcelable { if (obj instanceof AngleOfArrivalMeasurement) { AngleOfArrivalMeasurement other = (AngleOfArrivalMeasurement) obj; - return mAzimuthAngleMeasurement.equals(other.getAzimuth()) - && mAltitudeAngleMeasurement.equals(other.getAltitude()); + return mAzimuthAngleMeasurement.equals(other.getAzimuthAngleMeasurement()) + && mAltitudeAngleMeasurement.equals(other.getAltitudeAngleMeasurement()); } return false; } @@ -105,7 +105,7 @@ public final class AngleOfArrivalMeasurement implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mAzimuthAngleMeasurement, flags); dest.writeParcelable(mAltitudeAngleMeasurement, flags); } @@ -143,6 +143,7 @@ public final class AngleOfArrivalMeasurement implements Parcelable { * * @param azimuthAngle azimuth angle */ + @NonNull public Builder setAzimuthAngleMeasurement(@NonNull AngleMeasurement azimuthAngle) { mAzimuthAngleMeasurement = azimuthAngle; return this; @@ -153,6 +154,7 @@ public final class AngleOfArrivalMeasurement implements Parcelable { * * @param altitudeAngle altitude angle */ + @NonNull public Builder setAltitudeAngleMeasurement(@NonNull AngleMeasurement altitudeAngle) { mAltitudeAngleMeasurement = altitudeAngle; return this; @@ -163,6 +165,7 @@ public final class AngleOfArrivalMeasurement implements Parcelable { * * @throws IllegalStateException if the required azimuth angle is not provided */ + @NonNull public AngleOfArrivalMeasurement build() { if (mAzimuthAngleMeasurement == null) { throw new IllegalStateException("Azimuth angle measurement is not set"); diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java index c959840c51ba..10c2172d5a6b 100644 --- a/core/java/android/uwb/DistanceMeasurement.java +++ b/core/java/android/uwb/DistanceMeasurement.java @@ -17,6 +17,7 @@ package android.uwb; import android.annotation.FloatRange; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; @@ -106,7 +107,7 @@ public final class DistanceMeasurement implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeDouble(mMeters); dest.writeDouble(mErrorMeters); dest.writeDouble(mConfidenceLevel); @@ -143,6 +144,7 @@ public final class DistanceMeasurement implements Parcelable { * @param meters distance in meters * @throws IllegalArgumentException if meters is NaN */ + @NonNull public Builder setMeters(double meters) { if (Double.isNaN(meters)) { throw new IllegalArgumentException("meters cannot be NaN"); @@ -157,6 +159,7 @@ public final class DistanceMeasurement implements Parcelable { * @param errorMeters distance error in meters * @throws IllegalArgumentException if error is negative or NaN */ + @NonNull public Builder setErrorMeters(double errorMeters) { if (Double.isNaN(errorMeters) || errorMeters < 0.0) { throw new IllegalArgumentException( @@ -172,6 +175,7 @@ public final class DistanceMeasurement implements Parcelable { * @param confidenceLevel the confidence level in the distance measurement * @throws IllegalArgumentException if confidence level is not in the range of [0.0, 1.0] */ + @NonNull public Builder setConfidenceLevel(double confidenceLevel) { if (confidenceLevel < 0.0 || confidenceLevel > 1.0) { throw new IllegalArgumentException( @@ -186,6 +190,7 @@ public final class DistanceMeasurement implements Parcelable { * * @throws IllegalStateException if meters, error, or confidence are not set */ + @NonNull public DistanceMeasurement build() { if (Double.isNaN(mMeters)) { throw new IllegalStateException("Meters cannot be NaN"); diff --git a/core/java/android/uwb/OWNERS b/core/java/android/uwb/OWNERS new file mode 100644 index 000000000000..ea41c3984dfd --- /dev/null +++ b/core/java/android/uwb/OWNERS @@ -0,0 +1,5 @@ +bstack@google.com +eliptus@google.com +jsolnit@google.com +siyuanh@google.com +zachoverflow@google.com diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java index f1c316289653..50e5f0d8d554 100644 --- a/core/java/android/uwb/RangingMeasurement.java +++ b/core/java/android/uwb/RangingMeasurement.java @@ -60,6 +60,9 @@ public final class RangingMeasurement implements Parcelable { return mRemoteDeviceAddress; } + /** + * @hide + */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { RANGING_STATUS_SUCCESS, @@ -115,7 +118,7 @@ public final class RangingMeasurement implements Parcelable { * {@link #RANGING_STATUS_SUCCESS} */ @Nullable - public DistanceMeasurement getDistance() { + public DistanceMeasurement getDistanceMeasurement() { return mDistanceMeasurement; } @@ -126,7 +129,7 @@ public final class RangingMeasurement implements Parcelable { * {@link #RANGING_STATUS_SUCCESS} */ @Nullable - public AngleOfArrivalMeasurement getAngleOfArrival() { + public AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() { return mAngleOfArrivalMeasurement; } @@ -144,8 +147,8 @@ public final class RangingMeasurement implements Parcelable { return mRemoteDeviceAddress.equals(other.getRemoteDeviceAddress()) && mStatus == other.getStatus() && mElapsedRealtimeNanos == other.getElapsedRealtimeNanos() - && mDistanceMeasurement.equals(other.getDistance()) - && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrival()); + && mDistanceMeasurement.equals(other.getDistanceMeasurement()) + && mAngleOfArrivalMeasurement.equals(other.getAngleOfArrivalMeasurement()); } return false; } @@ -165,7 +168,7 @@ public final class RangingMeasurement implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mRemoteDeviceAddress, flags); dest.writeInt(mStatus); dest.writeLong(mElapsedRealtimeNanos); @@ -210,6 +213,7 @@ public final class RangingMeasurement implements Parcelable { * * @param remoteDeviceAddress remote device's address */ + @NonNull public Builder setRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) { mRemoteDeviceAddress = remoteDeviceAddress; return this; @@ -220,6 +224,7 @@ public final class RangingMeasurement implements Parcelable { * * @param status the status of the ranging measurement */ + @NonNull public Builder setStatus(@Status int status) { mStatus = status; return this; @@ -230,6 +235,7 @@ public final class RangingMeasurement implements Parcelable { * * @param elapsedRealtimeNanos time the ranging measurement occurred */ + @NonNull public Builder setElapsedRealtimeNanos(long elapsedRealtimeNanos) { if (elapsedRealtimeNanos < 0) { throw new IllegalArgumentException("elapsedRealtimeNanos must be >= 0"); @@ -243,6 +249,7 @@ public final class RangingMeasurement implements Parcelable { * * @param distanceMeasurement the distance measurement for this ranging measurement */ + @NonNull public Builder setDistanceMeasurement(@NonNull DistanceMeasurement distanceMeasurement) { mDistanceMeasurement = distanceMeasurement; return this; @@ -254,6 +261,7 @@ public final class RangingMeasurement implements Parcelable { * @param angleOfArrivalMeasurement the angle of arrival measurement for this ranging * measurement */ + @NonNull public Builder setAngleOfArrivalMeasurement( @NonNull AngleOfArrivalMeasurement angleOfArrivalMeasurement) { mAngleOfArrivalMeasurement = angleOfArrivalMeasurement; @@ -268,6 +276,7 @@ public final class RangingMeasurement implements Parcelable { * elapsedRealtimeNanos of the measurement is invalid, or * if no remote device address is set */ + @NonNull public RangingMeasurement build() { if (mStatus != RANGING_STATUS_SUCCESS) { if (mDistanceMeasurement != null) { diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java index 45180bfa6981..5b5f084914ab 100644 --- a/core/java/android/uwb/RangingReport.java +++ b/core/java/android/uwb/RangingReport.java @@ -83,7 +83,7 @@ public final class RangingReport implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeTypedList(mRangingMeasurements); } @@ -113,6 +113,7 @@ public final class RangingReport implements Parcelable { * * @param rangingMeasurement a ranging measurement */ + @NonNull public Builder addMeasurement(@NonNull RangingMeasurement rangingMeasurement) { mMeasurements.add(rangingMeasurement); return this; @@ -123,6 +124,7 @@ public final class RangingReport implements Parcelable { * * @param rangingMeasurements {@link List} of {@link RangingMeasurement}s to add */ + @NonNull public Builder addMeasurements(@NonNull List<RangingMeasurement> rangingMeasurements) { mMeasurements.addAll(rangingMeasurements); return this; @@ -133,6 +135,7 @@ public final class RangingReport implements Parcelable { * * @throws IllegalStateException if measurements are not in monotonically increasing order */ + @NonNull public RangingReport build() { // Verify that all measurement timestamps are monotonically increasing RangingMeasurement prevMeasurement = null; diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java index 863926924aad..e1af9b1d7ce3 100644 --- a/core/java/android/uwb/RangingSession.java +++ b/core/java/android/uwb/RangingSession.java @@ -17,6 +17,7 @@ package android.uwb; import android.annotation.IntDef; +import android.annotation.NonNull; import android.os.PersistableBundle; import java.lang.annotation.Retention; @@ -50,8 +51,11 @@ public final class RangingSession implements AutoCloseable { * @param session the newly opened {@link RangingSession} * @param sessionInfo session specific parameters from lower layers */ - void onOpenSuccess(RangingSession session, PersistableBundle sessionInfo); + void onOpenSuccess(@NonNull RangingSession session, @NonNull PersistableBundle sessionInfo); + /** + * @hide + */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { CLOSE_REASON_UNKNOWN, @@ -125,7 +129,7 @@ public final class RangingSession implements AutoCloseable { * * @param rangingReport ranging report for this interval's measurements */ - void onReportReceived(RangingReport rangingReport); + void onReportReceived(@NonNull RangingReport rangingReport); } /** diff --git a/core/java/android/uwb/UwbAddress.java b/core/java/android/uwb/UwbAddress.java index 828324c54c5a..b9523a307c42 100644 --- a/core/java/android/uwb/UwbAddress.java +++ b/core/java/android/uwb/UwbAddress.java @@ -51,7 +51,7 @@ public final class UwbAddress implements Parcelable { * {@link #SHORT_ADDRESS_BYTE_LENGTH} or {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes */ @NonNull - public static UwbAddress fromBytes(@NonNull byte[] address) throws IllegalArgumentException { + public static UwbAddress fromBytes(@NonNull byte[] address) { if (address.length != SHORT_ADDRESS_BYTE_LENGTH && address.length != EXTENDED_ADDRESS_BYTE_LENGTH) { throw new IllegalArgumentException("Invalid UwbAddress length " + address.length); @@ -107,7 +107,7 @@ public final class UwbAddress implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mAddressBytes.length); dest.writeByteArray(mAddressBytes); } diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java index ed5cf3625525..bb2be0242342 100644 --- a/core/java/android/uwb/UwbManager.java +++ b/core/java/android/uwb/UwbManager.java @@ -55,6 +55,9 @@ public final class UwbManager { * Interface for receiving UWB adapter state changes */ public interface AdapterStateCallback { + /** + * @hide + */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { STATE_CHANGED_REASON_SESSION_STARTED, @@ -195,6 +198,9 @@ public final class UwbManager { } } + /** + * @hide + */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE, @@ -387,7 +393,7 @@ public final class UwbManager { */ @NonNull public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters, - @NonNull Executor executor, + @NonNull @CallbackExecutor Executor executor, @NonNull RangingSession.Callback callbacks) { throw new UnsupportedOperationException(); } diff --git a/core/java/com/android/internal/util/AnnotationValidations.java b/core/java/com/android/internal/util/AnnotationValidations.java index 2d3b45023c9d..cf5e48f9657f 100644 --- a/core/java/com/android/internal/util/AnnotationValidations.java +++ b/core/java/com/android/internal/util/AnnotationValidations.java @@ -182,7 +182,7 @@ public class AnnotationValidations { Annotation ignored, int value, Object... params) {} public static void validate(Class<? extends Annotation> annotation, Annotation ignored, int value) { - if (("android.annotation".equals(annotation.getPackageName$()) + if (("android.annotation".equals(annotation.getPackageName()) && annotation.getSimpleName().endsWith("Res")) || ColorInt.class.equals(annotation)) { if (value < 0) { @@ -192,7 +192,7 @@ public class AnnotationValidations { } public static void validate(Class<? extends Annotation> annotation, Annotation ignored, long value) { - if ("android.annotation".equals(annotation.getPackageName$()) + if ("android.annotation".equals(annotation.getPackageName()) && annotation.getSimpleName().endsWith("Long")) { if (value < 0L) { invalid(annotation, value); diff --git a/core/tests/coretests/BstatsTestApp/OWNERS b/core/tests/coretests/BstatsTestApp/OWNERS new file mode 100644 index 000000000000..4068e2bc03b7 --- /dev/null +++ b/core/tests/coretests/BstatsTestApp/OWNERS @@ -0,0 +1 @@ +include /BATTERY_STATS_OWNERS diff --git a/core/tests/coretests/src/com/android/internal/os/OWNERS b/core/tests/coretests/src/com/android/internal/os/OWNERS new file mode 100644 index 000000000000..4068e2bc03b7 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/OWNERS @@ -0,0 +1 @@ +include /BATTERY_STATS_OWNERS diff --git a/core/tests/uwbtests/OWNERS b/core/tests/uwbtests/OWNERS new file mode 100644 index 000000000000..c7b09a21e1d0 --- /dev/null +++ b/core/tests/uwbtests/OWNERS @@ -0,0 +1 @@ +include /core/java/android/uwb/OWNERS diff --git a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java index 077b08f41b59..e0884e3e1c28 100644 --- a/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java +++ b/core/tests/uwbtests/src/android/uwb/AngleOfArrivalMeasurementTest.java @@ -48,8 +48,8 @@ public class AngleOfArrivalMeasurementTest { builder.setAzimuthAngleMeasurement(azimuth); AngleOfArrivalMeasurement measurement = tryBuild(builder, true); - assertEquals(azimuth, measurement.getAzimuth()); - assertEquals(altitude, measurement.getAltitude()); + assertEquals(azimuth, measurement.getAzimuthAngleMeasurement()); + assertEquals(altitude, measurement.getAltitudeAngleMeasurement()); } private AngleMeasurement getAngleMeasurement(double radian, double error, double confidence) { diff --git a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java index a7559d86221e..edd4d08992ba 100644 --- a/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java +++ b/core/tests/uwbtests/src/android/uwb/RangingMeasurementTest.java @@ -63,8 +63,8 @@ public class RangingMeasurementTest { assertEquals(status, measurement.getStatus()); assertEquals(address, measurement.getRemoteDeviceAddress()); assertEquals(time, measurement.getElapsedRealtimeNanos()); - assertEquals(angleMeasurement, measurement.getAngleOfArrival()); - assertEquals(distanceMeasurement, measurement.getDistance()); + assertEquals(angleMeasurement, measurement.getAngleOfArrivalMeasurement()); + assertEquals(distanceMeasurement, measurement.getDistanceMeasurement()); } private RangingMeasurement tryBuild(RangingMeasurement.Builder builder, diff --git a/services/core/Android.bp b/services/core/Android.bp index 4b9d0f1266f5..77cb12506ce6 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -196,7 +196,6 @@ filegroup { "java/com/android/server/connectivity/KeepaliveTracker.java", "java/com/android/server/connectivity/LingerMonitor.java", "java/com/android/server/connectivity/MockableSystemProperties.java", - "java/com/android/server/connectivity/MultipathPolicyTracker.java", "java/com/android/server/connectivity/Nat464Xlat.java", "java/com/android/server/connectivity/NetdEventListenerService.java", "java/com/android/server/connectivity/NetworkAgentInfo.java", diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2c765bd896fa..184f1bfaa091 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -876,6 +876,10 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @VisibleForTesting public static class Dependencies { + public int getCallingUid() { + return Binder.getCallingUid(); + } + /** * Get system properties to use in ConnectivityService. */ @@ -1408,7 +1412,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkInfo getActiveNetworkInfo() { enforceAccessPermission(); - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); final NetworkState state = getUnfilteredActiveNetworkState(uid); filterNetworkStateForUid(state, uid, false); maybeLogBlockedNetworkInfo(state.networkInfo, uid); @@ -1418,7 +1422,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public Network getActiveNetwork() { enforceAccessPermission(); - return getActiveNetworkForUidInternal(Binder.getCallingUid(), false); + return getActiveNetworkForUidInternal(mDeps.getCallingUid(), false); } @Override @@ -1458,7 +1462,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Public because it's used by mLockdownTracker. public NetworkInfo getActiveNetworkInfoUnfiltered() { enforceAccessPermission(); - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); NetworkState state = getUnfilteredActiveNetworkState(uid); return state.networkInfo; } @@ -1474,7 +1478,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkInfo getNetworkInfo(int networkType) { enforceAccessPermission(); - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); if (getVpnUnderlyingNetworks(uid) != null) { // A VPN is active, so we may need to return one of its underlying networks. This // information is not available in LegacyTypeTracker, so we have to get it from @@ -1519,7 +1523,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public Network getNetworkForType(int networkType) { enforceAccessPermission(); - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); NetworkState state = getFilteredNetworkState(networkType, uid); if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) { return state.network; @@ -1566,7 +1570,7 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( nai.network, maybeSanitizeLocationInfoForCaller( - nc, Binder.getCallingUid(), callingPackageName)); + nc, mDeps.getCallingUid(), callingPackageName)); } synchronized (mVpns) { @@ -1581,7 +1585,7 @@ public class ConnectivityService extends IConnectivityManager.Stub result.put( network, maybeSanitizeLocationInfoForCaller( - nc, Binder.getCallingUid(), callingPackageName)); + nc, mDeps.getCallingUid(), callingPackageName)); } } } @@ -1611,7 +1615,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public LinkProperties getActiveLinkProperties() { enforceAccessPermission(); - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); NetworkState state = getUnfilteredActiveNetworkState(uid); if (state.linkProperties == null) return null; return linkPropertiesRestrictedForCallerPermissions(state.linkProperties, @@ -1625,7 +1629,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final LinkProperties lp = getLinkProperties(nai); if (lp == null) return null; return linkPropertiesRestrictedForCallerPermissions( - lp, Binder.getCallingPid(), Binder.getCallingUid()); + lp, Binder.getCallingPid(), mDeps.getCallingUid()); } // TODO - this should be ALL networks @@ -1635,7 +1639,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network)); if (lp == null) return null; return linkPropertiesRestrictedForCallerPermissions( - lp, Binder.getCallingPid(), Binder.getCallingUid()); + lp, Binder.getCallingPid(), mDeps.getCallingUid()); } @Nullable @@ -1657,17 +1661,17 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (nai) { if (nai.networkCapabilities == null) return null; return networkCapabilitiesRestrictedForCallerPermissions( - nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid()); + nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid()); } } @Override public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) { - mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName); + mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName); enforceAccessPermission(); return maybeSanitizeLocationInfoForCaller( getNetworkCapabilitiesInternal(network), - Binder.getCallingUid(), callingPackageName); + mDeps.getCallingUid(), callingPackageName); } @VisibleForTesting @@ -1755,7 +1759,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) { - if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) { + if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(mDeps.getCallingUid())) { nc.addCapability(NET_CAPABILITY_FOREGROUND); } } @@ -1808,7 +1812,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost // for devices launched with Q and above. However, existing devices upgrading to Q and // above must continued to be supported for few more releases. - if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt( + if (isSystem(mDeps.getCallingUid()) && SystemProperties.getInt( "ro.product.first_api_level", 0) > Build.VERSION_CODES.P) { log("This method exists only for app backwards compatibility" + " and must not be called by system services."); @@ -1874,7 +1878,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { LinkProperties lp; @@ -2294,7 +2298,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void systemReady() { - if (Binder.getCallingUid() != Process.SYSTEM_UID) { + if (mDeps.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Calling Uid is not system uid."); } systemReadyInternal(); @@ -2520,7 +2524,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump " + tag + " from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + Binder.getCallingPid() + ", uid=" + mDeps.getCallingUid() + " due to missing android.permission.DUMP permission"); return false; } else { @@ -3900,7 +3904,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) { checkNetworkStackPermission(); - nm.forceReevaluation(Binder.getCallingUid()); + nm.forceReevaluation(mDeps.getCallingUid()); } } @@ -4367,7 +4371,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public void reportNetworkConnectivity(Network network, boolean hasConnectivity) { enforceAccessPermission(); enforceInternetPermission(); - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); final int connectivityInfo = encodeBool(hasConnectivity); // Handle ConnectivityDiagnostics event before attempting to revalidate the network. This @@ -4437,13 +4441,13 @@ public class ConnectivityService extends IConnectivityManager.Stub if (globalProxy != null) return globalProxy; if (network == null) { // Get the network associated with the calling UID. - final Network activeNetwork = getActiveNetworkForUidInternal(Binder.getCallingUid(), + final Network activeNetwork = getActiveNetworkForUidInternal(mDeps.getCallingUid(), true); if (activeNetwork == null) { return null; } return getLinkPropertiesProxyInfo(activeNetwork); - } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.getNetId())) { + } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network.getNetId())) { // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which // caller may not have. return getLinkPropertiesProxyInfo(network); @@ -4612,7 +4616,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public ParcelFileDescriptor establishVpn(VpnConfig config) { - int user = UserHandle.getUserId(Binder.getCallingUid()); + int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { throwIfLockdownEnabled(); return mVpns.get(user).establish(config); @@ -4633,7 +4637,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore); } @@ -4651,7 +4655,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void deleteVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { mVpns.get(user).deleteVpnProfile(packageName, mKeyStore); } @@ -4668,7 +4672,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void startVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { throwIfLockdownEnabled(); mVpns.get(user).startVpnProfile(packageName, mKeyStore); @@ -4685,7 +4689,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void stopVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { mVpns.get(user).stopVpnProfile(packageName); } @@ -4697,7 +4701,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void startLegacyVpn(VpnProfile profile) { - int user = UserHandle.getUserId(Binder.getCallingUid()); + int user = UserHandle.getUserId(mDeps.getCallingUid()); final LinkProperties egress = getActiveLinkProperties(); if (egress == null) { throw new IllegalStateException("Missing active network connection"); @@ -4846,7 +4850,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean updateLockdownVpn() { - if (Binder.getCallingUid() != Process.SYSTEM_UID) { + if (mDeps.getCallingUid() != Process.SYSTEM_UID) { logw("Lockdown VPN only available to AID_SYSTEM"); return false; } @@ -4868,7 +4872,7 @@ public class ConnectivityService extends IConnectivityManager.Stub setLockdownTracker(null); return true; } - int user = UserHandle.getUserId(Binder.getCallingUid()); + int user = UserHandle.getUserId(mDeps.getCallingUid()); Vpn vpn = mVpns.get(user); if (vpn == null) { logw("VPN for user " + user + " not ready yet. Skipping lockdown"); @@ -5433,7 +5437,7 @@ public class ConnectivityService extends IConnectivityManager.Stub messenger = null; mBinder = null; mPid = getCallingPid(); - mUid = getCallingUid(); + mUid = mDeps.getCallingUid(); enforceRequestCountLimit(); } @@ -5445,7 +5449,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureAllNetworkRequestsHaveType(mRequests); mBinder = binder; mPid = getCallingPid(); - mUid = getCallingUid(); + mUid = mDeps.getCallingUid(); mPendingIntent = null; enforceRequestCountLimit(); @@ -5588,7 +5592,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { - final UserHandle user = UserHandle.getUserHandleForUid(Binder.getCallingUid()); + final UserHandle user = UserHandle.getUserHandleForUid(mDeps.getCallingUid()); final PackageManager pm = mContext.createContextAsUser(user, 0 /* flags */).getPackageManager(); try { @@ -5608,7 +5612,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new SecurityException("Insufficient permissions to specify legacy type"); } } - final int callingUid = Binder.getCallingUid(); + final int callingUid = mDeps.getCallingUid(); final NetworkRequest.Type type = (networkCapabilities == null) ? NetworkRequest.Type.TRACK_DEFAULT : NetworkRequest.Type.REQUEST; @@ -5678,7 +5682,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nai != null) { nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE); synchronized (mBandwidthRequests) { - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); Integer uidReqs = mBandwidthRequests.get(uid); if (uidReqs == null) { uidReqs = 0; @@ -5695,7 +5699,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) { - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); if (isSystem(uid)) { // Exemption for system uid. return; @@ -5715,7 +5719,7 @@ public class ConnectivityService extends IConnectivityManager.Stub PendingIntent operation, @NonNull String callingPackageName, @Nullable String callingAttributionTag) { Objects.requireNonNull(operation, "PendingIntent cannot be null."); - final int callingUid = Binder.getCallingUid(); + final int callingUid = mDeps.getCallingUid(); networkCapabilities = new NetworkCapabilities(networkCapabilities); enforceNetworkRequestPermissions(networkCapabilities, callingPackageName, callingAttributionTag); @@ -5774,7 +5778,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, IBinder binder, @NonNull String callingPackageName) { - final int callingUid = Binder.getCallingUid(); + final int callingUid = mDeps.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); } @@ -5804,7 +5808,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName) { Objects.requireNonNull(operation, "PendingIntent cannot be null."); - final int callingUid = Binder.getCallingUid(); + final int callingUid = mDeps.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); } @@ -5905,7 +5909,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { enforceNetworkFactoryPermission(); } - mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true)); + mHandler.post(() -> handleReleaseNetworkRequest(request, mDeps.getCallingUid(), true)); } // NOTE: Accessed on multiple threads, must be synchronized on itself. @@ -5999,7 +6003,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceNetworkFactoryPermission(); } - final int uid = Binder.getCallingUid(); + final int uid = mDeps.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { return registerNetworkAgentInternal(messenger, networkInfo, linkProperties, @@ -7653,7 +7657,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean addVpnAddress(String address, int prefixLength) { - int user = UserHandle.getUserId(Binder.getCallingUid()); + int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { throwIfLockdownEnabled(); return mVpns.get(user).addAddress(address, prefixLength); @@ -7662,7 +7666,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean removeVpnAddress(String address, int prefixLength) { - int user = UserHandle.getUserId(Binder.getCallingUid()); + int user = UserHandle.getUserId(mDeps.getCallingUid()); synchronized (mVpns) { throwIfLockdownEnabled(); return mVpns.get(user).removeAddress(address, prefixLength); @@ -7671,7 +7675,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean setUnderlyingNetworksForVpn(Network[] networks) { - int user = UserHandle.getUserId(Binder.getCallingUid()); + int user = UserHandle.getUserId(mDeps.getCallingUid()); final boolean success; synchronized (mVpns) { throwIfLockdownEnabled(); @@ -7898,7 +7902,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") private Vpn getVpnIfOwner() { - return getVpnIfOwner(Binder.getCallingUid()); + return getVpnIfOwner(mDeps.getCallingUid()); } @GuardedBy("mVpns") @@ -8376,7 +8380,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." + " Please use NetworkCapabilities instead."); } - final int callingUid = Binder.getCallingUid(); + final int callingUid = mDeps.getCallingUid(); mAppOpsManager.checkPackage(callingUid, callingPackageName); // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid @@ -8411,7 +8415,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mConnectivityDiagnosticsHandler.obtainMessage( ConnectivityDiagnosticsHandler .EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK, - Binder.getCallingUid(), + mDeps.getCallingUid(), 0, callback)); } @@ -8427,7 +8431,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai == null || nai.creatorUid != Binder.getCallingUid()) { + if (nai == null || nai.creatorUid != mDeps.getCallingUid()) { throw new SecurityException("Data Stall simulation is only possible for network " + "creators"); } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index cabfbc02491c..228ad588525f 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -246,7 +246,12 @@ public class Vpn { void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException; } - static class Dependencies { + @VisibleForTesting + public static class Dependencies { + public boolean isCallerSystem() { + return Binder.getCallingUid() == Process.SYSTEM_UID; + } + public void startService(final String serviceName) { SystemService.start(serviceName); } @@ -267,6 +272,10 @@ public class Vpn { return new File("/data/misc/vpn/state"); } + public DeviceIdleInternal getDeviceIdleInternal() { + return LocalServices.getService(DeviceIdleInternal.class); + } + public void sendArgumentsToDaemon( final String daemon, final LocalSocket socket, final String[] arguments, final RetryScheduler retryScheduler) throws IOException, InterruptedException { @@ -373,6 +382,14 @@ public class Vpn { } @VisibleForTesting + public Vpn(Looper looper, Context context, Dependencies deps, + INetworkManagementService netService, INetd netd, @UserIdInt int userId, + @NonNull KeyStore keyStore) { + this(looper, context, deps, netService, netd, userId, keyStore, + new SystemServices(context), new Ikev2SessionCreator()); + } + + @VisibleForTesting protected Vpn(Looper looper, Context context, Dependencies deps, INetworkManagementService netService, INetd netd, int userId, @NonNull KeyStore keyStore, SystemServices systemServices, @@ -772,8 +789,7 @@ public class Vpn { // Tell the OS that background services in this app need to be allowed for // a short time, so we can bootstrap the VPN service. - DeviceIdleInternal idleController = - LocalServices.getService(DeviceIdleInternal.class); + DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage, VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, "vpn"); @@ -1959,10 +1975,6 @@ public class Vpn { return mContext.createContextAsUser( UserHandle.of(userId), 0 /* flags */).getContentResolver(); } - - public boolean isCallerSystem() { - return Binder.getCallingUid() == Process.SYSTEM_UID; - } } private native int jniCreate(int mtu); @@ -3112,7 +3124,7 @@ public class Vpn { @VisibleForTesting @Nullable VpnProfile getVpnProfilePrivileged(@NonNull String packageName, @NonNull KeyStore keyStore) { - if (!mSystemServices.isCallerSystem()) { + if (!mDeps.isCallerSystem()) { Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID "); return null; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index ea2453216a59..c24973d4f2d4 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -156,7 +156,6 @@ public class HdmiCecMessageValidator { addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT); - // TODO: Handle messages for the Tuner Control. addValidationInfo( Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS, statusRequestValidator, DEST_DIRECT); addValidationInfo( @@ -167,6 +166,10 @@ public class HdmiCecMessageValidator { Constants.MESSAGE_SELECT_DIGITAL_SERVICE, new SelectDigitalServiceValidator(), DEST_DIRECT); + addValidationInfo( + Constants.MESSAGE_TUNER_DEVICE_STATUS, + new TunerDeviceStatusValidator(), + DEST_DIRECT); // Messages for the Vendor Specific Commands. VariableLengthValidator maxLengthValidator = new VariableLengthValidator(0, 14); @@ -306,7 +309,14 @@ public class HdmiCecMessageValidator { } private boolean isValidPhysicalAddress(byte[] params, int offset) { - // TODO: Add more logic like validating 1.0.1.0. + int physicalAddress = HdmiUtils.twoBytesToInt(params, offset); + while (physicalAddress != 0) { + int maskedAddress = physicalAddress & 0xF000; + physicalAddress = (physicalAddress << 4) & 0xFFFF; + if (maskedAddress == 0 && physicalAddress != 0) { + return false; + } + } if (!mService.isTvDevice()) { // If the device is not TV, we can't convert path to port-id, so stop here. @@ -722,6 +732,35 @@ public class HdmiCecMessageValidator { || (isWithinRange(value, 0xC1, 0xC3))); } + /* + * Check if the given value is a valid Tuner Device info. A valid value is one which falls + * within the range description defined in CEC 1.4 Specification : Operand Descriptions + * (Section 17) + * + * @param params Tuner device info + * @return true if the Tuner device info is valid + */ + private boolean isValidTunerDeviceInfo(byte[] params) { + int tunerDisplayInfo = params[0] & 0x7F; + if (tunerDisplayInfo == 0x00) { + // Displaying digital tuner + if (params.length >= 5) { + return isValidDigitalServiceIdentification(params, 1); + } + } else if (tunerDisplayInfo == 0x01) { + // Not displaying Tuner + return true; + } else if (tunerDisplayInfo == 0x02) { + // Displaying Analogue tuner + if (params.length >= 5) { + return (isValidAnalogueBroadcastType(params[1]) + && isValidAnalogueFrequency(HdmiUtils.twoBytesToInt(params, 2)) + && isValidBroadcastSystem(params[4])); + } + } + return false; + } + private class PhysicalAddressValidator implements ParameterValidator { @Override public int isValid(byte[] params) { @@ -1000,6 +1039,21 @@ public class HdmiCecMessageValidator { } } + /** + * Check if the given tuner device status parameter is valid. A valid parameter should lie + * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section + * 17) + */ + private class TunerDeviceStatusValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + if (params.length < 1) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isValidTunerDeviceInfo(params)); + } + } + /** Check if the given user control press parameter is valid. */ private class UserControlPressedValidator implements ParameterValidator { @Override diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index e2145f077a90..8e50bb4885d8 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -66,6 +66,8 @@ import android.os.Looper; import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ShellCallback; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; @@ -2291,6 +2293,16 @@ public class HdmiControlService extends SystemService { } @Override + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, String[] args, + @Nullable ShellCallback callback, ResultReceiver resultReceiver) + throws RemoteException { + enforceAccessPermission(); + new HdmiControlShellCommand(this) + .exec(this, in, out, err, args, callback, resultReceiver); + } + + @Override protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return; final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java new file mode 100644 index 000000000000..ee3427f0a383 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.hdmi; + + +import android.hardware.hdmi.HdmiControlManager; +import android.hardware.hdmi.IHdmiControlCallback; +import android.hardware.hdmi.IHdmiControlService; +import android.os.RemoteException; +import android.os.ShellCommand; +import android.util.Slog; + +import java.io.PrintWriter; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +final class HdmiControlShellCommand extends ShellCommand { + + private static final String TAG = "HdmiShellCommand"; + + private final IHdmiControlService.Stub mBinderService; + + + HdmiControlShellCommand(IHdmiControlService.Stub binderService) { + mBinderService = binderService; + } + + @Override + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + + try { + return handleShellCommand(cmd); + } catch (Exception e) { + getErrPrintWriter().println( + "Caught error for command '" + cmd + "': " + e.getMessage()); + Slog.e(TAG, "Error handling hdmi_control shell command: " + cmd, e); + return 1; + } + } + + @Override + public void onHelp() { + PrintWriter pw = getOutPrintWriter(); + + pw.println("HdmiControlManager (hdmi_control) commands:"); + pw.println(" help"); + pw.println(" Print this help text."); + pw.println(" onetouchplay, otp"); + pw.println(" Send the \"One Touch Play\" feature from a source to the TV"); + pw.println(" vendorcommand --device_type <originating device type>"); + pw.println(" --destination <destination device>"); + pw.println(" --args <vendor specific arguments>"); + pw.println(" [--id <true if vendor command should be sent with vendor id>]"); + pw.println(" Send a Vendor Command to the given target device"); + } + + private int handleShellCommand(String cmd) throws RemoteException { + PrintWriter pw = getOutPrintWriter(); + + switch (cmd) { + case "otp": + case "onetouchplay": + return oneTouchPlay(pw); + case "vendorcommand": + return vendorCommand(pw); + } + + getErrPrintWriter().println("Unhandled command: " + cmd); + return 1; + } + + private int oneTouchPlay(PrintWriter pw) throws RemoteException { + final CountDownLatch latch = new CountDownLatch(1); + AtomicInteger cecResult = new AtomicInteger(); + pw.print("Sending One Touch Play..."); + mBinderService.oneTouchPlay(new IHdmiControlCallback.Stub() { + @Override + public void onComplete(int result) { + pw.println(" done (" + result + ")"); + latch.countDown(); + cecResult.set(result); + } + }); + + try { + if (!latch.await(HdmiConfig.TIMEOUT_MS, TimeUnit.MILLISECONDS)) { + getErrPrintWriter().println("One Touch Play timed out."); + return 1; + } + } catch (InterruptedException e) { + getErrPrintWriter().println("Caught InterruptedException"); + Thread.currentThread().interrupt(); + } + return cecResult.get() == HdmiControlManager.RESULT_SUCCESS ? 0 : 1; + } + + private int vendorCommand(PrintWriter pw) throws RemoteException { + if (6 > getRemainingArgsCount()) { + throw new IllegalArgumentException("Expected 3 arguments."); + } + + int deviceType = -1; + int destination = -1; + String parameters = ""; + boolean hasVendorId = false; + + String arg = getNextOption(); + while (arg != null) { + switch (arg) { + case "-t": + case "--device_type": + deviceType = Integer.parseInt(getNextArgRequired()); + break; + case "-d": + case "--destination": + destination = Integer.parseInt(getNextArgRequired()); + break; + case "-a": + case "--args": + parameters = getNextArgRequired(); + break; + case "-i": + case "--id": + hasVendorId = Boolean.parseBoolean(getNextArgRequired()); + break; + default: + throw new IllegalArgumentException("Unknown argument: " + arg); + } + arg = getNextArg(); + } + + String[] parts = parameters.split(":"); + byte[] params = new byte[parts.length]; + for (int i = 0; i < params.length; i++) { + params[i] = (byte) Integer.parseInt(parts[i], 16); + } + + pw.println("Sending <Vendor Command>"); + mBinderService.sendVendorCommand(deviceType, destination, params, hasVendorId); + return 0; + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS new file mode 100644 index 000000000000..e95633abe79a --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/OWNERS @@ -0,0 +1 @@ +include /core/java/android/app/admin/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java index 24a010039666..ae7f422817e5 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -121,6 +121,16 @@ public class HdmiCecMessageValidatorTest { } @Test + public void isValid_systemAudioModeRequest() { + assertMessageValidity("40:70:00:00").isEqualTo(OK); + assertMessageValidity("40:70").isEqualTo(OK); + + assertMessageValidity("F0:70").isEqualTo(ERROR_SOURCE); + // Invalid physical address + assertMessageValidity("40:70:10:10").isEqualTo(ERROR_PARAMETER); + } + + @Test public void isValid_setSystemAudioMode() { assertMessageValidity("40:72:00").isEqualTo(OK); assertMessageValidity("4F:72:01:03").isEqualTo(OK); @@ -340,6 +350,8 @@ public class HdmiCecMessageValidatorTest { assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER); // Invalid External PLug assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER); + // Invalid Physical Address + assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:10").isEqualTo(ERROR_PARAMETER); } @Test @@ -476,6 +488,51 @@ public class HdmiCecMessageValidatorTest { } @Test + public void isValid_tunerDeviceStatus() { + // Displaying digital tuner + assertMessageValidity("40:07:00:00:11:CE:90:0F:00:78").isEqualTo(OK); + assertMessageValidity("40:07:80:10:13:0B:34:38").isEqualTo(OK); + assertMessageValidity("40:07:00:9A:06:F9:D3:E6").isEqualTo(OK); + assertMessageValidity("40:07:00:91:09:F4:40:C8").isEqualTo(OK); + // Not displaying tuner + assertMessageValidity("40:07:01").isEqualTo(OK); + assertMessageValidity("40:07:81:07:64:B9:02").isEqualTo(OK); + // Displaying analogue tuner + assertMessageValidity("40:07:02:00:13:0F:00:96").isEqualTo(OK); + assertMessageValidity("40:07:82:02:EA:60:1F").isEqualTo(OK); + + assertMessageValidity("4F:07:00:00:11:CE:90:0F:00:78").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:07:82:02:EA:60:1F").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:07").isEqualTo(ERROR_PARAMETER_SHORT); + + // Invalid display info + assertMessageValidity("40:07:09:A1:8C:17:51").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:07:A7:0C:29").isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("40:07:00:14:11:CE:90:0F:00:78").isEqualTo(ERROR_PARAMETER); + // Invalid Digital Broadcast System + assertMessageValidity("40:07:80:A0:07:95:F1").isEqualTo(ERROR_PARAMETER); + // Insufficient data for ARIB Broadcast system + assertMessageValidity("40:07:00:00:11:CE:90:0F:00").isEqualTo(ERROR_PARAMETER); + // Insufficient data for ATSC Broadcast system + assertMessageValidity("40:07:80:10:13:0B:34").isEqualTo(ERROR_PARAMETER); + // Insufficient data for DVB Broadcast system + assertMessageValidity("40:07:00:18:BE:77:00:7D:01").isEqualTo(ERROR_PARAMETER); + // Invalid channel number format + assertMessageValidity("40:07:80:9A:10:F9:D3").isEqualTo(ERROR_PARAMETER); + // Insufficient data for 1 part channel number + assertMessageValidity("40:07:00:90:04:F7").isEqualTo(ERROR_PARAMETER); + // Insufficient data for 2 part channel number + assertMessageValidity("40:07:80:91:09:F4:40").isEqualTo(ERROR_PARAMETER); + // Invalid Analogue Broadcast type + assertMessageValidity("40:07:02:03:EA:60:1F").isEqualTo(ERROR_PARAMETER); + // Invalid Analogue Frequency + assertMessageValidity("40:07:82:00:FF:FF:00").isEqualTo(ERROR_PARAMETER); + // Invalid Broadcast system + assertMessageValidity("40:07:02:02:EA:60:20").isEqualTo(ERROR_PARAMETER); + } + + @Test public void isValid_UserControlPressed() { assertMessageValidity("40:44:07").isEqualTo(OK); assertMessageValidity("40:44:52:A7").isEqualTo(OK); @@ -518,6 +575,59 @@ public class HdmiCecMessageValidatorTest { assertMessageValidity("40:44:57:40").isEqualTo(ERROR_PARAMETER); } + @Test + public void isValid_physicalAddress() { + assertMessageValidity("4F:82:10:00").isEqualTo(OK); + assertMessageValidity("4F:82:12:34").isEqualTo(OK); + assertMessageValidity("0F:82:00:00").isEqualTo(OK); + assertMessageValidity("40:9D:14:00").isEqualTo(OK); + assertMessageValidity("40:9D:10:00").isEqualTo(OK); + assertMessageValidity("0F:81:44:20").isEqualTo(OK); + assertMessageValidity("4F:81:13:10").isEqualTo(OK); + assertMessageValidity("4F:86:14:14").isEqualTo(OK); + assertMessageValidity("0F:86:15:24").isEqualTo(OK); + + assertMessageValidity("4F:82:10").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:9D:14").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("0F:81:44").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("0F:86:15").isEqualTo(ERROR_PARAMETER_SHORT); + + assertMessageValidity("4F:82:10:10").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:82:10:06").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:9D:14:04").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("40:9D:10:01").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("0F:81:44:02").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:81:13:05").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:86:10:14").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("0F:86:10:24").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_reportPhysicalAddress() { + assertMessageValidity("4F:84:10:00:04").isEqualTo(OK); + assertMessageValidity("0F:84:00:00:00").isEqualTo(OK); + + assertMessageValidity("4F:84:10:00").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("0F:84:00").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:84:10:00:04").isEqualTo(ERROR_DESTINATION); + // Invalid Physical Address + assertMessageValidity("4F:84:10:10:04").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("0F:84:00:30:00").isEqualTo(ERROR_PARAMETER); + // Invalid Device Type + assertMessageValidity("4F:84:12:34:08").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_routingChange() { + assertMessageValidity("0F:80:10:00:40:00").isEqualTo(OK); + assertMessageValidity("4F:80:12:00:50:00").isEqualTo(OK); + + assertMessageValidity("0F:80:10:00:40").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:80:12:00:50:00").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("0F:80:10:01:40:00").isEqualTo(ERROR_PARAMETER); + assertMessageValidity("4F:80:12:00:50:50").isEqualTo(ERROR_PARAMETER); + } + private IntegerSubject assertMessageValidity(String message) { return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message))); } diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java index 3104c7e7e0a1..f923721b19ea 100644 --- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java +++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java @@ -34,6 +34,7 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.Log; @@ -154,9 +155,27 @@ public class IorapForwardingService extends SystemService { @VisibleForTesting protected boolean isIorapEnabled() { + // These two mendel flags should match those in iorapd native process + // system/iorapd/src/common/property.h + boolean isTracingEnabled = + getMendelFlag("iorap_perfetto_enable", "iorapd.perfetto.enable", false); + boolean isReadAheadEnabled = + getMendelFlag("iorap_readahead_enable", "iorapd.readahead.enable", false); // Same as the property in iorapd.rc -- disabling this will mean the 'iorapd' binder process // never comes up, so all binder connections will fail indefinitely. - return IS_ENABLED; + return IS_ENABLED && (isTracingEnabled || isReadAheadEnabled); + } + + private boolean getMendelFlag(String mendelFlag, String sysProperty, boolean defaultValue) { + // TODO(yawanng) use DeviceConfig to get mendel property. + // DeviceConfig doesn't work and the reason is not clear. + // Provider service is already up before IORapForwardService. + String mendelProperty = "persist.device_config." + + DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT + + "." + + mendelFlag; + return SystemProperties.getBoolean(mendelProperty, + SystemProperties.getBoolean(sysProperty, defaultValue)); } //</editor-fold> @@ -239,7 +258,9 @@ public class IorapForwardingService extends SystemService { // // TODO: it would be good to get nodified of 'adb shell stop iorapd' to avoid // printing this warning. - Log.w(TAG, "Failed to connect to iorapd, is it down? Delay for " + sleepTime); + if (DEBUG) { + Log.v(TAG, "Failed to connect to iorapd, is it down? Delay for " + sleepTime); + } // Use a handler instead of Thread#sleep to avoid backing up the binder thread // when this is called from the death recipient callback. @@ -275,7 +296,9 @@ public class IorapForwardingService extends SystemService { // Connect to the native binder service. mIorapRemote = provideIorapRemote(); if (mIorapRemote == null) { - Log.e(TAG, "connectToRemoteAndConfigure - null iorap remote. check for Log.wtf?"); + if (DEBUG) { + Log.e(TAG, "connectToRemoteAndConfigure - null iorap remote. check for Log.wtf?"); + } return false; } invokeRemote(mIorapRemote, diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 21cca4ca8204..52f263fad695 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -521,6 +521,8 @@ public interface RILConstants { int RIL_REQUEST_CANCEL_HANDOVER = 218; int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219; int RIL_REQUEST_SET_DATA_THROTTLING = 221; + int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP = 222; + int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP = 223; /* Responses begin */ int RIL_RESPONSE_ACKNOWLEDGEMENT = 800; diff --git a/tests/BatteryStatsPerfTest/OWNERS b/tests/BatteryStatsPerfTest/OWNERS new file mode 100644 index 000000000000..4068e2bc03b7 --- /dev/null +++ b/tests/BatteryStatsPerfTest/OWNERS @@ -0,0 +1 @@ +include /BATTERY_STATS_OWNERS diff --git a/tests/BatteryWaster/OWNERS b/tests/BatteryWaster/OWNERS new file mode 100644 index 000000000000..4068e2bc03b7 --- /dev/null +++ b/tests/BatteryWaster/OWNERS @@ -0,0 +1 @@ +include /BATTERY_STATS_OWNERS diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 8c403f1b6898..21dbbc6fed28 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -39,6 +39,7 @@ import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; +import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK; @@ -101,6 +102,8 @@ 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 static org.mockito.AdditionalMatchers.aryEq; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; @@ -132,6 +135,7 @@ import android.app.AppOpsManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; @@ -140,6 +144,8 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.content.res.Resources; import android.location.LocationManager; @@ -176,6 +182,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; +import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkStack; @@ -332,12 +339,13 @@ public class ConnectivityServiceTest { private static final String WIFI_WOL_IFNAME = "test_wlan_wol"; private static final String VPN_IFNAME = "tun10042"; private static final String TEST_PACKAGE_NAME = "com.android.test.package"; - private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn"; private static final String INTERFACE_NAME = "interface"; private MockContext mServiceContext; private HandlerThread mCsHandlerThread; + private ConnectivityService.Dependencies mDeps; private ConnectivityService mService; private WrappedConnectivityManager mCm; private TestNetworkAgentWrapper mWiFiNetworkAgent; @@ -353,6 +361,7 @@ public class ConnectivityServiceTest { @Mock IIpConnectivityMetrics mIpConnectivityMetrics; @Mock IpConnectivityMetrics.Logger mMetricsService; @Mock DefaultNetworkMetrics mDefaultNetworkMetrics; + @Mock DeviceIdleInternal mDeviceIdleInternal; @Mock INetworkManagementService mNetworkManagementService; @Mock INetworkStatsService mStatsService; @Mock IBatteryStats mBatteryStatsService; @@ -450,6 +459,15 @@ public class ConnectivityServiceTest { } @Override + public ComponentName startService(Intent service) { + final String action = service.getAction(); + if (!VpnConfig.SERVICE_INTERFACE.equals(action)) { + fail("Attempt to start unknown service, action=" + action); + } + return new ComponentName(service.getPackage(), "com.android.test.Service"); + } + + @Override public Object getSystemService(String name) { if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager; @@ -1055,9 +1073,19 @@ public class ConnectivityServiceTest { private VpnInfo mVpnInfo; public MockVpn(int userId) { - super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, - mMockNetd, userId, mock(KeyStore.class)); - mConfig = new VpnConfig(); + super(startHandlerThreadAndReturnLooper(), mServiceContext, + new Dependencies() { + @Override + public boolean isCallerSystem() { + return true; + } + + @Override + public DeviceIdleInternal getDeviceIdleInternal() { + return mDeviceIdleInternal; + } + }, + mNetworkManagementService, mMockNetd, userId, mock(KeyStore.class)); } public void setUids(Set<UidRange> uids) { @@ -1086,9 +1114,16 @@ public class ConnectivityServiceTest { return mVpnType; } + private LinkProperties makeLinkProperties() { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(VPN_IFNAME); + return lp; + } + private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp) throws Exception { if (mAgentRegistered) throw new IllegalStateException("already registered"); + mConfig = new VpnConfig(); setUids(uids); if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); mInterface = VPN_IFNAME; @@ -1101,12 +1136,13 @@ public class ConnectivityServiceTest { verify(mMockNetd, never()) .networkRemoveUidRanges(eq(mMockVpn.getNetId()), any()); mAgentRegistered = true; + updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent"); mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); mNetworkAgent = mMockNetworkAgent.getNetworkAgent(); } private void registerAgent(Set<UidRange> uids) throws Exception { - registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties()); + registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties()); } private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) { @@ -1142,12 +1178,12 @@ public class ConnectivityServiceTest { public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode) throws Exception { final int uid = Process.myUid(); - establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet, + establish(makeLinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet, isStrictMode); } public void establishForMyUid() throws Exception { - establishForMyUid(new LinkProperties()); + establishForMyUid(makeLinkProperties()); } public void sendLinkProperties(LinkProperties lp) { @@ -1155,7 +1191,10 @@ public class ConnectivityServiceTest { } public void disconnect() { - if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect(); + if (mMockNetworkAgent != null) { + mMockNetworkAgent.disconnect(); + updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect"); + } mAgentRegistered = false; } @@ -1229,6 +1268,17 @@ public class ConnectivityServiceTest { fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms"); } + private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback, + int uid) { + when(mDeps.getCallingUid()).thenReturn(uid); + try { + mCm.registerNetworkCallback(request, callback); + waitForIdle(); + } finally { + returnRealCallingUid(); + } + } + private static final int VPN_USER = 0; private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100); private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101); @@ -1271,7 +1321,8 @@ public class ConnectivityServiceTest { initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler()); mCsHandlerThread = new HandlerThread("TestConnectivityService"); - final ConnectivityService.Dependencies deps = makeDependencies(); + mDeps = makeDependencies(); + returnRealCallingUid(); mService = new ConnectivityService(mServiceContext, mNetworkManagementService, mStatsService, @@ -1279,9 +1330,9 @@ public class ConnectivityServiceTest { mMockDnsResolver, mock(IpConnectivityLog.class), mMockNetd, - deps); + mDeps); mService.mLingerDelayMs = TEST_LINGER_DELAY_MS; - verify(deps).makeMultinetworkPolicyTracker(any(), any(), any()); + verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any()); final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor = ArgumentCaptor.forClass(INetworkPolicyListener.class); @@ -1301,6 +1352,10 @@ public class ConnectivityServiceTest { setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com"); } + private void returnRealCallingUid() { + doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid(); + } + private ConnectivityService.Dependencies makeDependencies() { doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties) .getInt("net.tcp.default_init_rwnd", 0); @@ -1376,13 +1431,13 @@ public class ConnectivityServiceTest { } private void mockDefaultPackages() throws Exception { - final String testPackageName = mContext.getPackageName(); - final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo( - testPackageName, PackageManager.GET_PERMISSIONS); + final String myPackageName = mContext.getPackageName(); + final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo( + myPackageName, PackageManager.GET_PERMISSIONS); when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn( - new String[] {testPackageName}); - when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(), - eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo); + new String[] {myPackageName}); + when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(), + eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo); when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { @@ -1390,6 +1445,25 @@ public class ConnectivityServiceTest { buildPackageInfo(/* SYSTEM */ false, APP2_UID), buildPackageInfo(/* SYSTEM */ false, VPN_UID) })); + + // Create a fake always-on VPN package. + final int userId = UserHandle.getCallingUserId(); + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; // Always-on supported in N+. + when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(), + eq(userId))).thenReturn(applicationInfo); + + // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy. + ResolveInfo rInfo = new ResolveInfo(); + rInfo.serviceInfo = new ServiceInfo(); + rInfo.serviceInfo.metaData = new Bundle(); + final List<ResolveInfo> services = Arrays.asList(new ResolveInfo[]{rInfo}); + when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), + eq(userId))).thenReturn(services); + when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId)) + .thenReturn(Process.myUid()); + when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId)) + .thenReturn(VPN_UID); } private void verifyActiveNetwork(int transport) { @@ -2252,10 +2326,10 @@ public class ConnectivityServiceTest { } private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception { - final String testPackageName = mContext.getPackageName(); - when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS))) + final String myPackageName = mContext.getPackageName(); + when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS))) .thenReturn(buildPackageInfo(true, uid)); - mService.mPermissionMonitor.onPackageAdded(testPackageName, uid); + mService.mPermissionMonitor.onPackageAdded(myPackageName, uid); } @Test @@ -5831,10 +5905,21 @@ public class ConnectivityServiceTest { assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); } + private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) { + final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser( + userId, "com.android.calling.package"); + final String defaultCapsString = Arrays.toString(defaultCaps); + assertEquals(defaultCapsString, defaultCaps.length, networks.length); + final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps); + for (NetworkAgentWrapper network : networks) { + final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork()); + final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps); + assertTrue(msg, defaultCapsSet.contains(nc)); + } + } + @Test public void testVpnSetUnderlyingNetworks() throws Exception { - final int uid = Process.myUid(); - final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() .removeCapability(NET_CAPABILITY_NOT_VPN) @@ -5857,6 +5942,9 @@ public class ConnectivityServiceTest { // A VPN without underlying networks is not suspended. assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + final int userId = UserHandle.getUserId(Process.myUid()); + assertDefaultNetworkCapabilities(userId /* no networks */); + // Connect cell and use it as an underlying network. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); @@ -5870,6 +5958,7 @@ public class ConnectivityServiceTest { && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); @@ -5884,6 +5973,7 @@ public class ConnectivityServiceTest { && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); // Don't disconnect, but note the VPN is not using wifi any more. mService.setUnderlyingNetworksForVpn( @@ -5894,6 +5984,9 @@ public class ConnectivityServiceTest { && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + // The return value of getDefaultNetworkCapabilitiesForUser always includes the default + // network (wifi) as well as the underlying networks (cell). + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended. mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); @@ -5922,6 +6015,7 @@ public class ConnectivityServiceTest { && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) && caps.hasCapability(NET_CAPABILITY_NOT_METERED) && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent); // Use both again. mService.setUnderlyingNetworksForVpn( @@ -5932,6 +6026,7 @@ public class ConnectivityServiceTest { && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); // Cell is suspended again. As WiFi is not, this should not cause a callback. mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); @@ -5949,6 +6044,7 @@ public class ConnectivityServiceTest { // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never // been public and are deprecated and slated for removal, there is no sense in spending // resources fixing this bug now. + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); // Use both again. mService.setUnderlyingNetworksForVpn( @@ -5961,6 +6057,7 @@ public class ConnectivityServiceTest { && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // As above, the RESUMED callback not being sent here is a bug, but not a bug that's // worth anybody's time to fix. + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent); // Disconnect cell. Receive update without even removing the dead network from the // underlying networks – it's dead anyway. Not metered any more. @@ -5969,6 +6066,7 @@ public class ConnectivityServiceTest { (caps) -> caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent); // Disconnect wifi too. No underlying networks means this is now metered. mWiFiNetworkAgent.disconnect(); @@ -5976,6 +6074,11 @@ public class ConnectivityServiceTest { (caps) -> caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + // When a network disconnects, the callbacks are fired before all state is updated, so for a + // short time, synchronous calls will behave as if the network is still connected. Wait for + // things to settle. + waitForIdle(); + assertDefaultNetworkCapabilities(userId /* no networks */); mMockVpn.disconnect(); } @@ -6276,6 +6379,7 @@ public class ConnectivityServiceTest { // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered. assertTrue(mCm.isActiveNetworkMetered()); + // VPN explicitly declares WiFi as its underlying network. mService.setUnderlyingNetworksForVpn( new Network[] { mWiFiNetworkAgent.getNetwork() }); @@ -6389,6 +6493,189 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(defaultCallback); } + private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add, + UidRangeParcel... expected) throws Exception { + inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected)); + } + + private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) { + assertNotNull(ni); + assertEquals(type, ni.getType()); + assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState()); + } + + private void assertActiveNetworkInfo(int type, DetailedState state) { + checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state); + } + private void assertNetworkInfo(int type, DetailedState state) { + checkNetworkInfo(mCm.getNetworkInfo(type), type, state); + } + + @Test + public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception { + mServiceContext.setPermission( + Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED); + mServiceContext.setPermission( + Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); + mServiceContext.setPermission( + Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); + + final TestNetworkCallback callback = new TestNetworkCallback(); + final NetworkRequest request = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .build(); + mCm.registerNetworkCallback(request, callback); + + final TestNetworkCallback defaultCallback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(defaultCallback); + + final TestNetworkCallback vpnUidCallback = new TestNetworkCallback(); + final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build(); + registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID); + + final int uid = Process.myUid(); + final int userId = UserHandle.getUserId(uid); + final ArrayList<String> allowList = new ArrayList<>(); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + + UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1); + UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999); + InOrder inOrder = inOrder(mMockNetd); + expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); + + // Connect a network when lockdown is active, expect to see it blocked. + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false /* validated */); + callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + // Mobile is BLOCKED even though it's not actually connected. + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + + // Disable lockdown, expect to see the network unblocked. + // There are no callbacks because they are not implemented yet. + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf); + vpnUidCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked. + allowList.add(TEST_PACKAGE_NAME); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + callback.assertNoCallback(); + defaultCallback.assertNoCallback(); + vpnUidCallback.assertNoCallback(); + + // The following requires that the UID of this test package is greater than VPN_UID. This + // is always true in practice because a plain AOSP build with no apps installed has almost + // 200 packages installed. + final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1); + final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1); + final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999); + expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Connect a new network, expect it to be unblocked. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(false /* validated */); + callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + defaultCallback.assertNoCallback(); + vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + // Cellular is DISCONNECTED because it's not the default and there are no requests for it. + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown. + // Everything should now be blocked. + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3); + allowList.clear(); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); + vpnUidCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + + // Disable lockdown. Everything is unblocked. + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + vpnUidCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Enable and disable an always-on VPN package without lockdown. Expect no changes. + reset(mMockNetd); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList); + inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); + callback.assertNoCallback(); + defaultCallback.assertNoCallback(); + vpnUidCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); + callback.assertNoCallback(); + defaultCallback.assertNoCallback(); + vpnUidCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Enable lockdown and connect a VPN. The VPN is not blocked. + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + vpnUidCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + + mMockVpn.establishForMyUid(); + defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + vpnUidCallback.assertNoCallback(); // vpnUidCallback has NOT_VPN capability. + assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); + assertEquals(null, mCm.getActiveNetworkForUid(VPN_UID)); // BUG? + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + mMockVpn.disconnect(); + defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); + defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + assertNull(mCm.getActiveNetwork()); + + mCm.unregisterNetworkCallback(callback); + mCm.unregisterNetworkCallback(defaultCallback); + mCm.unregisterNetworkCallback(vpnUidCallback); + } + @Test public final void testLoseTrusted() throws Exception { final NetworkRequest trustedRequest = new NetworkRequest.Builder() diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 6e380be6c583..cc473175540c 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -228,7 +228,6 @@ public class VpnTest { R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) .thenReturn(true); - when(mSystemServices.isCallerSystem()).thenReturn(true); // Used by {@link Notification.Builder} ApplicationInfo applicationInfo = new ApplicationInfo(); @@ -1102,6 +1101,11 @@ public class VpnTest { } @Override + public boolean isCallerSystem() { + return true; + } + + @Override public void startService(final String serviceName) { mRunningServices.put(serviceName, true); } |