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("Network service " + mComponentName + " for transport type " 186 + AccessNetworkConstants.transportTypeToString(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 logd("RemoteException " + exception); 206 } 207 } 208 209 @Override onServiceDisconnected(ComponentName name)210 public void onServiceDisconnected(ComponentName name) { 211 logd("service " + name + " for transport " 212 + AccessNetworkConstants.transportTypeToString(mTransportType) 213 + " is now disconnected."); 214 mTargetBindingPackageName = null; 215 } 216 } 217 218 private class NetworkRegStateCallback extends INetworkServiceCallback.Stub { 219 @Override onRequestNetworkRegistrationInfoComplete( int result, NetworkRegistrationInfo info)220 public void onRequestNetworkRegistrationInfoComplete( 221 int result, NetworkRegistrationInfo info) { 222 logd("onRequestNetworkRegistrationInfoComplete result: " 223 + result + ", info: " + info); 224 Message onCompleteMessage = mCallbackTable.remove(this); 225 if (onCompleteMessage != null) { 226 onCompleteMessage.arg1 = result; 227 onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, 228 new NetworkRegistrationInfo(info), null); 229 onCompleteMessage.sendToTarget(); 230 } else { 231 loge("onCompleteMessage is null"); 232 } 233 } 234 235 @Override onNetworkStateChanged()236 public void onNetworkStateChanged() { 237 logd("onNetworkStateChanged"); 238 mRegStateChangeRegistrants.notifyRegistrants(); 239 } 240 } 241 unbindService()242 private void unbindService() { 243 if (mINetworkService != null && mINetworkService.asBinder().isBinderAlive()) { 244 logd("unbinding service"); 245 // Remove the network availability updater and then unbind the service. 246 try { 247 mINetworkService.removeNetworkServiceProvider(mPhone.getPhoneId()); 248 } catch (RemoteException e) { 249 loge("Cannot remove data service provider. " + e); 250 } 251 } 252 253 if (mServiceConnection != null) { 254 mPhone.getContext().unbindService(mServiceConnection); 255 } 256 mINetworkService = null; 257 mServiceConnection = null; 258 mTargetBindingPackageName = null; 259 } 260 bindService(String packageName)261 private void bindService(String packageName) { 262 if (mPhone == null || !SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())) { 263 loge("can't bindService with invalid phone or phoneId."); 264 return; 265 } 266 267 if (TextUtils.isEmpty(packageName)) { 268 loge("Can't find the binding package"); 269 return; 270 } 271 272 Intent intent = null; 273 String className = getClassName(); 274 if (TextUtils.isEmpty(className)) { 275 intent = new Intent(NetworkService.SERVICE_INTERFACE); 276 intent.setPackage(packageName); 277 } else { 278 ComponentName cm = new ComponentName(packageName, className); 279 intent = new Intent(NetworkService.SERVICE_INTERFACE).setComponent(cm); 280 } 281 282 try { 283 // We bind this as a foreground service because it is operating directly on the SIM, 284 // and we do not want it subjected to power-savings restrictions while doing so. 285 logd("Trying to bind " + getPackageName() + " for transport " 286 + AccessNetworkConstants.transportTypeToString(mTransportType)); 287 mServiceConnection = new NetworkServiceConnection(); 288 if (!mPhone.getContext().bindService(intent, mServiceConnection, 289 Context.BIND_AUTO_CREATE)) { 290 loge("Cannot bind to the data service."); 291 return; 292 } 293 mTargetBindingPackageName = packageName; 294 } catch (SecurityException e) { 295 loge("bindService failed " + e); 296 } 297 } 298 rebindService()299 private void rebindService() { 300 String packageName = getPackageName(); 301 // Do nothing if no need to rebind. 302 if (SubscriptionManager.isValidPhoneId(mPhone.getPhoneId()) 303 && TextUtils.equals(packageName, mTargetBindingPackageName)) { 304 logd("Service " + packageName + " already bound or being bound."); 305 return; 306 } 307 308 unbindService(); 309 bindService(packageName); 310 } 311 getPackageName()312 private String getPackageName() { 313 String packageName; 314 int resourceId; 315 String carrierConfig; 316 317 switch (mTransportType) { 318 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 319 resourceId = com.android.internal.R.string.config_wwan_network_service_package; 320 carrierConfig = CarrierConfigManager 321 .KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING; 322 break; 323 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 324 resourceId = com.android.internal.R.string.config_wlan_network_service_package; 325 carrierConfig = CarrierConfigManager 326 .KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING; 327 break; 328 default: 329 throw new IllegalStateException("Transport type not WWAN or WLAN. type=" 330 + mTransportType); 331 } 332 333 // Read package name from resource overlay 334 packageName = mPhone.getContext().getResources().getString(resourceId); 335 336 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); 337 338 if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) { 339 // If carrier config overrides it, use the one from carrier config 340 packageName = b.getString(carrierConfig, packageName); 341 } 342 343 return packageName; 344 } 345 getClassName()346 private String getClassName() { 347 String className; 348 int resourceId; 349 String carrierConfig; 350 351 switch (mTransportType) { 352 case AccessNetworkConstants.TRANSPORT_TYPE_WWAN: 353 resourceId = com.android.internal.R.string.config_wwan_network_service_class; 354 carrierConfig = CarrierConfigManager 355 .KEY_CARRIER_NETWORK_SERVICE_WWAN_CLASS_OVERRIDE_STRING; 356 break; 357 case AccessNetworkConstants.TRANSPORT_TYPE_WLAN: 358 resourceId = com.android.internal.R.string.config_wlan_network_service_class; 359 carrierConfig = CarrierConfigManager 360 .KEY_CARRIER_NETWORK_SERVICE_WLAN_CLASS_OVERRIDE_STRING; 361 break; 362 default: 363 throw new IllegalStateException("Transport type not WWAN or WLAN. type=" 364 + mTransportType); 365 } 366 367 // Read class name from resource overlay 368 className = mPhone.getContext().getResources().getString(resourceId); 369 370 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); 371 372 if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) { 373 // If carrier config overrides it, use the one from carrier config 374 className = b.getString(carrierConfig, className); 375 } 376 377 return className; 378 } logd(String msg)379 private void logd(String msg) { 380 Rlog.d(mTag, msg); 381 } 382 loge(String msg)383 private void loge(String msg) { 384 Rlog.e(mTag, msg); 385 } 386 } 387