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