diff options
30 files changed, 716 insertions, 195 deletions
diff --git a/Android.bp b/Android.bp index 57d03b6daf98..58cb9afa06bf 100644 --- a/Android.bp +++ b/Android.bp @@ -1037,6 +1037,7 @@ droiddoc { "core/java/overview.html", ":current-support-api", ], + dex_api_filename: "public-dex.txt", private_dex_api_filename: "private-dex.txt", removed_dex_api_filename: "removed-dex.txt", args: framework_docs_args + diff --git a/Android.mk b/Android.mk index a6566ebc79d6..eddcadae456b 100644 --- a/Android.mk +++ b/Android.mk @@ -594,6 +594,7 @@ LOCAL_BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) LOCAL_SRC_GREYLIST := frameworks/base/config/hiddenapi-light-greylist.txt LOCAL_SRC_VENDOR_LIST := frameworks/base/config/hiddenapi-vendor-list.txt LOCAL_SRC_FORCE_BLACKLIST := frameworks/base/config/hiddenapi-force-blacklist.txt +LOCAL_SRC_PUBLIC_API := $(INTERNAL_PLATFORM_DEX_API_FILE) LOCAL_SRC_PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) LOCAL_SRC_REMOVED_API := $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) @@ -601,6 +602,7 @@ LOCAL_SRC_ALL := \ $(LOCAL_SRC_GREYLIST) \ $(LOCAL_SRC_VENDOR_LIST) \ $(LOCAL_SRC_FORCE_BLACKLIST) \ + $(LOCAL_SRC_PUBLIC_API) \ $(LOCAL_SRC_PRIVATE_API) \ $(LOCAL_SRC_REMOVED_API) @@ -673,7 +675,8 @@ $(LOCAL_LIGHT_GREYLIST): $(LOCAL_SRC_ALL) # (4) subtract entries shared with LOCAL_LIGHT_GREYLIST $(LOCAL_DARK_GREYLIST): $(LOCAL_SRC_ALL) $(LOCAL_LIGHT_GREYLIST) comm -13 <(sort $(LOCAL_LIGHT_GREYLIST) $(LOCAL_SRC_FORCE_BLACKLIST)) \ - <(sed 's/\->.*//' $(LOCAL_LIGHT_GREYLIST) | sed 's/\(.*\/\).*/\1/' | sort | uniq | \ + <(cat $(LOCAL_SRC_PUBLIC_API) $(LOCAL_LIGHT_GREYLIST) | \ + sed 's/\->.*//' | sed 's/\(.*\/\).*/\1/' | sort | uniq | \ while read PKG_NAME; do \ grep -E "^$${PKG_NAME}[^/;]*;" $(LOCAL_SRC_PRIVATE_API); \ done | sort | uniq) \ diff --git a/api/current.txt b/api/current.txt index 5b15e6f040b8..71b2ca278920 100644 --- a/api/current.txt +++ b/api/current.txt @@ -20097,6 +20097,7 @@ package android.icu.util { field public static final android.icu.util.MeasureUnit PICOMETER; field public static final android.icu.util.MeasureUnit PINT; field public static final android.icu.util.MeasureUnit PINT_METRIC; + field public static final android.icu.util.MeasureUnit POINT; field public static final android.icu.util.MeasureUnit POUND; field public static final android.icu.util.MeasureUnit POUND_PER_SQUARE_INCH; field public static final android.icu.util.MeasureUnit QUART; diff --git a/api/system-current.txt b/api/system-current.txt index 5a4fef13b1d0..9a54ac625b46 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -90,6 +90,7 @@ package android { field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"; field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES"; field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS"; + field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS"; field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS"; field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB"; field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS"; @@ -2611,10 +2612,10 @@ package android.net { } public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable { - method public void addAddress(android.net.LinkAddress) throws java.io.IOException; + method public void addAddress(java.net.InetAddress, int) throws java.io.IOException; method public void close(); method public java.lang.String getInterfaceName(); - method public void removeAddress(android.net.LinkAddress) throws java.io.IOException; + method public void removeAddress(java.net.InetAddress, int) throws java.io.IOException; } public final class IpSecTransform implements java.lang.AutoCloseable { @@ -4728,6 +4729,7 @@ package android.telephony.euicc { package android.telephony.ims { public final class ImsCallForwardInfo implements android.os.Parcelable { + ctor public ImsCallForwardInfo(int, int, int, int, java.lang.String, int); method public int describeContents(); method public int getCondition(); method public java.lang.String getNumber(); @@ -5059,7 +5061,7 @@ package android.telephony.ims { } public final class ImsSsData implements android.os.Parcelable { - ctor public ImsSsData(); + ctor public ImsSsData(int, int, int, int, int); method public int describeContents(); method public boolean isTypeBarring(); method public boolean isTypeCf(); @@ -5110,7 +5112,7 @@ package android.telephony.ims { } public final class ImsSsInfo implements android.os.Parcelable { - ctor public ImsSsInfo(); + ctor public ImsSsInfo(int, java.lang.String); method public int describeContents(); method public java.lang.String getIcbNum(); method public int getStatus(); diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index b7d3f578df27..6e37525db587 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -189,7 +189,7 @@ public final class PendingIntent implements Parcelable { */ public interface OnFinished { /** - * Called when a send operation as completed. + * Called when a send operation has completed. * * @param pendingIntent The PendingIntent this operation was sent through. * @param intent The original Intent that was sent. diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 97c668117ee0..69bd4532cdaf 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -271,12 +271,12 @@ final class SystemServiceRegistry { }}); registerService(Context.IPSEC_SERVICE, IpSecManager.class, - new StaticServiceFetcher<IpSecManager>() { + new CachedServiceFetcher<IpSecManager>() { @Override - public IpSecManager createService() { + public IpSecManager createService(ContextImpl ctx) throws ServiceNotFoundException { IBinder b = ServiceManager.getService(Context.IPSEC_SERVICE); IIpSecService service = IIpSecService.Stub.asInterface(b); - return new IpSecManager(service); + return new IpSecManager(ctx, service); }}); registerService(Context.COUNTRY_DETECTOR, CountryDetector.class, diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 3a3ddcc48360..d6774d47b49e 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -45,25 +45,31 @@ interface IIpSecService in String localAddr, in String remoteAddr, in Network underlyingNetwork, - in IBinder binder); + in IBinder binder, + in String callingPackage); void addAddressToTunnelInterface( int tunnelResourceId, - in LinkAddress localAddr); + in LinkAddress localAddr, + in String callingPackage); void removeAddressFromTunnelInterface( int tunnelResourceId, - in LinkAddress localAddr); + in LinkAddress localAddr, + in String callingPackage); - void deleteTunnelInterface(int resourceId); + void deleteTunnelInterface(int resourceId, in String callingPackage); - IpSecTransformResponse createTransform(in IpSecConfig c, in IBinder binder); + IpSecTransformResponse createTransform( + in IpSecConfig c, in IBinder binder, in String callingPackage); void deleteTransform(int transformId); - void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); + void applyTransportModeTransform( + in ParcelFileDescriptor socket, int direction, int transformId); - void applyTunnelModeTransform(int tunnelResourceId, int direction, int transformResourceId); + void applyTunnelModeTransform( + int tunnelResourceId, int direction, int transformResourceId, in String callingPackage); void removeTransportModeTransforms(in ParcelFileDescriptor socket); } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index cc227713cb8c..1145d5bd4d9a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -27,6 +27,9 @@ import android.content.Context; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.system.ErrnoException; +import android.system.OsConstants; import android.util.AndroidException; import android.util.Log; @@ -140,6 +143,7 @@ public final class IpSecManager { } } + private final Context mContext; private final IIpSecService mService; /** @@ -172,11 +176,16 @@ public final class IpSecManager { public void close() { try { mService.releaseSecurityParameterIndex(mResourceId); - mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } - mCloseGuard.close(); } /** Check that the SPI was closed properly. */ @@ -227,7 +236,6 @@ public final class IpSecManager { throw new RuntimeException( "Invalid Resource ID returned by IpSecService: " + status); } - } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -239,6 +247,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("SecurityParameterIndex{spi=") + .append(mSpi) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } /** @@ -261,7 +280,11 @@ public final class IpSecManager { mService, destinationAddress, IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); + } catch (ServiceSpecificException e) { + throw rethrowUncheckedExceptionFromServiceSpecificException(e); } catch (SpiUnavailableException unlikely) { + // Because this function allocates a totally random SPI, it really shouldn't ever + // fail to allocate an SPI; we simply need this because the exception is checked. throw new ResourceUnavailableException("No SPIs available"); } } @@ -274,8 +297,8 @@ public final class IpSecManager { * * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. The range 1-255 is - * reserved and may not be used. See RFC 4303 Section 2.1. + * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See + * RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user @@ -289,7 +312,11 @@ public final class IpSecManager { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); } - return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + try { + return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + } catch (ServiceSpecificException e) { + throw rethrowUncheckedExceptionFromServiceSpecificException(e); + } } /** @@ -424,6 +451,8 @@ public final class IpSecManager { // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -482,6 +511,8 @@ public final class IpSecManager { public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.removeTransportModeTransforms(pfd); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -575,6 +606,13 @@ public final class IpSecManager { mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } try { @@ -583,7 +621,6 @@ public final class IpSecManager { Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); throw e; } - mCloseGuard.close(); } /** Check that the socket was closed properly. */ @@ -600,6 +637,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("UdpEncapsulationSocket{port=") + .append(mPort) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } }; /** @@ -627,7 +675,11 @@ public final class IpSecManager { if (port == 0) { throw new IllegalArgumentException("Specified port must be a valid port number!"); } - return new UdpEncapsulationSocket(mService, port); + try { + return new UdpEncapsulationSocket(mService, port); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -650,7 +702,11 @@ public final class IpSecManager { @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { - return new UdpEncapsulationSocket(mService, 0); + try { + return new UdpEncapsulationSocket(mService, 0); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -667,6 +723,7 @@ public final class IpSecManager { */ @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { + private final String mOpPackageName; private final IIpSecService mService; private final InetAddress mRemoteAddress; private final InetAddress mLocalAddress; @@ -688,12 +745,17 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel + * @param prefixLen length of the InetAddress prefix * @hide */ @SystemApi - public void addAddress(@NonNull LinkAddress address) throws IOException { + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) + public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { - mService.addAddressToTunnelInterface(mResourceId, address); + mService.addAddressToTunnelInterface( + mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -705,21 +767,27 @@ public final class IpSecManager { * <p>Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed + * @param prefixLen length of the InetAddress prefix * @hide */ @SystemApi - public void removeAddress(@NonNull LinkAddress address) throws IOException { + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) + public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { - mService.removeAddressFromTunnelInterface(mResourceId, address); + mService.removeAddressFromTunnelInterface( + mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - private IpSecTunnelInterface(@NonNull IIpSecService service, + private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { + mOpPackageName = ctx.getOpPackageName(); mService = service; mLocalAddress = localAddress; mRemoteAddress = remoteAddress; @@ -731,7 +799,8 @@ public final class IpSecManager { localAddress.getHostAddress(), remoteAddress.getHostAddress(), underlyingNetwork, - new Binder()); + new Binder(), + mOpPackageName); switch (result.status) { case Status.OK: break; @@ -760,12 +829,17 @@ public final class IpSecManager { @Override public void close() { try { - mService.deleteTunnelInterface(mResourceId); - mResourceId = INVALID_RESOURCE_ID; + mService.deleteTunnelInterface(mResourceId, mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } - mCloseGuard.close(); } /** Check that the Interface was closed properly. */ @@ -782,6 +856,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("IpSecTunnelInterface{ifname=") + .append(mInterfaceName) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } /** @@ -801,11 +886,16 @@ public final class IpSecManager { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { - return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork); + try { + return new IpSecTunnelInterface( + mContext, mService, localAddress, remoteAddress, underlyingNetwork); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -826,12 +916,15 @@ public final class IpSecManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( - tunnel.getResourceId(), direction, transform.getResourceId()); + tunnel.getResourceId(), direction, + transform.getResourceId(), mContext.getOpPackageName()); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -843,7 +936,48 @@ public final class IpSecManager { * @param context the application context for this manager * @hide */ - public IpSecManager(IIpSecService service) { + public IpSecManager(Context ctx, IIpSecService service) { + mContext = ctx; mService = checkNotNull(service, "missing service"); } + + private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) { + // OsConstants are late binding, so switch statements can't be used. + if (sse.errorCode == OsConstants.EINVAL) { + throw new IllegalArgumentException(sse); + } else if (sse.errorCode == OsConstants.EAGAIN) { + throw new IllegalStateException(sse); + } else if (sse.errorCode == OsConstants.EOPNOTSUPP) { + throw new UnsupportedOperationException(sse); + } + } + + /** + * Convert an Errno SSE to the correct Unchecked exception type. + * + * This method never actually returns. + */ + // package + static RuntimeException + rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) { + maybeHandleServiceSpecificException(sse); + throw new RuntimeException(sse); + } + + /** + * Convert an Errno SSE to the correct Checked or Unchecked exception type. + * + * This method may throw IOException, or it may throw an unchecked exception; it will never + * actually return. + */ + // package + static IOException rethrowCheckedExceptionFromServiceSpecificException( + ServiceSpecificException sse) throws IOException { + // First see if this is an unchecked exception of a type we know. + // If so, then we prefer the unchecked (specific) type of exception. + maybeHandleServiceSpecificException(sse); + // If not, then all we can do is provide the SSE in the form of an IOException. + throw new ErrnoException( + "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException(); + } } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index cf58647bbb47..23c8aa368d87 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -29,6 +29,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -130,12 +131,15 @@ public final class IpSecTransform implements AutoCloseable { synchronized (this) { try { IIpSecService svc = getIpSecService(); - IpSecTransformResponse result = svc.createTransform(mConfig, new Binder()); + IpSecTransformResponse result = svc.createTransform( + mConfig, new Binder(), mContext.getOpPackageName()); int status = result.status; checkResultStatus(status); mResourceId = result.resourceId; Log.d(TAG, "Added Transform with Id " + mResourceId); mCloseGuard.open("build"); + } catch (ServiceSpecificException e) { + throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -180,6 +184,10 @@ public final class IpSecTransform implements AutoCloseable { stopNattKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); } finally { mResourceId = INVALID_RESOURCE_ID; mCloseGuard.close(); @@ -282,7 +290,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD }) public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, @@ -325,7 +333,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD }) public void stopNattKeepalive() { @@ -478,7 +486,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) @@ -506,4 +514,13 @@ public final class IpSecTransform implements AutoCloseable { mConfig = new IpSecConfig(); } } + + @Override + public String toString() { + return new StringBuilder() + .append("IpSecTransform{resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index a21e05e314b2..932f0c2b52ef 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -318,7 +318,9 @@ public class VolumeInfo implements Parcelable { * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}. */ public File getInternalPathForUser(int userId) { - if (type == TYPE_PUBLIC) { + if (path == null) { + return null; + } else if (type == TYPE_PUBLIC) { // TODO: plumb through cleaner path from vold return new File(path.replace("/storage/", "/mnt/media_rw/")); } else { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 64949ce472ae..6087229c871f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1311,6 +1311,13 @@ android:label="@string/permlab_changeWifiState" android:protectionLevel="normal" /> + <!-- @SystemApi @hide Allows apps to create and manage IPsec tunnels. + <p>Only granted to applications that are currently bound by the + system for creating and managing IPsec-based interfaces. + --> + <permission android:name="android.permission.MANAGE_IPSEC_TUNNELS" + android:protectionLevel="signature|appop" /> + <!-- @SystemApi @hide Allows applications to read Wi-Fi credential. <p>Not for use by third-party applications. --> <permission android:name="android.permission.READ_WIFI_CREDENTIAL" diff --git a/data/sounds/AllAudio.mk b/data/sounds/AllAudio.mk index edfd3800600c..bf8067ccbd5c 100644 --- a/data/sounds/AllAudio.mk +++ b/data/sounds/AllAudio.mk @@ -232,4 +232,5 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \ $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \ - + $(LOCAL_PATH)/effects/ogg/ChargingStarted.ogg:system/media/audio/ui/ChargingStarted.ogg \ + $(LOCAL_PATH)/effects/ogg/InCallNotification.ogg:system/media/audio/ui/InCallNotification.ogg \ diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk index c5222afcc2f7..72aa7fe1c38a 100644 --- a/data/sounds/AudioPackage10.mk +++ b/data/sounds/AudioPackage10.mk @@ -32,6 +32,8 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \ $(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \ $(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \ + $(LOCAL_PATH)/effects/ogg/ChargingStarted.ogg:system/media/audio/ui/ChargingStarted.ogg \ + $(LOCAL_PATH)/effects/ogg/InCallNotification.ogg:system/media/audio/ui/InCallNotification.ogg \ $(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \ $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \ diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk index 43c83b99b11f..665ce521690e 100644 --- a/data/sounds/AudioPackage11.mk +++ b/data/sounds/AudioPackage11.mk @@ -32,6 +32,8 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \ $(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \ $(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \ + $(LOCAL_PATH)/effects/ogg/ChargingStarted.ogg:system/media/audio/ui/ChargingStarted.ogg \. + $(LOCAL_PATH)/effects/ogg/InCallNotification.ogg:system/media/audio/ui/InCallNotification.ogg \ $(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \ $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \ diff --git a/data/sounds/AudioPackage12.mk b/data/sounds/AudioPackage12.mk index cd4d35b4d3fc..44a8f9e34cd3 100644 --- a/data/sounds/AudioPackage12.mk +++ b/data/sounds/AudioPackage12.mk @@ -12,7 +12,7 @@ ALARM_FILES := Argon Carbon Helium Krypton Neon Oxygen Osmium Platinum NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \ - camera_focus Dock Undock Lock Unlock Trusted + camera_focus Dock Undock Lock Unlock Trusted ChargingStarted InCallNotification MATERIAL_EFFECT_FILES := camera_click VideoRecord LowBattery WirelessChargingStarted VideoStop PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\ diff --git a/data/sounds/AudioPackage12_48.mk b/data/sounds/AudioPackage12_48.mk index 80758f495035..09fab041505e 100644 --- a/data/sounds/AudioPackage12_48.mk +++ b/data/sounds/AudioPackage12_48.mk @@ -12,7 +12,7 @@ ALARM_FILES := Argon Carbon Helium Krypton Neon Oxygen Osmium Platinum NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \ - Lock Unlock Trusted + Lock Unlock Trusted ChargingStarted InCallNotification MATERIAL_EFFECT_FILES := camera_click VideoRecord LowBattery WirelessChargingStarted VideoStop # Alarms not yet available in 48 kHz diff --git a/data/sounds/AudioPackage13.mk b/data/sounds/AudioPackage13.mk index d33a4aff22b8..de4ee047986d 100644 --- a/data/sounds/AudioPackage13.mk +++ b/data/sounds/AudioPackage13.mk @@ -13,7 +13,7 @@ NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Tit RINGTONE_FILES := Atria Callisto Dione Ganymede Luna Oberon Phobos Pyxis Sedna Titania Triton \ Umbriel EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \ - camera_focus Dock Undock Lock Unlock Trusted + camera_focus Dock Undock Lock Unlock Trusted ChargingStarted InCallNotification MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery VideoStop PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\ diff --git a/data/sounds/AudioPackage13_48.mk b/data/sounds/AudioPackage13_48.mk index 9c320ae8855e..889d58172290 100644 --- a/data/sounds/AudioPackage13_48.mk +++ b/data/sounds/AudioPackage13_48.mk @@ -13,7 +13,7 @@ NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Tit RINGTONE_FILES := Atria Callisto Dione Ganymede Luna Oberon Phobos Pyxis Sedna Titania Triton \ Umbriel EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \ - Lock Unlock Trusted + Lock Unlock Trusted ChargingStarted InCallNotification MATERIAL_EFFECT_FILES := camera_click VideoRecord WirelessChargingStarted LowBattery VideoStop PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\ diff --git a/data/sounds/effects/ChargingStarted.ogg b/data/sounds/effects/ChargingStarted.ogg Binary files differnew file mode 100644 index 000000000000..f09e273ea5ac --- /dev/null +++ b/data/sounds/effects/ChargingStarted.ogg diff --git a/data/sounds/effects/ogg/ChargingStarted.ogg b/data/sounds/effects/ogg/ChargingStarted.ogg Binary files differnew file mode 100644 index 000000000000..f09e273ea5ac --- /dev/null +++ b/data/sounds/effects/ogg/ChargingStarted.ogg diff --git a/data/sounds/effects/ogg/ChargingStarted_48k.ogg b/data/sounds/effects/ogg/ChargingStarted_48k.ogg Binary files differnew file mode 100644 index 000000000000..f09e273ea5ac --- /dev/null +++ b/data/sounds/effects/ogg/ChargingStarted_48k.ogg diff --git a/data/sounds/effects/ogg/InCallNotification_48k.ogg b/data/sounds/effects/ogg/InCallNotification_48k.ogg Binary files differnew file mode 100644 index 000000000000..4481ccb25614 --- /dev/null +++ b/data/sounds/effects/ogg/InCallNotification_48k.ogg diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 131c463bad9e..968f204da4cb 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4619,7 +4619,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before // we do anything else, make sure its LinkProperties are accurate. if (networkAgent.clatd != null) { - networkAgent.clatd.fixupLinkProperties(oldLp); + networkAgent.clatd.fixupLinkProperties(oldLp, newLp); } updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities); diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 35bde8e18d5d..744ed25f160f 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -24,6 +24,8 @@ import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; +import android.annotation.NonNull; +import android.app.AppOpsManager; import android.content.Context; import android.net.ConnectivityManager; import android.net.IIpSecService; @@ -42,6 +44,7 @@ import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; +import android.os.DeadSystemException; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -973,6 +976,13 @@ public class IpSecService extends IIpSecService.Stub { return service; } + @NonNull + private AppOpsManager getAppOpsManager() { + AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); + return appOps; + } + /** @hide */ @VisibleForTesting public IpSecService(Context context, IpSecServiceConfiguration config) { @@ -1090,9 +1100,11 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResource<SpiRecord>( new SpiRecord(resourceId, "", destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { - // TODO: Add appropriate checks when other ServiceSpecificException types are supported - return new IpSecSpiResponse( - IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi); + if (e.errorCode == OsConstants.ENOENT) { + return new IpSecSpiResponse( + IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi); + } + throw e; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1104,7 +1116,6 @@ public class IpSecService extends IIpSecService.Stub { */ private void releaseResource(RefcountedResourceArray resArray, int resourceId) throws RemoteException { - resArray.getRefcountedResourceOrThrow(resourceId).userRelease(); } @@ -1239,7 +1250,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized IpSecTunnelInterfaceResponse createTunnelInterface( - String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder) { + String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, + String callingPackage) { + enforceTunnelPermissions(callingPackage); checkNotNull(binder, "Null Binder passed to createTunnelInterface"); checkNotNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); @@ -1302,15 +1315,12 @@ public class IpSecService extends IIpSecService.Stub { releaseNetId(ikey); releaseNetId(okey); throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (Throwable t) { + // Release keys if we got an error. + releaseNetId(ikey); + releaseNetId(okey); + throw t; } - - // If we make it to here, then something has gone wrong and we couldn't create a VTI. - // Release the keys that we reserved, and return an error status. - releaseNetId(ikey); - releaseNetId(okey); - return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } /** @@ -1319,8 +1329,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void addAddressToTunnelInterface( - int tunnelResourceId, LinkAddress localAddr) { - enforceNetworkStackPermission(); + int tunnelResourceId, LinkAddress localAddr, String callingPackage) { + enforceTunnelPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1339,9 +1349,6 @@ public class IpSecService extends IIpSecService.Stub { localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. - throw new IllegalArgumentException(e); } } @@ -1351,10 +1358,10 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( - int tunnelResourceId, LinkAddress localAddr) { - enforceNetworkStackPermission(); - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int tunnelResourceId, LinkAddress localAddr, String callingPackage) { + enforceTunnelPermissions(callingPackage); + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw // IllegalArgumentException TunnelInterfaceRecord tunnelInterfaceInfo = @@ -1371,9 +1378,6 @@ public class IpSecService extends IIpSecService.Stub { localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. - throw new IllegalArgumentException(e); } } @@ -1382,7 +1386,9 @@ public class IpSecService extends IIpSecService.Stub { * server */ @Override - public synchronized void deleteTunnelInterface(int resourceId) throws RemoteException { + public synchronized void deleteTunnelInterface( + int resourceId, String callingPackage) throws RemoteException { + enforceTunnelPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); releaseResource(userRecord.mTunnelInterfaceRecords, resourceId); } @@ -1468,7 +1474,6 @@ public class IpSecService extends IIpSecService.Stub { case IpSecTransform.MODE_TRANSPORT: break; case IpSecTransform.MODE_TUNNEL: - enforceNetworkStackPermission(); break; default: throw new IllegalArgumentException( @@ -1476,9 +1481,24 @@ public class IpSecService extends IIpSecService.Stub { } } - private void enforceNetworkStackPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, - "IpSecService"); + private static final String TUNNEL_OP = "STOPSHIP"; // = AppOpsManager.OP_MANAGE_IPSEC_TUNNELS; + + private void enforceTunnelPermissions(String callingPackage) { + checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); + if (false) { // STOPSHIP if this line is present + switch (getAppOpsManager().noteOp( + TUNNEL_OP, + Binder.getCallingUid(), callingPackage)) { + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); + break; + case AppOpsManager.MODE_ALLOWED: + return; + default: + throw new SecurityException("Request to ignore AppOps for non-legacy API"); + } + } } private void createOrUpdateTransform( @@ -1534,8 +1554,12 @@ public class IpSecService extends IIpSecService.Stub { * result in all of those sockets becoming unable to send or receive data. */ @Override - public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder) - throws RemoteException { + public synchronized IpSecTransformResponse createTransform( + IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { + checkNotNull(c); + if (c.getMode() == IpSecTransform.MODE_TUNNEL) { + enforceTunnelPermissions(callingPackage); + } checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; @@ -1561,12 +1585,7 @@ public class IpSecService extends IIpSecService.Stub { dependencies.add(refcountedSpiRecord); SpiRecord spiRecord = refcountedSpiRecord.getResource(); - try { - createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); - } + createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); // SA was created successfully, time to construct a record and lock it away userRecord.mTransformRecords.put( @@ -1613,23 +1632,15 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TRANSPORT, "Transform mode was not Transport mode; cannot be applied to a socket"); - try { - mSrvConfig - .getNetdInstance() - .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), - resourceId, - direction, - c.getSourceAddress(), - c.getDestinationAddress(), - info.getSpiRecord().getSpi()); - } catch (ServiceSpecificException e) { - if (e.errorCode == EINVAL) { - throw new IllegalArgumentException(e.toString()); - } else { - throw e; - } - } + mSrvConfig + .getNetdInstance() + .ipSecApplyTransportModeTransform( + socket.getFileDescriptor(), + resourceId, + direction, + c.getSourceAddress(), + c.getDestinationAddress(), + info.getSpiRecord().getSpi()); } /** @@ -1641,13 +1652,9 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { - try { - mSrvConfig - .getNetdInstance() - .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } + mSrvConfig + .getNetdInstance() + .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); } /** @@ -1656,8 +1663,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void applyTunnelModeTransform( - int tunnelResourceId, int direction, int transformResourceId) throws RemoteException { - enforceNetworkStackPermission(); + int tunnelResourceId, int direction, + int transformResourceId, String callingPackage) throws RemoteException { + enforceTunnelPermissions(callingPackage); checkDirection(direction); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index fceacba4239c..f523d594aa0c 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -224,15 +224,14 @@ public class Nat464Xlat extends BaseNetworkObserver { } /** - * Copies the stacked clat link in oldLp, if any, to the LinkProperties in mNetwork. + * Copies the stacked clat link in oldLp, if any, to the passed LinkProperties. * This is necessary because the LinkProperties in mNetwork come from the transport layer, which * has no idea that 464xlat is running on top of it. */ - public void fixupLinkProperties(LinkProperties oldLp) { + public void fixupLinkProperties(LinkProperties oldLp, LinkProperties lp) { if (!isRunning()) { return; } - LinkProperties lp = mNetwork.linkProperties; if (lp == null || lp.getAllInterfaceNames().contains(mIface)) { return; } diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java index 6d7218179067..283112793d87 100644 --- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java +++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java @@ -29,27 +29,47 @@ import android.os.Parcelable; public final class ImsCallForwardInfo implements Parcelable { // Refer to ImsUtInterface#CDIV_CF_XXX /** @hide */ + // TODO: Make private, do not modify this field directly, use getter. public int mCondition; // 0: disabled, 1: enabled /** @hide */ + // TODO: Make private, do not modify this field directly, use getter. public int mStatus; // 0x91: International, 0x81: Unknown /** @hide */ + // TODO: Make private, do not modify this field directly, use getter. public int mToA; // Service class /** @hide */ + // TODO: Make private, do not modify this field directly, use getter. public int mServiceClass; // Number (it will not include the "sip" or "tel" URI scheme) /** @hide */ + // TODO: Make private, do not modify this field directly, use getter. public String mNumber; // No reply timer for CF /** @hide */ + // TODO: Make private, do not modify this field directly, use getter. public int mTimeSeconds; /** @hide */ + // TODO: Will be removed in the future, use public constructor instead. public ImsCallForwardInfo() { } + /** + * IMS Call Forward Information. + */ + public ImsCallForwardInfo(int condition, int status, int toA, int serviceClass, String number, + int replyTimerSec) { + mCondition = condition; + mStatus = status; + mToA = toA; + mServiceClass = serviceClass; + mNumber = number; + mTimeSeconds = replyTimerSec; + } + /** @hide */ public ImsCallForwardInfo(Parcel in) { readFromParcel(in); diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java index 1ddf1994f26b..b68055ea4e11 100644 --- a/telephony/java/android/telephony/ims/ImsSsData.java +++ b/telephony/java/android/telephony/ims/ImsSsData.java @@ -15,19 +15,24 @@ */ package android.telephony.ims; +import android.annotation.IntDef; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** - * Provided STK Call Control Suplementary Service information + * Provides STK Call Control Supplementary Service information. * * {@hide} */ @SystemApi public final class ImsSsData implements Parcelable { - //ServiceType + // Supplementary Service Type + // Call Forwarding public static final int SS_CFU = 0; public static final int SS_CF_BUSY = 1; public static final int SS_CF_NO_REPLY = 2; @@ -35,12 +40,16 @@ public final class ImsSsData implements Parcelable { public static final int SS_CF_ALL = 4; public static final int SS_CF_ALL_CONDITIONAL = 5; public static final int SS_CFUT = 6; + // Called Line Presentation public static final int SS_CLIP = 7; public static final int SS_CLIR = 8; public static final int SS_COLP = 9; public static final int SS_COLR = 10; + // Calling Name Presentation public static final int SS_CNAP = 11; + // Call Waiting public static final int SS_WAIT = 12; + // Call Barring public static final int SS_BAOC = 13; public static final int SS_BAOIC = 14; public static final int SS_BAOIC_EXC_HOME = 15; @@ -52,14 +61,14 @@ public final class ImsSsData implements Parcelable { public static final int SS_INCOMING_BARRING_DN = 21; public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; - //SSRequestType + //Supplementary Service Request Types public static final int SS_ACTIVATION = 0; public static final int SS_DEACTIVATION = 1; public static final int SS_INTERROGATION = 2; public static final int SS_REGISTRATION = 3; public static final int SS_ERASURE = 4; - //TeleserviceType + // Supplementary Service Teleservice Type public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; public static final int SS_ALL_TELESEVICES = 1; public static final int SS_TELEPHONY = 2; @@ -67,40 +76,227 @@ public final class ImsSsData implements Parcelable { public static final int SS_SMS_SERVICES = 4; public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; - // Refer to ServiceType + // Service Class of Supplementary Service + // See 27.007 +CCFC or +CLCK /** @hide */ - public int serviceType; - // Refere to SSRequestType + public static final int SERVICE_CLASS_NONE = 0; // no user input /** @hide */ - public int requestType; - // Refer to TeleserviceType + public static final int SERVICE_CLASS_VOICE = 1; /** @hide */ - public int teleserviceType; - // Service Class + public static final int SERVICE_CLASS_DATA = (1 << 1); /** @hide */ - public int serviceClass; - // Error information + public static final int SERVICE_CLASS_FAX = (1 << 2); /** @hide */ - public int result; - + public static final int SERVICE_CLASS_SMS = (1 << 3); + /** @hide */ + public static final int SERVICE_CLASS_DATA_SYNC = (1 << 4); + /** @hide */ + public static final int SERVICE_CLASS_DATA_ASYNC = (1 << 5); /** @hide */ - public int[] ssInfo; /* Valid for all supplementary services. - This field will be empty for RequestType SS_INTERROGATION - and ServiceType SS_CF_*, SS_INCOMING_BARRING_DN, - SS_INCOMING_BARRING_ANONYMOUS.*/ + public static final int SERVICE_CLASS_PACKET = (1 << 6); + /** @hide */ + public static final int SERVICE_CLASS_PAD = (1 << 7); + + /** + * Result code used if the operation was successful. See {@link #result}. + * @hide + */ + public static final int RESULT_SUCCESS = 0; /** @hide */ - public ImsCallForwardInfo[] cfInfo; /* Valid only for supplementary services - ServiceType SS_CF_* and RequestType SS_INTERROGATION */ + @IntDef(flag = true, prefix = { "SS_" }, value = { + SS_CFU, + SS_CF_BUSY, + SS_CF_NO_REPLY, + SS_CF_NOT_REACHABLE, + SS_CF_ALL, + SS_CF_ALL_CONDITIONAL, + SS_CFUT, + SS_CLIP, + SS_CLIR, + SS_COLP, + SS_COLR, + SS_CNAP, + SS_WAIT, + SS_BAOC, + SS_BAOIC, + SS_BAOIC_EXC_HOME, + SS_BAIC, + SS_BAIC_ROAMING, + SS_ALL_BARRING, + SS_OUTGOING_BARRING, + SS_INCOMING_BARRING, + SS_INCOMING_BARRING_DN, + SS_INCOMING_BARRING_ANONYMOUS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ServiceType{} /** @hide */ - public ImsSsInfo[] imsSsInfo; /* Valid only for ServiceType SS_INCOMING_BARRING_DN and - ServiceType SS_INCOMING_BARRING_ANONYMOUS */ + @IntDef(flag = true, prefix = { "SERVICE_CLASS" }, value = { + SERVICE_CLASS_NONE, + SERVICE_CLASS_VOICE, + SERVICE_CLASS_DATA, + SERVICE_CLASS_FAX, + SERVICE_CLASS_SMS, + SERVICE_CLASS_DATA_SYNC, + SERVICE_CLASS_DATA_ASYNC, + SERVICE_CLASS_PACKET, + SERVICE_CLASS_PAD + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ServiceClass{} + + /** + * The Service type of this Supplementary service. Valid values include: + * SS_CFU, + * SS_CF_BUSY, + * SS_CF_NO_REPLY, + * SS_CF_NOT_REACHABLE, + * SS_CF_ALL, + * SS_CF_ALL_CONDITIONAL, + * SS_CFUT, + * SS_CLIP, + * SS_CLIR, + * SS_COLP, + * SS_COLR, + * SS_CNAP, + * SS_WAIT, + * SS_BAOC, + * SS_BAOIC, + * SS_BAOIC_EXC_HOME, + * SS_BAIC, + * SS_BAIC_ROAMING, + * SS_ALL_BARRING, + * SS_OUTGOING_BARRING, + * SS_INCOMING_BARRING, + * SS_INCOMING_BARRING_DN, + * SS_INCOMING_BARRING_ANONYMOUS + * + * @hide + */ + // TODO: Make final, do not modify this field directly! + public int serviceType; + + /** + * Supplementary Service request Type. Valid values are: + * SS_ACTIVATION, + * SS_DEACTIVATION, + * SS_INTERROGATION, + * SS_REGISTRATION, + * SS_ERASURE + * + * @hide + */ + // TODO: Make final, do not modify this field directly! + public int requestType; + + /** + * Supplementary Service teleservice type: + * SS_TELESERVICE_ALL_TELE_AND_BEARER, + * SS_TELESERVICE_ALL_TELESEVICES, + * SS_TELESERVICE_TELEPHONY, + * SS_TELESERVICE_ALL_DATA, + * SS_TELESERVICE_SMS, + * SS_TELESERVICE_ALL_TELESERVICES_EXCEPT_SMS + * + * @hide + */ + // TODO: Make this param final! Do not try to modify this param directly. + public int teleserviceType; + + /** + * Supplementary Service service class. Valid values are: + * SERVICE_CLASS_NONE, + * SERVICE_CLASS_VOICE, + * SERVICE_CLASS_DATA, + * SERVICE_CLASS_FAX, + * SERVICE_CLASS_SMS, + * SERVICE_CLASS_DATA_SYNC, + * SERVICE_CLASS_DATA_ASYNC, + * SERVICE_CLASS_PACKET, + * SERVICE_CLASS_PAD + * + * @hide + */ + // TODO: Make this param final! Do not try to modify this param directly. + public int serviceClass; + + /** + * Result of Supplementary Service operation. Valid values are: + * RESULT_SUCCESS if the result is success, or + * ImsReasonInfo code if the result is a failure. + * + * @hide + */ + // TODO: Make this param final! Do not try to modify this param directly. + public final int result; + + private int[] mSsInfo; + private ImsCallForwardInfo[] mCfInfo; + private ImsSsInfo[] mImsSsInfo; - public ImsSsData() {} + /** + * Generate IMS Supplementary Service information. + * @param serviceType The Supplementary Service type. Valid entries: + * SS_CFU, + * SS_CF_BUSY, + * SS_CF_NO_REPLY, + * SS_CF_NOT_REACHABLE, + * SS_CF_ALL, + * SS_CF_ALL_CONDITIONAL, + * SS_CFUT, + * SS_CLIP, + * SS_CLIR, + * SS_COLP, + * SS_COLR, + * SS_CNAP, + * SS_WAIT, + * SS_BAOC, + * SS_BAOIC, + * SS_BAOIC_EXC_HOME, + * SS_BAIC, + * SS_BAIC_ROAMING, + * SS_ALL_BARRING, + * SS_OUTGOING_BARRING, + * SS_INCOMING_BARRING, + * SS_INCOMING_BARRING_DN, + * SS_INCOMING_BARRING_ANONYMOUS + * @param requestType Supplementary Service request Type. Valid values are: + * SS_ACTIVATION, + * SS_DEACTIVATION, + * SS_INTERROGATION, + * SS_REGISTRATION, + * SS_ERASURE + * @param teleserviceType Supplementary Service teleservice type: + * SS_TELESERVICE_ALL_TELE_AND_BEARER, + * SS_TELESERVICE_ALL_TELESEVICES, + * SS_TELESERVICE_TELEPHONY, + * SS_TELESERVICE_ALL_DATA, + * SS_TELESERVICE_SMS, + * SS_TELESERVICE_ALL_TELESERVICES_EXCEPT_SMS + * @param serviceClass Supplementary Service service class. See See 27.007 +CCFC or +CLCK. + * @param result Result of Supplementary Service operation. Valid values are 0 if the result is + * success, or ImsReasonInfo code if the result is a failure. + */ + public ImsSsData(@ServiceType int serviceType, int requestType, int teleserviceType, + @ServiceClass int serviceClass, int result) { + this.serviceType = serviceType; + this.requestType = requestType; + this.teleserviceType = teleserviceType; + this.serviceClass = serviceClass; + this.result = result; + } private ImsSsData(Parcel in) { - readFromParcel(in); + serviceType = in.readInt(); + requestType = in.readInt(); + teleserviceType = in.readInt(); + serviceClass = in.readInt(); + result = in.readInt(); + mSsInfo = in.createIntArray(); + mCfInfo = (ImsCallForwardInfo[])in.readParcelableArray(this.getClass().getClassLoader()); + mImsSsInfo = (ImsSsInfo[])in.readParcelableArray(this.getClass().getClassLoader()); } public static final Creator<ImsSsData> CREATOR = new Creator<ImsSsData>() { @@ -122,18 +318,9 @@ public final class ImsSsData implements Parcelable { out.writeInt(teleserviceType); out.writeInt(serviceClass); out.writeInt(result); - out.writeIntArray(ssInfo); - out.writeParcelableArray(cfInfo, 0); - } - - private void readFromParcel(Parcel in) { - serviceType = in.readInt(); - requestType = in.readInt(); - teleserviceType = in.readInt(); - serviceClass = in.readInt(); - result = in.readInt(); - ssInfo = in.createIntArray(); - cfInfo = (ImsCallForwardInfo[])in.readParcelableArray(this.getClass().getClassLoader()); + out.writeIntArray(mSsInfo); + out.writeParcelableArray(mCfInfo, 0); + out.writeParcelableArray(mImsSsInfo, 0); } @Override @@ -200,7 +387,55 @@ public final class ImsSsData implements Parcelable { } public boolean isTypeInterrogation() { - return (requestType == SS_INTERROGATION); + return (serviceType == SS_INTERROGATION); + } + + /** @hide */ + public void setSuppServiceInfo(int[] ssInfo) { + mSsInfo = ssInfo; + } + + /** @hide */ + public void setImsSpecificSuppServiceInfo(ImsSsInfo[] imsSsInfo) { + mImsSsInfo = imsSsInfo; + } + + /** @hide */ + public void setCallForwardingInfo(ImsCallForwardInfo[] cfInfo) { + mCfInfo = cfInfo; + } + + /** + * This field will be null for RequestType SS_INTERROGATION + * and ServiceType SS_CF_*, SS_INCOMING_BARRING_DN, + * SS_INCOMING_BARRING_ANONYMOUS. + * + * @hide + */ + public int[] getSuppServiceInfo() { + return mSsInfo; + } + + /** + * Valid only for ServiceTypes + * - SS_INCOMING_BARRING_DN and + * - ServiceType SS_INCOMING_BARRING_ANONYMOUS. + * Will be null otherwise. + * @hide + */ + public ImsSsInfo[] getImsSpecificSuppServiceInfo() { + return mImsSsInfo; + } + + /** + * Valid only for supplementary services + * - ServiceType SS_CF_* and + * - RequestType SS_INTERROGATION. + * Will be null otherwise. + * @hide + **/ + public ImsCallForwardInfo[] getCallForwardInfo() { + return mCfInfo; } public String toString() { diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java index 1d1292fb9f72..c6f8622f3fd9 100644 --- a/telephony/java/android/telephony/ims/ImsSsInfo.java +++ b/telephony/java/android/telephony/ims/ImsSsInfo.java @@ -36,13 +36,31 @@ public final class ImsSsInfo implements Parcelable { // 0: disabled, 1: enabled /** @hide */ + // TODO: Make private, do not modify this field directly, use getter! public int mStatus; /** @hide */ + // TODO: Make private, do not modify this field directly, use getter! public String mIcbNum; + /**@hide*/ + // TODO: Remove! Do not use this constructor, instead use public version. public ImsSsInfo() { } + /** + * + * @param status The status of the service registration of activation/deactiviation. Valid + * entries include: + * {@link #NOT_REGISTERED}, + * {@link #DISABLED}, + * {@link #ENABLED} + * @param icbNum The Incoming barring number. + */ + public ImsSsInfo(int status, String icbNum) { + mStatus = status; + mIcbNum = icbNum; + } + private ImsSsInfo(Parcel in) { readFromParcel(in); } @@ -81,6 +99,12 @@ public final class ImsSsInfo implements Parcelable { } }; + /** + * @return Supplementary Service Configuration status. Valid Values are: + * {@link #NOT_REGISTERED}, + * {@link #DISABLED}, + * {@link #ENABLED} + */ public int getStatus() { return mStatus; } diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java index 9191bd369cc1..8160924c41fa 100644 --- a/tests/net/java/android/net/IpSecManagerTest.java +++ b/tests/net/java/android/net/IpSecManagerTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.test.mock.MockContext; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.system.Os; @@ -70,11 +71,17 @@ public class IpSecManagerTest { private IpSecService mMockIpSecService; private IpSecManager mIpSecManager; + private MockContext mMockContext = new MockContext() { + @Override + public String getOpPackageName() { + return "fooPackage"; + } + }; @Before public void setUp() throws Exception { mMockIpSecService = mock(IpSecService.class); - mIpSecManager = new IpSecManager(mMockIpSecService); + mIpSecManager = new IpSecManager(mMockContext, mMockIpSecService); } /* @@ -255,7 +262,7 @@ public class IpSecManagerTest { new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); when(mMockIpSecService.createTunnelInterface( eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()), - anyObject(), anyObject())) + anyObject(), anyObject(), anyString())) .thenReturn(dummyResponse); IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface( @@ -273,7 +280,7 @@ public class IpSecManagerTest { assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName()); tunnelIntf.close(); - verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID)); + verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID), anyString()); } @Test @@ -281,12 +288,16 @@ public class IpSecManagerTest { IpSecManager.IpSecTunnelInterface tunnelIntf = createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME); - tunnelIntf.addAddress(VTI_INNER_ADDRESS); + tunnelIntf.addAddress(VTI_INNER_ADDRESS.getAddress(), + VTI_INNER_ADDRESS.getPrefixLength()); verify(mMockIpSecService) - .addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS)); + .addAddressToTunnelInterface( + eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString()); - tunnelIntf.removeAddress(VTI_INNER_ADDRESS); + tunnelIntf.removeAddress(VTI_INNER_ADDRESS.getAddress(), + VTI_INNER_ADDRESS.getPrefixLength()); verify(mMockIpSecService) - .addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS)); + .addAddressToTunnelInterface( + eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString()); } -}
\ No newline at end of file +} diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 410f754fb5ed..102cb7c77055 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.AppOpsManager; import android.content.Context; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -40,6 +41,7 @@ import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; import android.os.ParcelFileDescriptor; +import android.test.mock.MockContext; import android.support.test.filters.SmallTest; import android.system.Os; @@ -48,6 +50,7 @@ import java.util.Arrays; import java.util.Collection; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -92,7 +95,28 @@ public class IpSecServiceParameterizedTest { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F }; - Context mMockContext; + AppOpsManager mMockAppOps = mock(AppOpsManager.class); + + MockContext mMockContext = new MockContext() { + @Override + public Object getSystemService(String name) { + switch(name) { + case Context.APP_OPS_SERVICE: + return mMockAppOps; + default: + return null; + } + } + + @Override + public void enforceCallingOrSelfPermission(String permission, String message) { + if (permission == android.Manifest.permission.MANAGE_IPSEC_TUNNELS) { + return; + } + throw new SecurityException("Unavailable permission requested"); + } + }; + INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -114,13 +138,22 @@ public class IpSecServiceParameterizedTest { @Before public void setUp() throws Exception { - mMockContext = mock(Context.class); mMockNetd = mock(INetd.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); + // A package granted the AppOp for MANAGE_IPSEC_TUNNELS will be MODE_ALLOWED. + when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("blessedPackage"))) + .thenReturn(AppOpsManager.MODE_ALLOWED); + // A system package will not be granted the app op, so this should fall back to + // a permissions check, which should pass. + when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("systemPackage"))) + .thenReturn(AppOpsManager.MODE_DEFAULT); + // A mismatch between the package name and the UID will return MODE_IGNORED. + when(mMockAppOps.noteOp(anyInt(), anyInt(), eq("badPackage"))) + .thenReturn(AppOpsManager.MODE_IGNORED); } @Test @@ -232,7 +265,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verify(mMockNetd) @@ -267,7 +300,7 @@ public class IpSecServiceParameterizedTest { ipSecConfig.setAuthenticatedEncryption(AEAD_ALGO); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); verify(mMockNetd) @@ -301,12 +334,12 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); assertEquals(IpSecManager.Status.OK, createTransformResp.status); // Attempting to create transform a second time with the same SPIs should throw an error... try { - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); fail("IpSecService should have thrown an error for reuse of SPI"); } catch (IllegalStateException expected) { } @@ -314,7 +347,7 @@ public class IpSecServiceParameterizedTest { // ... even if the transform is deleted mIpSecService.deleteTransform(createTransformResp.resourceId); try { - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); fail("IpSecService should have thrown an error for reuse of SPI"); } catch (IllegalStateException expected) { } @@ -327,7 +360,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent); @@ -351,7 +384,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); mIpSecService.deleteTransform(createTransformResp.resourceId); verify(mMockNetd, times(1)) @@ -398,7 +431,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); @@ -435,7 +468,7 @@ public class IpSecServiceParameterizedTest { addAuthAndCryptToIpSecConfig(ipSecConfig); IpSecTransformResponse createTransformResp = - mIpSecService.createTransform(ipSecConfig, new Binder()); + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); int resourceId = createTransformResp.resourceId; @@ -460,10 +493,10 @@ public class IpSecServiceParameterizedTest { } private IpSecTunnelInterfaceResponse createAndValidateTunnel( - String localAddr, String remoteAddr) { + String localAddr, String remoteAddr, String pkgName) { IpSecTunnelInterfaceResponse createTunnelResp = mIpSecService.createTunnelInterface( - mSourceAddr, mDestinationAddr, fakeNetwork, new Binder()); + mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName); assertNotNull(createTunnelResp); assertEquals(IpSecManager.Status.OK, createTunnelResp.status); @@ -473,7 +506,7 @@ public class IpSecServiceParameterizedTest { @Test public void testCreateTunnelInterface() throws Exception { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); // Check that we have stored the tracking object, and retrieve it IpSecService.UserRecord userRecord = @@ -495,12 +528,12 @@ public class IpSecServiceParameterizedTest { @Test public void testDeleteTunnelInterface() throws Exception { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); - mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId); + mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, "blessedPackage"); // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent); @@ -516,7 +549,7 @@ public class IpSecServiceParameterizedTest { @Test public void testTunnelInterfaceBinderDeath() throws Exception { IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr); + createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid()); @@ -539,22 +572,35 @@ public class IpSecServiceParameterizedTest { @Test public void testAddRemoveAddressFromTunnelInterface() throws Exception { - IpSecTunnelInterfaceResponse createTunnelResp = - createAndValidateTunnel(mSourceAddr, mDestinationAddr); - - mIpSecService.addAddressToTunnelInterface(createTunnelResp.resourceId, mLocalInnerAddress); - verify(mMockNetd) - .interfaceAddAddress( - eq(createTunnelResp.interfaceName), - eq(mLocalInnerAddress.getAddress().getHostAddress()), - eq(mLocalInnerAddress.getPrefixLength())); + for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) { + IpSecTunnelInterfaceResponse createTunnelResp = + createAndValidateTunnel(mSourceAddr, mDestinationAddr, pkgName); + mIpSecService.addAddressToTunnelInterface( + createTunnelResp.resourceId, mLocalInnerAddress, pkgName); + verify(mMockNetd, times(1)) + .interfaceAddAddress( + eq(createTunnelResp.interfaceName), + eq(mLocalInnerAddress.getAddress().getHostAddress()), + eq(mLocalInnerAddress.getPrefixLength())); + mIpSecService.removeAddressFromTunnelInterface( + createTunnelResp.resourceId, mLocalInnerAddress, pkgName); + verify(mMockNetd, times(1)) + .interfaceDelAddress( + eq(createTunnelResp.interfaceName), + eq(mLocalInnerAddress.getAddress().getHostAddress()), + eq(mLocalInnerAddress.getPrefixLength())); + mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId, pkgName); + } + } - mIpSecService.removeAddressFromTunnelInterface( - createTunnelResp.resourceId, mLocalInnerAddress); - verify(mMockNetd) - .interfaceDelAddress( - eq(createTunnelResp.interfaceName), - eq(mLocalInnerAddress.getAddress().getHostAddress()), - eq(mLocalInnerAddress.getPrefixLength())); + @Ignore + @Test + public void testAddTunnelFailsForBadPackageName() throws Exception { + try { + IpSecTunnelInterfaceResponse createTunnelResp = + createAndValidateTunnel(mSourceAddr, mDestinationAddr, "badPackage"); + fail("Expected a SecurityException for badPackage."); + } catch (SecurityException expected) { + } } } |