1 /*
2  * Copyright (C) 2020 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.networkstack;
18 
19 import static android.os.Build.VERSION.SDK_INT;
20 
21 import android.annotation.NonNull;
22 import android.content.Context;
23 import android.net.INetworkStackConnector;
24 import android.net.NetworkStack;
25 import android.os.Build;
26 import android.os.IBinder;
27 import android.util.Log;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 /**
32  * A {@link NetworkStackClientBase} implementation for use within modules (not the system server).
33  */
34 public class ModuleNetworkStackClient extends NetworkStackClientBase {
35     private static final String TAG = ModuleNetworkStackClient.class.getSimpleName();
36 
ModuleNetworkStackClient()37     private ModuleNetworkStackClient() {}
38 
39     private static ModuleNetworkStackClient sInstance;
40 
41     /**
42      * Get an instance of the ModuleNetworkStackClient.
43      * @param packageContext Context to use to obtain the network stack connector.
44      */
45     @NonNull
getInstance(Context packageContext)46     public static synchronized ModuleNetworkStackClient getInstance(Context packageContext) {
47         // TODO(b/149676685): change this check to "< R" once R is defined
48         if (SDK_INT < Build.VERSION_CODES.Q
49                 || (SDK_INT == Build.VERSION_CODES.Q && "REL".equals(Build.VERSION.CODENAME))) {
50             // The NetworkStack connector is not available through NetworkStack before R
51             throw new UnsupportedOperationException(
52                     "ModuleNetworkStackClient is not supported on API " + SDK_INT);
53         }
54 
55         if (sInstance == null) {
56             sInstance = new ModuleNetworkStackClient();
57             sInstance.startPolling();
58         }
59         return sInstance;
60     }
61 
62     @VisibleForTesting
resetInstanceForTest()63     protected static synchronized void resetInstanceForTest() {
64         sInstance = null;
65     }
66 
startPolling()67     private void startPolling() {
68         // If the service is already registered (as it will be most of the time), do not poll and
69         // fulfill requests immediately.
70         final IBinder nss = NetworkStack.getService();
71         if (nss != null) {
72             // Calling onNetworkStackConnected here means that pending oneway Binder calls to the
73             // NetworkStack get sent from the current thread and not a worker thread; this is fine
74             // considering that those are only non-blocking, oneway Binder calls.
75             onNetworkStackConnected(INetworkStackConnector.Stub.asInterface(nss));
76             return;
77         }
78         new Thread(new PollingRunner()).start();
79     }
80 
81     private class PollingRunner implements Runnable {
82 
PollingRunner()83         private PollingRunner() {}
84 
85         @Override
run()86         public void run() {
87             // Block until the NetworkStack connector is registered in ServiceManager.
88             IBinder nss;
89             while ((nss = NetworkStack.getService()) == null) {
90                 try {
91                     Thread.sleep(200);
92                 } catch (InterruptedException e) {
93                     Log.e(TAG, "Interrupted while waiting for NetworkStack connector", e);
94                     // Keep trying, the system would just crash without a connector
95                 }
96             }
97 
98             onNetworkStackConnected(INetworkStackConnector.Stub.asInterface(nss));
99         }
100     }
101 }
102