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 occured: " + 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