Move the IpMemoryStore to the network stack.

Test: atest FrameworksNetTests
Change-Id: Ic5bd6ff54b09a6fa92b6863f240a5b053011acb6
diff --git a/Android.bp b/Android.bp
index 8ffb11d..fd61e60 100644
--- a/Android.bp
+++ b/Android.bp
@@ -841,6 +841,9 @@
         "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl",
         "core/java/android/net/ip/IIpClient.aidl",
         "core/java/android/net/ip/IIpClientCallbacks.aidl",
+        "core/java/android/net/IIpMemoryStore.aidl",
+        "core/java/android/net/IIpMemoryStoreCallbacks.aidl",
+        "core/java/android/net/ipmemorystore/**/*.aidl",
     ],
     backend: {
         ndk: {
@@ -854,29 +857,44 @@
 }
 
 aidl_interface {
+    name: "ipmemorystore-aidl-interfaces",
+    local_include_dir: "core/java",
+    srcs: [
+        "core/java/android/net/IIpMemoryStore.aidl",
+        "core/java/android/net/IIpMemoryStoreCallbacks.aidl",
+        "core/java/android/net/ipmemorystore/**/*.aidl",
+    ],
+}
+
+aidl_interface {
     name: "networkstack-aidl-framework",
     local_include_dir: "core/java",
     srcs: [
         "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl",
-        "core/java/android/net/IIpMemoryStore.aidl",
-        "core/java/android/net/ipmemorystore/**/*.aidl",
     ],
     api_dir: "aidl/networkstack",
 }
 
 filegroup {
+    name: "framework-annotations",
+    srcs: [
+        "core/java/android/annotation/NonNull.java",
+        "core/java/android/annotation/Nullable.java",
+        "core/java/android/annotation/IntDef.java",
+        "core/java/android/annotation/IntRange.java",
+        "core/java/android/annotation/UnsupportedAppUsage.java",
+        "core/java/com/android/internal/annotations/GuardedBy.java",
+        "core/java/com/android/internal/annotations/VisibleForTesting.java",
+    ]
+}
+
+filegroup {
     name: "framework-networkstack-shared-srcs",
     srcs: [
         // TODO: remove these annotations as soon as we can use andoid.support.annotations.*
-        "core/java/android/annotation/NonNull.java",
-        "core/java/android/annotation/Nullable.java",
-        "core/java/android/annotation/IntDef.java",
-        "core/java/android/annotation/IntRange.java",
-        "core/java/android/annotation/UnsupportedAppUsage.java",
+        ":framework-annotations",
         "core/java/android/net/DhcpResults.java",
         "core/java/android/util/LocalLog.java",
-        "core/java/com/android/internal/annotations/GuardedBy.java",
-        "core/java/com/android/internal/annotations/VisibleForTesting.java",
         "core/java/com/android/internal/util/HexDump.java",
         "core/java/com/android/internal/util/IndentingPrintWriter.java",
         "core/java/com/android/internal/util/IState.java",
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index a3ee849..b4330fb 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -81,11 +81,9 @@
 import android.net.EthernetManager;
 import android.net.IConnectivityManager;
 import android.net.IEthernetManager;
-import android.net.IIpMemoryStore;
 import android.net.IIpSecService;
 import android.net.INetworkPolicyManager;
 import android.net.ITestNetworkManager;
-import android.net.IpMemoryStore;
 import android.net.IpSecManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkScoreManager;
@@ -298,17 +296,6 @@
             }
         });
 
