1 /* 2 * Copyright (C) 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.ons; 18 19 import android.app.Service; 20 import android.compat.Compatibility; 21 import android.compat.annotation.ChangeId; 22 import android.compat.annotation.EnabledAfter; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.SharedPreferences; 28 import android.content.pm.PackageManager; 29 import android.os.Binder; 30 import android.os.Build; 31 import android.os.Handler; 32 import android.os.IBinder; 33 import android.os.Message; 34 import android.os.RemoteException; 35 import android.os.TelephonyServiceManager.ServiceRegisterer; 36 import android.telephony.AvailableNetworkInfo; 37 import android.telephony.SubscriptionInfo; 38 import android.telephony.SubscriptionManager; 39 import android.telephony.TelephonyFrameworkInitializer; 40 import android.telephony.TelephonyManager; 41 42 import com.android.internal.annotations.VisibleForTesting; 43 import com.android.internal.telephony.IOns; 44 import com.android.internal.telephony.ISetOpportunisticDataCallback; 45 import com.android.internal.telephony.IUpdateAvailableNetworksCallback; 46 import com.android.internal.telephony.TelephonyIntents; 47 import com.android.internal.telephony.TelephonyPermissions; 48 import com.android.telephony.Rlog; 49 50 import java.util.ArrayList; 51 import java.util.HashMap; 52 import java.util.List; 53 54 /** 55 * OpportunisticNetworkService implements ions. 56 * It scans network and matches the results with opportunistic subscriptions. 57 * Use the same to provide user opportunistic data in areas with corresponding networks 58 */ 59 public class OpportunisticNetworkService extends Service { 60 @VisibleForTesting protected Context mContext; 61 private TelephonyManager mTelephonyManager; 62 @VisibleForTesting protected SubscriptionManager mSubscriptionManager; 63 64 private final Object mLock = new Object(); 65 @VisibleForTesting protected boolean mIsEnabled; 66 @VisibleForTesting protected ONSProfileSelector mProfileSelector; 67 private SharedPreferences mSharedPref; 68 @VisibleForTesting protected HashMap<String, ONSConfigInput> mONSConfigInputHashMap; 69 70 private static final String TAG = "ONS"; 71 private static final String PREF_NAME = TAG; 72 private static final String PREF_ENABLED = "isEnabled"; 73 private static final String CARRIER_APP_CONFIG_NAME = "carrierApp"; 74 private static final String SYSTEM_APP_CONFIG_NAME = "systemApp"; 75 private static final boolean DBG = true; 76 /* message to indicate sim state update */ 77 private static final int MSG_SIM_STATE_CHANGE = 1; 78 79 /** 80 * To expand the error codes for {@link TelephonyManager#updateAvailableNetworks} and 81 * {@link TelephonyManager#setPreferredOpportunisticDataSubscription}. 82 */ 83 @ChangeId 84 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) 85 static final long CALLBACK_ON_MORE_ERROR_CODE_CHANGE = 130595455L; 86 87 /** 88 * Profile selection callback. Will be called once Profile selector decides on 89 * the opportunistic data profile. 90 */ 91 private ONSProfileSelector.ONSProfileSelectionCallback mProfileSelectionCallback = 92 new ONSProfileSelector.ONSProfileSelectionCallback() { 93 94 @Override 95 public void onProfileSelectionDone() { 96 logDebug("profile selection done"); 97 } 98 }; 99 100 /** Broadcast receiver to get SIM card state changed event */ 101 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 102 @Override 103 public void onReceive(Context context, Intent intent) { 104 mHandler.sendEmptyMessage(MSG_SIM_STATE_CHANGE); 105 } 106 }; 107 108 private Handler mHandler = new Handler() { 109 @Override 110 public void handleMessage(Message msg) { 111 switch (msg.what) { 112 case MSG_SIM_STATE_CHANGE: 113 synchronized (mLock) { 114 handleSimStateChange(); 115 } 116 break; 117 default: 118 log("invalid message"); 119 break; 120 } 121 } 122 }; 123 enforceModifyPhoneStatePermission(Context context)124 private static boolean enforceModifyPhoneStatePermission(Context context) { 125 if (context.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 126 == PackageManager.PERMISSION_GRANTED) { 127 return true; 128 } 129 130 return false; 131 } 132 133 @VisibleForTesting handleSimStateChange()134 protected void handleSimStateChange() { 135 logDebug("SIM state changed"); 136 ONSConfigInput carrierAppConfigInput = mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME); 137 if (carrierAppConfigInput == null) { 138 return; 139 } 140 List<SubscriptionInfo> subscriptionInfos = 141 mSubscriptionManager.getActiveSubscriptionInfoList(false); 142 if (subscriptionInfos == null) { 143 return; 144 } 145 146 logDebug("handleSimStateChange: subscriptionInfos - " + subscriptionInfos); 147 for (SubscriptionInfo subscriptionInfo : subscriptionInfos) { 148 if (subscriptionInfo.getSubscriptionId() == carrierAppConfigInput.getPrimarySub()) { 149 return; 150 } 151 } 152 153 logDebug("Carrier subscription is not available, removing entry"); 154 mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, null); 155 if (!mIsEnabled) { 156 return; 157 } 158 if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null) { 159 mProfileSelector.startProfileSelection( 160 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME).getAvailableNetworkInfos(), 161 mONSConfigInputHashMap.get( 162 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback()); 163 } 164 } 165 hasOpportunisticSubPrivilege(String callingPackage, int subId)166 private boolean hasOpportunisticSubPrivilege(String callingPackage, int subId) { 167 return mTelephonyManager.hasCarrierPrivileges(subId) 168 || mSubscriptionManager.canManageSubscription( 169 mProfileSelector.getOpprotunisticSubInfo(subId), callingPackage); 170 } 171 172 private final IOns.Stub mBinder = new IOns.Stub() { 173 /** 174 * Enable or disable Opportunistic Network service. 175 * 176 * This method should be called to enable or disable 177 * OpportunisticNetwork service on the device. 178 * 179 * <p> 180 * Requires Permission: 181 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} 182 * Or the calling app has carrier privileges. @see #hasCarrierPrivileges 183 * 184 * @param enable enable(True) or disable(False) 185 * @param callingPackage caller's package name 186 * @return returns true if successfully set. 187 */ 188 @Override 189 public boolean setEnable(boolean enable, String callingPackage) { 190 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( 191 mContext, mSubscriptionManager.getDefaultSubscriptionId(), "setEnable"); 192 log("setEnable: " + enable); 193 194 final long identity = Binder.clearCallingIdentity(); 195 try { 196 enableOpportunisticNetwork(enable); 197 } finally { 198 Binder.restoreCallingIdentity(identity); 199 } 200 201 return true; 202 } 203 204 /** 205 * is Opportunistic Network service enabled 206 * 207 * This method should be called to determine if the Opportunistic Network service 208 * is enabled 209 * 210 * <p> 211 * Requires Permission: 212 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} 213 * Or the calling app has carrier privileges. @see #hasCarrierPrivileges 214 * 215 * @param callingPackage caller's package name 216 */ 217 @Override 218 public boolean isEnabled(String callingPackage) { 219 TelephonyPermissions 220 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( 221 mContext, mSubscriptionManager.getDefaultSubscriptionId(), "isEnabled"); 222 return mIsEnabled; 223 } 224 225 /** 226 * Set preferred opportunistic data. 227 * 228 * <p>Requires that the calling app has carrier privileges on both primary and 229 * secondary subscriptions (see 230 * {@link #hasCarrierPrivileges}), or has permission 231 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. 232 * @param subId which opportunistic subscription 233 * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data. 234 * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference 235 * @param needValidation whether validation is needed before switch happens. 236 * @param callback callback upon request completion. 237 * @param callingPackage caller's package name 238 * 239 */ 240 public void setPreferredDataSubscriptionId(int subId, boolean needValidation, 241 ISetOpportunisticDataCallback callbackStub, String callingPackage) { 242 logDebug("setPreferredDataSubscriptionId subId:" + subId + "callingPackage: " + callingPackage); 243 if (!enforceModifyPhoneStatePermission(mContext)) { 244 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, 245 mSubscriptionManager.getDefaultSubscriptionId(), "setPreferredDataSubscriptionId"); 246 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 247 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, 248 "setPreferredDataSubscriptionId"); 249 } 250 } else { 251 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) != null) { 252 sendSetOpptCallbackHelper(callbackStub, 253 TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED); 254 return; 255 } 256 } 257 258 259 final long identity = Binder.clearCallingIdentity(); 260 try { 261 mProfileSelector.selectProfileForData(subId, needValidation, callbackStub); 262 } finally { 263 Binder.restoreCallingIdentity(identity); 264 } 265 } 266 267 /** 268 * Get preferred default data sub Id 269 * 270 * <p>Requires that the calling app has carrier privileges 271 * (see {@link #hasCarrierPrivileges}),or has either 272 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or. 273 * {@link android.Manifest.permission#READ_PHONE_STATE} permission. 274 * @return subId preferred opportunistic subscription id or 275 * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred 276 * subscription id 277 * 278 */ 279 @Override 280 public int getPreferredDataSubscriptionId(String callingPackage, 281 String callingFeatureId) { 282 TelephonyPermissions 283 .checkCallingOrSelfReadPhoneState(mContext, 284 mSubscriptionManager.getDefaultSubscriptionId(), 285 callingPackage, callingFeatureId, "getPreferredDataSubscriptionId"); 286 final long identity = Binder.clearCallingIdentity(); 287 try { 288 return mProfileSelector.getPreferredDataSubscriptionId(); 289 } finally { 290 Binder.restoreCallingIdentity(identity); 291 } 292 } 293 294 /** 295 * Update availability of a list of networks in the current location. 296 * 297 * This api should be called if the caller is aware of the availability of a network 298 * at the current location. This information will be used by OpportunisticNetwork service 299 * to decide to attach to the network. If an empty list is passed, 300 * it is assumed that no network is available. 301 * @param availableNetworks is a list of available network information. 302 * @param callback callback upon request completion. 303 * @param callingPackage caller's package name 304 * <p> 305 * <p>Requires that the calling app has carrier privileges on both primary and 306 * secondary subscriptions (see 307 * {@link #hasCarrierPrivileges}), or has permission 308 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. 309 * 310 */ 311 public void updateAvailableNetworks(List<AvailableNetworkInfo> availableNetworks, 312 IUpdateAvailableNetworksCallback callbackStub, String callingPackage) { 313 logDebug("updateAvailableNetworks: " + availableNetworks); 314 /* check if system app */ 315 if (enforceModifyPhoneStatePermission(mContext)) { 316 handleSystemAppAvailableNetworks( 317 (ArrayList<AvailableNetworkInfo>) availableNetworks, callbackStub); 318 } else { 319 /* check if the app has primary carrier permission */ 320 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, 321 mSubscriptionManager.getDefaultSubscriptionId(), "updateAvailableNetworks"); 322 handleCarrierAppAvailableNetworks( 323 (ArrayList<AvailableNetworkInfo>) availableNetworks, callbackStub, 324 callingPackage); 325 } 326 } 327 }; 328 329 @Override onBind(Intent intent)330 public IBinder onBind(Intent intent) { 331 return mBinder; 332 } 333 334 @Override onCreate()335 public void onCreate() { 336 initialize(getBaseContext()); 337 338 /* register the service */ 339 ServiceRegisterer opportunisticNetworkServiceRegisterer = TelephonyFrameworkInitializer 340 .getTelephonyServiceManager() 341 .getOpportunisticNetworkServiceRegisterer(); 342 if (opportunisticNetworkServiceRegisterer.get() == null) { 343 opportunisticNetworkServiceRegisterer.register(mBinder); 344 } 345 } 346 347 @Override onStartCommand(Intent intent, int flags, int startId)348 public int onStartCommand(Intent intent, int flags, int startId) { 349 if (intent == null) { 350 return START_STICKY; 351 } 352 353 String action = intent.getAction(); 354 if (action == null) { 355 return START_STICKY; 356 } 357 358 switch (action) { 359 case ONSProfileSelector.ACTION_SUB_SWITCH: { 360 if (mProfileSelector != null) { 361 mProfileSelector.onSubSwitchComplete(intent); 362 } 363 break; 364 } 365 } 366 367 return START_STICKY; 368 } 369 370 @Override onDestroy()371 public void onDestroy() { 372 super.onDestroy(); 373 log("Destroyed Successfully..."); 374 375 } 376 377 /** 378 * initialize ONS and register as service. 379 * Read persistent state to update enable state 380 * Start sub components if already enabled. 381 * @param context context instance 382 */ 383 @VisibleForTesting initialize(Context context)384 protected void initialize(Context context) { 385 mContext = context; 386 mTelephonyManager = TelephonyManager.from(mContext); 387 mProfileSelector = new ONSProfileSelector(mContext, mProfileSelectionCallback); 388 mSharedPref = mContext.createDeviceProtectedStorageContext().getSharedPreferences( 389 PREF_NAME, Context.MODE_PRIVATE); 390 mSubscriptionManager = (SubscriptionManager) mContext.getSystemService( 391 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 392 mONSConfigInputHashMap = new HashMap<String, ONSConfigInput>(); 393 mContext.registerReceiver(mBroadcastReceiver, 394 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 395 enableOpportunisticNetwork(getPersistentEnableState()); 396 } 397 handleCarrierAppAvailableNetworks( ArrayList<AvailableNetworkInfo> availableNetworks, IUpdateAvailableNetworksCallback callbackStub, String callingPackage)398 private void handleCarrierAppAvailableNetworks( 399 ArrayList<AvailableNetworkInfo> availableNetworks, 400 IUpdateAvailableNetworksCallback callbackStub, String callingPackage) { 401 if ((availableNetworks != null) && (availableNetworks.size() > 0)) { 402 /* carrier apps should report only subscription */ 403 if (availableNetworks.size() > 1) { 404 log("Carrier app should not pass more than one subscription"); 405 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 406 sendUpdateNetworksCallbackHelper(callbackStub, 407 TelephonyManager 408 .UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED); 409 } else { 410 sendUpdateNetworksCallbackHelper(callbackStub, 411 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS); 412 } 413 return; 414 } 415 416 if (!mProfileSelector.hasOpprotunisticSub(availableNetworks)) { 417 log("No opportunistic subscriptions received"); 418 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 419 sendUpdateNetworksCallbackHelper(callbackStub, 420 TelephonyManager 421 .UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE); 422 } else { 423 sendUpdateNetworksCallbackHelper(callbackStub, 424 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS); 425 } 426 return; 427 } 428 429 for (AvailableNetworkInfo availableNetworkInfo : availableNetworks) { 430 final long identity = Binder.clearCallingIdentity(); 431 boolean isActiveSubId = false; 432 try { 433 isActiveSubId = 434 mSubscriptionManager.isActiveSubId(availableNetworkInfo.getSubId()); 435 } finally { 436 Binder.restoreCallingIdentity(identity); 437 } 438 if (isActiveSubId) { 439 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, 440 availableNetworkInfo.getSubId(), "updateAvailableNetworks"); 441 } else { 442 /* check if the app has opportunistic carrier permission */ 443 if (!hasOpportunisticSubPrivilege(callingPackage, 444 availableNetworkInfo.getSubId())) { 445 log("No carrier privilege for opportunistic subscription"); 446 sendUpdateNetworksCallbackHelper(callbackStub, 447 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE); 448 return; 449 } 450 } 451 } 452 453 final long identity = Binder.clearCallingIdentity(); 454 try { 455 ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworks, callbackStub); 456 SubscriptionInfo subscriptionInfo = mSubscriptionManager.getDefaultVoiceSubscriptionInfo(); 457 if (subscriptionInfo != null) { 458 onsConfigInput.setPrimarySub(subscriptionInfo.getSubscriptionId()); 459 onsConfigInput.setPreferredDataSub(availableNetworks.get(0).getSubId()); 460 mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, onsConfigInput); 461 } 462 /* standalone opportunistic subscription should be handled in priority. */ 463 if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null) { 464 if (mProfileSelector.containStandaloneOppSubs(mONSConfigInputHashMap.get( 465 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkInfos())) { 466 log("standalone opportunistic subscription is using."); 467 return; 468 } 469 } 470 471 if (mIsEnabled) { 472 /* if carrier is reporting availability, then it takes higher priority. */ 473 mProfileSelector.startProfileSelection(availableNetworks, callbackStub); 474 } else { 475 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 476 sendUpdateNetworksCallbackHelper(callbackStub, 477 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED); 478 } else { 479 sendUpdateNetworksCallbackHelper(callbackStub, 480 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED); 481 } 482 } 483 } finally { 484 Binder.restoreCallingIdentity(identity); 485 } 486 } else { 487 final long identity = Binder.clearCallingIdentity(); 488 try { 489 mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, null); 490 if (!mIsEnabled) { 491 sendUpdateNetworksCallbackHelper(callbackStub, 492 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 493 return; 494 } 495 /* if carrier is reporting unavailability, then decide whether to start 496 system app request or not. */ 497 if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null) { 498 sendUpdateNetworksCallbackHelper(callbackStub, 499 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 500 mProfileSelector.startProfileSelection( 501 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) 502 .getAvailableNetworkInfos(), 503 mONSConfigInputHashMap.get( 504 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback()); 505 } else { 506 mProfileSelector.stopProfileSelection(callbackStub); 507 } 508 } finally { 509 Binder.restoreCallingIdentity(identity); 510 } 511 } 512 } 513 sendUpdateNetworksCallbackHelper(IUpdateAvailableNetworksCallback callback, int result)514 private void sendUpdateNetworksCallbackHelper(IUpdateAvailableNetworksCallback callback, int result) { 515 if (callback == null) return; 516 try { 517 callback.onComplete(result); 518 } catch (RemoteException exception) { 519 log("RemoteException " + exception); 520 } 521 } 522 sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result)523 private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) { 524 if (callback == null) return; 525 try { 526 callback.onComplete(result); 527 } catch (RemoteException exception) { 528 log("RemoteException " + exception); 529 } 530 } 531 handleSystemAppAvailableNetworks( ArrayList<AvailableNetworkInfo> availableNetworks, IUpdateAvailableNetworksCallback callbackStub)532 private void handleSystemAppAvailableNetworks( 533 ArrayList<AvailableNetworkInfo> availableNetworks, 534 IUpdateAvailableNetworksCallback callbackStub) { 535 final long identity = Binder.clearCallingIdentity(); 536 try { 537 if ((availableNetworks != null) && (availableNetworks.size() > 0)) { 538 /* all subscriptions should be opportunistic subscriptions */ 539 if (!mProfileSelector.hasOpprotunisticSub(availableNetworks)) { 540 log("No opportunistic subscriptions received"); 541 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 542 sendUpdateNetworksCallbackHelper(callbackStub, 543 TelephonyManager 544 .UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE); 545 } else { 546 sendUpdateNetworksCallbackHelper(callbackStub, 547 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS); 548 } 549 return; 550 } 551 mONSConfigInputHashMap.put(SYSTEM_APP_CONFIG_NAME, 552 new ONSConfigInput(availableNetworks, callbackStub)); 553 /* reporting availability. proceed if carrier app has not requested any, but 554 standalone opportunistic subscription should be handled in priority. */ 555 if (mIsEnabled) { 556 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) == null 557 || mProfileSelector.containStandaloneOppSubs(availableNetworks)) { 558 mProfileSelector.startProfileSelection(availableNetworks, callbackStub); 559 } 560 } else { 561 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 562 sendUpdateNetworksCallbackHelper(callbackStub, 563 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED); 564 } else { 565 sendUpdateNetworksCallbackHelper(callbackStub, 566 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED); 567 } 568 } 569 } else { 570 if (!mIsEnabled) { 571 mONSConfigInputHashMap.put(SYSTEM_APP_CONFIG_NAME, null); 572 sendUpdateNetworksCallbackHelper(callbackStub, 573 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 574 return; 575 } 576 /* if system is reporting unavailability, then decide whether to start 577 carrier app request or not. */ 578 mONSConfigInputHashMap.put(SYSTEM_APP_CONFIG_NAME, null); 579 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) == null) { 580 mProfileSelector.stopProfileSelection(callbackStub); 581 } else { 582 sendUpdateNetworksCallbackHelper(callbackStub, 583 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 584 log("Try to start carrier app request"); 585 mProfileSelector.startProfileSelection( 586 mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) 587 .getAvailableNetworkInfos(), 588 mONSConfigInputHashMap.get( 589 CARRIER_APP_CONFIG_NAME).getAvailableNetworkCallback()); 590 } 591 } 592 } finally { 593 Binder.restoreCallingIdentity(identity); 594 } 595 } 596 getPersistentEnableState()597 private boolean getPersistentEnableState() { 598 return mSharedPref.getBoolean(PREF_ENABLED, true); 599 } 600 updateEnableState(boolean enable)601 private void updateEnableState(boolean enable) { 602 mIsEnabled = enable; 603 mSharedPref.edit().putBoolean(PREF_ENABLED, mIsEnabled).apply(); 604 } 605 606 /** 607 * update the enable state 608 * start profile selection if enabled. 609 * @param enable enable(true) or disable(false) 610 */ enableOpportunisticNetwork(boolean enable)611 private void enableOpportunisticNetwork(boolean enable) { 612 synchronized (mLock) { 613 if (mIsEnabled != enable) { 614 updateEnableState(enable); 615 if (!mIsEnabled) { 616 mProfileSelector.stopProfileSelection(null); 617 } else { 618 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) != null && 619 mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) 620 .getAvailableNetworkInfos() != null) { 621 mProfileSelector.startProfileSelection( 622 mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) 623 .getAvailableNetworkInfos(), 624 mONSConfigInputHashMap.get( 625 CARRIER_APP_CONFIG_NAME).getAvailableNetworkCallback()); 626 } else if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null && 627 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) 628 .getAvailableNetworkInfos() != null) { 629 mProfileSelector.startProfileSelection( 630 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) 631 .getAvailableNetworkInfos(), 632 mONSConfigInputHashMap.get( 633 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback()); 634 } 635 } 636 } 637 } 638 logDebug("service is enable state " + mIsEnabled); 639 } 640 log(String msg)641 private void log(String msg) { 642 Rlog.d(TAG, msg); 643 } 644 logDebug(String msg)645 private void logDebug(String msg) { 646 if (DBG) Rlog.d(TAG, msg); 647 } 648 } 649