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