-        registerService(Context.IP_MEMORY_STORE_SERVICE, IpMemoryStore.class,
-                new CachedServiceFetcher<IpMemoryStore>() {
-                    @Override
-                    public IpMemoryStore createService(final ContextImpl ctx)
-                            throws ServiceNotFoundException {
-                        IBinder b = ServiceManager.getServiceOrThrow(
-                                Context.IP_MEMORY_STORE_SERVICE);
-                        IIpMemoryStore service = IIpMemoryStore.Stub.asInterface(b);
-                        return new IpMemoryStore(ctx, service);
-                    }});
-
         registerService(Context.IPSEC_SERVICE, IpSecManager.class,
                 new CachedServiceFetcher<IpSecManager>() {
             @Override
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5a75d5df..8625a04 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3523,14 +3523,6 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
-     * {@link android.net.IpMemoryStore} to store and read information about
-     * known networks.
-     * @hide
-     */
-    public static final String IP_MEMORY_STORE_SERVICE = "ipmemorystore";
-
-    /**
-     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.net.IpSecManager} for encrypting Sockets or Networks with
      * IPSec.
      *
diff --git a/core/java/android/net/IIpMemoryStoreCallbacks.aidl b/core/java/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..53108db
--- /dev/null
+++ b/core/java/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.IIpMemoryStore;
+
+/** {@hide} */
+oneway interface IIpMemoryStoreCallbacks {
+    void onIpMemoryStoreFetched(in IIpMemoryStore ipMemoryStore);
+}
diff --git a/core/java/android/net/INetworkStackConnector.aidl b/core/java/android/net/INetworkStackConnector.aidl
index edb9df6..3751c36 100644
--- a/core/java/android/net/INetworkStackConnector.aidl
+++ b/core/java/android/net/INetworkStackConnector.aidl
@@ -15,6 +15,7 @@
  */
 package android.net;
 
+import android.net.IIpMemoryStoreCallbacks;
 import android.net.INetworkMonitorCallbacks;
 import android.net.Network;
 import android.net.dhcp.DhcpServingParamsParcel;
@@ -27,4 +28,5 @@
         in IDhcpServerCallbacks cb);
     void makeNetworkMonitor(in Network network, String name, in INetworkMonitorCallbacks cb);
     void makeIpClient(in String ifName, in IIpClientCallbacks callbacks);
-}
\ No newline at end of file
+    void fetchIpMemoryStore(in IIpMemoryStoreCallbacks cb);
+}
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index 190247a..8872147 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -25,6 +25,7 @@
         ":services-networkstack-shared-srcs",
     ],
     static_libs: [
+        "ipmemorystore-client",
         "netd_aidl_interface-java",
         "networkstack-aidl-interfaces-java",
         "datastallprotosnano",
diff --git a/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
new file mode 100644
index 0000000..475f826
--- /dev/null
+++ b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.content.Context;
+
+/**
+ * service used to communicate with the ip memory store service in network stack,
+ * which is running in the same module.
+ * @see com.android.server.connectivity.ipmemorystore.IpMemoryStoreService
+ * @hide
+ */
+public class NetworkStackIpMemoryStore extends IpMemoryStoreClient {
+    @NonNull private final IIpMemoryStore mService;
+
+    public NetworkStackIpMemoryStore(@NonNull final Context context,
+            @NonNull final IIpMemoryStore service) {
+        super(context);
+        mService = service;
+    }
+
+    @Override
+    @NonNull
+    protected IIpMemoryStore getService() {
+        return mService;
+    }
+}
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index 7c7cdbd..b68fe23 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -29,6 +29,7 @@
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.NetworkStackIpMemoryStore;
 import android.net.ProvisioningConfigurationParcelable;
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
@@ -61,6 +62,7 @@
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.WakeupMessage;
 import com.android.server.NetworkObserverRegistry;
+import com.android.server.NetworkStackService.NetworkStackServiceManager;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -100,6 +102,7 @@
     // One holds StateMachine logs and the other connectivity packet logs.
     private static final ConcurrentHashMap<String, SharedLog> sSmLogs = new ConcurrentHashMap<>();
     private static final ConcurrentHashMap<String, LocalLog> sPktLogs = new ConcurrentHashMap<>();
+    private final NetworkStackIpMemoryStore mIpMemoryStore;
 
     /**
      * Dump all state machine and connectivity packet logs to the specified writer.
@@ -388,13 +391,14 @@
     }
 
     public IpClient(Context context, String ifName, IIpClientCallbacks callback,
-            NetworkObserverRegistry observerRegistry) {
-        this(context, ifName, callback, observerRegistry, new Dependencies());
+            NetworkObserverRegistry observerRegistry, NetworkStackServiceManager nssManager) {
+        this(context, ifName, callback, observerRegistry, nssManager, new Dependencies());
     }
 
     @VisibleForTesting
     IpClient(Context context, String ifName, IIpClientCallbacks callback,
-            NetworkObserverRegistry observerRegistry, Dependencies deps) {
+            NetworkObserverRegistry observerRegistry, NetworkStackServiceManager nssManager,
+            Dependencies deps) {
         super(IpClient.class.getSimpleName() + "." + ifName);
         Preconditions.checkNotNull(ifName);
         Preconditions.checkNotNull(callback);
@@ -408,6 +412,8 @@
         mShutdownLatch = new CountDownLatch(1);
         mCm = mContext.getSystemService(ConnectivityManager.class);
         mObserverRegistry = observerRegistry;
+        mIpMemoryStore =
+                new NetworkStackIpMemoryStore(context, nssManager.getIpMemoryStoreService());
 
         sSmLogs.putIfAbsent(mInterfaceName, new SharedLog(MAX_LOG_RECORDS, mTag));
         mLog = sSmLogs.get(mInterfaceName);
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index e7c8e85..335d951 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -29,6 +29,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.IIpMemoryStore;
+import android.net.IIpMemoryStoreCallbacks;
 import android.net.INetd;
 import android.net.INetworkMonitor;
 import android.net.INetworkMonitorCallbacks;
@@ -49,6 +51,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -86,7 +89,19 @@
         return makeConnector(this);
     }
 
-    private static class NetworkStackConnector extends INetworkStackConnector.Stub {
+    /**
+     * An interface for internal clients of the network stack service that can return
+     * or create inline instances of the service it manages.
+     */
+    public interface NetworkStackServiceManager {
+        /**
+         * Get an instance of the IpMemoryStoreService.
+         */
+        IIpMemoryStore getIpMemoryStoreService();
+    }
+
+    private static class NetworkStackConnector extends INetworkStackConnector.Stub
+            implements NetworkStackServiceManager {
         private static final int NUM_VALIDATION_LOG_LINES = 20;
         private final Context mContext;
         private final INetd mNetd;
@@ -94,6 +109,7 @@
         private final ConnectivityManager mCm;
         @GuardedBy("mIpClients")
         private final ArrayList<WeakReference<IpClient>> mIpClients = new ArrayList<>();
+        private final IpMemoryStoreService mIpMemoryStoreService;
 
         private static final int MAX_VALIDATION_LOGS = 10;
         @GuardedBy("mValidationLogs")
@@ -116,6 +132,7 @@
                     (IBinder) context.getSystemService(Context.NETD_SERVICE));
             mObserverRegistry = new NetworkObserverRegistry();
             mCm = context.getSystemService(ConnectivityManager.class);
+            mIpMemoryStoreService = new IpMemoryStoreService(context);
 
             try {
                 mObserverRegistry.register(mNetd);
@@ -159,7 +176,7 @@
 
         @Override
         public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException {
-            final IpClient ipClient = new IpClient(mContext, ifName, cb, mObserverRegistry);
+            final IpClient ipClient = new IpClient(mContext, ifName, cb, mObserverRegistry, this);
 
             synchronized (mIpClients) {
                 final Iterator<WeakReference<IpClient>> it = mIpClients.iterator();
@@ -176,6 +193,17 @@
         }
 
         @Override
+        public IIpMemoryStore getIpMemoryStoreService() {
+            return mIpMemoryStoreService;
+        }
+
+        @Override
+        public void fetchIpMemoryStore(@NonNull final IIpMemoryStoreCallbacks cb)
+                throws RemoteException {
+            cb.onIpMemoryStoreFetched(mIpMemoryStoreService);
+        }
+
+        @Override
         protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
                 @Nullable String[] args) {
             checkDumpPermission();
diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java
similarity index 99%
rename from services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java
rename to packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java
index bbecc63..4d4ceed 100644
--- a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.net.ipmemorystore;
+package com.android.server.connectivity.ipmemorystore;
 
 import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH;
 import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
similarity index 98%
rename from services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java
rename to packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
index d43dc6a..f801b35 100644
--- a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.server.net.ipmemorystore;
+package com.android.server.connectivity.ipmemorystore;
 
 import static android.net.ipmemorystore.Status.ERROR_DATABASE_CANNOT_BE_OPENED;
 import static android.net.ipmemorystore.Status.ERROR_GENERIC;
 import static android.net.ipmemorystore.Status.ERROR_ILLEGAL_ARGUMENT;
 import static android.net.ipmemorystore.Status.SUCCESS;
 
-import static com.android.server.net.ipmemorystore.IpMemoryStoreDatabase.EXPIRY_ERROR;
+import static com.android.server.connectivity.ipmemorystore.IpMemoryStoreDatabase.EXPIRY_ERROR;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -40,7 +40,6 @@
 import android.net.ipmemorystore.SameL3NetworkResponse;
 import android.net.ipmemorystore.Status;
 import android.net.ipmemorystore.StatusParcelable;
-import android.net.ipmemorystore.Utils;
 import android.os.RemoteException;
 import android.util.Log;
 
diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/RelevanceUtils.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RelevanceUtils.java
similarity index 99%
rename from services/ipmemorystore/java/com/android/server/net/ipmemorystore/RelevanceUtils.java
rename to packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RelevanceUtils.java
index aa45400..38d5544 100644
--- a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/RelevanceUtils.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RelevanceUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.net.ipmemorystore;
+package com.android.server.connectivity.ipmemorystore;
 
 import com.android.internal.annotations.VisibleForTesting;
 
diff --git a/core/java/android/net/ipmemorystore/Utils.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/Utils.java
similarity index 94%
rename from core/java/android/net/ipmemorystore/Utils.java
rename to packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/Utils.java
index b361aca..9cbf490 100644
--- a/core/java/android/net/ipmemorystore/Utils.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/Utils.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package android.net.ipmemorystore;
+package com.android.server.connectivity.ipmemorystore;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.ipmemorystore.Blob;
 
 /** {@hide} */
 public class Utils {
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index 4536c47..eee12d6 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -51,6 +51,7 @@
 import com.android.internal.R;
 import com.android.server.NetworkObserver;
 import com.android.server.NetworkObserverRegistry;
+import com.android.server.NetworkStackService;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -90,6 +91,7 @@
     @Mock private AlarmManager mAlarm;
     @Mock private IpClient.Dependencies mDependencies;
     @Mock private ContentResolver mContentResolver;
+    @Mock private NetworkStackService.NetworkStackServiceManager mNetworkStackServiceManager;
 
     private NetworkObserver mObserver;
     private InterfaceParams mIfParams;
@@ -118,7 +120,8 @@
 
     private IpClient makeIpClient(String ifname) throws Exception {
         setTestInterfaceParams(ifname);
-        final IpClient ipc = new IpClient(mContext, ifname, mCb, mObserverRegistry, mDependencies);
+        final IpClient ipc = new IpClient(mContext, ifname, mCb, mObserverRegistry,
+                mNetworkStackServiceManager, mDependencies);
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(ifname, false);
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(ifname);
         ArgumentCaptor<NetworkObserver> arg = ArgumentCaptor.forClass(NetworkObserver.class);
@@ -142,8 +145,8 @@
     public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
         setTestInterfaceParams(null);
         try {
-            final IpClient ipc = new IpClient(
-                    mContext, null, mCb, mObserverRegistry, mDependencies);
+            final IpClient ipc = new IpClient(mContext, null, mCb, mObserverRegistry,
+                    mNetworkStackServiceManager, mDependencies);
             ipc.shutdown();
             fail();
         } catch (NullPointerException npe) {
@@ -156,8 +159,8 @@
         final String ifname = "lo";
         setTestInterfaceParams(ifname);
         try {
-            final IpClient ipc = new IpClient(
-                    mContext, ifname, null, mObserverRegistry, mDependencies);
+            final IpClient ipc = new IpClient(mContext, ifname, null, mObserverRegistry,
+                    mNetworkStackServiceManager, mDependencies);
             ipc.shutdown();
             fail();
         } catch (NullPointerException npe) {
@@ -168,16 +171,16 @@
     @Test
     public void testInvalidInterfaceDoesNotThrow() throws Exception {
         setTestInterfaceParams(TEST_IFNAME);
-        final IpClient ipc = new IpClient(
-                mContext, TEST_IFNAME, mCb, mObserverRegistry, mDependencies);
+        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry,
+                mNetworkStackServiceManager, mDependencies);
         ipc.shutdown();
     }
 
     @Test
     public void testInterfaceNotFoundFailsImmediately() throws Exception {
         setTestInterfaceParams(null);
-        final IpClient ipc = new IpClient(
-                mContext, TEST_IFNAME, mCb, mObserverRegistry, mDependencies);
+        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry,
+                mNetworkStackServiceManager, mDependencies);
         ipc.startProvisioning(new ProvisioningConfiguration());
         verify(mCb, times(1)).onProvisioningFailure(any());
         ipc.shutdown();
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
similarity index 99%
rename from tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
rename to packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
index be10680..d0e58b8 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.net.ipmemorystore;
+package com.android.server.connectivity.ipmemorystore;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
similarity index 97%
rename from tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
rename to packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
index 7413b914..3d3aabc 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.net.ipmemorystore;
+package com.android.server.connectivity.ipmemorystore;
 
-import static com.android.server.net.ipmemorystore.RelevanceUtils.CAPPED_RELEVANCE;
+import static com.android.server.connectivity.ipmemorystore.RelevanceUtils.CAPPED_RELEVANCE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
diff --git a/services/Android.bp b/services/Android.bp
index a416ca0..bea51be 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -23,7 +23,6 @@
         "services.companion",
         "services.coverage",
         "services.devicepolicy",
-        "services.ipmemorystore",
         "services.midi",
         "services.net",
         "services.print",
diff --git a/services/ipmemorystore/Android.bp b/services/ipmemorystore/Android.bp
deleted file mode 100644
index 013cf56..0000000
--- a/services/ipmemorystore/Android.bp
+++ /dev/null
@@ -1,4 +0,0 @@
-java_library_static {
-    name: "services.ipmemorystore",
-    srcs: ["java/**/*.java"],
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4125b92..ed5928f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -98,7 +98,6 @@
 import com.android.server.media.projection.MediaProjectionManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
-import com.android.server.net.ipmemorystore.IpMemoryStoreService;
 import com.android.server.net.watchlist.NetworkWatchlistService;
 import com.android.server.notification.NotificationManagerService;
 import com.android.server.oemlock.OemLockService;
@@ -1135,14 +1134,6 @@
             }
             traceEnd();
 
-            traceBeginAndSlog("StartIpMemoryStoreService");
-            try {
-                ServiceManager.addService(Context.IP_MEMORY_STORE_SERVICE,
-                        new IpMemoryStoreService(context));
-            } catch (Throwable e) {
-                reportWtf("starting IP Memory Store Service", e);
-            }
-            traceEnd();
 
             traceBeginAndSlog("StartIpSecService");
             try {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 8ad4d76..486d15d 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -7,6 +7,19 @@
     ]
 }
 
+java_library_static {
+    name: "ipmemorystore-client",
+    sdk_version: "system_current",
+    srcs: [
+        ":framework-annotations",
+        "java/android/net/IpMemoryStoreClient.java",
+        "java/android/net/ipmemorystore/**.java",
+    ],
+    static_libs: [
+        "ipmemorystore-aidl-interfaces-java",
+    ]
+}
+
 filegroup {
     name: "services-networkstack-shared-srcs",
     srcs: [
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
new file mode 100644
index 0000000..9248299
--- /dev/null
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.content.Context;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Manager class used to communicate with the ip memory store service in the network stack,
+ * which is running in a separate module.
+ * @hide
+*/
+public class IpMemoryStore extends IpMemoryStoreClient {
+    private final CompletableFuture<IIpMemoryStore> mService;
+
+    public IpMemoryStore(@NonNull final Context context) {
+        super(context);
+        mService = new CompletableFuture<>();
+        getNetworkStackClient().fetchIpMemoryStore(
+                new IIpMemoryStoreCallbacks.Stub() {
+                    @Override
+                    public void onIpMemoryStoreFetched(final IIpMemoryStore memoryStore) {
+                        mService.complete(memoryStore);
+                    }
+                });
+    }
+
+    @Override
+    protected IIpMemoryStore getService() throws InterruptedException, ExecutionException {
+        return mService.get();
+    }
+
+    @VisibleForTesting
+    protected NetworkStackClient getNetworkStackClient() {
+        return NetworkStackClient.getInstance();
+    }
+
+    /** Gets an instance of the memory store */
+    @NonNull
+    public static IpMemoryStore getMemoryStore(final Context context) {
+        return new IpMemoryStore(context);
+    }
+}
diff --git a/core/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStoreClient.java
similarity index 68%
rename from core/java/android/net/IpMemoryStore.java
rename to services/net/java/android/net/IpMemoryStoreClient.java
index 2f4d9bc..2f4fdbd 100644
--- a/core/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStoreClient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemService;
 import android.content.Context;
 import android.net.ipmemorystore.Blob;
 import android.net.ipmemorystore.IOnBlobRetrievedListener;
@@ -27,23 +26,34 @@
 import android.net.ipmemorystore.IOnSameNetworkResponseListener;
 import android.net.ipmemorystore.IOnStatusListener;
 import android.net.ipmemorystore.NetworkAttributes;
+import android.net.ipmemorystore.Status;
+import android.net.ipmemorystore.StatusParcelable;
 import android.os.RemoteException;
+import android.util.Log;
 
-import com.android.internal.util.Preconditions;
+import java.util.concurrent.ExecutionException;
 
 /**
- * The interface for system components to access the IP memory store.
- * @see com.android.server.net.ipmemorystore.IpMemoryStoreService
+ * service used to communicate with the ip memory store service in network stack,
+ * which is running in a separate module.
  * @hide
  */
-@SystemService(Context.IP_MEMORY_STORE_SERVICE)
-public class IpMemoryStore {
-    @NonNull final Context mContext;
-    @NonNull final IIpMemoryStore mService;
+public abstract class IpMemoryStoreClient {
+    private static final String TAG = IpMemoryStoreClient.class.getSimpleName();
+    private final Context mContext;
 
-    public IpMemoryStore(@NonNull final Context context, @NonNull final IIpMemoryStore service) {
-        mContext = Preconditions.checkNotNull(context, "missing context");
-        mService = Preconditions.checkNotNull(service, "missing IIpMemoryStore");
+    public IpMemoryStoreClient(@NonNull final Context context) {
+        if (context == null) throw new IllegalArgumentException("missing context");
+        mContext = context;
+    }
+
+    @NonNull
+    protected abstract IIpMemoryStore getService() throws InterruptedException, ExecutionException;
+
+    protected StatusParcelable internalErrorStatus() {
+        final StatusParcelable error = new StatusParcelable();
+        error.resultCode = Status.ERROR_UNKNOWN;
+        return error;
     }
 
     /**
@@ -66,9 +76,13 @@
             @NonNull final NetworkAttributes attributes,
             @Nullable final IOnStatusListener listener) {
         try {
-            mService.storeNetworkAttributes(l2Key, attributes.toParcelable(), listener);
+            try {
+                getService().storeNetworkAttributes(l2Key, attributes.toParcelable(), listener);
+            } catch (InterruptedException | ExecutionException m) {
+                listener.onComplete(internalErrorStatus());
+            }
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            Log.e(TAG, "Error storing network attributes", e);
         }
     }
 
@@ -87,9 +101,13 @@
             @NonNull final String name, @NonNull final Blob data,
             @Nullable final IOnStatusListener listener) {
         try {
-            mService.storeBlob(l2Key, clientId, name, data, listener);
+            try {
+                getService().storeBlob(l2Key, clientId, name, data, listener);
+            } catch (InterruptedException | ExecutionException m) {
+                listener.onComplete(internalErrorStatus());
+            }
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            Log.e(TAG, "Error storing blob", e);
         }
     }
 
@@ -110,9 +128,13 @@
     public void findL2Key(@NonNull final NetworkAttributes attributes,
             @NonNull final IOnL2KeyResponseListener listener) {
         try {
-            mService.findL2Key(attributes.toParcelable(), listener);
+            try {
+                getService().findL2Key(attributes.toParcelable(), listener);
+            } catch (InterruptedException | ExecutionException m) {
+                listener.onL2KeyResponse(internalErrorStatus(), null);
+            }
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            Log.e(TAG, "Error finding L2 Key", e);
         }
     }
 
@@ -128,9 +150,13 @@
     public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2,
             @NonNull final IOnSameNetworkResponseListener listener) {
         try {
-            mService.isSameNetwork(l2Key1, l2Key2, listener);
+            try {
+                getService().isSameNetwork(l2Key1, l2Key2, listener);
+            } catch (InterruptedException | ExecutionException m) {
+                listener.onSameNetworkResponse(internalErrorStatus(), null);
+            }
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            Log.e(TAG, "Error checking for network sameness", e);
         }
     }
 
@@ -146,9 +172,13 @@
     public void retrieveNetworkAttributes(@NonNull final String l2Key,
             @NonNull final IOnNetworkAttributesRetrieved listener) {
         try {
-            mService.retrieveNetworkAttributes(l2Key, listener);
+            try {
+                getService().retrieveNetworkAttributes(l2Key, listener);
+            } catch (InterruptedException | ExecutionException m) {
+                listener.onNetworkAttributesRetrieved(internalErrorStatus(), null, null);
+            }
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            Log.e(TAG, "Error retrieving network attributes", e);
         }
     }
 
@@ -166,14 +196,13 @@
     public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId,
             @NonNull final String name, @NonNull final IOnBlobRetrievedListener listener) {
         try {
-            mService.retrieveBlob(l2Key, clientId, name, listener);
+            try {
+                getService().retrieveBlob(l2Key, clientId, name, listener);
+            } catch (InterruptedException | ExecutionException m) {
+                listener.onBlobRetrieved(internalErrorStatus(), null, null, null);
+            }
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            Log.e(TAG, "Error retrieving blob", e);
         }
     }
-
-    /** Gets an instance of the memory store */
-    public static IpMemoryStore getMemoryStore(final Context context) {
-        return (IpMemoryStore) context.getSystemService(Context.IP_MEMORY_STORE_SERVICE);
-    }
 }
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index cc09fe3..7befd087 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -130,6 +130,21 @@
         });
     }
 
+    /**
+     * Get an instance of the IpMemoryStore.
+     *
+     * <p>The IpMemoryStore will be returned asynchronously through the provided callbacks.
+     */
+    public void fetchIpMemoryStore(IIpMemoryStoreCallbacks cb) {
+        requestConnector(connector -> {
+            try {
+                connector.fetchIpMemoryStore(cb);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        });
+    }
+
     private class NetworkStackConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
diff --git a/core/java/android/net/ipmemorystore/NetworkAttributes.java b/services/net/java/android/net/ipmemorystore/NetworkAttributes.java
similarity index 100%
rename from core/java/android/net/ipmemorystore/NetworkAttributes.java
rename to services/net/java/android/net/ipmemorystore/NetworkAttributes.java
diff --git a/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java b/services/net/java/android/net/ipmemorystore/SameL3NetworkResponse.java
similarity index 100%
rename from core/java/android/net/ipmemorystore/SameL3NetworkResponse.java
rename to services/net/java/android/net/ipmemorystore/SameL3NetworkResponse.java
diff --git a/core/java/android/net/ipmemorystore/Status.java b/services/net/java/android/net/ipmemorystore/Status.java
similarity index 97%
rename from core/java/android/net/ipmemorystore/Status.java
rename to services/net/java/android/net/ipmemorystore/Status.java
index cacd42d..13242c0 100644
--- a/core/java/android/net/ipmemorystore/Status.java
+++ b/services/net/java/android/net/ipmemorystore/Status.java
@@ -32,6 +32,7 @@
     public static final int ERROR_ILLEGAL_ARGUMENT = -2;
     public static final int ERROR_DATABASE_CANNOT_BE_OPENED = -3;
     public static final int ERROR_STORAGE = -4;
+    public static final int ERROR_UNKNOWN = -5;
 
     public final int resultCode;
 
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 2539c0f..c62d85e 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -13,7 +13,6 @@
         "mockito-target-minus-junit4",
         "platform-test-annotations",
         "services.core",
-        "services.ipmemorystore",
         "services.net",
     ],
     libs: [
diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java
index 57ecc8f..18c6768 100644
--- a/tests/net/java/android/net/IpMemoryStoreTest.java
+++ b/tests/net/java/android/net/IpMemoryStoreTest.java
@@ -16,6 +16,9 @@
 
 package android.net;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+
 import android.content.Context;
 
 import androidx.test.filters.SmallTest;
@@ -33,13 +36,25 @@
     @Mock
     Context mMockContext;
     @Mock
+    NetworkStackClient mNetworkStackClient;
+    @Mock
     IIpMemoryStore mMockService;
     IpMemoryStore mStore;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mStore = new IpMemoryStore(mMockContext, mMockService);
+        doAnswer(invocation -> {
+            ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
+                    .onIpMemoryStoreFetched(mMockService);
+            return null;
+        }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+        mStore = new IpMemoryStore(mMockContext) {
+            @Override
+            protected NetworkStackClient getNetworkStackClient() {
+                return mNetworkStackClient;
+            }
+        };
     }
 
     @Test