Home | History | Annotate | Download | only in telephony
      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 
     88         public NetworkServiceProvider(int slotId) {
     89             mSlotId = slotId;
     90         }
     91 
     92         /**
     93          * @return SIM slot id the network service associated with.
     94          */
     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          */
    105         public void getNetworkRegistrationState(int domain, NetworkServiceCallback callback) {
    106             callback.onGetNetworkRegistrationStateComplete(
    107                     NetworkServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
    108         }
    109 
    110         public final void notifyNetworkRegistrationStateChanged() {
    111             mHandler.obtainMessage(NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED,
    112                     mSlotId, 0, null).sendToTarget();
    113         }
    114 
    115         private void registerForStateChanged(INetworkServiceCallback callback) {
    116             synchronized (mNetworkRegistrationStateChangedCallbacks) {
    117                 mNetworkRegistrationStateChangedCallbacks.add(callback);
    118             }
    119         }
    120 
    121         private void unregisterForStateChanged(INetworkServiceCallback callback) {
    122             synchronized (mNetworkRegistrationStateChangedCallbacks) {
    123                 mNetworkRegistrationStateChangedCallbacks.remove(callback);
    124             }
    125         }
    126 
    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
    141         protected void onDestroy() {
    142             mNetworkRegistrationStateChangedCallbacks.clear();
    143         }
    144     }
    145 
    146     private class NetworkServiceHandler extends Handler {
    147 
    148         NetworkServiceHandler(Looper looper) {
    149             super(looper);
    150         }
    151 
    152         @Override
    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      */
    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      */
    226     protected abstract NetworkServiceProvider createNetworkServiceProvider(int slotId);
    227 
    228     /** @hide */
    229     @Override
    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
    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
    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
    261         public void createNetworkServiceProvider(int slotId) {
    262             mHandler.obtainMessage(NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER, slotId,
    263                     0, null).sendToTarget();
    264         }
    265 
    266         @Override
    267         public void removeNetworkServiceProvider(int slotId) {
    268             mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER, slotId,
    269                     0, null).sendToTarget();
    270         }
    271 
    272         @Override
    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
    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
    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 
    294     private final void log(String s) {
    295         Rlog.d(TAG, s);
    296     }
    297 
    298     private final void loge(String s) {
    299         Rlog.e(TAG, s);
    300     }
    301 }
    302