1 /*
2  * Copyright 2017 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.telephony;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SdkConstant;
22 import android.annotation.SystemApi;
23 import android.app.Service;
24 import android.content.Intent;
25 import android.os.Handler;
26 import android.os.HandlerThread;
27 import android.os.IBinder;
28 import android.os.Looper;
29 import android.os.Message;
30 import android.os.RemoteException;
31 import android.telephony.NetworkRegistrationInfo.Domain;
32 import android.util.SparseArray;
33 
34 import com.android.internal.annotations.VisibleForTesting;
35 import com.android.telephony.Rlog;
36 
37 import java.util.ArrayList;
38 import java.util.List;
39 
40 /**
41  * Base class of network service. Services that extend NetworkService must register the service in
42  * their AndroidManifest to be detected by the framework. They must be protected by the permission
43  * "android.permission.BIND_TELEPHONY_NETWORK_SERVICE". The network service definition in the
44  * manifest must follow the following format:
45  * ...
46  * <service android:name=".xxxNetworkService"
47  *     android:permission="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" >
48  *     <intent-filter>
49  *         <action android:name="android.telephony.NetworkService" />
50  *     </intent-filter>
51  * </service>
52  * @hide
53  */
54 @SystemApi
55 public abstract class NetworkService extends Service {
56 
57     private final String TAG = NetworkService.class.getSimpleName();
58 
59     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
60     public static final String SERVICE_INTERFACE = "android.telephony.NetworkService";
61 
62     private static final int NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER                 = 1;
63     private static final int NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER                 = 2;
64     private static final int NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS            = 3;
65     private static final int NETWORK_SERVICE_GET_REGISTRATION_INFO                           = 4;
66     private static final int NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE                        = 5;
67     private static final int NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE                      = 6;
68     private static final int NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED                 = 7;
69 
70 
71     private final HandlerThread mHandlerThread;
72 
73     private final NetworkServiceHandler mHandler;
74 
75     private final SparseArray<NetworkServiceProvider> mServiceMap = new SparseArray<>();
76 
77     /**
78      * @hide
79      */
80     @VisibleForTesting
81     public final INetworkServiceWrapper mBinder = new INetworkServiceWrapper();
82 
83     /**
84      * The abstract class of the actual network service implementation. The network service provider
85      * must extend this class to support network connection. Note that each instance of network
86      * service is associated with one physical SIM slot.
87      */
88     public abstract class NetworkServiceProvider implements AutoCloseable {
89         private final int mSlotIndex;
90 
91         private final List<INetworkServiceCallback>
92                 mNetworkRegistrationInfoChangedCallbacks = new ArrayList<>();
93 
94         /**
95          * Constructor
96          * @param slotIndex SIM slot id the data service provider associated with.
97          */
NetworkServiceProvider(int slotIndex)98         public NetworkServiceProvider(int slotIndex) {
99             mSlotIndex = slotIndex;
100         }
101 
102         /**
103          * @return SIM slot index the network service associated with.
104          */
getSlotIndex()105         public final int getSlotIndex() {
106             return mSlotIndex;
107         }
108 
109         /**
110          * Request network registration info. The result will be passed to the callback.
111          *
112          * @param domain Network domain
113          * @param callback The callback for reporting network registration info
114          */
requestNetworkRegistrationInfo(@omain int domain, @NonNull NetworkServiceCallback callback)115         public void requestNetworkRegistrationInfo(@Domain int domain,
116                                                    @NonNull NetworkServiceCallback callback) {
117             callback.onRequestNetworkRegistrationInfoComplete(
118                     NetworkServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
119         }
120 
121         /**
122          * Notify the system that network registration info is changed.
123          */
notifyNetworkRegistrationInfoChanged()124         public final void notifyNetworkRegistrationInfoChanged() {
125             mHandler.obtainMessage(NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED,
126                     mSlotIndex, 0, null).sendToTarget();
127         }
128 
registerForInfoChanged(@onNull INetworkServiceCallback callback)129         private void registerForInfoChanged(@NonNull INetworkServiceCallback callback) {
130             synchronized (mNetworkRegistrationInfoChangedCallbacks) {
131                 mNetworkRegistrationInfoChangedCallbacks.add(callback);
132             }
133         }
134 
unregisterForInfoChanged(@onNull INetworkServiceCallback callback)135         private void unregisterForInfoChanged(@NonNull INetworkServiceCallback callback) {
136             synchronized (mNetworkRegistrationInfoChangedCallbacks) {
137                 mNetworkRegistrationInfoChangedCallbacks.remove(callback);
138             }
139         }
140 
notifyInfoChangedToCallbacks()141         private void notifyInfoChangedToCallbacks() {
142             for (INetworkServiceCallback callback : mNetworkRegistrationInfoChangedCallbacks) {
143                 try {
144                     callback.onNetworkStateChanged();
145                 } catch (RemoteException exception) {
146                     // Doing nothing.
147                 }
148             }
149         }
150 
151         /**
152          * Called when the instance of network service is destroyed (e.g. got unbind or binder died)
153          * or when the network service provider is removed. The extended class should implement this
154          * method to perform cleanup works.
155          */
156         @Override
close()157         public abstract void close();
158     }
159 
160     private class NetworkServiceHandler extends Handler {
161 
NetworkServiceHandler(Looper looper)162         NetworkServiceHandler(Looper looper) {
163             super(looper);
164         }
165 
166         @Override
handleMessage(Message message)167         public void handleMessage(Message message) {
168             final int slotIndex = message.arg1;
169             final INetworkServiceCallback callback = (INetworkServiceCallback) message.obj;
170 
171             NetworkServiceProvider serviceProvider = mServiceMap.get(slotIndex);
172 
173             switch (message.what) {
174                 case NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER:
175                     // If the service provider doesn't exist yet, we try to create it.
176                     if (serviceProvider == null) {
177                         mServiceMap.put(slotIndex, onCreateNetworkServiceProvider(slotIndex));
178                     }
179                     break;
180                 case NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER:
181                     // If the service provider doesn't exist yet, we try to create it.
182                     if (serviceProvider != null) {
183                         serviceProvider.close();
184                         mServiceMap.remove(slotIndex);
185                     }
186                     break;
187                 case NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS:
188                     for (int i = 0; i < mServiceMap.size(); i++) {
189                         serviceProvider = mServiceMap.get(i);
190                         if (serviceProvider != null) {
191                             serviceProvider.close();
192                         }
193                     }
194                     mServiceMap.clear();
195                     break;
196                 case NETWORK_SERVICE_GET_REGISTRATION_INFO:
197                     if (serviceProvider == null) break;
198                     int domainId = message.arg2;
199                     serviceProvider.requestNetworkRegistrationInfo(domainId,
200                             new NetworkServiceCallback(callback));
201 
202                     break;
203                 case NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE:
204                     if (serviceProvider == null) break;
205                     serviceProvider.registerForInfoChanged(callback);
206                     break;
207                 case NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE:
208                     if (serviceProvider == null) break;
209                     serviceProvider.unregisterForInfoChanged(callback);
210                     break;
211                 case NETWORK_SERVICE_INDICATION_NETWORK_INFO_CHANGED:
212                     if (serviceProvider == null) break;
213                     serviceProvider.notifyInfoChangedToCallbacks();
214                     break;
215                 default:
216                     break;
217             }
218         }
219     }
220 
221     /**
222      * Default constructor.
223      */
NetworkService()224     public NetworkService() {
225         mHandlerThread = new HandlerThread(TAG);
226         mHandlerThread.start();
227 
228         mHandler = new NetworkServiceHandler(mHandlerThread.getLooper());
229         log("network service created");
230     }
231 
232     /**
233      * Create the instance of {@link NetworkServiceProvider}. Network service provider must override
234      * this method to facilitate the creation of {@link NetworkServiceProvider} instances. The system
235      * will call this method after binding the network service for each active SIM slot id.
236      *
237      * This methead is guaranteed to be invoked in {@link NetworkService}'s internal handler thread
238      * whose looper can be retrieved with {@link Looper.myLooper()} when override this method.
239      *
240      * @param slotIndex SIM slot id the network service associated with.
241      * @return Network service object. Null if failed to create the provider (e.g. invalid slot
242      * index)
243      */
244     @Nullable
onCreateNetworkServiceProvider(int slotIndex)245     public abstract NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex);
246 
247     @Override
onBind(Intent intent)248     public IBinder onBind(Intent intent) {
249         if (intent == null || !SERVICE_INTERFACE.equals(intent.getAction())) {
250             loge("Unexpected intent " + intent);
251             return null;
252         }
253 
254         return mBinder;
255     }
256 
257     @Override
onUnbind(Intent intent)258     public boolean onUnbind(Intent intent) {
259         mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS, 0,
260                 0, null).sendToTarget();
261 
262         return false;
263     }
264 
265     /** @hide */
266     @Override
onDestroy()267     public void onDestroy() {
268         mHandlerThread.quit();
269         super.onDestroy();
270     }
271 
272     /**
273      * A wrapper around INetworkService that forwards calls to implementations of
274      * {@link NetworkService}.
275      */
276     private class INetworkServiceWrapper extends INetworkService.Stub {
277 
278         @Override
createNetworkServiceProvider(int slotIndex)279         public void createNetworkServiceProvider(int slotIndex) {
280             mHandler.obtainMessage(NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER, slotIndex,
281                     0, null).sendToTarget();
282         }
283 
284         @Override
removeNetworkServiceProvider(int slotIndex)285         public void removeNetworkServiceProvider(int slotIndex) {
286             mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER, slotIndex,
287                     0, null).sendToTarget();
288         }
289 
290         @Override
requestNetworkRegistrationInfo(int slotIndex, int domain, INetworkServiceCallback callback)291         public void requestNetworkRegistrationInfo(int slotIndex, int domain,
292                                                    INetworkServiceCallback callback) {
293             mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_INFO, slotIndex,
294                     domain, callback).sendToTarget();
295         }
296 
297         @Override
registerForNetworkRegistrationInfoChanged( int slotIndex, INetworkServiceCallback callback)298         public void registerForNetworkRegistrationInfoChanged(
299                 int slotIndex, INetworkServiceCallback callback) {
300             mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_INFO_CHANGE, slotIndex,
301                     0, callback).sendToTarget();
302         }
303 
304         @Override
unregisterForNetworkRegistrationInfoChanged( int slotIndex, INetworkServiceCallback callback)305         public void unregisterForNetworkRegistrationInfoChanged(
306                 int slotIndex, INetworkServiceCallback callback) {
307             mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_INFO_CHANGE, slotIndex,
308                     0, callback).sendToTarget();
309         }
310     }
311 
log(String s)312     private final void log(String s) {
313         Rlog.d(TAG, s);
314     }
315 
loge(String s)316     private final void loge(String s) {
317         Rlog.e(TAG, s);
318     }
319 }
320