diff --git a/Android.mk b/Android.mk index 974c410535c6d..1aaa09a40ffde 100644 --- a/Android.mk +++ b/Android.mk @@ -211,6 +211,7 @@ LOCAL_SRC_FILES += \ core/java/android/net/IEthernetManager.aidl \ core/java/android/net/IEthernetServiceListener.aidl \ core/java/android/net/INetdEventCallback.aidl \ + core/java/android/net/IIpSecService.aidl \ core/java/android/net/INetworkManagementEventObserver.aidl \ core/java/android/net/INetworkPolicyListener.aidl \ core/java/android/net/INetworkPolicyManager.aidl \ diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 93f88cce03636..ce019cac3772e 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -73,7 +73,9 @@ import android.net.ConnectivityThread; import android.net.EthernetManager; import android.net.IConnectivityManager; import android.net.IEthernetManager; +import android.net.IIpSecService; import android.net.INetworkPolicyManager; +import android.net.IpSecManager; import android.net.NetworkPolicyManager; import android.net.NetworkScoreManager; import android.net.nsd.INsdManager; @@ -239,6 +241,15 @@ final class SystemServiceRegistry { return new ConnectivityManager(context, service); }}); + registerService(Context.IPSEC_SERVICE, IpSecManager.class, + new StaticServiceFetcher() { + @Override + public IpSecManager createService() { + IBinder b = ServiceManager.getService(Context.IPSEC_SERVICE); + IIpSecService service = IIpSecService.Stub.asInterface(b); + return new IpSecManager(service); + }}); + registerService(Context.COUNTRY_DETECTOR, CountryDetector.class, new StaticServiceFetcher() { @Override diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl new file mode 100644 index 0000000000000..b8737fef72e26 --- /dev/null +++ b/core/java/android/net/IIpSecService.aidl @@ -0,0 +1,24 @@ +/* +** Copyright 2017, 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; + +/** + * @hide + */ +interface IIpSecService +{ +} diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 2c544e9b9bfe4..93a76dfbb4f5e 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -18,8 +18,6 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.SystemApi; -import android.content.Context; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.util.AndroidException; import dalvik.system.CloseGuard; @@ -79,11 +77,10 @@ public final class IpSecManager { } } - private final Context mContext; - private final INetworkManagementService mService; + private final IIpSecService mService; public static final class SecurityParameterIndex implements AutoCloseable { - private final Context mContext; + private final IIpSecService mService; private final InetAddress mDestinationAddress; private final CloseGuard mCloseGuard = CloseGuard.get(); private int mSpi; @@ -93,9 +90,10 @@ public final class IpSecManager { return mSpi; } - private SecurityParameterIndex(Context context, InetAddress destinationAddress, int spi) + private SecurityParameterIndex( + IIpSecService service, InetAddress destinationAddress, int spi) throws ResourceUnavailableException, SpiUnavailableException { - mContext = context; + mService = service; mDestinationAddress = destinationAddress; mSpi = spi; mCloseGuard.open("open"); @@ -152,7 +150,7 @@ public final class IpSecManager { public SecurityParameterIndex reserveSecurityParameterIndex( InetAddress destinationAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { - return new SecurityParameterIndex(mContext, destinationAddress, requestedSpi); + return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); } /** @@ -260,19 +258,19 @@ public final class IpSecManager { */ public static final class UdpEncapsulationSocket implements AutoCloseable { private final FileDescriptor mFd; - private final Context mContext; + private final IIpSecService mService; private final CloseGuard mCloseGuard = CloseGuard.get(); - private UdpEncapsulationSocket(Context context, int port) + private UdpEncapsulationSocket(IIpSecService service, int port) throws ResourceUnavailableException { - mContext = context; + mService = service; mCloseGuard.open("constructor"); // TODO: go down to the kernel and get a socket on the specified mFd = new FileDescriptor(); } - private UdpEncapsulationSocket(Context context) throws ResourceUnavailableException { - mContext = context; + private UdpEncapsulationSocket(IIpSecService service) throws ResourceUnavailableException { + mService = service; mCloseGuard.open("constructor"); // TODO: go get a random socket on a random port mFd = new FileDescriptor(); @@ -339,7 +337,7 @@ public final class IpSecManager { public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) throws IOException, ResourceUnavailableException { // Temporary code - return new UdpEncapsulationSocket(mContext, port); + return new UdpEncapsulationSocket(mService, port); } /** @@ -363,7 +361,7 @@ public final class IpSecManager { public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { // Temporary code - return new UdpEncapsulationSocket(mContext); + return new UdpEncapsulationSocket(mService); } /** @@ -372,8 +370,7 @@ public final class IpSecManager { * @param context the application context for this manager * @hide */ - public IpSecManager(Context context, INetworkManagementService service) { - mContext = checkNotNull(context, "missing context"); + public IpSecManager(IIpSecService service) { mService = checkNotNull(service, "missing service"); } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java new file mode 100644 index 0000000000000..994adc480fb5a --- /dev/null +++ b/services/core/java/com/android/server/IpSecService.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static android.Manifest.permission.DUMP; + +import android.content.Context; +import android.net.IIpSecService; +import android.net.INetd; +import android.net.util.NetdService; +import android.os.RemoteException; +import android.util.Log; +import android.util.Slog; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +/** @hide */ +public class IpSecService extends IIpSecService.Stub { + private static final String TAG = "IpSecService"; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final String NETD_SERVICE_NAME = "netd"; + + /** Binder context for this service */ + private final Context mContext; + + private Object mLock = new Object(); + + private static final int NETD_FETCH_TIMEOUT = 5000; //ms + + /** + * Constructs a new IpSecService instance + * + * @param context Binder context for this service + */ + private IpSecService(Context context) { + mContext = context; + } + + static IpSecService create(Context context) throws InterruptedException { + final IpSecService service = new IpSecService(context); + service.connectNativeNetdService(); + return service; + } + + public void systemReady() { + if (isNetdAlive()) { + Slog.d(TAG, "IpSecService is ready"); + } else { + Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!"); + } + } + + private void connectNativeNetdService() { + // Avoid blocking the system server to do this + Thread t = + new Thread( + new Runnable() { + @Override + public void run() { + synchronized (mLock) { + NetdService.get(NETD_FETCH_TIMEOUT); + } + } + }); + t.run(); + } + + INetd getNetdInstance() { + final INetd netd = NetdService.getInstance(); + if (netd == null) { + throw new RemoteException("Failed to Get Netd Instance").rethrowFromSystemServer(); + } + return netd; + } + + boolean isNetdAlive() { + synchronized (mLock) { + final INetd netd = getNetdInstance(); + if (netd == null) { + return false; + } + + try { + return netd.isAlive(); + } catch (RemoteException re) { + return false; + } + } + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mContext.enforceCallingOrSelfPermission(DUMP, TAG); + + pw.println("IpSecService Log:"); + pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead")); + pw.println(); + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 0b9017e42fe68..b4e806bfdd0c7 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -533,6 +533,7 @@ public final class SystemServer { VibratorService vibrator = null; IMountService mountService = null; NetworkManagementService networkManagement = null; + IpSecService ipSecService = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; ConnectivityService connectivity = null; @@ -809,6 +810,15 @@ public final class SystemServer { reportWtf("starting NetworkManagement Service", e); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); + + traceBeginAndSlog("StartIpSecService"); + try { + ipSecService = IpSecService.create(context); + ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService); + } catch (Throwable e) { + reportWtf("starting IpSec Service", e); + } + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } if (!disableNonCoreServices && !disableTextServices) { @@ -1327,6 +1337,7 @@ public final class SystemServer { final TelephonyRegistry telephonyRegistryF = telephonyRegistry; final MediaRouterService mediaRouterF = mediaRouter; final MmsServiceBroker mmsServiceF = mmsService; + final IpSecService ipSecServiceF = ipSecService; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -1377,6 +1388,13 @@ public final class SystemServer { reportWtf("making Network Managment Service ready", e); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); + Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeIpSecServiceReady"); + try { + if (ipSecServiceF != null) ipSecServiceF.systemReady(); + } catch (Throwable e) { + reportWtf("making IpSec Service ready", e); + } + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkStatsServiceReady"); try { if (networkStatsF != null) networkStatsF.systemReady();