1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net; 18 19 import android.annotation.NonNull; 20 import android.content.Context; 21 import android.net.networkstack.ModuleNetworkStackClient; 22 import android.util.Log; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 26 import java.util.concurrent.CompletableFuture; 27 import java.util.concurrent.ExecutionException; 28 import java.util.concurrent.atomic.AtomicReference; 29 import java.util.function.Consumer; 30 31 /** 32 * Manager class used to communicate with the ip memory store service in the network stack, 33 * which is running in a separate module. 34 * @hide 35 */ 36 public class IpMemoryStore extends IpMemoryStoreClient { 37 private static final String TAG = IpMemoryStore.class.getSimpleName(); 38 @NonNull private final CompletableFuture<IIpMemoryStore> mService; 39 @NonNull private final AtomicReference<CompletableFuture<IIpMemoryStore>> mTailNode; 40 IpMemoryStore(@onNull final Context context)41 public IpMemoryStore(@NonNull final Context context) { 42 super(context); 43 mService = new CompletableFuture<>(); 44 mTailNode = new AtomicReference<CompletableFuture<IIpMemoryStore>>(mService); 45 getModuleNetworkStackClient(context).fetchIpMemoryStore( 46 new IIpMemoryStoreCallbacks.Stub() { 47 @Override 48 public void onIpMemoryStoreFetched(@NonNull final IIpMemoryStore memoryStore) { 49 mService.complete(memoryStore); 50 } 51 52 @Override 53 public int getInterfaceVersion() { 54 return this.VERSION; 55 } 56 57 @Override 58 public String getInterfaceHash() { 59 return this.HASH; 60 } 61 }); 62 } 63 64 /* 65 * If the IpMemoryStore is ready, this function will run the request synchronously. 66 * Otherwise, it will enqueue the requests for execution immediately after the 67 * service becomes ready. The requests are guaranteed to be executed in the order 68 * they are sumbitted. 69 */ 70 @Override runWhenServiceReady(Consumer<IIpMemoryStore> cb)71 protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException { 72 mTailNode.getAndUpdate(future -> future.handle((store, exception) -> { 73 if (exception != null) { 74 // this should never happens since we also catch the exception below 75 Log.wtf(TAG, "Error fetching IpMemoryStore", exception); 76 return store; 77 } 78 79 try { 80 cb.accept(store); 81 } catch (Exception e) { 82 Log.wtf(TAG, "Exception occurred: " + e.getMessage()); 83 } 84 return store; 85 })); 86 } 87 88 @VisibleForTesting getModuleNetworkStackClient(Context context)89 protected ModuleNetworkStackClient getModuleNetworkStackClient(Context context) { 90 return ModuleNetworkStackClient.getInstance(context); 91 } 92 93 /** Gets an instance of the memory store */ 94 @NonNull getMemoryStore(final Context context)95 public static IpMemoryStore getMemoryStore(final Context context) { 96 return new IpMemoryStore(context); 97 } 98 } 99