Merge "create owners"
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 061d4cc..230863d 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -11,6 +11,7 @@
package android.net {
public class ConnectivityManager {
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
}
@@ -18,6 +19,14 @@
method public int getResourceId();
}
+ public final class NetworkAgentConfig implements android.os.Parcelable {
+ method @Nullable public String getSubscriberId();
+ }
+
+ public static final class NetworkAgentConfig.Builder {
+ method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ }
+
public final class NetworkCapabilities implements android.os.Parcelable {
field public static final int TRANSPORT_TEST = 7; // 0x7
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a7c5b74..6026211 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1415,8 +1415,10 @@
package android.apphibernation {
public final class AppHibernationManager {
- method public boolean isHibernating(@NonNull String);
- method public void setHibernating(@NonNull String, boolean);
+ method public boolean isHibernatingForUser(@NonNull String);
+ method public boolean isHibernatingGlobally(@NonNull String);
+ method public void setHibernatingForUser(@NonNull String, boolean);
+ method public void setHibernatingGlobally(@NonNull String, boolean);
}
}
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index afa1560..e6aa7a7 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -47,8 +47,19 @@
per-file *Zen* = file:/packages/SystemUI/OWNERS
per-file *StatusBar* = file:/packages/SystemUI/OWNERS
+# PackageManager
+per-file ApplicationPackageManager.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file InstantAppResolverService.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file LoadedApk.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file PackageDeleteObserver.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file PackageInstallObserver.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file EphemeralResolveInfo.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+per-file IEphemeralResolver.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+per-file IInstantAppResolver.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+per-file InstantAppResolveInfo.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+
# ResourcesManager
-per-file ResourcesManager = rtmitchell@google.com, toddke@google.com
+per-file ResourcesManager.java = rtmitchell@google.com, toddke@google.com
# VoiceInteraction
per-file *VoiceInteract* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/android/apphibernation/AppHibernationManager.java b/core/java/android/apphibernation/AppHibernationManager.java
index 8f1934c..7281d50 100644
--- a/core/java/android/apphibernation/AppHibernationManager.java
+++ b/core/java/android/apphibernation/AppHibernationManager.java
@@ -49,31 +49,61 @@
}
/**
- * Returns true if the package is hibernating, false otherwise.
+ * Returns true if the package is hibernating for this context's user, false otherwise.
*
* @hide
*/
@SystemApi
- public boolean isHibernating(@NonNull String packageName) {
+ public boolean isHibernatingForUser(@NonNull String packageName) {
try {
- return mIAppHibernationService.isHibernating(packageName, mContext.getUserId());
+ return mIAppHibernationService.isHibernatingForUser(packageName, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Set whether the package is hibernating.
+ * Set whether the package is hibernating for this context's user.
*
* @hide
*/
@SystemApi
- public void setHibernating(@NonNull String packageName, boolean isHibernating) {
+ public void setHibernatingForUser(@NonNull String packageName, boolean isHibernating) {
try {
- mIAppHibernationService.setHibernating(packageName, mContext.getUserId(),
+ mIAppHibernationService.setHibernatingForUser(packageName, mContext.getUserId(),
isHibernating);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Returns true if app is hibernating globally / at the package level.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isHibernatingGlobally(@NonNull String packageName) {
+ try {
+ return mIAppHibernationService.isHibernatingGlobally(packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Set whether a package should be globally hibernating. This hibernates the package at a
+ * package level. User-level hibernation (e.g.. {@link #isHibernatingForUser} is independent
+ * from global hibernation.
+ *
+ * @hide
+ */
+ @SystemApi
+ public void setHibernatingGlobally(@NonNull String packageName, boolean isHibernating) {
+ try {
+ mIAppHibernationService.setHibernatingGlobally(packageName, isHibernating);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/apphibernation/IAppHibernationService.aidl b/core/java/android/apphibernation/IAppHibernationService.aidl
index db57ecb..6a068ee 100644
--- a/core/java/android/apphibernation/IAppHibernationService.aidl
+++ b/core/java/android/apphibernation/IAppHibernationService.aidl
@@ -21,6 +21,8 @@
* @hide
*/
interface IAppHibernationService {
- boolean isHibernating(String packageName, int userId);
- void setHibernating(String packageName, int userId, boolean isHibernating);
+ boolean isHibernatingForUser(String packageName, int userId);
+ void setHibernatingForUser(String packageName, int userId, boolean isHibernating);
+ boolean isHibernatingGlobally(String packageName);
+ void setHibernatingGlobally(String packageName, boolean isHibernating);
}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 36076da..4fb5577 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -80,7 +80,7 @@
/**
* Intent used to broadcast the change in the Audio Connection state of the
- * A2DP profile.
+ * HFP profile.
*
* <p>This intent will have 3 extras:
* <ul>
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 0ef55f4..3730790 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -954,7 +954,10 @@
/**
* Returns whether the given functions are valid inputs to UsbManager.
- * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted.
+ * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM are accepted.
+ *
+ * Only one function may be set at a time, except for RNDIS and NCM, which can be set together
+ * because from a user perspective they are the same function (tethering).
*
* @return Whether the mask is settable.
*
@@ -962,7 +965,9 @@
*/
public static boolean areSettableFunctions(long functions) {
return functions == FUNCTION_NONE
- || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1);
+ || ((~SETTABLE_FUNCTIONS & functions) == 0
+ && ((Long.bitCount(functions) == 1)
+ || (functions == (FUNCTION_RNDIS | FUNCTION_NCM))));
}
/**
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d107261..7f07bba 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -15,7 +15,9 @@
*/
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
+import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.LISTEN;
import static android.net.NetworkRequest.Type.REQUEST;
import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
@@ -28,6 +30,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.PendingIntent;
@@ -4964,4 +4967,92 @@
}
return null;
}
+
+ /**
+ * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, but
+ * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can
+ * be used to request that the system provide a network without causing the network to be
+ * in the foreground.
+ *
+ * <p>This method will attempt to find the best network that matches the passed
+ * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the
+ * criteria. The platform will evaluate which network is the best at its own discretion.
+ * Throughput, latency, cost per byte, policy, user preference and other considerations
+ * may be factored in the decision of what is considered the best network.
+ *
+ * <p>As long as this request is outstanding, the platform will try to maintain the best network
+ * matching this request, while always attempting to match the request to a better network if
+ * possible. If a better match is found, the platform will switch this request to the now-best
+ * network and inform the app of the newly best network by invoking
+ * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform
+ * will not try to maintain any other network than the best one currently matching the request:
+ * a network not matching any network request may be disconnected at any time.
+ *
+ * <p>For example, an application could use this method to obtain a connected cellular network
+ * even if the device currently has a data connection over Ethernet. This may cause the cellular
+ * radio to consume additional power. Or, an application could inform the system that it wants
+ * a network supporting sending MMSes and have the system let it know about the currently best
+ * MMS-supporting network through the provided {@link NetworkCallback}.
+ *
+ * <p>The status of the request can be followed by listening to the various callbacks described
+ * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be
+ * used to direct traffic to the network (although accessing some networks may be subject to
+ * holding specific permissions). Callers will learn about the specific characteristics of the
+ * network through
+ * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and
+ * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the
+ * provided {@link NetworkCallback} will only be invoked due to changes in the best network
+ * matching the request at any given time; therefore when a better network matching the request
+ * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called
+ * with the new network after which no further updates are given about the previously-best
+ * network, unless it becomes the best again at some later time. All callbacks are invoked
+ * in order on the same thread, which by default is a thread created by the framework running
+ * in the app.
+ *
+ * <p>This{@link NetworkRequest} will live until released via
+ * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at
+ * which point the system may let go of the network at any time.
+ *
+ * <p>It is presently unsupported to request a network with mutable
+ * {@link NetworkCapabilities} such as
+ * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+ * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
+ * as these {@code NetworkCapabilities} represent states that a particular
+ * network may never attain, and whether a network will attain these states
+ * is unknown prior to bringing up the network so the framework does not
+ * know how to go about satisfying a request with these capabilities.
+ *
+ * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
+ * number of outstanding requests to 100 per app (identified by their UID), shared with
+ * all variants of this method, of {@link #registerNetworkCallback} as well as
+ * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}.
+ * Requesting a network with this method will count toward this limit. If this limit is
+ * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources,
+ * make sure to unregister the callbacks with
+ * {@link #unregisterNetworkCallback(NetworkCallback)}.
+ *
+ * @param request {@link NetworkRequest} describing this request.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * If null, the callback is invoked on the default internal Handler.
+ * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+ * the callback must not be shared - it uniquely specifies this request.
+ * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @throws RuntimeException if the app already has too many callbacks registered.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @SuppressLint("ExecutorRegistration")
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+ })
+ public void requestBackgroundNetwork(@NonNull NetworkRequest request,
+ @Nullable Handler handler, @NonNull NetworkCallback networkCallback) {
+ final NetworkCapabilities nc = request.networkCapabilities;
+ sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST,
+ TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler));
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 7197831..1b4d2e4 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -31,7 +31,6 @@
import android.net.NetworkState;
import android.net.ProxyInfo;
import android.net.UidRange;
-import android.net.VpnInfo;
import android.net.QosSocketInfo;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index d5aede7..0baf11e 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -23,7 +23,7 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.os.IBinder;
@@ -70,7 +70,7 @@
in Network[] defaultNetworks,
in NetworkState[] networkStates,
in String activeIface,
- in VpnInfo[] vpnInfos);
+ in UnderlyingNetworkInfo[] underlyingNetworkInfos);
/** Force update of statistics. */
@UnsupportedAppUsage
void forceUpdate();
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
index fe1268d..664c265 100644
--- a/core/java/android/net/NetworkAgentConfig.java
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -16,6 +16,8 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -125,6 +127,7 @@
* @return the subscriber ID, or null if none.
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
@Nullable
public String getSubscriberId() {
return subscriberId;
@@ -275,6 +278,7 @@
* @hide
*/
@NonNull
+ @SystemApi(client = MODULE_LIBRARIES)
public Builder setSubscriberId(@Nullable String subscriberId) {
mConfig.subscriberId = subscriberId;
return this;
diff --git a/core/java/android/net/VpnInfo.aidl b/core/java/android/net/UnderlyingNetworkInfo.aidl
similarity index 94%
rename from core/java/android/net/VpnInfo.aidl
rename to core/java/android/net/UnderlyingNetworkInfo.aidl
index 8bcaa81..a56f2f4 100644
--- a/core/java/android/net/VpnInfo.aidl
+++ b/core/java/android/net/UnderlyingNetworkInfo.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable VpnInfo;
+parcelable UnderlyingNetworkInfo;
diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java
new file mode 100644
index 0000000..8fb4832
--- /dev/null
+++ b/core/java/android/net/UnderlyingNetworkInfo.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A lightweight container used to carry information on the networks that underly a given
+ * virtual network.
+ *
+ * @hide
+ */
+public final class UnderlyingNetworkInfo implements Parcelable {
+ /** The owner of this network. */
+ public final int ownerUid;
+ /** The interface name of this network. */
+ @NonNull
+ public final String iface;
+ /** The names of the interfaces underlying this network. */
+ @NonNull
+ public final List<String> underlyingIfaces;
+
+ public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface,
+ @NonNull List<String> underlyingIfaces) {
+ Objects.requireNonNull(iface);
+ Objects.requireNonNull(underlyingIfaces);
+ this.ownerUid = ownerUid;
+ this.iface = iface;
+ this.underlyingIfaces = underlyingIfaces;
+ }
+
+ private UnderlyingNetworkInfo(@NonNull Parcel in) {
+ this.ownerUid = in.readInt();
+ this.iface = in.readString();
+ this.underlyingIfaces = new ArrayList<>();
+ in.readList(this.underlyingIfaces, null /*classLoader*/);
+ }
+
+ @Override
+ public String toString() {
+ return "UnderlyingNetworkInfo{"
+ + "ownerUid=" + ownerUid
+ + ", iface='" + iface + '\''
+ + ", underlyingIfaces='" + underlyingIfaces.toString() + '\''
+ + '}';
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(ownerUid);
+ dest.writeString(iface);
+ dest.writeList(underlyingIfaces);
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<UnderlyingNetworkInfo> CREATOR =
+ new Parcelable.Creator<UnderlyingNetworkInfo>() {
+ @NonNull
+ @Override
+ public UnderlyingNetworkInfo createFromParcel(@NonNull Parcel in) {
+ return new UnderlyingNetworkInfo(in);
+ }
+
+ @NonNull
+ @Override
+ public UnderlyingNetworkInfo[] newArray(int size) {
+ return new UnderlyingNetworkInfo[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UnderlyingNetworkInfo)) return false;
+ final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o;
+ return ownerUid == that.ownerUid
+ && Objects.equals(iface, that.iface)
+ && Objects.equals(underlyingIfaces, that.underlyingIfaces);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ownerUid, iface, underlyingIfaces);
+ }
+}
diff --git a/core/java/android/net/VpnInfo.java b/core/java/android/net/VpnInfo.java
deleted file mode 100644
index cf58c57..0000000
--- a/core/java/android/net/VpnInfo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * A lightweight container used to carry information of the ongoing VPN.
- * Internal use only.
- *
- * @hide
- */
-public class VpnInfo implements Parcelable {
- public final int ownerUid;
- @Nullable
- public final String vpnIface;
- @Nullable
- public final String[] underlyingIfaces;
-
- public VpnInfo(int ownerUid, @Nullable String vpnIface, @Nullable String[] underlyingIfaces) {
- this.ownerUid = ownerUid;
- this.vpnIface = vpnIface;
- this.underlyingIfaces = underlyingIfaces;
- }
-
- private VpnInfo(@NonNull Parcel in) {
- this.ownerUid = in.readInt();
- this.vpnIface = in.readString();
- this.underlyingIfaces = in.createStringArray();
- }
-
- @Override
- public String toString() {
- return "VpnInfo{"
- + "ownerUid=" + ownerUid
- + ", vpnIface='" + vpnIface + '\''
- + ", underlyingIfaces='" + Arrays.toString(underlyingIfaces) + '\''
- + '}';
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(ownerUid);
- dest.writeString(vpnIface);
- dest.writeStringArray(underlyingIfaces);
- }
-
- @NonNull
- public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() {
- @NonNull
- @Override
- public VpnInfo createFromParcel(@NonNull Parcel in) {
- return new VpnInfo(in);
- }
-
- @NonNull
- @Override
- public VpnInfo[] newArray(int size) {
- return new VpnInfo[size];
- }
- };
-}
diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl
index 80ac64b..4f293ee 100644
--- a/core/java/android/net/vcn/IVcnManagementService.aidl
+++ b/core/java/android/net/vcn/IVcnManagementService.aidl
@@ -16,8 +16,11 @@
package android.net.vcn;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.os.ParcelUuid;
/**
@@ -29,4 +32,5 @@
void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
+ VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(in NetworkCapabilities nc, in LinkProperties lp);
}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 2d0a6d7..33beb6a 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -21,6 +21,8 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.content.Context;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -62,7 +64,7 @@
* @hide
*/
@SystemService(Context.VCN_MANAGEMENT_SERVICE)
-public final class VcnManager {
+public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
/** @hide */
@@ -223,6 +225,37 @@
}
/**
+ * Queries the underlying network policy for a network with the given parameters.
+ *
+ * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
+ * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network
+ * Provider MUST poll for the updated Network policy based on that Network's capabilities and
+ * properties.
+ *
+ * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
+ * policy for this Network.
+ * @param linkProperties the LinkProperties to be used in determining the Network policy for
+ * this Network.
+ * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
+ * @return the VcnUnderlyingNetworkPolicy to be used for this Network.
+ * @hide
+ */
+ @NonNull
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
+ @NonNull NetworkCapabilities networkCapabilities,
+ @NonNull LinkProperties linkProperties) {
+ requireNonNull(networkCapabilities, "networkCapabilities must not be null");
+ requireNonNull(linkProperties, "linkProperties must not be null");
+
+ try {
+ return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System
* Server.
*
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 71344f9..f853e67 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -288,6 +288,20 @@
}
/**
+ * Get service debug info.
+ * @return an array of information for each service (like listServices, but with PIDs)
+ * @hide
+ */
+ public static ServiceDebugInfo[] getServiceDebugInfo() {
+ try {
+ return getIServiceManager().getServiceDebugInfo();
+ } catch (RemoteException e) {
+ Log.e(TAG, "error in getServiceDebugInfo", e);
+ return null;
+ }
+ }
+
+ /**
* This is only intended to be called when the process is first being brought
* up and bound by the activity manager. There is only one thread in the process
* at that time, so no locking is done.
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index b70b6b5..60acc57 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -103,6 +103,10 @@
throw new RemoteException();
}
+ public ServiceDebugInfo[] getServiceDebugInfo() throws RemoteException {
+ return mServiceManager.getServiceDebugInfo();
+ }
+
/**
* Same as mServiceManager but used by apps.
*
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 24dabfc..a668e8e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4507,7 +4507,7 @@
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|setup" />
<!-- Allows applications to set the initial lockscreen state.
<p>Not for use by third-party applications. @hide -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d30efa9..20cb270 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4411,4 +4411,7 @@
<!-- Component names of the services which will keep critical code path warm -->
<string-array name="config_keep_warming_services" translatable="false" />
+
+ <!-- Whether to select voice/data/sms preference without user confirmation -->
+ <bool name="config_voice_data_sms_auto_fallback">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 937716d..4509b4e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4057,4 +4057,6 @@
<java-symbol type="array" name="config_notificationMsgPkgsAllowedAsConvos" />
<java-symbol type="array" name="config_keep_warming_services" />
+
+ <java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
</resources>
diff --git a/core/tests/mockingcoretests/src/android/view/OWNERS b/core/tests/mockingcoretests/src/android/view/OWNERS
new file mode 100644
index 0000000..9c9f824
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/view/OWNERS
@@ -0,0 +1,2 @@
+# Display
+per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 30501fb..a664ee3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -345,7 +345,6 @@
<permission name="android.permission.MOVE_PACKAGE"/>
<!-- Needed for test only -->
<permission name="android.permission.RESTART_WIFI_SUBSYSTEM"/>
- <permission name="android.permission.NETWORK_AIRPLANE_MODE"/>
<permission name="android.permission.OBSERVE_APP_USAGE"/>
<permission name="android.permission.NETWORK_SCAN"/>
<permission name="android.permission.PACKAGE_USAGE_STATS" />
@@ -444,6 +443,9 @@
<!-- Permission needed for CTS test - WifiManagerTest -->
<permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+ <!-- Permission required for GTS test - GtsAssistIntentTestCases -->
+ <permission name="android.permission.MANAGE_SOUND_TRIGGER" />
+ <permission name="android.permission.CAPTURE_AUDIO_HOTWORD" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index d67cf8c..621f286 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -301,7 +301,8 @@
}
sk_sp<SkImage> image = bitmap.makeImage();
- applyLooper(get_looper(paint), *filterBitmap(paint), [&](SkScalar x, SkScalar y, const SkPaint& p) {
+ applyLooper(get_looper(paint), *filterBitmap(std::move(filteredPaint)),
+ [&](SkScalar x, SkScalar y, const SkPaint& p) {
mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), &p, bitmap.palette());
});
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index 0f930b5..742db34 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -61,8 +61,6 @@
AMIDI_DEVICE_TYPE_BLUETOOTH = 3 /* A MIDI device connected via BlueTooth */
};
-#if __ANDROID_API__ >= 29
-
/*
* Device API
*/
@@ -249,8 +247,6 @@
*/
void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
#ifdef __cplusplus
}
#endif
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 266bfe0..6568bff 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -846,8 +846,8 @@
try {
stmt = db.compileStatement("INSERT INTO system(name,value)"
+ " VALUES(?,?);");
- loadBooleanSetting(stmt, Settings.System.USER_ROTATION,
- R.integer.def_user_rotation); // should be zero degrees
+ loadIntegerSetting(stmt, Settings.System.USER_ROTATION,
+ R.integer.def_user_rotation);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -2265,6 +2265,8 @@
loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
R.bool.def_accelerometer_rotation);
+ loadIntegerSetting(stmt, Settings.System.USER_ROTATION, R.integer.def_user_rotation);
+
loadDefaultHapticSettings(stmt);
loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index dcbad30..135356c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -296,9 +296,6 @@
<uses-permission android:name="android.permission.RESTART_WIFI_SUBSYSTEM" />
<!-- Permission needed to read wifi network credentials for CtsNetTestCases -->
- <uses-permission android:name="android.permission.NETWORK_AIRPLANE_MODE" />
-
- <!-- Permission needed to read wifi network credentials for CtsNetTestCases -->
<uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL" />
<!-- Permission needed to use wifi usability API's for CtsNetTestCases -->
@@ -352,6 +349,13 @@
<!-- Permission required for CTS test - CtsSensorPrivacyTestCases -->
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+ <!-- Permission required for GTS test - GtsAssistIntentTestCases -->
+ <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+ <uses-permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD" />
+ <uses-permission android:name="android.permission.BIND_VOICE_INTERACTION" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d129b9c..554edc6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -132,8 +132,8 @@
import android.net.TetheringManager;
import android.net.UidRange;
import android.net.UidRangeParcel;
+import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
-import android.net.VpnInfo;
import android.net.VpnManager;
import android.net.VpnService;
import android.net.metrics.INetdEventListener;
@@ -4854,28 +4854,28 @@
*
* <p>Must be called on the handler thread.
*/
- private VpnInfo[] getAllVpnInfo() {
+ private UnderlyingNetworkInfo[] getAllVpnInfo() {
ensureRunningOnConnectivityServiceThread();
synchronized (mVpns) {
if (mLockdownEnabled) {
- return new VpnInfo[0];
+ return new UnderlyingNetworkInfo[0];
}
}
- List<VpnInfo> infoList = new ArrayList<>();
+ List<UnderlyingNetworkInfo> infoList = new ArrayList<>();
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
- VpnInfo info = createVpnInfo(nai);
+ UnderlyingNetworkInfo info = createVpnInfo(nai);
if (info != null) {
infoList.add(info);
}
}
- return infoList.toArray(new VpnInfo[infoList.size()]);
+ return infoList.toArray(new UnderlyingNetworkInfo[infoList.size()]);
}
/**
* @return VPN information for accounting, or null if we can't retrieve all required
* information, e.g underlying ifaces.
*/
- private VpnInfo createVpnInfo(NetworkAgentInfo nai) {
+ private UnderlyingNetworkInfo createVpnInfo(NetworkAgentInfo nai) {
if (!nai.isVPN()) return null;
Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
@@ -4907,11 +4907,11 @@
// Must be non-null or NetworkStatsService will crash.
// Cannot happen in production code because Vpn only registers the NetworkAgent after the
// tun or ipsec interface is created.
+ // TODO: Remove this check.
if (nai.linkProperties.getInterfaceName() == null) return null;
- return new VpnInfo(nai.networkCapabilities.getOwnerUid(),
- nai.linkProperties.getInterfaceName(),
- interfaces.toArray(new String[0]));
+ return new UnderlyingNetworkInfo(nai.networkCapabilities.getOwnerUid(),
+ nai.linkProperties.getInterfaceName(), interfaces);
}
/**
@@ -5707,6 +5707,9 @@
networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
enforceAccessPermission();
break;
+ case BACKGROUND_REQUEST:
+ enforceNetworkStackOrSettingsPermission();
+ // Fall-through since other checks are the same with normal requests.
case REQUEST:
networkCapabilities = new NetworkCapabilities(networkCapabilities);
enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
@@ -7998,10 +8001,10 @@
activeIface = activeLinkProperties.getInterfaceName();
}
- final VpnInfo[] vpnInfos = getAllVpnInfo();
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo();
try {
- mStatsService.forceUpdateIfaces(
- getDefaultNetworks(), getAllNetworkState(), activeIface, vpnInfos);
+ mStatsService.forceUpdateIfaces(getDefaultNetworks(), getAllNetworkState(), activeIface,
+ underlyingNetworkInfos);
} catch (Exception ignored) {
}
}
@@ -8261,6 +8264,7 @@
return getVpnIfOwner(mDeps.getCallingUid());
}
+ // TODO: stop calling into Vpn.java and get this information from data in this class.
@GuardedBy("mVpns")
private Vpn getVpnIfOwner(int uid) {
final int user = UserHandle.getUserId(uid);
@@ -8269,7 +8273,7 @@
if (vpn == null) {
return null;
} else {
- final VpnInfo info = vpn.getVpnInfo();
+ final UnderlyingNetworkInfo info = vpn.getUnderlyingNetworkInfo();
return (info == null || info.ownerUid != uid) ? null : vpn;
}
}
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 76db019..8562b0d 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -25,9 +25,12 @@
import android.app.AppOpsManager;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -527,7 +530,7 @@
@NonNull IVcnUnderlyingNetworkPolicyListener listener) {
requireNonNull(listener, "listener was null");
- mContext.enforceCallingPermission(
+ mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.NETWORK_FACTORY,
"Must have permission NETWORK_FACTORY to register a policy listener");
@@ -561,4 +564,27 @@
}
}
}
+
+ /**
+ * Gets the UnderlyingNetworkPolicy as determined by the provided NetworkCapabilities and
+ * LinkProperties.
+ */
+ @NonNull
+ @Override
+ public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
+ @NonNull NetworkCapabilities networkCapabilities,
+ @NonNull LinkProperties linkProperties) {
+ requireNonNull(networkCapabilities, "networkCapabilities was null");
+ requireNonNull(linkProperties, "linkProperties was null");
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.NETWORK_FACTORY,
+ "Must have permission NETWORK_FACTORY or be the SystemServer to get underlying"
+ + " Network policies");
+
+ // TODO(b/175914059): implement policy generation once VcnManagementService is able to
+ // determine policies
+
+ return new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, networkCapabilities);
+ }
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index ab24015..c3f4294 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -31,6 +31,7 @@
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceDebugInfo;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -135,6 +136,11 @@
"android.system.suspend@1.0::ISystemSuspend"
);
+ public static final String[] AIDL_INTERFACE_PREFIXES_OF_INTEREST = new String[] {
+ "android.hardware.light.ILights/",
+ "android.hardware.power.stats.IPowerStats/",
+ };
+
private static Watchdog sWatchdog;
/* This handler will be used to post message back onto the main thread */
@@ -515,12 +521,11 @@
return builder.toString();
}
- private static ArrayList<Integer> getInterestingHalPids() {
+ private static void addInterestingHidlPids(HashSet<Integer> pids) {
try {
IServiceManager serviceManager = IServiceManager.getService();
ArrayList<IServiceManager.InstanceDebugInfo> dump =
serviceManager.debugDump();
- HashSet<Integer> pids = new HashSet<>();
for (IServiceManager.InstanceDebugInfo info : dump) {
if (info.pid == IServiceManager.PidConstant.NO_PID) {
continue;
@@ -532,24 +537,37 @@
pids.add(info.pid);
}
- return new ArrayList<Integer>(pids);
} catch (RemoteException e) {
- return new ArrayList<Integer>();
+ Log.w(TAG, e);
+ }
+ }
+
+ private static void addInterestingAidlPids(HashSet<Integer> pids) {
+ ServiceDebugInfo[] infos = ServiceManager.getServiceDebugInfo();
+ if (infos == null) return;
+
+ for (ServiceDebugInfo info : infos) {
+ for (String prefix : AIDL_INTERFACE_PREFIXES_OF_INTEREST) {
+ if (info.name.startsWith(prefix)) {
+ pids.add(info.debugPid);
+ }
+ }
}
}
static ArrayList<Integer> getInterestingNativePids() {
- ArrayList<Integer> pids = getInterestingHalPids();
+ HashSet<Integer> pids = new HashSet<>();
+ addInterestingAidlPids(pids);
+ addInterestingHidlPids(pids);
int[] nativePids = Process.getPidsForCommands(NATIVE_STACKS_OF_INTEREST);
if (nativePids != null) {
- pids.ensureCapacity(pids.size() + nativePids.length);
for (int i : nativePids) {
pids.add(i);
}
}
- return pids;
+ return new ArrayList<Integer>(pids);
}
@Override
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 508bb01..fded85c 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -20,6 +20,7 @@
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS;
import static android.content.Intent.EXTRA_REPLACING;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
@@ -46,6 +47,7 @@
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -55,6 +57,7 @@
import java.io.FileDescriptor;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* System service that manages app hibernation state, a state apps can enter that means they are
@@ -74,6 +77,8 @@
private final UserManager mUserManager;
@GuardedBy("mLock")
private final SparseArray<Map<String, UserPackageState>> mUserStates = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final Set<String> mGloballyHibernatedPackages = new ArraySet<>();
/**
* Initializes the system service.
@@ -138,7 +143,7 @@
* @param userId the user to check
* @return true if package is hibernating for the user
*/
- public boolean isHibernating(String packageName, int userId) {
+ boolean isHibernatingForUser(String packageName, int userId) {
userId = handleIncomingUser(userId, "isHibernating");
synchronized (mLock) {
final Map<String, UserPackageState> packageStates = mUserStates.get(userId);
@@ -151,7 +156,19 @@
String.format("Package %s is not installed for user %s",
packageName, userId));
}
- return pkgState != null ? pkgState.hibernated : null;
+ return pkgState.hibernated;
+ }
+ }
+
+ /**
+ * Whether a package is hibernated globally. This only occurs when a package is hibernating for
+ * all users and allows us to make optimizations at the package or APK level.
+ *
+ * @param packageName package to check
+ */
+ boolean isHibernatingGlobally(String packageName) {
+ synchronized (mLock) {
+ return mGloballyHibernatedPackages.contains(packageName);
}
}
@@ -162,7 +179,7 @@
* @param userId user
* @param isHibernating new hibernation state
*/
- public void setHibernating(String packageName, int userId, boolean isHibernating) {
+ void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
userId = handleIncomingUser(userId, "setHibernating");
synchronized (mLock) {
if (!mUserStates.contains(userId)) {
@@ -180,32 +197,99 @@
return;
}
-
- final long caller = Binder.clearCallingIdentity();
- try {
- if (isHibernating) {
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
- mIActivityManager.forceStopPackage(packageName, userId);
- mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
- null /* observer */);
- } else {
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
- mIPackageManager.setPackageStoppedState(packageName, false, userId);
- }
- pkgState.hibernated = isHibernating;
- } catch (RemoteException e) {
- throw new IllegalStateException(
- "Failed to hibernate due to manager not being available", e);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- Binder.restoreCallingIdentity(caller);
+ if (isHibernating) {
+ hibernatePackageForUserL(packageName, userId, pkgState);
+ } else {
+ unhibernatePackageForUserL(packageName, userId, pkgState);
}
-
- // TODO: Support package level hibernation when package is hibernating for all users
}
}
/**
+ * Set whether the package should be hibernated globally at a package level, allowing the
+ * the system to make optimizations at the package or APK level.
+ *
+ * @param packageName package to hibernate globally
+ * @param isHibernating new hibernation state
+ */
+ void setHibernatingGlobally(String packageName, boolean isHibernating) {
+ if (isHibernating != mGloballyHibernatedPackages.contains(packageName)) {
+ synchronized (mLock) {
+ if (isHibernating) {
+ hibernatePackageGloballyL(packageName);
+ } else {
+ unhibernatePackageGloballyL(packageName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Put an app into hibernation for a given user, allowing user-level optimizations to occur.
+ * The caller should hold {@link #mLock}
+ *
+ * @param pkgState package hibernation state
+ */
+ private void hibernatePackageForUserL(@NonNull String packageName, int userId,
+ @NonNull UserPackageState pkgState) {
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mIActivityManager.forceStopPackage(packageName, userId);
+ mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
+ null /* observer */);
+ pkgState.hibernated = true;
+ } catch (RemoteException e) {
+ throw new IllegalStateException(
+ "Failed to hibernate due to manager not being available", e);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+ }
+
+ /**
+ * Remove a package from hibernation for a given user. The caller should hold {@link #mLock}.
+ *
+ * @param pkgState package hibernation state
+ */
+ private void unhibernatePackageForUserL(@NonNull String packageName, int userId,
+ UserPackageState pkgState) {
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mIPackageManager.setPackageStoppedState(packageName, false, userId);
+ pkgState.hibernated = false;
+ } catch (RemoteException e) {
+ throw new IllegalStateException(
+ "Failed to unhibernate due to manager not being available", e);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+ }
+
+ /**
+ * Put a package into global hibernation, optimizing its storage at a package / APK level.
+ * The caller should hold {@link #mLock}.
+ */
+ private void hibernatePackageGloballyL(@NonNull String packageName) {
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackageGlobally");
+ // TODO(175830194): Delete vdex/odex when DexManager API is built out
+ mGloballyHibernatedPackages.add(packageName);
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+
+ /**
+ * Unhibernate a package from global hibernation. The caller should hold {@link #mLock}.
+ */
+ private void unhibernatePackageGloballyL(@NonNull String packageName) {
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackageGlobally");
+ mGloballyHibernatedPackages.remove(packageName);
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+
+ /**
* Populates {@link #mUserStates} with the users installed packages. The caller should hold
* {@link #mLock}.
*
@@ -220,8 +304,8 @@
throw new IllegalStateException("Package manager not available.", e);
}
- for (PackageInfo pkg : packageList) {
- packages.put(pkg.packageName, new UserPackageState());
+ for (int i = 0, size = packageList.size(); i < size; i++) {
+ packages.put(packageList.get(i).packageName, new UserPackageState());
}
mUserStates.put(userId, packages);
}
@@ -250,6 +334,12 @@
}
}
+ private void onPackageRemovedForAllUsers(@NonNull String packageName) {
+ synchronized (mLock) {
+ mGloballyHibernatedPackages.remove(packageName);
+ }
+ }
+
/**
* Private helper method to get the real user id and enforce permission checks.
*
@@ -277,13 +367,23 @@
}
@Override
- public boolean isHibernating(String packageName, int userId) {
- return mService.isHibernating(packageName, userId);
+ public boolean isHibernatingForUser(String packageName, int userId) {
+ return mService.isHibernatingForUser(packageName, userId);
}
@Override
- public void setHibernating(String packageName, int userId, boolean isHibernating) {
- mService.setHibernating(packageName, userId, isHibernating);
+ public void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
+ mService.setHibernatingForUser(packageName, userId, isHibernating);
+ }
+
+ @Override
+ public void setHibernatingGlobally(String packageName, boolean isHibernating) {
+ mService.setHibernatingGlobally(packageName, isHibernating);
+ }
+
+ @Override
+ public boolean isHibernatingGlobally(String packageName) {
+ return mService.isHibernatingGlobally(packageName);
}
@Override
@@ -322,6 +422,9 @@
onPackageAdded(packageName, userId);
} else if (ACTION_PACKAGE_REMOVED.equals(action)) {
onPackageRemoved(packageName, userId);
+ if (intent.getBooleanExtra(EXTRA_REMOVED_FOR_ALL_USERS, false)) {
+ onPackageRemovedForAllUsers(packageName);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java b/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java
index 869885e..7d6eea2 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java
@@ -18,7 +18,6 @@
import android.os.ShellCommand;
import android.os.UserHandle;
-import android.text.TextUtils;
import java.io.PrintWriter;
@@ -27,6 +26,7 @@
*/
final class AppHibernationShellCommand extends ShellCommand {
private static final String USER_OPT = "--user";
+ private static final String GLOBAL_OPT = "--global";
private static final int SUCCESS = 0;
private static final int ERROR = -1;
private final AppHibernationService mService;
@@ -51,7 +51,21 @@
}
private int runSetState() {
- int userId = parseUserOption();
+ String opt;
+ boolean setsGlobal = false;
+ int userId = UserHandle.USER_CURRENT;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case USER_OPT:
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+ case GLOBAL_OPT:
+ setsGlobal = true;
+ break;
+ default:
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ }
+ }
String pkg = getNextArgRequired();
if (pkg == null) {
@@ -66,32 +80,43 @@
}
boolean newState = Boolean.parseBoolean(newStateRaw);
- mService.setHibernating(pkg, userId, newState);
+ if (setsGlobal) {
+ mService.setHibernatingGlobally(pkg, newState);
+ } else {
+ mService.setHibernatingForUser(pkg, userId, newState);
+ }
return SUCCESS;
}
private int runGetState() {
- int userId = parseUserOption();
+ String opt;
+ boolean requestsGlobal = false;
+ int userId = UserHandle.USER_CURRENT;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case USER_OPT:
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+ case GLOBAL_OPT:
+ requestsGlobal = true;
+ break;
+ default:
+ getErrPrintWriter().println("Error: Unknown option: " + opt);
+ }
+ }
String pkg = getNextArgRequired();
if (pkg == null) {
getErrPrintWriter().println("Error: No package specified");
return ERROR;
}
- boolean isHibernating = mService.isHibernating(pkg, userId);
+ boolean isHibernating = requestsGlobal
+ ? mService.isHibernatingGlobally(pkg) : mService.isHibernatingForUser(pkg, userId);
final PrintWriter pw = getOutPrintWriter();
pw.println(isHibernating);
return SUCCESS;
}
- private int parseUserOption() {
- String option = getNextOption();
- if (TextUtils.equals(option, USER_OPT)) {
- return UserHandle.parseUserArg(getNextArgRequired());
- }
- return UserHandle.USER_CURRENT;
- }
-
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -99,11 +124,13 @@
pw.println(" help");
pw.println(" Print this help text.");
pw.println("");
- pw.println(" set-state [--user USER_ID] PACKAGE true|false");
- pw.println(" Sets the hibernation state of the package to value specified");
+ pw.println(" set-state [--user USER_ID] [--global] PACKAGE true|false");
+ pw.println(" Sets the hibernation state of the package to value specified. Optionally");
+ pw.println(" may specify a user id or set global hibernation state.");
pw.println("");
- pw.println(" get-state [--user USER_ID] PACKAGE");
- pw.println(" Gets the hibernation state of the package");
+ pw.println(" get-state [--user USER_ID] [--global] PACKAGE");
+ pw.println(" Gets the hibernation state of the package. Optionally may specify a user");
+ pw.println(" id or request global hibernation state.");
pw.println("");
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 8ce6746..b455a3f 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -70,7 +70,7 @@
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.UidRangeParcel;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
import android.net.VpnManager;
import android.net.VpnService;
import android.net.ipsec.ike.ChildSessionCallback;
@@ -426,6 +426,7 @@
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+ mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
loadAlwaysOnPackage(keyStore);
}
@@ -1819,12 +1820,12 @@
* This method should not be called if underlying interfaces field is needed, because it doesn't
* have enough data to fill VpnInfo.underlyingIfaces field.
*/
- public synchronized VpnInfo getVpnInfo() {
+ public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
if (!isRunningLocked()) {
return null;
}
- return new VpnInfo(mOwnerUID, mInterface, null);
+ return new UnderlyingNetworkInfo(mOwnerUID, mInterface, new ArrayList<>());
}
public synchronized boolean appliesToUid(int uid) {
diff --git a/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java b/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java
index 8399f54..a1e18bd 100644
--- a/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java
+++ b/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java
@@ -106,6 +106,8 @@
private final Context mContext;
private final ComponentName mComponentName;
private IResumeOnRebootService mBinder;
+ @Nullable
+ ServiceConnection mServiceConnection;
private ResumeOnRebootServiceConnection(Context context,
@NonNull ComponentName componentName) {
@@ -115,17 +117,9 @@
/** Unbind from the service */
public void unbindService() {
- mContext.unbindService(new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mBinder = null;
-
- }
- });
+ if (mServiceConnection != null) {
+ mContext.unbindService(mServiceConnection);
+ }
}
/** Bind to the service */
@@ -134,17 +128,19 @@
CountDownLatch connectionLatch = new CountDownLatch(1);
Intent intent = new Intent();
intent.setComponent(mComponentName);
- final boolean success = mContext.bindServiceAsUser(intent, new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mBinder = IResumeOnRebootService.Stub.asInterface(service);
- connectionLatch.countDown();
- }
+ mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mBinder = IResumeOnRebootService.Stub.asInterface(service);
+ connectionLatch.countDown();
+ }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- }
- },
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mBinder = null;
+ }
+ };
+ final boolean success = mContext.bindServiceAsUser(intent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
BackgroundThread.getHandler(), UserHandle.SYSTEM);
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 4faa790..d042b88 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -27,7 +27,7 @@
import android.annotation.Nullable;
import android.net.INetd;
import android.net.NetworkStats;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
import android.net.util.NetdService;
import android.os.RemoteException;
import android.os.StrictMode;
@@ -81,7 +81,7 @@
private final Object mPersistentDataLock = new Object();
/** Set containing info about active VPNs and their underlying networks. */
- private volatile VpnInfo[] mVpnInfos = new VpnInfo[0];
+ private volatile UnderlyingNetworkInfo[] mUnderlyingNetworkInfos = new UnderlyingNetworkInfo[0];
// A persistent snapshot of cumulative stats since device start
@GuardedBy("mPersistentDataLock")
@@ -116,8 +116,8 @@
*
* @param vpnArray The snapshot of the currently-running VPNs.
*/
- public void updateVpnInfos(VpnInfo[] vpnArray) {
- mVpnInfos = vpnArray.clone();
+ public void updateUnderlyingNetworkInfos(UnderlyingNetworkInfo[] vpnArray) {
+ mUnderlyingNetworkInfos = vpnArray.clone();
}
/**
@@ -319,7 +319,7 @@
// code that will acquire other locks within the system server. See b/134244752.
synchronized (mPersistentDataLock) {
// Take a reference. If this gets swapped out, we still have the old reference.
- final VpnInfo[] vpnArray = mVpnInfos;
+ final UnderlyingNetworkInfo[] vpnArray = mUnderlyingNetworkInfos;
// Take a defensive copy. mPersistSnapshot is mutated in some cases below
final NetworkStats prev = mPersistSnapshot.clone();
@@ -369,8 +369,8 @@
}
@GuardedBy("mPersistentDataLock")
- private NetworkStats adjustForTunAnd464Xlat(
- NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) {
+ private NetworkStats adjustForTunAnd464Xlat(NetworkStats uidDetailStats,
+ NetworkStats previousStats, UnderlyingNetworkInfo[] vpnArray) {
// Calculate delta from last snapshot
final NetworkStats delta = uidDetailStats.subtract(previousStats);
@@ -381,8 +381,9 @@
delta.apply464xlatAdjustments(mStackedIfaces);
// Migrate data usage over a VPN to the TUN network.
- for (VpnInfo info : vpnArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
+ for (UnderlyingNetworkInfo info : vpnArray) {
+ delta.migrateTun(info.ownerUid, info.iface,
+ info.underlyingIfaces.toArray(new String[0]));
// Filter out debug entries as that may lead to over counting.
delta.filterDebugEntries();
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4be7b48..0ab35a9 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -104,8 +104,8 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
+import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
-import android.net.VpnInfo;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
@@ -973,7 +973,7 @@
Network[] defaultNetworks,
NetworkState[] networkStates,
String activeIface,
- VpnInfo[] vpnInfos) {
+ UnderlyingNetworkInfo[] underlyingNetworkInfos) {
checkNetworkStackPermission(mContext);
final long token = Binder.clearCallingIdentity();
@@ -986,7 +986,7 @@
// Update the VPN underlying interfaces only after the poll is made and tun data has been
// migrated. Otherwise the migration would use the new interfaces instead of the ones that
// were current when the polled data was transferred.
- mStatsFactory.updateVpnInfos(vpnInfos);
+ mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index d0370b6..45bca68 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -64,6 +64,8 @@
private static final int USER_ID_1 = 1;
private static final int USER_ID_2 = 2;
+ private final List<UserInfo> mUserInfos = new ArrayList<>();
+
private AppHibernationService mAppHibernationService;
private BroadcastReceiver mBroadcastReceiver;
@Mock
@@ -88,47 +90,42 @@
verify(mContext, times(2)).registerReceiver(mReceiverCaptor.capture(), any());
mBroadcastReceiver = mReceiverCaptor.getValue();
- List<UserInfo> userList = new ArrayList<>();
- userList.add(new UserInfo(USER_ID_1, "user 1", 0 /* flags */));
- doReturn(userList).when(mUserManager).getUsers();
-
- List<PackageInfo> userPackages = new ArrayList<>();
- userPackages.add(makePackageInfo(PACKAGE_NAME_1));
-
- doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
- .getInstalledPackages(anyInt(), eq(USER_ID_1));
+ doReturn(mUserInfos).when(mUserManager).getUsers();
doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(),
anyInt(), anyBoolean(), anyBoolean(), any(), any());
+ addUser(USER_ID_1);
mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
}
@Test
- public void testSetHibernating_packageIsHibernating() {
+ public void testSetHibernatingForUser_packageIsHibernating() throws RemoteException {
// WHEN we hibernate a package for a user
- mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_1, true);
+ mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);
// THEN the package is marked hibernating for the user
- assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_1));
+ assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
}
@Test
- public void testSetHibernating_newPackageAdded_packageIsHibernating() {
+ public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating()
+ throws RemoteException {
// WHEN a new package is added and it is hibernated
Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED,
Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */));
intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1);
mBroadcastReceiver.onReceive(mContext, intent);
- mAppHibernationService.setHibernating(PACKAGE_NAME_2, USER_ID_1, true);
+ mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_1, true);
// THEN the new package is hibernated
- assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_2, USER_ID_1));
+ assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_2, USER_ID_1));
}
@Test
- public void testSetHibernating_newUserAdded_packageIsHibernating() throws RemoteException {
+ public void testSetHibernatingForUser_newUserAdded_packageIsHibernating()
+ throws RemoteException {
// WHEN a new user is added and a package from the user is hibernated
List<PackageInfo> userPackages = new ArrayList<>();
userPackages.add(makePackageInfo(PACKAGE_NAME_1));
@@ -138,16 +135,17 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_2);
mBroadcastReceiver.onReceive(mContext, intent);
- mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_2, true);
+ mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true);
// THEN the new user's package is hibernated
- assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_2));
+ assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2));
}
@Test
- public void testIsHibernating_packageReplaced_stillReturnsHibernating() {
+ public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating()
+ throws RemoteException {
// GIVEN a package is currently hibernated
- mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_1, true);
+ mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);
// WHEN the package is removed but marked as replacing
Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
@@ -157,7 +155,38 @@
mBroadcastReceiver.onReceive(mContext, intent);
// THEN the package is still hibernating
- assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_1));
+ assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
+ }
+
+ @Test
+ public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException {
+ // WHEN we hibernate a package
+ mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true);
+
+ // THEN the package is marked hibernating for the user
+ assertTrue(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
+ }
+
+ /**
+ * Add a mock user with one package. Must be called before
+ * {@link AppHibernationService#onBootPhase(int)} to work properly.
+ */
+ private void addUser(int userId) throws RemoteException {
+ addUser(userId, new String[]{PACKAGE_NAME_1});
+ }
+
+ /**
+ * Add a mock user with the packages specified. Must be called before
+ * {@link AppHibernationService#onBootPhase(int)} to work properly
+ */
+ private void addUser(int userId, String[] packageNames) throws RemoteException {
+ mUserInfos.add(new UserInfo(userId, "user_" + userId, 0 /* flags */));
+ List<PackageInfo> userPackages = new ArrayList<>();
+ for (String pkgName : packageNames) {
+ userPackages.add(makePackageInfo(pkgName));
+ }
+ doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
+ .getInstalledPackages(anyInt(), eq(userId));
}
private static PackageInfo makePackageInfo(String packageName) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 9d48955..e567208 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -1025,6 +1025,8 @@
writeLocked(fos, stats, version, packagesTokenData);
file.finishWrite(fos);
fos = null;
+ } catch (Exception e) {
+ // Do nothing. Exception has already been handled.
} finally {
// When fos is null (successful write), this will no-op
file.failWrite(fos);
@@ -1032,7 +1034,7 @@
}
private static void writeLocked(OutputStream out, IntervalStats stats, int version,
- PackagesTokenData packagesTokenData) throws RuntimeException {
+ PackagesTokenData packagesTokenData) throws Exception {
switch (version) {
case 1:
case 2:
@@ -1044,6 +1046,7 @@
UsageStatsProto.write(out, stats);
} catch (Exception e) {
Slog.e(TAG, "Unable to write interval stats to proto.", e);
+ throw e;
}
break;
case 5:
@@ -1052,6 +1055,7 @@
UsageStatsProtoV2.write(out, stats);
} catch (Exception e) {
Slog.e(TAG, "Unable to write interval stats to proto.", e);
+ throw e;
}
break;
default:
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
index a0fd9d4..b8bd98e 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
@@ -16,6 +16,8 @@
package com.android.server.usb;
+import static org.junit.Assert.assertEquals;
+
import android.content.Context;
import android.hardware.usb.UsbManager;
@@ -23,12 +25,12 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.usblib.UsbManagerTestLib;
+
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.server.usblib.UsbManagerTestLib;
-
/**
* Unit tests for {@link android.hardware.usb.UsbManager}.
* Note: NOT claimed MANAGE_USB permission in Manifest
@@ -78,4 +80,35 @@
public void testUsbApi_SetCurrentFunctions_OnSecurityException() throws Exception {
mUsbManagerTestLib.testSetCurrentFunctionsEx(UsbManager.FUNCTION_NONE);
}
+
+ public void assertSettableFunctions(boolean settable, long functions) {
+ assertEquals(
+ "areSettableFunctions(" + UsbManager.usbFunctionsToString(functions) + "):",
+ settable, UsbManager.areSettableFunctions(functions));
+ }
+
+ /**
+ * Tests the behaviour of the static areSettableFunctions method. This method performs no IPCs
+ * and requires no permissions.
+ */
+ @Test
+ public void testUsbManager_AreSettableFunctions() {
+ // NONE is settable.
+ assertSettableFunctions(true, UsbManager.FUNCTION_NONE);
+
+ // MTP, PTP, RNDIS, MIDI, NCM are all settable by themselves.
+ assertSettableFunctions(true, UsbManager.FUNCTION_MTP);
+ assertSettableFunctions(true, UsbManager.FUNCTION_PTP);
+ assertSettableFunctions(true, UsbManager.FUNCTION_RNDIS);
+ assertSettableFunctions(true, UsbManager.FUNCTION_MIDI);
+ assertSettableFunctions(true, UsbManager.FUNCTION_NCM);
+
+ // Setting two functions at the same time is not allowed...
+ assertSettableFunctions(false, UsbManager.FUNCTION_MTP | UsbManager.FUNCTION_PTP);
+ assertSettableFunctions(false, UsbManager.FUNCTION_PTP | UsbManager.FUNCTION_RNDIS);
+ assertSettableFunctions(false, UsbManager.FUNCTION_MIDI | UsbManager.FUNCTION_NCM);
+
+ // ... except in the special case of RNDIS and NCM.
+ assertSettableFunctions(true, UsbManager.FUNCTION_RNDIS | UsbManager.FUNCTION_NCM);
+ }
}
diff --git a/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt b/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt
new file mode 100644
index 0000000..87cfb34
--- /dev/null
+++ b/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.os.Build
+import androidx.test.filters.SmallTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+
+private const val TEST_OWNER_UID = 123
+private const val TEST_IFACE = "test_tun0"
+private val TEST_IFACE_LIST = listOf("wlan0", "rmnet_data0", "eth0")
+
+@SmallTest
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+class UnderlyingNetworkInfoTest {
+ @Test
+ fun testParcelUnparcel() {
+ val testInfo = UnderlyingNetworkInfo(TEST_OWNER_UID, TEST_IFACE, TEST_IFACE_LIST)
+ assertEquals(TEST_OWNER_UID, testInfo.ownerUid)
+ assertEquals(TEST_IFACE, testInfo.iface)
+ assertEquals(TEST_IFACE_LIST, testInfo.underlyingIfaces)
+ assertParcelSane(testInfo, 3)
+
+ val emptyInfo = UnderlyingNetworkInfo(0, String(), listOf())
+ assertEquals(0, emptyInfo.ownerUid)
+ assertEquals(String(), emptyInfo.iface)
+ assertEquals(listOf(), emptyInfo.underlyingIfaces)
+ assertParcelSane(emptyInfo, 3)
+ }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index f2dd27e..c2fddf3 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -32,6 +32,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.REQUEST;
import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
@@ -368,6 +369,12 @@
eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
eq(testPkgName), eq(null));
reset(mService);
+
+ manager.requestBackgroundNetwork(request, null, callback);
+ verify(mService).requestNetwork(eq(request.networkCapabilities),
+ eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
+ eq(testPkgName), eq(null));
+ reset(mService);
}
static Message makeMessage(NetworkRequest req, int messageType) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 81c1688..6523acc 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -201,8 +201,8 @@
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.net.UidRangeParcel;
+import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
-import android.net.VpnInfo;
import android.net.VpnManager;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
@@ -1076,7 +1076,7 @@
private boolean mAgentRegistered = false;
private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
- private VpnInfo mVpnInfo;
+ private UnderlyingNetworkInfo mUnderlyingNetworkInfo;
// These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started.
// TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
@@ -1250,14 +1250,15 @@
}
@Override
- public synchronized VpnInfo getVpnInfo() {
- if (mVpnInfo != null) return mVpnInfo;
+ public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
+ if (mUnderlyingNetworkInfo != null) return mUnderlyingNetworkInfo;
- return super.getVpnInfo();
+ return super.getUnderlyingNetworkInfo();
}
- private synchronized void setVpnInfo(VpnInfo vpnInfo) {
- mVpnInfo = vpnInfo;
+ private synchronized void setUnderlyingNetworkInfo(
+ UnderlyingNetworkInfo underlyingNetworkInfo) {
+ mUnderlyingNetworkInfo = underlyingNetworkInfo;
}
}
@@ -3693,10 +3694,13 @@
@Test
public void testBackgroundNetworks() throws Exception {
- // Create a background request. We can't do this ourselves because ConnectivityService
- // doesn't have an API for it. So just turn on mobile data always on.
- setAlwaysOnNetworks(true);
+ // Create a cellular background request.
grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
+ final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
+ mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build(), null, cellBgCallback);
+
+ // Make callbacks for monitoring.
final NetworkRequest request = new NetworkRequest.Builder().build();
final NetworkRequest fgRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_FOREGROUND).build();
@@ -3765,6 +3769,7 @@
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(fgCallback);
+ mCm.unregisterNetworkCallback(cellBgCallback);
}
@Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
@@ -5195,20 +5200,22 @@
private void expectForceUpdateIfaces(Network[] networks, String defaultIface,
Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception {
ArgumentCaptor<Network[]> networksCaptor = ArgumentCaptor.forClass(Network[].class);
- ArgumentCaptor<VpnInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass(VpnInfo[].class);
+ ArgumentCaptor<UnderlyingNetworkInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass(
+ UnderlyingNetworkInfo[].class);
verify(mStatsService, atLeastOnce()).forceUpdateIfaces(networksCaptor.capture(),
any(NetworkState[].class), eq(defaultIface), vpnInfosCaptor.capture());
assertSameElementsNoDuplicates(networksCaptor.getValue(), networks);
- VpnInfo[] infos = vpnInfosCaptor.getValue();
+ UnderlyingNetworkInfo[] infos = vpnInfosCaptor.getValue();
if (vpnUid != null) {
assertEquals("Should have exactly one VPN:", 1, infos.length);
- VpnInfo info = infos[0];
+ UnderlyingNetworkInfo info = infos[0];
assertEquals("Unexpected VPN owner:", (int) vpnUid, info.ownerUid);
- assertEquals("Unexpected VPN interface:", vpnIfname, info.vpnIface);
- assertSameElementsNoDuplicates(underlyingIfaces, info.underlyingIfaces);
+ assertEquals("Unexpected VPN interface:", vpnIfname, info.iface);
+ assertSameElementsNoDuplicates(underlyingIfaces,
+ info.underlyingIfaces.toArray(new String[0]));
} else {
assertEquals(0, infos.length);
return;
@@ -5269,7 +5276,7 @@
waitForIdle();
verify(mStatsService, never())
.forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
- eq(new VpnInfo[0]));
+ eq(new UnderlyingNetworkInfo[0]));
reset(mStatsService);
// Roaming change should update ifaces
@@ -5352,8 +5359,8 @@
// network for the VPN...
verify(mStatsService, never()).forceUpdateIfaces(any(Network[].class),
any(NetworkState[].class), any() /* anyString() doesn't match null */,
- argThat(infos -> infos[0].underlyingIfaces.length == 1
- && WIFI_IFNAME.equals(infos[0].underlyingIfaces[0])));
+ argThat(infos -> infos[0].underlyingIfaces.size() == 1
+ && WIFI_IFNAME.equals(infos[0].underlyingIfaces.get(0))));
verifyNoMoreInteractions(mStatsService);
reset(mStatsService);
@@ -5366,8 +5373,8 @@
waitForIdle();
verify(mStatsService).forceUpdateIfaces(any(Network[].class),
any(NetworkState[].class), any() /* anyString() doesn't match null */,
- argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.length == 1
- && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces[0])));
+ argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.size() == 1
+ && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces.get(0))));
mEthernetNetworkAgent.disconnect();
waitForIdle();
reset(mStatsService);
@@ -8347,8 +8354,9 @@
assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
mMockVpn.setVpnType(vpnType);
- final VpnInfo vpnInfo = new VpnInfo(vpnOwnerUid, null, null);
- mMockVpn.setVpnInfo(vpnInfo);
+ final UnderlyingNetworkInfo underlyingNetworkInfo =
+ new UnderlyingNetworkInfo(vpnOwnerUid, VPN_IFNAME, new ArrayList<String>());
+ mMockVpn.setUnderlyingNetworkInfo(underlyingNetworkInfo);
}
private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
diff --git a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
index 1b33930e..a058a46 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
@@ -33,7 +33,9 @@
import static org.junit.Assert.assertEquals;
import android.net.NetworkStats;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
+
+import java.util.Arrays;
/** Superclass with utilities for NetworkStats(Service|Factory)Test */
abstract class NetworkStatsBaseTest {
@@ -107,11 +109,11 @@
assertEquals("unexpected operations", operations, entry.operations);
}
- static VpnInfo createVpnInfo(String[] underlyingIfaces) {
+ static UnderlyingNetworkInfo createVpnInfo(String[] underlyingIfaces) {
return createVpnInfo(TUN_IFACE, underlyingIfaces);
}
- static VpnInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) {
- return new VpnInfo(UID_VPN, vpnIface, underlyingIfaces);
+ static UnderlyingNetworkInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) {
+ return new UnderlyingNetworkInfo(UID_VPN, vpnIface, Arrays.asList(underlyingIfaces));
}
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
index 76647a6..f3ae9b0 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -36,7 +36,7 @@
import android.content.res.Resources;
import android.net.NetworkStats;
import android.net.TrafficStats;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -79,7 +79,7 @@
// related to networkStatsFactory is compiled to a minimal native library and loaded here.
System.loadLibrary("networkstatsfactorytestjni");
mFactory = new NetworkStatsFactory(mTestProc, false);
- mFactory.updateVpnInfos(new VpnInfo[0]);
+ mFactory.updateUnderlyingNetworkInfos(new UnderlyingNetworkInfo[0]);
}
@After
@@ -105,8 +105,9 @@
@Test
public void testVpnRewriteTrafficThroughItself() throws Exception {
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- mFactory.updateVpnInfos(vpnInfos);
+ UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -134,8 +135,9 @@
@Test
public void testVpnWithClat() throws Exception {
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos = new UnderlyingNetworkInfo[] {
+ createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
mFactory.noteStackedIface(CLAT_PREFIX + TEST_IFACE, TEST_IFACE);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
@@ -167,8 +169,9 @@
@Test
public void testVpnWithOneUnderlyingIface() throws Exception {
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -191,8 +194,9 @@
@Test
public void testVpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception {
// WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -219,8 +223,9 @@
@Test
public void testVpnWithOneUnderlyingIface_withCompression() throws Exception {
// WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -242,8 +247,9 @@
// WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
// Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
// Additionally, VPN is duplicating traffic across both WiFi and Cell.
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -267,10 +273,10 @@
public void testConcurrentVpns() throws Exception {
// Assume two VPNs are connected on two different network interfaces. VPN1 is using
// TEST_IFACE and VPN2 is using TEST_IFACE2.
- final VpnInfo[] vpnInfos = new VpnInfo[] {
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos = new UnderlyingNetworkInfo[] {
createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}),
createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})};
- mFactory.updateVpnInfos(vpnInfos);
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -308,8 +314,9 @@
// WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
// Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
// Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell.
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
@@ -335,8 +342,9 @@
// WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
// Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
// Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell.
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface:
// 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
@@ -357,8 +365,9 @@
public void testVpnWithIncorrectUnderlyingIface() throws Exception {
// WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2),
// but has declared only WiFi (TEST_IFACE) in its underlying network set.
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- mFactory.updateVpnInfos(vpnInfos);
+ final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+ new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index b4e37de..dde78aa 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -86,7 +86,7 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.os.ConditionVariable;
import android.os.Handler;
@@ -286,7 +286,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -328,7 +329,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -401,7 +403,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// modify some number on wifi, and trigger poll event
incrementCurrentTime(2 * HOUR_IN_MILLIS);
@@ -441,7 +444,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// create some traffic on first network
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -475,7 +479,8 @@
.insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
forcePollAndWaitForIdle();
@@ -514,7 +519,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// create some traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -581,7 +587,7 @@
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
- new VpnInfo[0]);
+ new UnderlyingNetworkInfo[0]);
// Create some traffic.
incrementCurrentTime(MINUTE_IN_MILLIS);
@@ -655,7 +661,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// create some traffic for two apps
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -713,7 +720,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
NetworkStats.Entry entry1 = new NetworkStats.Entry(
TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L);
@@ -756,7 +764,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
NetworkStats.Entry uidStats = new NetworkStats.Entry(
TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
@@ -810,7 +819,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// create some initial traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -867,7 +877,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// create some initial traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -906,7 +917,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// Create some traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -943,7 +955,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// create some tethering traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -999,7 +1012,8 @@
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -1104,7 +1118,8 @@
mService.registerNetworkStatsProvider("TEST", provider);
assertNotNull(cb);
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// Verifies that one requestStatsUpdate will be called during iface update.
provider.expectOnRequestStatsUpdate(0 /* unused */);
@@ -1155,7 +1170,8 @@
expectDefaultSettings();
NetworkState[] states =
new NetworkState[]{buildWifiState(true /* isMetered */, TEST_IFACE)};
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// Register custom provider and retrieve callback.
final TestableNetworkStatsProviderBinder provider =
@@ -1204,7 +1220,7 @@
// 3G network comes online.
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
- new VpnInfo[0]);
+ new UnderlyingNetworkInfo[0]);
// Create some traffic.
incrementCurrentTime(MINUTE_IN_MILLIS);
@@ -1274,7 +1290,8 @@
NetworkState[] states = new NetworkState[]{
buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)};
expectNetworkStatsUidDetail(buildEmptyStats());
- mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+ new UnderlyingNetworkInfo[0]);
// Create some traffic on mobile network.
incrementCurrentTime(HOUR_IN_MILLIS);
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 9c6b719..f9db408 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -18,14 +18,19 @@
import static androidx.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener;
import org.junit.Before;
@@ -103,4 +108,28 @@
public void testRemoveVcnUnderlyingNetworkPolicyListenerNullListener() {
mVcnManager.removeVcnUnderlyingNetworkPolicyListener(null);
}
+
+ @Test
+ public void testGetUnderlyingNetworkPolicy() throws Exception {
+ NetworkCapabilities nc = new NetworkCapabilities();
+ LinkProperties lp = new LinkProperties();
+ when(mMockVcnManagementService.getUnderlyingNetworkPolicy(eq(nc), eq(lp)))
+ .thenReturn(new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, nc));
+
+ VcnUnderlyingNetworkPolicy policy = mVcnManager.getUnderlyingNetworkPolicy(nc, lp);
+
+ assertFalse(policy.isTeardownRequested());
+ assertEquals(nc, policy.getMergedNetworkCapabilities());
+ verify(mMockVcnManagementService).getUnderlyingNetworkPolicy(eq(nc), eq(lp));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testGetUnderlyingNetworkPolicyNullNetworkCapabilities() throws Exception {
+ mVcnManager.getUnderlyingNetworkPolicy(null, new LinkProperties());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testGetUnderlyingNetworkPolicyNullLinkProperties() throws Exception {
+ mVcnManager.getUnderlyingNetworkPolicy(new NetworkCapabilities(), null);
+ }
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index f0cdde3..e26bf19 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -21,6 +21,8 @@
import static com.android.server.vcn.VcnTestUtils.setupSystemService;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -41,9 +43,12 @@
import android.app.AppOpsManager;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnConfigTest;
+import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.PersistableBundle;
@@ -63,6 +68,7 @@
import com.android.server.vcn.VcnNetworkProvider;
import com.android.server.vcn.util.PersistableBundleUtils;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -192,6 +198,14 @@
mTestLooper.dispatchAll();
}
+ @Before
+ public void setUp() {
+ doNothing()
+ .when(mMockContext)
+ .enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.NETWORK_FACTORY), any());
+ }
+
private void setupMockedCarrierPrivilege(boolean isPrivileged) {
doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
.when(mSubMgr)
@@ -455,10 +469,6 @@
@Test
public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception {
- doNothing()
- .when(mMockContext)
- .enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
-
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
verify(mMockIBinder).linkToDeath(any(), anyInt());
@@ -468,17 +478,14 @@
public void testAddVcnUnderlyingNetworkPolicyListenerInvalidPermission() {
doThrow(new SecurityException())
.when(mMockContext)
- .enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
+ .enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.NETWORK_FACTORY), any());
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
@Test
public void testRemoveVcnUnderlyingNetworkPolicyListener() {
- // verify listener added
- doNothing()
- .when(mMockContext)
- .enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
@@ -488,4 +495,24 @@
public void testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered() {
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
+
+ @Test
+ public void testGetUnderlyingNetworkPolicy() throws Exception {
+ VcnUnderlyingNetworkPolicy policy =
+ mVcnMgmtSvc.getUnderlyingNetworkPolicy(
+ new NetworkCapabilities(), new LinkProperties());
+
+ assertFalse(policy.isTeardownRequested());
+ assertNotNull(policy.getMergedNetworkCapabilities());
+ }
+
+ @Test(expected = SecurityException.class)
+ public void testGetUnderlyingNetworkPolicyInvalidPermission() {
+ doThrow(new SecurityException())
+ .when(mMockContext)
+ .enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.NETWORK_FACTORY), any());
+
+ mVcnMgmtSvc.getUnderlyingNetworkPolicy(new NetworkCapabilities(), new LinkProperties());
+ }
}