1 /* 2 * Copyright 2018 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 com.android.internal.telephony; 18 19 import android.content.BroadcastReceiver; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.ServiceConnection; 25 import android.content.pm.PackageManager; 26 import android.os.AsyncResult; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Message; 30 import android.os.PersistableBundle; 31 import android.os.RegistrantList; 32 import android.os.RemoteException; 33 import android.os.UserHandle; 34 import android.telephony.AccessNetworkConstants; 35 import android.telephony.AccessNetworkConstants.TransportType; 36 import android.telephony.CarrierConfigManager; 37 import android.telephony.INetworkService; 38 import android.telephony.INetworkServiceCallback; 39 import android.telephony.NetworkRegistrationInfo; 40 import android.telephony.NetworkService; 41 import android.telephony.SubscriptionManager; 42 import android.text.TextUtils; 43 44 import com.android.telephony.Rlog; 45 46 import java.util.Hashtable; 47 import java.util.Map; 48 49 /** 50 * Class that serves as the layer between NetworkService and ServiceStateTracker. It helps binding, 51 * sending request and registering for state change to NetworkService. 52 */ 53 public class NetworkRegistrationManager extends Handler { 54 private final String mTag; 55 56 private static final int EVENT_BIND_NETWORK_SERVICE = 1; 57 58 private final int mTransportType; 59 60 private final Phone mPhone; 61 62 private final CarrierConfigManager mCarrierConfigManager; 63 64 // Registrants who listens registration state change callback from this class. 65 private final RegistrantList mRegStateChangeRegistrants = new RegistrantList(); 66 67 private INetworkService mINetworkService; 68 69 private RegManagerDeathRecipient mDeathRecipient; 70 71 private String mTargetBindingPackageName; 72 73 private NetworkServiceConnection mServiceConnection; 74 75 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 76 @Override 77 public void onReceive(Context context, Intent intent) { 78 final String action = intent.getAction(); 79 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action) 80 && mPhone.getPhoneId() == intent.getIntExtra( 81 CarrierConfigManager.EXTRA_SLOT_INDEX, 0)) { 82 // We should wait for carrier config changed event because the target binding 83 // package name can come from the carrier config. Note that we still get this event 84 // even when SIM is absent. 85 logd("Carrier config changed. Try to bind network service."); 86 sendEmptyMessage(EVENT_BIND_NETWORK_SERVICE); 87 } 88 } 89 }; 90 NetworkRegistrationManager(@ransportType int transportType, Phone phone)91 public NetworkRegistrationManager(@TransportType int transportType, Phone phone) { 92 mTransportType = transportType; 93 mPhone = phone; 94 95 String tagSuffix = "-" + ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 96 ? "C" : "I") + "-" + mPhone.getPhoneId(); 97 mTag = "NRM" + tagSuffix; 98 99 mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService( 100 Context.CARRIER_CONFIG_SERVICE); 101 102 IntentFilter intentFilter = new IntentFilter(); 103 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 104 try { 105 Context contextAsUser = phone.getContext().createPackageContextAsUser( 106 phone.getContext().getPackageName(), 0, UserHandle.ALL); 107 contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter, 108 null /* broadcastPermission */, null); 109 } catch (PackageManager.NameNotFoundException e) { 110 loge("Package name not found: " + e.getMessage()); 111 } 112 PhoneConfigurationManager.registerForMultiSimConfigChange( 113 this, EVENT_BIND_NETWORK_SERVICE, null); 114 115 sendEmptyMessage(EVENT_BIND_NETWORK_SERVICE); 116 } 117 118 /** 119 * Handle message events 120 * 121 * @param msg The message to handle 122 */ 123 @Override handleMessage(Message msg)124 public void handleMessage(Message msg) { 125 switch (msg.what) { 126 case EVENT_BIND_NETWORK_SERVICE: 127 rebindService(); 128 break; 129 default: 130 loge("Unhandled event " + msg.what); 131 } 132 } 133 isServiceConnected()134 public boolean isServiceConnected() { 135 return (mINetworkService != null) && (mINetworkService.asBinder().isBinderAlive()); 136 } 137 unregisterForNetworkRegistrationInfoChanged(Handler h)138 public void unregisterForNetworkRegistrationInfoChanged(Handler h) { 139 mRegStateChangeRegistrants.remove(h); 140 } 141 registerForNetworkRegistrationInfoChanged(Handler h, int what, Object obj)142 public void registerForNetworkRegistrationInfoChanged(Handler h, int what, Object obj) { 143 logd("registerForNetworkRegistrationInfoChanged"); 144 mRegStateChangeRegistrants.addUnique(h, what, obj); 145 } 146 147 private final Map<NetworkRegStateCallback, Message> mCallbackTable = new Hashtable(); 148 requestNetworkRegistrationInfo(@etworkRegistrationInfo.Domain int domain, Message onCompleteMessage)149 public void requestNetworkRegistrationInfo(@NetworkRegistrationInfo.Domain int domain, 150 Message onCompleteMessage) { 151 if (onCompleteMessage == null) return; 152 153 if (!isServiceConnected()) { 154 loge("service not connected. Domain = " 155 + ((domain == NetworkRegistrationInfo.DOMAIN_CS) ? "CS" : "PS")); 156 onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, null, 157 new IllegalStateException("Service not connected.")); 158 onCompleteMessage.sendToTarget(); 159 return; 160 } 161 162 NetworkRegStateCallback callback = new NetworkRegStateCallback(); 163 try { 164 mCallbackTable.put(callback, onCompleteMessage); 165 mINetworkService.requestNetworkRegistrationInfo(mPhone.getPhoneId(), domain, callback); 166 } catch (RemoteException e) { 167 loge("requestNetworkRegistrationInfo RemoteException " + e); 168 mCallbackTable.remove(callback); 169 onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, null, e); 170 onCompleteMessage.sendToTarget(); 171 } 172 } 173 174 private class RegManagerDeathRecipient implements IBinder.DeathRecipient { 175 176 private final ComponentName mComponentName; 177 RegManagerDeathRecipient(ComponentName name)178 RegManagerDeathRecipient(ComponentName name) { 179 mComponentName = name; 180 } 181 182 @Override binderDied()183 public void binderDied() { 184 // TODO: try to restart the service. 185 logd("NetworkService(" + mComponentName + " transport type " 186 + mTransportType + ") died."); 187 } 188 } 189 190 private class NetworkServiceConnection implements ServiceConnection { 191 @Override onServiceConnected(ComponentName name, IBinder service)192 public void onServiceConnected(ComponentName name, IBinder service) { 193 logd("service " + name + " for transport " 194 + AccessNetworkConstants.transportTypeToString(mTransportType) 195 + " is now connected."); 196 mINetworkService = INetworkService.Stub.asInterface(service); 197 mDeathRecipient = new RegManagerDeathRecipient(name); 198 try { 199 service.linkToDeath(mDeathRecipient, 0); 200 mINetworkService.createNetworkServiceProvider(mPhone.getPhoneId()); 201 mINetworkService.registerForNetworkRegistrationInfoChanged(mPhone.getPhoneId(), 202 new NetworkRegStateCallback()); 203 } catch (RemoteException exception) { 204 // Remote exception means that the binder already died. 205 mDeathRecipient.binderDied(); 206 logd("RemoteException " + exception); 207 } 208 } 209 210 @Override onServiceDisconnected(ComponentName name)211 public void onServiceDisconnected(ComponentName name) { 212 logd("service " + name + " for transport " 213 + AccessNetworkConstants.transportTypeToString(mTransportType) 214 + " is now disconnected."); 215 mTargetBindingPackageName = null; 216 } 217 } 218 219 private class NetworkRegStateCallback extends INetworkServiceCallback.Stub { 220 @Override onRequestNetworkRegistrationInfoComplete( int result, NetworkRegistrationInfo info)221 public void onRequestNetworkRegistrationInfoComplete( 222 int result, NetworkRegistrationInfo info) { 223 logd("onRequestNetworkRegistrationInfoComplete result: " 224 + result + ", info: " + info); 225 Message onCompleteMessage = mCallbackTable.remove(this); 226 if (onCompleteMessage != null) { 227 onCompleteMessage.arg1 = result; 228 onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, 229 new NetworkRegistrationInfo(info), null); 230 onCompleteMessage.sendToTarget(); 231 } else { 232 loge("onCompleteMessage is null"); 233 } 234 } 235 236 @Override onNetworkStateChanged()237 public void onNetworkStateChanged() { 238 logd("onNetworkStateChanged"); 239 mRegStateChangeRegistrants.notifyRegistrants(); 240 } 241 } 242 unbindService()243 private void unbindService() { 244 if (mINetworkService != null && mINetworkService.asBinder().isBinderAlive()) { 245 logd("unbinding service"); 246 // Remove the network availability updater and then unbind the service. 247 try { 248 mINetworkService.removeNetworkServiceProvider(mPhone.getPhoneId()); 249 } catch (RemoteException e) { 250 loge("Cannot remove data service provider. " + e); 251 } 252 } 253 254 if (mServiceConnection != null) { 255 mPhone.getContext().unbindService(mServiceConnection); 256 } 257 mINetworkService = null; 258 mServiceConnection = null; 259 mTargetBindingPackageName = null; 260 } 261 bindService(String packageName)262 private void bindService(String packageName) { 263 if (mPhone == null || !SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())) { 264 loge("can't bindService with invalid phone or phoneId."); 265 return; 266 } 267 268 if (TextUtils.isEmpty(packageName)) { 269 loge("Can't find the binding package"); 270 return; 271 } 272 273 Intent intent = null; 274 String className = getClassName(); 275 if (TextUtils.isEmpty(className)) { 276 intent = new Intent(NetworkService.SERVICE_INTERFACE); 277 intent.setPackage(packageName); 278 } else { 279 ComponentName cm = new ComponentName(packageName, className); 280 intent = new Intent(NetworkService.SERVICE_INTERFACE).setComponent(cm); 281 } 282 283 try { 284 // We bind this as a foreground service because it is operating directly on the SIM, 285 // and we do not want it subjected to power-savings restrictions while doing so. 286 logd("Trying to bind " + getPackageName() + " for transport " 287 + AccessNetworkConstants.transportTypeToString(mTransportType)); 288 mServiceConnection = new NetworkServiceConnection(); 289 if (!mPhone.getContext().bindService(intent, mServiceConnection, 290 Context.BIND_AUTO_CREATE)) { 291 loge("Cannot bind to the data service."); 292 return; 293 } 294 mTargetBindingPackageName = packageName; 295 } catch (SecurityException e) { 296 loge("bindService failed " + e); 297 } 298 } 299 rebindService()300 private void rebindService() { 301 String packageName = getPackageName(); 302 // Do nothing if no need to rebind. 303 if (SubscriptionManager.isValidPhoneId(mPhone.getPhoneId()) 304 && TextUtils.equals(packageName, mTargetBindingPackageName)) { 305 logd("Service " + packageName + " already bound or being bound."); 306 return; 307 } 308 309 unbindService(); 310 bindService(packageName); 311 } 312 getPackageName()313 private String getPackageName() { 314 String packageName; 315 int resourceId; 316 String carrierConfig; 317 318 switch (mTransportType) { 319 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 320 resourceId = com.android.internal.R.string.config_wwan_network_service_package; 321 carrierConfig = CarrierConfigManager 322 .KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING; 323 break; 324 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 325 resourceId = com.android.internal.R.string.config_wlan_network_service_package; 326 carrierConfig = CarrierConfigManager 327 .KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING; 328 break; 329 default: 330 throw new IllegalStateException("Transport type not WWAN or WLAN. type=" 331 + mTransportType); 332 } 333 334 // Read package name from resource overlay 335 packageName = mPhone.getContext().getResources().getString(resourceId); 336 337 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); 338 339 if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) { 340 // If carrier config overrides it, use the one from carrier config 341 packageName = b.getString(carrierConfig, packageName); 342 } 343 344 return packageName; 345 } 346 getClassName()347 private String getClassName() { 348 String className; 349 int resourceId; 350 String carrierConfig; 351 352 switch (mTransportType) { 353 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 354 resourceId = com.android.internal.R.string.config_wwan_network_service_class; 355 carrierConfig = CarrierConfigManager 356 .KEY_CARRIER_NETWORK_SERVICE_WWAN_CLASS_OVERRIDE_STRING; 357 break; 358 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 359 resourceId = com.android.internal.R.string.config_wlan_network_service_class; 360 carrierConfig = CarrierConfigManager 361 .KEY_CARRIER_NETWORK_SERVICE_WLAN_CLASS_OVERRIDE_STRING; 362 break; 363 default: 364 throw new IllegalStateException("Transport type not WWAN or WLAN. type=" 365 + mTransportType); 366 } 367 368 // Read class name from resource overlay 369 className = mPhone.getContext().getResources().getString(resourceId); 370 371 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); 372 373 if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) { 374 // If carrier config overrides it, use the one from carrier config 375 className = b.getString(carrierConfig, className); 376 } 377 378 return className; 379 } logd(String msg)380 private void logd(String msg) { 381 Rlog.d(mTag, msg); 382 } 383 loge(String msg)384 private void loge(String msg) { 385 Rlog.e(mTag, msg); 386 } 387 } 388