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