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 static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.app.Service; 24 import android.app.compat.CompatChanges; 25 import android.compat.Compatibility; 26 import android.compat.annotation.ChangeId; 27 import android.compat.annotation.EnabledAfter; 28 import android.content.BroadcastReceiver; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.IntentFilter; 32 import android.content.SharedPreferences; 33 import android.content.pm.PackageManager; 34 import android.os.Binder; 35 import android.os.Build; 36 import android.os.Handler; 37 import android.os.IBinder; 38 import android.os.Looper; 39 import android.os.Message; 40 import android.os.RemoteException; 41 import android.os.SystemProperties; 42 import android.os.TelephonyServiceManager.ServiceRegisterer; 43 import android.os.UserManager; 44 import android.telephony.AvailableNetworkInfo; 45 import android.telephony.CarrierConfigManager; 46 import android.telephony.SubscriptionInfo; 47 import android.telephony.SubscriptionManager; 48 import android.telephony.TelephonyFrameworkInitializer; 49 import android.telephony.TelephonyManager; 50 51 import com.android.internal.annotations.VisibleForTesting; 52 import com.android.internal.telephony.IOns; 53 import com.android.internal.telephony.ISetOpportunisticDataCallback; 54 import com.android.internal.telephony.IUpdateAvailableNetworksCallback; 55 import com.android.internal.telephony.TelephonyIntents; 56 import com.android.internal.telephony.TelephonyPermissions; 57 import com.android.internal.telephony.flags.Flags; 58 import com.android.telephony.Rlog; 59 60 import java.util.ArrayList; 61 import java.util.HashMap; 62 import java.util.List; 63 64 /** 65 * OpportunisticNetworkService implements ions. 66 * It scans network and matches the results with opportunistic subscriptions. 67 * Use the same to provide user opportunistic data in areas with corresponding networks 68 */ 69 public class OpportunisticNetworkService extends Service { 70 @VisibleForTesting protected Context mContext; 71 private TelephonyManager mTelephonyManager; 72 @VisibleForTesting protected PackageManager mPackageManager; 73 @VisibleForTesting protected SubscriptionManager mSubscriptionManager; 74 @VisibleForTesting protected ONSProfileActivator mONSProfileActivator; 75 private ONSStats mONSStats; 76 private Handler mHandler = null; 77 78 private final Object mLock = new Object(); 79 @VisibleForTesting protected boolean mIsEnabled; 80 @VisibleForTesting protected ONSProfileSelector mProfileSelector; 81 private SharedPreferences mSharedPref; 82 @VisibleForTesting protected HashMap<String, ONSConfigInput> mONSConfigInputHashMap; 83 private int mVendorApiLevel; 84 85 private static final String TAG = "ONS"; 86 private static final String PREF_NAME = TAG; 87 private static final String PREF_ENABLED = "isEnabled"; 88 private static final String CARRIER_APP_CONFIG_NAME = "carrierApp"; 89 private static final String SYSTEM_APP_CONFIG_NAME = "systemApp"; 90 private static final boolean DBG = true; 91 /* message to indicate sim state update */ 92 private static final int MSG_SIM_STATE_CHANGE = 1; 93 @VisibleForTesting protected CarrierConfigManager mCarrierConfigManager; 94 @VisibleForTesting protected UserManager mUserManager; 95 96 /** 97 * To expand the error codes for {@link TelephonyManager#updateAvailableNetworks} and 98 * {@link TelephonyManager#setPreferredOpportunisticDataSubscription}. 99 */ 100 @ChangeId 101 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) 102 static final long CALLBACK_ON_MORE_ERROR_CODE_CHANGE = 130595455L; 103 104 /** 105 * Profile selection callback. Will be called once Profile selector decides on 106 * the opportunistic data profile. 107 */ 108 private ONSProfileSelector.ONSProfileSelectionCallback mProfileSelectionCallback = 109 new ONSProfileSelector.ONSProfileSelectionCallback() { 110 111 @Override 112 public void onProfileSelectionDone() { 113 logDebug("profile selection done"); 114 } 115 }; 116 117 /** Broadcast receiver to get SIM card state changed event */ 118 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 119 @Override 120 public void onReceive(Context context, Intent intent) { 121 mHandler.sendEmptyMessage(MSG_SIM_STATE_CHANGE); 122 } 123 }; 124 createMsgHandler()125 private void createMsgHandler() { 126 mHandler = new Handler(Looper.myLooper()) { 127 @Override 128 public void handleMessage(Message msg) { 129 switch (msg.what) { 130 case MSG_SIM_STATE_CHANGE: 131 synchronized (mLock) { 132 handleSimStateChange(); 133 } 134 break; 135 default: 136 log("invalid message"); 137 break; 138 } 139 } 140 }; 141 } 142 startWorkerThreadAndInit()143 private void startWorkerThreadAndInit() { 144 Thread thread = new Thread() { 145 @Override 146 public void run() { 147 super.run(); 148 Looper.prepare(); 149 Looper looper = Looper.myLooper(); 150 initialize(getBaseContext()); 151 synchronized (this) { 152 this.notifyAll(); 153 } 154 looper.loop(); 155 } 156 }; 157 158 thread.start(); 159 synchronized (thread) { 160 try { 161 thread.wait(); 162 } catch (Exception e) { 163 log(e.getLocalizedMessage()); 164 } 165 } 166 } 167 enforceModifyPhoneStatePermission(Context context)168 private static boolean enforceModifyPhoneStatePermission(Context context) { 169 if (context.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 170 == PackageManager.PERMISSION_GRANTED) { 171 return true; 172 } 173 174 return false; 175 } 176 177 @VisibleForTesting handleSimStateChange()178 protected void handleSimStateChange() { 179 logDebug("SIM state changed"); 180 181 ONSConfigInput carrierAppConfigInput = mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME); 182 if (carrierAppConfigInput == null) { 183 return; 184 } 185 List<SubscriptionInfo> subscriptionInfos = 186 mSubscriptionManager.getActiveSubscriptionInfoList(false); 187 if (subscriptionInfos == null) { 188 return; 189 } 190 191 logDebug("handleSimStateChange: subscriptionInfos - " + subscriptionInfos); 192 for (SubscriptionInfo subscriptionInfo : subscriptionInfos) { 193 if (subscriptionInfo.getSubscriptionId() == carrierAppConfigInput.getPrimarySub()) { 194 return; 195 } 196 } 197 198 logDebug("Carrier subscription is not available, removing entry"); 199 mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, null); 200 if (!mIsEnabled) { 201 return; 202 } 203 if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null) { 204 mProfileSelector.startProfileSelection( 205 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME).getAvailableNetworkInfos(), 206 mONSConfigInputHashMap.get( 207 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback()); 208 } 209 } 210 hasOpportunisticSubPrivilege(String callingPackage, int subId)211 private boolean hasOpportunisticSubPrivilege(String callingPackage, int subId) { 212 return mTelephonyManager.hasCarrierPrivileges(subId) 213 || mSubscriptionManager.canManageSubscription( 214 mProfileSelector.getOpprotunisticSubInfo(subId), callingPackage); 215 } 216 217 private final IOns.Stub mBinder = new IOns.Stub() { 218 /** 219 * Enable or disable Opportunistic Network service. 220 * 221 * This method should be called to enable or disable 222 * OpportunisticNetwork service on the device. 223 * 224 * <p> 225 * Requires Permission: 226 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} 227 * Or the calling app has carrier privileges. @see #hasCarrierPrivileges 228 * 229 * @param enable enable(True) or disable(False) 230 * @param callingPackage caller's package name 231 * @return returns true if successfully set. 232 */ 233 @Override 234 public boolean setEnable(boolean enable, String callingPackage) { 235 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege( 236 mContext, mSubscriptionManager.getDefaultSubscriptionId(), "setEnable"); 237 238 enforceTelephonyFeatureWithException(callingPackage, 239 PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "setEnable"); 240 241 log("setEnable: " + enable); 242 243 final long identity = Binder.clearCallingIdentity(); 244 try { 245 enableOpportunisticNetwork(enable); 246 } finally { 247 Binder.restoreCallingIdentity(identity); 248 } 249 250 return true; 251 } 252 253 /** 254 * is Opportunistic Network service enabled 255 * 256 * This method should be called to determine if the Opportunistic Network service 257 * is enabled 258 * 259 * <p> 260 * Requires Permission: 261 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} 262 * Or the calling app has carrier privileges. @see #hasCarrierPrivileges 263 * 264 * @param callingPackage caller's package name 265 */ 266 @Override 267 public boolean isEnabled(String callingPackage) { 268 TelephonyPermissions 269 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege( 270 mContext, mSubscriptionManager.getDefaultSubscriptionId(), "isEnabled"); 271 272 enforceTelephonyFeatureWithException(callingPackage, 273 PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "isEnabled"); 274 275 return mIsEnabled; 276 } 277 278 /** 279 * Set preferred opportunistic data. 280 * 281 * <p>Requires that the calling app has carrier privileges on both primary and 282 * secondary subscriptions (see 283 * {@link #hasCarrierPrivileges}), or has permission 284 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. 285 * @param subId which opportunistic subscription 286 * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data. 287 * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference 288 * @param needValidation whether validation is needed before switch happens. 289 * @param callback callback upon request completion. 290 * @param callingPackage caller's package name 291 * 292 */ 293 public void setPreferredDataSubscriptionId(int subId, boolean needValidation, 294 ISetOpportunisticDataCallback callbackStub, String callingPackage) { 295 logDebug("setPreferredDataSubscriptionId subId:" + subId 296 + " callingPackage:" + callingPackage); 297 if (!enforceModifyPhoneStatePermission(mContext)) { 298 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, 299 mSubscriptionManager.getDefaultSubscriptionId(), "setPreferredDataSubscriptionId"); 300 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 301 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, subId, 302 "setPreferredDataSubscriptionId"); 303 } 304 } else { 305 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) != null) { 306 sendSetOpptCallbackHelper(callbackStub, 307 TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED); 308 return; 309 } 310 } 311 312 enforceTelephonyFeatureWithException(callingPackage, 313 PackageManager.FEATURE_TELEPHONY_DATA, "setPreferredDataSubscriptionId"); 314 315 final long identity = Binder.clearCallingIdentity(); 316 try { 317 mProfileSelector.selectProfileForData(subId, needValidation, callbackStub); 318 } finally { 319 Binder.restoreCallingIdentity(identity); 320 } 321 } 322 323 /** 324 * Get preferred default data sub Id 325 * 326 * <p>Requires that the calling app has carrier privileges 327 * (see {@link #hasCarrierPrivileges}),or has either 328 * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or. 329 * {@link android.Manifest.permission#READ_PHONE_STATE} permission. 330 * @return subId preferred opportunistic subscription id or 331 * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred 332 * subscription id 333 * 334 */ 335 @Override 336 public int getPreferredDataSubscriptionId(String callingPackage, 337 String callingFeatureId) { 338 if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub( 339 mContext, 340 Binder.getCallingPid(), 341 Binder.getCallingUid(), 342 callingPackage, 343 callingFeatureId, 344 "getPreferredDataSubscriptionId")) { 345 throw new SecurityException( 346 "getPreferredDataSubscriptionId requires READ_PHONE_STATE," 347 + " READ_PRIVILEGED_PHONE_STATE, or carrier privileges on" 348 + " any active subscription."); 349 } 350 351 enforceTelephonyFeatureWithException(callingPackage, 352 PackageManager.FEATURE_TELEPHONY_DATA, "getPreferredDataSubscriptionId"); 353 354 final long identity = Binder.clearCallingIdentity(); 355 try { 356 return mProfileSelector.getPreferredDataSubscriptionId(); 357 } finally { 358 Binder.restoreCallingIdentity(identity); 359 } 360 } 361 362 /** 363 * Update availability of a list of networks in the current location. 364 * 365 * This api should be called if the caller is aware of the availability of a network 366 * at the current location. This information will be used by OpportunisticNetwork service 367 * to decide to attach to the network. If an empty list is passed, 368 * it is assumed that no network is available. 369 * @param availableNetworks is a list of available network information. 370 * @param callback callback upon request completion. 371 * @param callingPackage caller's package name 372 * <p> 373 * <p>Requires that the calling app has carrier privileges on both primary and 374 * secondary subscriptions (see 375 * {@link #hasCarrierPrivileges}), or has permission 376 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. 377 * 378 */ 379 public void updateAvailableNetworks(List<AvailableNetworkInfo> availableNetworks, 380 IUpdateAvailableNetworksCallback callbackStub, String callingPackage) { 381 logDebug("updateAvailableNetworks: " + availableNetworks); 382 /* check if system app */ 383 if (enforceModifyPhoneStatePermission(mContext)) { 384 385 enforceTelephonyFeatureWithException(callingPackage, 386 PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "updateAvailableNetworks"); 387 388 handleSystemAppAvailableNetworks( 389 (ArrayList<AvailableNetworkInfo>) availableNetworks, callbackStub); 390 } else { 391 /* check if the app has primary carrier permission */ 392 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, 393 mSubscriptionManager.getDefaultSubscriptionId(), "updateAvailableNetworks"); 394 395 enforceTelephonyFeatureWithException(callingPackage, 396 PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "updateAvailableNetworks"); 397 398 handleCarrierAppAvailableNetworks( 399 (ArrayList<AvailableNetworkInfo>) availableNetworks, callbackStub, 400 callingPackage); 401 } 402 } 403 }; 404 405 @Override onBind(Intent intent)406 public IBinder onBind(Intent intent) { 407 return mBinder; 408 } 409 410 @Override onCreate()411 public void onCreate() { 412 startWorkerThreadAndInit(); 413 414 /* register the service */ 415 ServiceRegisterer opportunisticNetworkServiceRegisterer = TelephonyFrameworkInitializer 416 .getTelephonyServiceManager() 417 .getOpportunisticNetworkServiceRegisterer(); 418 if (opportunisticNetworkServiceRegisterer.get() == null) { 419 opportunisticNetworkServiceRegisterer.register(mBinder); 420 } 421 } 422 423 @Override onStartCommand(Intent intent, int flags, int startId)424 public int onStartCommand(Intent intent, int flags, int startId) { 425 mHandler.post(new Runnable() { 426 427 private Intent mIntent = null; 428 Runnable setIntent(Intent intent) { 429 mIntent = intent; 430 return this; 431 } 432 433 @Override 434 public void run() { 435 if (mIntent == null) { 436 return; 437 } 438 439 String action = mIntent.getAction(); 440 if (action == null) { 441 return; 442 } 443 444 switch (action) { 445 case ONSProfileSelector.ACTION_SUB_SWITCH: { 446 if (mProfileSelector != null) { 447 mProfileSelector.onSubSwitchComplete(mIntent); 448 } 449 } 450 break; 451 452 case ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD: { 453 mONSProfileActivator.getONSProfileDownloader().onCallbackIntentReceived( 454 mIntent.getParcelableExtra(Intent.EXTRA_INTENT), 455 mIntent.getIntExtra(ONSProfileResultReceiver.EXTRA_RESULT_CODE, 0) 456 ); 457 } 458 break; 459 460 case ONSProfileConfigurator.ACTION_ONS_ESIM_CONFIG: { 461 mONSProfileActivator.getONSProfileConfigurator().onCallbackIntentReceived( 462 mIntent.getParcelableExtra(Intent.EXTRA_INTENT), 463 mIntent.getIntExtra(ONSProfileResultReceiver.EXTRA_RESULT_CODE, 0) 464 ); 465 } 466 break; 467 } 468 } 469 }.setIntent(intent)); 470 471 return START_STICKY; 472 } 473 474 @Override onDestroy()475 public void onDestroy() { 476 super.onDestroy(); 477 log("Destroyed Successfully..."); 478 mHandler.getLooper().quitSafely(); 479 480 if (mCarrierConfigManager != null && mCarrierConfigChangeListener != null) { 481 mCarrierConfigManager.unregisterCarrierConfigChangeListener( 482 mCarrierConfigChangeListener); 483 } 484 } 485 486 /** 487 * initialize ONS and register as service. 488 * Read persistent state to update enable state 489 * Start sub components if already enabled. 490 * @param context context instance 491 */ 492 @VisibleForTesting initialize(Context context)493 protected void initialize(Context context) { 494 mContext = context; 495 createMsgHandler(); 496 mTelephonyManager = TelephonyManager.from(mContext); 497 mProfileSelector = new ONSProfileSelector(mContext, mProfileSelectionCallback); 498 mSharedPref = mContext.createDeviceProtectedStorageContext().getSharedPreferences( 499 PREF_NAME, Context.MODE_PRIVATE); 500 mSubscriptionManager = (SubscriptionManager) mContext.getSystemService( 501 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 502 if (Flags.workProfileApiSplit()) { 503 mSubscriptionManager = mSubscriptionManager.createForAllUserProfiles(); 504 } 505 mONSConfigInputHashMap = new HashMap<String, ONSConfigInput>(); 506 mONSStats = new ONSStats(mContext, mSubscriptionManager); 507 mContext.registerReceiver(mBroadcastReceiver, 508 new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED)); 509 enableOpportunisticNetwork(getPersistentEnableState()); 510 mONSProfileActivator = new ONSProfileActivator(mContext, mONSStats); 511 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 512 if (mCarrierConfigManager != null) { 513 // Registers for carrier config changes and runs on handler thread 514 mCarrierConfigManager.registerCarrierConfigChangeListener(mHandler::post, 515 mCarrierConfigChangeListener); 516 } 517 mUserManager = mContext.getSystemService(UserManager.class); 518 mPackageManager = mContext.getPackageManager(); 519 mVendorApiLevel = SystemProperties.getInt( 520 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); 521 } 522 523 /** 524 * This is only register CarrierConfigChangeListener for testing 525 */ 526 @VisibleForTesting registerCarrierConfigChangListener()527 protected void registerCarrierConfigChangListener() { 528 mCarrierConfigManager.registerCarrierConfigChangeListener(mHandler::post, 529 mCarrierConfigChangeListener); 530 } 531 532 private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener = 533 new CarrierConfigManager.CarrierConfigChangeListener() { 534 @Override 535 public void onCarrierConfigChanged(int logicalSlotIndex, int subscriptionId, 536 int carrierId, int specificCarrierId) { 537 538 boolean isUserUnlocked = mUserManager.isUserUnlocked(); 539 if (isUserUnlocked) { 540 mONSProfileActivator.handleCarrierConfigChange(); 541 } else { 542 log("User is locked"); 543 // Register the UnlockReceiver for trigger after Unlocked. 544 mContext.registerReceiver(mUserUnlockedReceiver, new IntentFilter( 545 Intent.ACTION_USER_UNLOCKED)); 546 } 547 } 548 }; 549 550 /** 551 * This is only sent to registered receivers, not manifest receivers. 552 * Note: The user's actual state might have changed by the time the broadcast is received. 553 */ 554 private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { 555 @Override 556 public void onReceive(Context context, Intent intent) { 557 if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) { 558 log("Received UserUnlockedReceiver"); 559 mONSProfileActivator.handleCarrierConfigChange(); 560 } 561 } 562 }; 563 handleCarrierAppAvailableNetworks( ArrayList<AvailableNetworkInfo> availableNetworks, IUpdateAvailableNetworksCallback callbackStub, String callingPackage)564 private void handleCarrierAppAvailableNetworks( 565 ArrayList<AvailableNetworkInfo> availableNetworks, 566 IUpdateAvailableNetworksCallback callbackStub, String callingPackage) { 567 if ((availableNetworks != null) && (availableNetworks.size() > 0)) { 568 /* carrier apps should report only subscription */ 569 if (availableNetworks.size() > 1) { 570 log("Carrier app should not pass more than one subscription"); 571 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 572 sendUpdateNetworksCallbackHelper(callbackStub, 573 TelephonyManager 574 .UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED); 575 } else { 576 sendUpdateNetworksCallbackHelper(callbackStub, 577 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS); 578 } 579 return; 580 } 581 582 if (!mProfileSelector.hasOpprotunisticSub(availableNetworks)) { 583 log("No opportunistic subscriptions received"); 584 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 585 sendUpdateNetworksCallbackHelper(callbackStub, 586 TelephonyManager 587 .UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE); 588 } else { 589 sendUpdateNetworksCallbackHelper(callbackStub, 590 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS); 591 } 592 return; 593 } 594 595 for (AvailableNetworkInfo availableNetworkInfo : availableNetworks) { 596 final long identity = Binder.clearCallingIdentity(); 597 boolean isActiveSubId = false; 598 try { 599 isActiveSubId = 600 mSubscriptionManager.isActiveSubId(availableNetworkInfo.getSubId()); 601 } finally { 602 Binder.restoreCallingIdentity(identity); 603 } 604 if (isActiveSubId) { 605 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, 606 availableNetworkInfo.getSubId(), "updateAvailableNetworks"); 607 } else { 608 /* check if the app has opportunistic carrier permission */ 609 if (!hasOpportunisticSubPrivilege(callingPackage, 610 availableNetworkInfo.getSubId())) { 611 log("No carrier privilege for opportunistic subscription"); 612 sendUpdateNetworksCallbackHelper(callbackStub, 613 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE); 614 return; 615 } 616 } 617 } 618 619 final long identity = Binder.clearCallingIdentity(); 620 try { 621 ONSConfigInput onsConfigInput = new ONSConfigInput(availableNetworks, callbackStub); 622 SubscriptionInfo subscriptionInfo = mSubscriptionManager.getDefaultVoiceSubscriptionInfo(); 623 if (subscriptionInfo != null) { 624 onsConfigInput.setPrimarySub(subscriptionInfo.getSubscriptionId()); 625 onsConfigInput.setPreferredDataSub(availableNetworks.get(0).getSubId()); 626 mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, onsConfigInput); 627 } 628 /* standalone opportunistic subscription should be handled in priority. */ 629 if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null) { 630 if (mProfileSelector.containStandaloneOppSubs(mONSConfigInputHashMap.get( 631 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkInfos())) { 632 log("standalone opportunistic subscription is using."); 633 return; 634 } 635 } 636 637 if (mIsEnabled) { 638 /* if carrier is reporting availability, then it takes higher priority. */ 639 mProfileSelector.startProfileSelection(availableNetworks, callbackStub); 640 } else { 641 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 642 sendUpdateNetworksCallbackHelper(callbackStub, 643 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED); 644 } else { 645 sendUpdateNetworksCallbackHelper(callbackStub, 646 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED); 647 } 648 } 649 } finally { 650 Binder.restoreCallingIdentity(identity); 651 } 652 } else { 653 final long identity = Binder.clearCallingIdentity(); 654 try { 655 mONSConfigInputHashMap.put(CARRIER_APP_CONFIG_NAME, null); 656 if (!mIsEnabled) { 657 sendUpdateNetworksCallbackHelper(callbackStub, 658 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 659 return; 660 } 661 /* if carrier is reporting unavailability, then decide whether to start 662 system app request or not. */ 663 if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null) { 664 sendUpdateNetworksCallbackHelper(callbackStub, 665 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 666 mProfileSelector.startProfileSelection( 667 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) 668 .getAvailableNetworkInfos(), 669 mONSConfigInputHashMap.get( 670 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback()); 671 } else { 672 mProfileSelector.stopProfileSelection(callbackStub); 673 } 674 } finally { 675 Binder.restoreCallingIdentity(identity); 676 } 677 } 678 } 679 sendUpdateNetworksCallbackHelper(IUpdateAvailableNetworksCallback callback, int result)680 private void sendUpdateNetworksCallbackHelper(IUpdateAvailableNetworksCallback callback, int result) { 681 if (callback == null) return; 682 try { 683 callback.onComplete(result); 684 } catch (RemoteException exception) { 685 log("RemoteException " + exception); 686 } 687 } 688 sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result)689 private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) { 690 if (callback == null) return; 691 try { 692 callback.onComplete(result); 693 } catch (RemoteException exception) { 694 log("RemoteException " + exception); 695 } 696 } 697 getPersistentEnableState()698 private boolean getPersistentEnableState() { 699 return mSharedPref.getBoolean(PREF_ENABLED, true); 700 } 701 handleSystemAppAvailableNetworks( ArrayList<AvailableNetworkInfo> availableNetworks, IUpdateAvailableNetworksCallback callbackStub)702 private void handleSystemAppAvailableNetworks( 703 ArrayList<AvailableNetworkInfo> availableNetworks, 704 IUpdateAvailableNetworksCallback callbackStub) { 705 final long identity = Binder.clearCallingIdentity(); 706 try { 707 if ((availableNetworks != null) && (availableNetworks.size() > 0)) { 708 /* all subscriptions should be opportunistic subscriptions */ 709 if (!mProfileSelector.hasOpprotunisticSub(availableNetworks)) { 710 log("No opportunistic subscriptions received"); 711 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 712 sendUpdateNetworksCallbackHelper(callbackStub, 713 TelephonyManager 714 .UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE); 715 } else { 716 sendUpdateNetworksCallbackHelper(callbackStub, 717 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS); 718 } 719 return; 720 } 721 mONSConfigInputHashMap.put(SYSTEM_APP_CONFIG_NAME, 722 new ONSConfigInput(availableNetworks, callbackStub)); 723 /* reporting availability. proceed if carrier app has not requested any, but 724 standalone opportunistic subscription should be handled in priority. */ 725 if (mIsEnabled) { 726 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) == null 727 || mProfileSelector.containStandaloneOppSubs(availableNetworks)) { 728 mProfileSelector.startProfileSelection(availableNetworks, callbackStub); 729 } 730 } else { 731 if (Compatibility.isChangeEnabled(CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) { 732 sendUpdateNetworksCallbackHelper(callbackStub, 733 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED); 734 } else { 735 sendUpdateNetworksCallbackHelper(callbackStub, 736 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_ABORTED); 737 } 738 } 739 } else { 740 if (!mIsEnabled) { 741 mONSConfigInputHashMap.put(SYSTEM_APP_CONFIG_NAME, null); 742 sendUpdateNetworksCallbackHelper(callbackStub, 743 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 744 return; 745 } 746 /* if system is reporting unavailability, then decide whether to start 747 carrier app request or not. */ 748 mONSConfigInputHashMap.put(SYSTEM_APP_CONFIG_NAME, null); 749 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) == null) { 750 mProfileSelector.stopProfileSelection(callbackStub); 751 } else { 752 sendUpdateNetworksCallbackHelper(callbackStub, 753 TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS); 754 log("Try to start carrier app request"); 755 mProfileSelector.startProfileSelection( 756 mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) 757 .getAvailableNetworkInfos(), 758 mONSConfigInputHashMap.get( 759 CARRIER_APP_CONFIG_NAME).getAvailableNetworkCallback()); 760 } 761 } 762 } finally { 763 Binder.restoreCallingIdentity(identity); 764 } 765 } 766 updateEnableState(boolean enable)767 private void updateEnableState(boolean enable) { 768 mIsEnabled = enable; 769 mSharedPref.edit().putBoolean(PREF_ENABLED, mIsEnabled).apply(); 770 } 771 772 /** 773 * update the enable state 774 * start profile selection if enabled. 775 * @param enable enable(true) or disable(false) 776 */ enableOpportunisticNetwork(boolean enable)777 private void enableOpportunisticNetwork(boolean enable) { 778 synchronized (mLock) { 779 if (mIsEnabled != enable) { 780 updateEnableState(enable); 781 if (!mIsEnabled) { 782 mProfileSelector.stopProfileSelection(null); 783 } else { 784 if (mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) != null && 785 mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) 786 .getAvailableNetworkInfos() != null) { 787 mProfileSelector.startProfileSelection( 788 mONSConfigInputHashMap.get(CARRIER_APP_CONFIG_NAME) 789 .getAvailableNetworkInfos(), 790 mONSConfigInputHashMap.get( 791 CARRIER_APP_CONFIG_NAME).getAvailableNetworkCallback()); 792 } else if (mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) != null && 793 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) 794 .getAvailableNetworkInfos() != null) { 795 mProfileSelector.startProfileSelection( 796 mONSConfigInputHashMap.get(SYSTEM_APP_CONFIG_NAME) 797 .getAvailableNetworkInfos(), 798 mONSConfigInputHashMap.get( 799 SYSTEM_APP_CONFIG_NAME).getAvailableNetworkCallback()); 800 } 801 } 802 } 803 } 804 logDebug("service is enable state " + mIsEnabled); 805 } 806 807 /** 808 * Make sure the device has required telephony feature 809 * 810 * @throws UnsupportedOperationException if the device does not have required telephony feature 811 */ enforceTelephonyFeatureWithException(@ullable String callingPackage, @NonNull String telephonyFeature, @NonNull String methodName)812 private void enforceTelephonyFeatureWithException(@Nullable String callingPackage, 813 @NonNull String telephonyFeature, @NonNull String methodName) { 814 if (callingPackage == null || mPackageManager == null) { 815 return; 816 } 817 818 if (!Flags.enforceTelephonyFeatureMappingForPublicApis() 819 || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage, 820 Binder.getCallingUserHandle()) 821 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) { 822 // Skip to check associated telephony feature, 823 // if compatibility change is not enabled for the current process or 824 // the SDK version of vendor partition is less than Android V. 825 return; 826 } 827 828 if (!mPackageManager.hasSystemFeature(telephonyFeature)) { 829 throw new UnsupportedOperationException( 830 methodName + " is unsupported without " + telephonyFeature); 831 } 832 } 833 log(String msg)834 private void log(String msg) { 835 Rlog.d(TAG, msg); 836 } 837 logDebug(String msg)838 private void logDebug(String msg) { 839 if (DBG) Rlog.d(TAG, msg); 840 } 841 } 842