1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.satellite; 18 19 import android.annotation.ArrayRes; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.bluetooth.BluetoothAdapter; 23 import android.content.BroadcastReceiver; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.SharedPreferences; 29 import android.content.res.Resources; 30 import android.database.ContentObserver; 31 import android.net.wifi.WifiManager; 32 import android.nfc.NfcAdapter; 33 import android.os.AsyncResult; 34 import android.os.Binder; 35 import android.os.Build; 36 import android.os.Bundle; 37 import android.os.CancellationSignal; 38 import android.os.Handler; 39 import android.os.HandlerExecutor; 40 import android.os.HandlerThread; 41 import android.os.IBinder; 42 import android.os.ICancellationSignal; 43 import android.os.Looper; 44 import android.os.Message; 45 import android.os.PersistableBundle; 46 import android.os.RemoteException; 47 import android.os.ResultReceiver; 48 import android.os.SystemProperties; 49 import android.provider.Settings; 50 import android.telephony.CarrierConfigManager; 51 import android.telephony.Rlog; 52 import android.telephony.SubscriptionManager; 53 import android.telephony.TelephonyManager; 54 import android.telephony.satellite.ISatelliteDatagramCallback; 55 import android.telephony.satellite.ISatelliteProvisionStateCallback; 56 import android.telephony.satellite.ISatelliteStateCallback; 57 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback; 58 import android.telephony.satellite.SatelliteCapabilities; 59 import android.telephony.satellite.SatelliteDatagram; 60 import android.telephony.satellite.SatelliteManager; 61 import android.util.Log; 62 import android.util.SparseArray; 63 import android.uwb.UwbManager; 64 65 import com.android.internal.R; 66 import com.android.internal.annotations.GuardedBy; 67 import com.android.internal.annotations.VisibleForTesting; 68 import com.android.internal.telephony.CommandsInterface; 69 import com.android.internal.telephony.IIntegerConsumer; 70 import com.android.internal.telephony.Phone; 71 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats; 72 import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats; 73 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats; 74 import com.android.internal.telephony.subscription.SubscriptionManagerService; 75 import com.android.internal.util.FunctionalUtils; 76 77 import java.util.ArrayList; 78 import java.util.HashMap; 79 import java.util.List; 80 import java.util.Map; 81 import java.util.Set; 82 import java.util.concurrent.ConcurrentHashMap; 83 import java.util.concurrent.atomic.AtomicBoolean; 84 import java.util.function.Consumer; 85 86 /** 87 * Satellite controller is the backend service of 88 * {@link android.telephony.satellite.SatelliteManager}. 89 */ 90 public class SatelliteController extends Handler { 91 private static final String TAG = "SatelliteController"; 92 /** Whether enabling verbose debugging message or not. */ 93 private static final boolean DBG = false; 94 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 95 private static final boolean DEBUG = !"user".equals(Build.TYPE); 96 /** File used to store shared preferences related to satellite. */ 97 public static final String SATELLITE_SHARED_PREF = "satellite_shared_pref"; 98 /** Value to pass for the setting key SATELLITE_MODE_ENABLED, enabled = 1, disabled = 0 */ 99 public static final int SATELLITE_MODE_ENABLED_TRUE = 1; 100 public static final int SATELLITE_MODE_ENABLED_FALSE = 0; 101 102 /** Message codes used in handleMessage() */ 103 //TODO: Move the Commands and events related to position updates to PointingAppController 104 private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1; 105 private static final int EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE = 2; 106 private static final int CMD_STOP_SATELLITE_TRANSMISSION_UPDATES = 3; 107 private static final int EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE = 4; 108 private static final int CMD_PROVISION_SATELLITE_SERVICE = 7; 109 private static final int EVENT_PROVISION_SATELLITE_SERVICE_DONE = 8; 110 private static final int CMD_DEPROVISION_SATELLITE_SERVICE = 9; 111 private static final int EVENT_DEPROVISION_SATELLITE_SERVICE_DONE = 10; 112 private static final int CMD_SET_SATELLITE_ENABLED = 11; 113 private static final int EVENT_SET_SATELLITE_ENABLED_DONE = 12; 114 private static final int CMD_IS_SATELLITE_ENABLED = 13; 115 private static final int EVENT_IS_SATELLITE_ENABLED_DONE = 14; 116 private static final int CMD_IS_SATELLITE_SUPPORTED = 15; 117 private static final int EVENT_IS_SATELLITE_SUPPORTED_DONE = 16; 118 private static final int CMD_GET_SATELLITE_CAPABILITIES = 17; 119 private static final int EVENT_GET_SATELLITE_CAPABILITIES_DONE = 18; 120 private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 19; 121 private static final int EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE = 20; 122 private static final int CMD_GET_TIME_SATELLITE_NEXT_VISIBLE = 21; 123 private static final int EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE = 22; 124 private static final int EVENT_RADIO_STATE_CHANGED = 23; 125 private static final int CMD_IS_SATELLITE_PROVISIONED = 24; 126 private static final int EVENT_IS_SATELLITE_PROVISIONED_DONE = 25; 127 private static final int EVENT_SATELLITE_PROVISION_STATE_CHANGED = 26; 128 private static final int EVENT_PENDING_DATAGRAMS = 27; 129 private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 28; 130 131 @NonNull private static SatelliteController sInstance; 132 @NonNull private final Context mContext; 133 @NonNull private final SatelliteModemInterface mSatelliteModemInterface; 134 @NonNull private SatelliteSessionController mSatelliteSessionController; 135 @NonNull private final PointingAppController mPointingAppController; 136 @NonNull private final DatagramController mDatagramController; 137 @NonNull private final ControllerMetricsStats mControllerMetricsStats; 138 @NonNull private final ProvisionMetricsStats mProvisionMetricsStats; 139 private SharedPreferences mSharedPreferences = null; 140 private final CommandsInterface mCi; 141 private ContentResolver mContentResolver = null; 142 143 private final Object mRadioStateLock = new Object(); 144 145 /** Flags to indicate whether the resepective radio is enabled */ 146 @GuardedBy("mRadioStateLock") 147 private boolean mBTStateEnabled = false; 148 @GuardedBy("mRadioStateLock") 149 private boolean mNfcStateEnabled = false; 150 @GuardedBy("mRadioStateLock") 151 private boolean mUwbStateEnabled = false; 152 @GuardedBy("mRadioStateLock") 153 private boolean mWifiStateEnabled = false; 154 155 // Flags to indicate that respective radios need to be disabled when satellite is enabled 156 private boolean mDisableBTOnSatelliteEnabled = false; 157 private boolean mDisableNFCOnSatelliteEnabled = false; 158 private boolean mDisableUWBOnSatelliteEnabled = false; 159 private boolean mDisableWifiOnSatelliteEnabled = false; 160 161 private final Object mSatelliteEnabledRequestLock = new Object(); 162 @GuardedBy("mSatelliteEnabledRequestLock") 163 private RequestSatelliteEnabledArgument mSatelliteEnabledRequest = null; 164 /** Flag to indicate that satellite is enabled successfully 165 * and waiting for all the radios to be disabled so that success can be sent to callback 166 */ 167 @GuardedBy("mSatelliteEnabledRequestLock") 168 private boolean mWaitingForRadioDisabled = false; 169 170 private boolean mWaitingForDisableSatelliteModemResponse = false; 171 private boolean mWaitingForSatelliteModemOff = false; 172 173 private final AtomicBoolean mRegisteredForProvisionStateChangedWithSatelliteService = 174 new AtomicBoolean(false); 175 private final AtomicBoolean mRegisteredForProvisionStateChangedWithPhone = 176 new AtomicBoolean(false); 177 private final AtomicBoolean mRegisteredForPendingDatagramCountWithSatelliteService = 178 new AtomicBoolean(false); 179 private final AtomicBoolean mRegisteredForPendingDatagramCountWithPhone = 180 new AtomicBoolean(false); 181 private final AtomicBoolean mRegisteredForSatelliteModemStateChangedWithSatelliteService = 182 new AtomicBoolean(false); 183 private final AtomicBoolean mRegisteredForSatelliteModemStateChangedWithPhone = 184 new AtomicBoolean(false); 185 /** 186 * Map key: subId, value: callback to get error code of the provision request. 187 */ 188 private final ConcurrentHashMap<Integer, Consumer<Integer>> mSatelliteProvisionCallbacks = 189 new ConcurrentHashMap<>(); 190 191 /** 192 * Map key: binder of the callback, value: callback to receive provision state changed events. 193 */ 194 private final ConcurrentHashMap<IBinder, ISatelliteProvisionStateCallback> 195 mSatelliteProvisionStateChangedListeners = new ConcurrentHashMap<>(); 196 private final Object mIsSatelliteSupportedLock = new Object(); 197 @GuardedBy("mIsSatelliteSupportedLock") 198 private Boolean mIsSatelliteSupported = null; 199 private boolean mIsDemoModeEnabled = false; 200 private final Object mIsSatelliteEnabledLock = new Object(); 201 @GuardedBy("mIsSatelliteEnabledLock") 202 private Boolean mIsSatelliteEnabled = null; 203 private boolean mIsRadioOn = false; 204 private final Object mIsSatelliteProvisionedLock = new Object(); 205 @GuardedBy("mIsSatelliteProvisionedLock") 206 private Boolean mIsSatelliteProvisioned = null; 207 private final Object mSatelliteCapabilitiesLock = new Object(); 208 @GuardedBy("mSatelliteCapabilitiesLock") 209 private SatelliteCapabilities mSatelliteCapabilities; 210 private final Object mNeedsSatellitePointingLock = new Object(); 211 @GuardedBy("mNeedsSatellitePointingLock") 212 private boolean mNeedsSatellitePointing = false; 213 /** Key: subId, value: (key: PLMN, value: set of 214 * {@link android.telephony.NetworkRegistrationInfo.ServiceType}) 215 */ 216 @GuardedBy("mSupportedSatelliteServicesLock") 217 @NonNull private final Map<Integer, Map<String, Set<Integer>>> mSupportedSatelliteServices = 218 new HashMap<>(); 219 @NonNull private final Object mSupportedSatelliteServicesLock = new Object(); 220 /** Key: PLMN, value: set of {@link android.telephony.NetworkRegistrationInfo.ServiceType} */ 221 @NonNull private final Map<String, Set<Integer>> mSatelliteServicesSupportedByProviders; 222 @NonNull private final CarrierConfigManager mCarrierConfigManager; 223 @NonNull private final CarrierConfigManager.CarrierConfigChangeListener 224 mCarrierConfigChangeListener; 225 @NonNull private final Object mCarrierConfigArrayLock = new Object(); 226 @GuardedBy("mCarrierConfigArrayLock") 227 @NonNull private final SparseArray<PersistableBundle> mCarrierConfigArray = new SparseArray<>(); 228 @NonNull private final List<String> mSatellitePlmnList; 229 230 /** 231 * @return The singleton instance of SatelliteController. 232 */ getInstance()233 public static SatelliteController getInstance() { 234 if (sInstance == null) { 235 loge("SatelliteController was not yet initialized."); 236 } 237 return sInstance; 238 } 239 240 /** 241 * Create the SatelliteController singleton instance. 242 * @param context The Context to use to create the SatelliteController. 243 */ make(@onNull Context context)244 public static void make(@NonNull Context context) { 245 if (sInstance == null) { 246 HandlerThread satelliteThread = new HandlerThread(TAG); 247 satelliteThread.start(); 248 sInstance = new SatelliteController(context, satelliteThread.getLooper()); 249 } 250 } 251 252 /** 253 * Create a SatelliteController to act as a backend service of 254 * {@link android.telephony.satellite.SatelliteManager} 255 * 256 * @param context The Context for the SatelliteController. 257 * @param looper The looper for the handler. It does not run on main thread. 258 */ 259 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) SatelliteController(@onNull Context context, @NonNull Looper looper)260 public SatelliteController(@NonNull Context context, @NonNull Looper looper) { 261 super(looper); 262 263 mContext = context; 264 Phone phone = SatelliteServiceUtils.getPhone(); 265 mCi = phone.mCi; 266 // Create the SatelliteModemInterface singleton, which is used to manage connections 267 // to the satellite service and HAL interface. 268 mSatelliteModemInterface = SatelliteModemInterface.make(mContext, this); 269 270 // Create the PointingUIController singleton, 271 // which is used to manage interactions with PointingUI app. 272 mPointingAppController = PointingAppController.make(mContext); 273 274 // Create the SatelliteControllerMetrics to report controller metrics 275 // should be called before making DatagramController 276 mControllerMetricsStats = ControllerMetricsStats.make(mContext); 277 mProvisionMetricsStats = ProvisionMetricsStats.getOrCreateInstance(); 278 279 // Create the DatagramController singleton, 280 // which is used to send and receive satellite datagrams. 281 mDatagramController = DatagramController.make(mContext, looper, mPointingAppController); 282 283 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 284 new ResultReceiver(this) { 285 @Override 286 protected void onReceiveResult(int resultCode, Bundle resultData) { 287 logd("requestIsSatelliteSupported: resultCode=" + resultCode); 288 } 289 }); 290 mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); 291 mIsRadioOn = phone.isRadioOn(); 292 registerForSatelliteProvisionStateChanged(); 293 registerForPendingDatagramCount(); 294 registerForSatelliteModemStateChanged(); 295 mContentResolver = mContext.getContentResolver(); 296 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 297 298 try { 299 mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF, 300 Context.MODE_PRIVATE); 301 } catch (Exception e) { 302 loge("Cannot get default shared preferences: " + e); 303 } 304 305 initializeSatelliteModeRadios(); 306 307 ContentObserver satelliteModeRadiosContentObserver = new ContentObserver(this) { 308 @Override 309 public void onChange(boolean selfChange) { 310 initializeSatelliteModeRadios(); 311 } 312 }; 313 if (mContentResolver != null) { 314 mContentResolver.registerContentObserver( 315 Settings.Global.getUriFor(Settings.Global.SATELLITE_MODE_RADIOS), 316 false, satelliteModeRadiosContentObserver); 317 } 318 319 mSatelliteServicesSupportedByProviders = readSupportedSatelliteServicesFromOverlayConfig(); 320 mSatellitePlmnList = 321 mSatelliteServicesSupportedByProviders.keySet().stream().toList(); 322 updateSupportedSatelliteServicesForActiveSubscriptions(); 323 mCarrierConfigChangeListener = 324 (slotIndex, subId, carrierId, specificCarrierId) -> 325 handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId); 326 mCarrierConfigManager.registerCarrierConfigChangeListener( 327 new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener); 328 } 329 330 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) initializeSatelliteModeRadios()331 protected void initializeSatelliteModeRadios() { 332 if (mContentResolver != null) { 333 BTWifiNFCStateReceiver bTWifiNFCSateReceiver = new BTWifiNFCStateReceiver(); 334 UwbAdapterStateCallback uwbAdapterStateCallback = new UwbAdapterStateCallback(); 335 IntentFilter radioStateIntentFilter = new IntentFilter(); 336 337 synchronized (mRadioStateLock) { 338 // Initialize radio states to default value 339 mDisableBTOnSatelliteEnabled = false; 340 mDisableNFCOnSatelliteEnabled = false; 341 mDisableWifiOnSatelliteEnabled = false; 342 mDisableUWBOnSatelliteEnabled = false; 343 344 mBTStateEnabled = false; 345 mNfcStateEnabled = false; 346 mWifiStateEnabled = false; 347 mUwbStateEnabled = false; 348 349 // Read satellite mode radios from settings 350 String satelliteModeRadios = Settings.Global.getString(mContentResolver, 351 Settings.Global.SATELLITE_MODE_RADIOS); 352 if (satelliteModeRadios == null) { 353 loge("initializeSatelliteModeRadios: satelliteModeRadios is null"); 354 return; 355 } 356 logd("Radios To be checked when satellite is on: " + satelliteModeRadios); 357 358 if (satelliteModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) { 359 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 360 if (bluetoothAdapter != null) { 361 mDisableBTOnSatelliteEnabled = true; 362 mBTStateEnabled = bluetoothAdapter.isEnabled(); 363 radioStateIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 364 } 365 } 366 367 if (satelliteModeRadios.contains(Settings.Global.RADIO_NFC)) { 368 Context applicationContext = mContext.getApplicationContext(); 369 NfcAdapter nfcAdapter = null; 370 if (applicationContext != null) { 371 nfcAdapter = NfcAdapter.getDefaultAdapter(mContext.getApplicationContext()); 372 } 373 if (nfcAdapter != null) { 374 mDisableNFCOnSatelliteEnabled = true; 375 mNfcStateEnabled = nfcAdapter.isEnabled(); 376 radioStateIntentFilter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 377 } 378 } 379 380 if (satelliteModeRadios.contains(Settings.Global.RADIO_WIFI)) { 381 WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 382 if (wifiManager != null) { 383 mDisableWifiOnSatelliteEnabled = true; 384 mWifiStateEnabled = wifiManager.isWifiEnabled(); 385 radioStateIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 386 } 387 } 388 mContext.registerReceiver(bTWifiNFCSateReceiver, radioStateIntentFilter); 389 390 if (satelliteModeRadios.contains(Settings.Global.RADIO_UWB)) { 391 UwbManager uwbManager = mContext.getSystemService(UwbManager.class); 392 if (uwbManager != null) { 393 mDisableUWBOnSatelliteEnabled = true; 394 mUwbStateEnabled = uwbManager.isUwbEnabled(); 395 final long identity = Binder.clearCallingIdentity(); 396 try { 397 uwbManager.registerAdapterStateCallback(mContext.getMainExecutor(), 398 uwbAdapterStateCallback); 399 } finally { 400 Binder.restoreCallingIdentity(identity); 401 } 402 } 403 } 404 405 logd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled 406 + " mDisableNFCOnSatelliteEnabled: " + mDisableNFCOnSatelliteEnabled 407 + " mDisableWifiOnSatelliteEnabled: " + mDisableWifiOnSatelliteEnabled 408 + " mDisableUWBOnSatelliteEnabled: " + mDisableUWBOnSatelliteEnabled); 409 410 logd("mBTStateEnabled: " + mBTStateEnabled 411 + " mNfcStateEnabled: " + mNfcStateEnabled 412 + " mWifiStateEnabled: " + mWifiStateEnabled 413 + " mUwbStateEnabled: " + mUwbStateEnabled); 414 } 415 } 416 } 417 418 protected class UwbAdapterStateCallback implements UwbManager.AdapterStateCallback { 419 toString(int state)420 public String toString(int state) { 421 switch (state) { 422 case UwbManager.AdapterStateCallback.STATE_DISABLED: 423 return "Disabled"; 424 425 case UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE: 426 return "Inactive"; 427 428 case UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE: 429 return "Active"; 430 431 default: 432 return ""; 433 } 434 } 435 436 @Override onStateChanged(int state, int reason)437 public void onStateChanged(int state, int reason) { 438 logd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state)); 439 logd("Adapter state changed reason " + String.valueOf(reason)); 440 synchronized (mRadioStateLock) { 441 if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) { 442 mUwbStateEnabled = false; 443 evaluateToSendSatelliteEnabledSuccess(); 444 } else { 445 mUwbStateEnabled = true; 446 } 447 logd("mUwbStateEnabled: " + mUwbStateEnabled); 448 } 449 } 450 } 451 452 protected class BTWifiNFCStateReceiver extends BroadcastReceiver { 453 @Override onReceive(Context context, Intent intent)454 public void onReceive(Context context, Intent intent) { 455 final String action = intent.getAction(); 456 if (action == null) { 457 logd("BTWifiNFCStateReceiver NULL action for intent " + intent); 458 return; 459 } 460 461 switch (action) { 462 case BluetoothAdapter.ACTION_STATE_CHANGED: 463 int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 464 BluetoothAdapter.ERROR); 465 synchronized (mRadioStateLock) { 466 boolean currentBTStateEnabled = mBTStateEnabled; 467 if (btState == BluetoothAdapter.STATE_OFF) { 468 mBTStateEnabled = false; 469 evaluateToSendSatelliteEnabledSuccess(); 470 } else if (btState == BluetoothAdapter.STATE_ON) { 471 mBTStateEnabled = true; 472 } 473 if (currentBTStateEnabled != mBTStateEnabled) { 474 logd("mBTStateEnabled=" + mBTStateEnabled); 475 } 476 } 477 break; 478 479 case NfcAdapter.ACTION_ADAPTER_STATE_CHANGED: 480 int nfcState = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, -1); 481 synchronized (mRadioStateLock) { 482 boolean currentNfcStateEnabled = mNfcStateEnabled; 483 if (nfcState == NfcAdapter.STATE_ON) { 484 mNfcStateEnabled = true; 485 } else if (nfcState == NfcAdapter.STATE_OFF) { 486 mNfcStateEnabled = false; 487 evaluateToSendSatelliteEnabledSuccess(); 488 } 489 if (currentNfcStateEnabled != mNfcStateEnabled) { 490 logd("mNfcStateEnabled=" + mNfcStateEnabled); 491 } 492 } 493 break; 494 495 case WifiManager.WIFI_STATE_CHANGED_ACTION: 496 int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 497 WifiManager.WIFI_STATE_UNKNOWN); 498 synchronized (mRadioStateLock) { 499 boolean currentWifiStateEnabled = mWifiStateEnabled; 500 if (wifiState == WifiManager.WIFI_STATE_ENABLED) { 501 mWifiStateEnabled = true; 502 } else if (wifiState == WifiManager.WIFI_STATE_DISABLED) { 503 mWifiStateEnabled = false; 504 evaluateToSendSatelliteEnabledSuccess(); 505 } 506 if (currentWifiStateEnabled != mWifiStateEnabled) { 507 logd("mWifiStateEnabled=" + mWifiStateEnabled); 508 } 509 } 510 break; 511 default: 512 break; 513 } 514 } 515 } 516 517 private static final class SatelliteControllerHandlerRequest { 518 /** The argument to use for the request */ 519 public @NonNull Object argument; 520 /** The caller needs to specify the phone to be used for the request */ 521 public @NonNull Phone phone; 522 /** The result of the request that is run on the main thread */ 523 public @Nullable Object result; 524 SatelliteControllerHandlerRequest(Object argument, Phone phone)525 SatelliteControllerHandlerRequest(Object argument, Phone phone) { 526 this.argument = argument; 527 this.phone = phone; 528 } 529 } 530 531 private static final class RequestSatelliteEnabledArgument { 532 public boolean enableSatellite; 533 public boolean enableDemoMode; 534 @NonNull public Consumer<Integer> callback; 535 RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode, Consumer<Integer> callback)536 RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode, 537 Consumer<Integer> callback) { 538 this.enableSatellite = enableSatellite; 539 this.enableDemoMode = enableDemoMode; 540 this.callback = callback; 541 } 542 } 543 544 private static final class ProvisionSatelliteServiceArgument { 545 @NonNull public String token; 546 @NonNull public byte[] provisionData; 547 @NonNull public Consumer<Integer> callback; 548 public int subId; 549 ProvisionSatelliteServiceArgument(String token, byte[] provisionData, Consumer<Integer> callback, int subId)550 ProvisionSatelliteServiceArgument(String token, byte[] provisionData, 551 Consumer<Integer> callback, int subId) { 552 this.token = token; 553 this.provisionData = provisionData; 554 this.callback = callback; 555 this.subId = subId; 556 } 557 } 558 559 /** 560 * Arguments to send to SatelliteTransmissionUpdate registrants 561 */ 562 public static final class SatelliteTransmissionUpdateArgument { 563 @NonNull public Consumer<Integer> errorCallback; 564 @NonNull public ISatelliteTransmissionUpdateCallback callback; 565 public int subId; 566 SatelliteTransmissionUpdateArgument(Consumer<Integer> errorCallback, ISatelliteTransmissionUpdateCallback callback, int subId)567 SatelliteTransmissionUpdateArgument(Consumer<Integer> errorCallback, 568 ISatelliteTransmissionUpdateCallback callback, int subId) { 569 this.errorCallback = errorCallback; 570 this.callback = callback; 571 this.subId = subId; 572 } 573 } 574 575 @Override handleMessage(Message msg)576 public void handleMessage(Message msg) { 577 SatelliteControllerHandlerRequest request; 578 Message onCompleted; 579 AsyncResult ar; 580 581 switch(msg.what) { 582 case CMD_START_SATELLITE_TRANSMISSION_UPDATES: { 583 request = (SatelliteControllerHandlerRequest) msg.obj; 584 onCompleted = 585 obtainMessage(EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE, request); 586 mPointingAppController.startSatelliteTransmissionUpdates(onCompleted, 587 request.phone); 588 break; 589 } 590 591 case EVENT_START_SATELLITE_TRANSMISSION_UPDATES_DONE: { 592 handleStartSatelliteTransmissionUpdatesDone((AsyncResult) msg.obj); 593 break; 594 } 595 596 case CMD_STOP_SATELLITE_TRANSMISSION_UPDATES: { 597 request = (SatelliteControllerHandlerRequest) msg.obj; 598 onCompleted = 599 obtainMessage(EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE, request); 600 mPointingAppController.stopSatelliteTransmissionUpdates(onCompleted, request.phone); 601 break; 602 } 603 604 case EVENT_STOP_SATELLITE_TRANSMISSION_UPDATES_DONE: { 605 ar = (AsyncResult) msg.obj; 606 request = (SatelliteControllerHandlerRequest) ar.userObj; 607 int error = SatelliteServiceUtils.getSatelliteError(ar, 608 "stopSatelliteTransmissionUpdates"); 609 ((Consumer<Integer>) request.argument).accept(error); 610 break; 611 } 612 613 case CMD_PROVISION_SATELLITE_SERVICE: { 614 request = (SatelliteControllerHandlerRequest) msg.obj; 615 ProvisionSatelliteServiceArgument argument = 616 (ProvisionSatelliteServiceArgument) request.argument; 617 if (mSatelliteProvisionCallbacks.containsKey(argument.subId)) { 618 argument.callback.accept( 619 SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS); 620 notifyRequester(request); 621 break; 622 } 623 mSatelliteProvisionCallbacks.put(argument.subId, argument.callback); 624 onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_SERVICE_DONE, request); 625 // Log the current time for provision triggered 626 mProvisionMetricsStats.setProvisioningStartTime(); 627 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 628 mSatelliteModemInterface.provisionSatelliteService(argument.token, 629 argument.provisionData, onCompleted); 630 break; 631 } 632 Phone phone = request.phone; 633 if (phone != null) { 634 phone.provisionSatelliteService(onCompleted, argument.token); 635 } else { 636 loge("provisionSatelliteService: No phone object"); 637 argument.callback.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 638 notifyRequester(request); 639 mProvisionMetricsStats 640 .setResultCode(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE) 641 .reportProvisionMetrics(); 642 mControllerMetricsStats.reportProvisionCount( 643 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 644 } 645 break; 646 } 647 648 case EVENT_PROVISION_SATELLITE_SERVICE_DONE: { 649 ar = (AsyncResult) msg.obj; 650 request = (SatelliteControllerHandlerRequest) ar.userObj; 651 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 652 "provisionSatelliteService"); 653 handleEventProvisionSatelliteServiceDone( 654 (ProvisionSatelliteServiceArgument) request.argument, errorCode); 655 notifyRequester(request); 656 break; 657 } 658 659 case CMD_DEPROVISION_SATELLITE_SERVICE: { 660 request = (SatelliteControllerHandlerRequest) msg.obj; 661 ProvisionSatelliteServiceArgument argument = 662 (ProvisionSatelliteServiceArgument) request.argument; 663 onCompleted = obtainMessage(EVENT_DEPROVISION_SATELLITE_SERVICE_DONE, request); 664 if (argument.callback != null) { 665 mProvisionMetricsStats.setProvisioningStartTime(); 666 } 667 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 668 mSatelliteModemInterface 669 .deprovisionSatelliteService(argument.token, onCompleted); 670 break; 671 } 672 Phone phone = request.phone; 673 if (phone != null) { 674 phone.deprovisionSatelliteService(onCompleted, argument.token); 675 } else { 676 loge("deprovisionSatelliteService: No phone object"); 677 if (argument.callback != null) { 678 argument.callback.accept( 679 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 680 mProvisionMetricsStats 681 .setResultCode(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE) 682 .reportProvisionMetrics(); 683 mControllerMetricsStats.reportDeprovisionCount( 684 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 685 } 686 } 687 break; 688 } 689 690 case EVENT_DEPROVISION_SATELLITE_SERVICE_DONE: { 691 ar = (AsyncResult) msg.obj; 692 request = (SatelliteControllerHandlerRequest) ar.userObj; 693 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 694 "deprovisionSatelliteService"); 695 handleEventDeprovisionSatelliteServiceDone( 696 (ProvisionSatelliteServiceArgument) request.argument, errorCode); 697 break; 698 } 699 700 case CMD_SET_SATELLITE_ENABLED: { 701 request = (SatelliteControllerHandlerRequest) msg.obj; 702 handleSatelliteEnabled(request); 703 break; 704 } 705 706 case EVENT_SET_SATELLITE_ENABLED_DONE: { 707 ar = (AsyncResult) msg.obj; 708 request = (SatelliteControllerHandlerRequest) ar.userObj; 709 RequestSatelliteEnabledArgument argument = 710 (RequestSatelliteEnabledArgument) request.argument; 711 int error = SatelliteServiceUtils.getSatelliteError(ar, "setSatelliteEnabled"); 712 logd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error); 713 714 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 715 if (argument.enableSatellite) { 716 synchronized (mSatelliteEnabledRequestLock) { 717 mWaitingForRadioDisabled = true; 718 } 719 setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE); 720 721 /** 722 * TODO for NTN-based satellites: Check if satellite is acquired. 723 */ 724 if (mNeedsSatellitePointing) { 725 mPointingAppController.startPointingUI(false); 726 } 727 evaluateToSendSatelliteEnabledSuccess(); 728 } else { 729 synchronized (mSatelliteEnabledRequestLock) { 730 if (mSatelliteEnabledRequest != null && 731 mSatelliteEnabledRequest.enableSatellite == true && 732 argument.enableSatellite == false && mWaitingForRadioDisabled) { 733 // Previous mSatelliteEnabledRequest is successful but waiting for 734 // all radios to be turned off. 735 mSatelliteEnabledRequest.callback.accept( 736 SatelliteManager.SATELLITE_ERROR_NONE); 737 } 738 } 739 740 synchronized (mIsSatelliteEnabledLock) { 741 if (!mWaitingForSatelliteModemOff) { 742 moveSatelliteToOffStateAndCleanUpResources( 743 SatelliteManager.SATELLITE_ERROR_NONE, argument.callback); 744 } else { 745 logd("Wait for satellite modem off before updating satellite" 746 + " modem state"); 747 } 748 mWaitingForDisableSatelliteModemResponse = false; 749 } 750 } 751 } else { 752 synchronized (mSatelliteEnabledRequestLock) { 753 if (mSatelliteEnabledRequest != null && 754 mSatelliteEnabledRequest.enableSatellite == true && 755 argument.enableSatellite == false && mWaitingForRadioDisabled) { 756 // Previous mSatelliteEnabledRequest is successful but waiting for 757 // all radios to be turned off. 758 mSatelliteEnabledRequest.callback.accept( 759 SatelliteManager.SATELLITE_ERROR_NONE); 760 } 761 } 762 resetSatelliteEnabledRequest(); 763 764 // If Satellite enable/disable request returned Error, no need to wait for radio 765 argument.callback.accept(error); 766 } 767 768 if (argument.enableSatellite) { 769 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 770 mControllerMetricsStats.onSatelliteEnabled(); 771 mControllerMetricsStats.reportServiceEnablementSuccessCount(); 772 } else { 773 mControllerMetricsStats.reportServiceEnablementFailCount(); 774 } 775 SessionMetricsStats.getInstance() 776 .setInitializationResult(error) 777 .setRadioTechnology(SatelliteManager.NT_RADIO_TECHNOLOGY_PROPRIETARY) 778 .reportSessionMetrics(); 779 } else { 780 mControllerMetricsStats.onSatelliteDisabled(); 781 synchronized (mIsSatelliteEnabledLock) { 782 mWaitingForDisableSatelliteModemResponse = false; 783 } 784 } 785 break; 786 } 787 788 case CMD_IS_SATELLITE_ENABLED: { 789 request = (SatelliteControllerHandlerRequest) msg.obj; 790 onCompleted = obtainMessage(EVENT_IS_SATELLITE_ENABLED_DONE, request); 791 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 792 mSatelliteModemInterface.requestIsSatelliteEnabled(onCompleted); 793 break; 794 } 795 Phone phone = request.phone; 796 if (phone != null) { 797 phone.isSatellitePowerOn(onCompleted); 798 } else { 799 loge("isSatelliteEnabled: No phone object"); 800 ((ResultReceiver) request.argument).send( 801 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 802 } 803 break; 804 } 805 806 case EVENT_IS_SATELLITE_ENABLED_DONE: { 807 ar = (AsyncResult) msg.obj; 808 request = (SatelliteControllerHandlerRequest) ar.userObj; 809 int error = SatelliteServiceUtils.getSatelliteError(ar, 810 "isSatelliteEnabled"); 811 Bundle bundle = new Bundle(); 812 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 813 if (ar.result == null) { 814 loge("isSatelliteEnabled: result is null"); 815 error = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 816 } else { 817 boolean enabled = ((int[]) ar.result)[0] == 1; 818 if (DBG) logd("isSatelliteEnabled: " + enabled); 819 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled); 820 updateSatelliteEnabledState(enabled, "EVENT_IS_SATELLITE_ENABLED_DONE"); 821 } 822 } else if (error == SatelliteManager.SATELLITE_REQUEST_NOT_SUPPORTED) { 823 updateSatelliteSupportedStateWhenSatelliteServiceConnected(false); 824 } 825 ((ResultReceiver) request.argument).send(error, bundle); 826 break; 827 } 828 829 case CMD_IS_SATELLITE_SUPPORTED: { 830 request = (SatelliteControllerHandlerRequest) msg.obj; 831 onCompleted = obtainMessage(EVENT_IS_SATELLITE_SUPPORTED_DONE, request); 832 833 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 834 mSatelliteModemInterface.requestIsSatelliteSupported(onCompleted); 835 break; 836 } 837 Phone phone = request.phone; 838 if (phone != null) { 839 phone.isSatelliteSupported(onCompleted); 840 } else { 841 loge("isSatelliteSupported: No phone object"); 842 ((ResultReceiver) request.argument).send( 843 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 844 } 845 break; 846 } 847 848 case EVENT_IS_SATELLITE_SUPPORTED_DONE: { 849 ar = (AsyncResult) msg.obj; 850 request = (SatelliteControllerHandlerRequest) ar.userObj; 851 int error = SatelliteServiceUtils.getSatelliteError(ar, "isSatelliteSupported"); 852 Bundle bundle = new Bundle(); 853 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 854 if (ar.result == null) { 855 loge("isSatelliteSupported: result is null"); 856 error = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 857 } else { 858 boolean supported = (boolean) ar.result; 859 if (DBG) logd("isSatelliteSupported: " + supported); 860 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported); 861 updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported); 862 } 863 } 864 ((ResultReceiver) request.argument).send(error, bundle); 865 break; 866 } 867 868 case CMD_GET_SATELLITE_CAPABILITIES: { 869 request = (SatelliteControllerHandlerRequest) msg.obj; 870 onCompleted = obtainMessage(EVENT_GET_SATELLITE_CAPABILITIES_DONE, request); 871 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 872 mSatelliteModemInterface.requestSatelliteCapabilities(onCompleted); 873 break; 874 } 875 Phone phone = request.phone; 876 if (phone != null) { 877 phone.getSatelliteCapabilities(onCompleted); 878 } else { 879 loge("getSatelliteCapabilities: No phone object"); 880 ((ResultReceiver) request.argument).send( 881 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 882 } 883 break; 884 } 885 886 case EVENT_GET_SATELLITE_CAPABILITIES_DONE: { 887 ar = (AsyncResult) msg.obj; 888 request = (SatelliteControllerHandlerRequest) ar.userObj; 889 int error = SatelliteServiceUtils.getSatelliteError(ar, 890 "getSatelliteCapabilities"); 891 Bundle bundle = new Bundle(); 892 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 893 if (ar.result == null) { 894 loge("getSatelliteCapabilities: result is null"); 895 error = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 896 } else { 897 SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result; 898 synchronized (mNeedsSatellitePointingLock) { 899 mNeedsSatellitePointing = capabilities.isPointingRequired(); 900 } 901 if (DBG) logd("getSatelliteCapabilities: " + capabilities); 902 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES, 903 capabilities); 904 synchronized (mSatelliteCapabilitiesLock) { 905 mSatelliteCapabilities = capabilities; 906 } 907 } 908 } 909 ((ResultReceiver) request.argument).send(error, bundle); 910 break; 911 } 912 913 case CMD_IS_SATELLITE_COMMUNICATION_ALLOWED: { 914 request = (SatelliteControllerHandlerRequest) msg.obj; 915 onCompleted = 916 obtainMessage(EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE, request); 917 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 918 mSatelliteModemInterface 919 .requestIsSatelliteCommunicationAllowedForCurrentLocation( 920 onCompleted); 921 break; 922 } 923 Phone phone = request.phone; 924 if (phone != null) { 925 phone.isSatelliteCommunicationAllowedForCurrentLocation(onCompleted); 926 } else { 927 loge("isSatelliteCommunicationAllowedForCurrentLocation: No phone object"); 928 ((ResultReceiver) request.argument).send( 929 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 930 } 931 break; 932 } 933 934 case EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE: { 935 ar = (AsyncResult) msg.obj; 936 request = (SatelliteControllerHandlerRequest) ar.userObj; 937 int error = SatelliteServiceUtils.getSatelliteError(ar, 938 "isSatelliteCommunicationAllowedForCurrentLocation"); 939 Bundle bundle = new Bundle(); 940 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 941 if (ar.result == null) { 942 loge("isSatelliteCommunicationAllowedForCurrentLocation: result is null"); 943 error = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 944 } else { 945 boolean communicationAllowed = (boolean) ar.result; 946 if (DBG) { 947 logd("isSatelliteCommunicationAllowedForCurrentLocation: " 948 + communicationAllowed); 949 } 950 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED, 951 communicationAllowed); 952 } 953 } 954 ((ResultReceiver) request.argument).send(error, bundle); 955 break; 956 } 957 958 case CMD_GET_TIME_SATELLITE_NEXT_VISIBLE: { 959 request = (SatelliteControllerHandlerRequest) msg.obj; 960 onCompleted = obtainMessage(EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE, 961 request); 962 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 963 mSatelliteModemInterface 964 .requestTimeForNextSatelliteVisibility(onCompleted); 965 break; 966 } 967 Phone phone = request.phone; 968 if (phone != null) { 969 phone.requestTimeForNextSatelliteVisibility(onCompleted); 970 } else { 971 loge("requestTimeForNextSatelliteVisibility: No phone object"); 972 ((ResultReceiver) request.argument).send( 973 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 974 } 975 break; 976 } 977 978 case EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE: { 979 ar = (AsyncResult) msg.obj; 980 request = (SatelliteControllerHandlerRequest) ar.userObj; 981 int error = SatelliteServiceUtils.getSatelliteError(ar, 982 "requestTimeForNextSatelliteVisibility"); 983 Bundle bundle = new Bundle(); 984 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 985 if (ar.result == null) { 986 loge("requestTimeForNextSatelliteVisibility: result is null"); 987 error = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 988 } else { 989 int nextVisibilityDuration = ((int[]) ar.result)[0]; 990 if (DBG) { 991 logd("requestTimeForNextSatelliteVisibility: " + 992 nextVisibilityDuration); 993 } 994 bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY, 995 nextVisibilityDuration); 996 } 997 } 998 ((ResultReceiver) request.argument).send(error, bundle); 999 break; 1000 } 1001 1002 case EVENT_RADIO_STATE_CHANGED: { 1003 if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF 1004 || mCi.getRadioState() == TelephonyManager.RADIO_POWER_UNAVAILABLE) { 1005 mIsRadioOn = false; 1006 logd("Radio State Changed to " + mCi.getRadioState()); 1007 if (isSatelliteEnabled()) { 1008 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() { 1009 @Override 1010 public void accept(int result) { 1011 logd("RequestSatelliteEnabled: result=" + result); 1012 } 1013 }; 1014 Phone phone = SatelliteServiceUtils.getPhone(); 1015 Consumer<Integer> result = FunctionalUtils 1016 .ignoreRemoteException(errorCallback::accept); 1017 RequestSatelliteEnabledArgument message = 1018 new RequestSatelliteEnabledArgument(false, false, result); 1019 request = new SatelliteControllerHandlerRequest(message, phone); 1020 handleSatelliteEnabled(request); 1021 } else { 1022 logd("EVENT_RADIO_STATE_CHANGED: Satellite modem is currently disabled." 1023 + " Ignored the event"); 1024 } 1025 } else { 1026 mIsRadioOn = true; 1027 if (!mSatelliteModemInterface.isSatelliteServiceSupported()) { 1028 synchronized (mIsSatelliteSupportedLock) { 1029 if (mIsSatelliteSupported == null) { 1030 ResultReceiver receiver = new ResultReceiver(this) { 1031 @Override 1032 protected void onReceiveResult( 1033 int resultCode, Bundle resultData) { 1034 logd("requestIsSatelliteSupported: resultCode=" 1035 + resultCode); 1036 } 1037 }; 1038 requestIsSatelliteSupported( 1039 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, receiver); 1040 } 1041 } 1042 } else { 1043 logd("EVENT_RADIO_STATE_CHANGED: Satellite vendor service is supported." 1044 + " Ignored the event"); 1045 } 1046 } 1047 break; 1048 } 1049 1050 case CMD_IS_SATELLITE_PROVISIONED: { 1051 request = (SatelliteControllerHandlerRequest) msg.obj; 1052 onCompleted = obtainMessage(EVENT_IS_SATELLITE_PROVISIONED_DONE, request); 1053 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 1054 mSatelliteModemInterface.requestIsSatelliteProvisioned(onCompleted); 1055 break; 1056 } 1057 Phone phone = request.phone; 1058 if (phone != null) { 1059 phone.isSatelliteProvisioned(onCompleted); 1060 } else { 1061 loge("isSatelliteProvisioned: No phone object"); 1062 ((ResultReceiver) request.argument).send( 1063 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1064 } 1065 break; 1066 } 1067 1068 case EVENT_IS_SATELLITE_PROVISIONED_DONE: { 1069 ar = (AsyncResult) msg.obj; 1070 request = (SatelliteControllerHandlerRequest) ar.userObj; 1071 int error = SatelliteServiceUtils.getSatelliteError(ar, 1072 "isSatelliteProvisioned"); 1073 Bundle bundle = new Bundle(); 1074 if (error == SatelliteManager.SATELLITE_ERROR_NONE) { 1075 if (ar.result == null) { 1076 loge("isSatelliteProvisioned: result is null"); 1077 error = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 1078 } else { 1079 boolean provisioned = ((int[]) ar.result)[0] == 1; 1080 if (DBG) logd("isSatelliteProvisioned: " + provisioned); 1081 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, provisioned); 1082 synchronized (mIsSatelliteProvisionedLock) { 1083 mIsSatelliteProvisioned = provisioned; 1084 } 1085 } 1086 } 1087 ((ResultReceiver) request.argument).send(error, bundle); 1088 break; 1089 } 1090 1091 case EVENT_SATELLITE_PROVISION_STATE_CHANGED: 1092 ar = (AsyncResult) msg.obj; 1093 if (ar.result == null) { 1094 loge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null"); 1095 } else { 1096 handleEventSatelliteProvisionStateChanged((boolean) ar.result); 1097 } 1098 break; 1099 1100 case EVENT_PENDING_DATAGRAMS: 1101 logd("Received EVENT_PENDING_DATAGRAMS"); 1102 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() { 1103 @Override 1104 public void accept(int result) { 1105 logd("pollPendingSatelliteDatagram result: " + result); 1106 } 1107 }; 1108 pollPendingSatelliteDatagrams( 1109 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, internalCallback); 1110 break; 1111 1112 case EVENT_SATELLITE_MODEM_STATE_CHANGED: 1113 ar = (AsyncResult) msg.obj; 1114 if (ar.result == null) { 1115 loge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null"); 1116 } else { 1117 handleEventSatelliteModemStateChanged((int) ar.result); 1118 } 1119 break; 1120 1121 default: 1122 Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " + 1123 msg.what); 1124 break; 1125 } 1126 } 1127 notifyRequester(SatelliteControllerHandlerRequest request)1128 private void notifyRequester(SatelliteControllerHandlerRequest request) { 1129 synchronized (request) { 1130 request.notifyAll(); 1131 } 1132 } 1133 1134 /** 1135 * Request to enable or disable the satellite modem and demo mode. If the satellite modem is 1136 * enabled, this will also disable the cellular modem, and if the satellite modem is disabled, 1137 * this will also re-enable the cellular modem. 1138 * 1139 * @param subId The subId of the subscription to set satellite enabled for. 1140 * @param enableSatellite {@code true} to enable the satellite modem and 1141 * {@code false} to disable. 1142 * @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable. 1143 * @param callback The callback to get the error code of the request. 1144 */ requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode, @NonNull IIntegerConsumer callback)1145 public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode, 1146 @NonNull IIntegerConsumer callback) { 1147 logd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite 1148 + " enableDemoMode: " + enableDemoMode); 1149 1150 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1151 1152 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1153 if (satelliteSupported == null) { 1154 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1155 return; 1156 } 1157 if (!satelliteSupported) { 1158 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED); 1159 return; 1160 } 1161 1162 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1163 if (satelliteProvisioned == null) { 1164 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1165 return; 1166 } 1167 if (!satelliteProvisioned) { 1168 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED); 1169 return; 1170 } 1171 1172 if (enableSatellite) { 1173 if (!mIsRadioOn) { 1174 loge("Radio is not on, can not enable satellite"); 1175 result.accept(SatelliteManager.SATELLITE_INVALID_MODEM_STATE); 1176 return; 1177 } 1178 } else { 1179 /* if disable satellite, always assume demo is also disabled */ 1180 enableDemoMode = false; 1181 } 1182 1183 synchronized (mIsSatelliteEnabledLock) { 1184 if (mIsSatelliteEnabled != null) { 1185 if (mIsSatelliteEnabled == enableSatellite) { 1186 if (enableDemoMode != mIsDemoModeEnabled) { 1187 loge("Received invalid demo mode while satellite session is enabled" 1188 + " enableDemoMode = " + enableDemoMode); 1189 result.accept(SatelliteManager.SATELLITE_INVALID_ARGUMENTS); 1190 return; 1191 } else { 1192 logd("Enable request matches with current state" 1193 + " enableSatellite = " + enableSatellite); 1194 result.accept(SatelliteManager.SATELLITE_ERROR_NONE); 1195 return; 1196 } 1197 } 1198 } 1199 } 1200 1201 RequestSatelliteEnabledArgument request = 1202 new RequestSatelliteEnabledArgument(enableSatellite, enableDemoMode, result); 1203 /** 1204 * Multiple satellite enabled requests are handled as below: 1205 * 1. If there are no ongoing requests, store current request in mSatelliteEnabledRequest 1206 * 2. If there is a ongoing request, then: 1207 * 1. ongoing request = enable, current request = enable: return IN_PROGRESS error 1208 * 2. ongoing request = disable, current request = disable: return IN_PROGRESS error 1209 * 3. ongoing request = disable, current request = enable: return SATELLITE_ERROR error 1210 * 4. ongoing request = enable, current request = disable: send request to modem 1211 */ 1212 synchronized (mSatelliteEnabledRequestLock) { 1213 if (mSatelliteEnabledRequest == null) { 1214 mSatelliteEnabledRequest = request; 1215 } else if (mSatelliteEnabledRequest.enableSatellite == request.enableSatellite) { 1216 logd("requestSatelliteEnabled enableSatellite: " + enableSatellite 1217 + " is already in progress."); 1218 result.accept(SatelliteManager.SATELLITE_REQUEST_IN_PROGRESS); 1219 return; 1220 } else if (mSatelliteEnabledRequest.enableSatellite == false 1221 && request.enableSatellite == true) { 1222 logd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be " 1223 + "processed. Disable satellite is already in progress."); 1224 result.accept(SatelliteManager.SATELLITE_ERROR); 1225 return; 1226 } 1227 } 1228 1229 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, SatelliteServiceUtils.getPhone()); 1230 } 1231 1232 /** 1233 * Request to get whether the satellite modem is enabled. 1234 * 1235 * @param subId The subId of the subscription to check whether satellite is enabled for. 1236 * @param result The result receiver that returns whether the satellite modem is enabled 1237 * if the request is successful or an error code if the request failed. 1238 */ requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result)1239 public void requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result) { 1240 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1241 if (satelliteSupported == null) { 1242 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1243 return; 1244 } 1245 if (!satelliteSupported) { 1246 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null); 1247 return; 1248 } 1249 1250 synchronized (mIsSatelliteEnabledLock) { 1251 if (mIsSatelliteEnabled != null) { 1252 /* We have already successfully queried the satellite modem. */ 1253 Bundle bundle = new Bundle(); 1254 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, mIsSatelliteEnabled); 1255 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle); 1256 return; 1257 } 1258 } 1259 1260 sendRequestAsync(CMD_IS_SATELLITE_ENABLED, result, SatelliteServiceUtils.getPhone()); 1261 } 1262 1263 /** 1264 * Get whether the satellite modem is enabled. 1265 * This will return the cached value instead of querying the satellite modem. 1266 * 1267 * @return {@code true} if the satellite modem is enabled and {@code false} otherwise. 1268 */ isSatelliteEnabled()1269 public boolean isSatelliteEnabled() { 1270 if (mIsSatelliteEnabled == null) return false; 1271 return mIsSatelliteEnabled; 1272 } 1273 1274 /** 1275 * Request to get whether the satellite service demo mode is enabled. 1276 * 1277 * @param subId The subId of the subscription to check whether the satellite demo mode 1278 * is enabled for. 1279 * @param result The result receiver that returns whether the satellite demo mode is enabled 1280 * if the request is successful or an error code if the request failed. 1281 */ requestIsDemoModeEnabled(int subId, @NonNull ResultReceiver result)1282 public void requestIsDemoModeEnabled(int subId, @NonNull ResultReceiver result) { 1283 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1284 if (satelliteSupported == null) { 1285 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1286 return; 1287 } 1288 if (!satelliteSupported) { 1289 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null); 1290 return; 1291 } 1292 1293 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1294 if (satelliteProvisioned == null) { 1295 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1296 return; 1297 } 1298 if (!satelliteProvisioned) { 1299 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null); 1300 return; 1301 } 1302 1303 final Bundle bundle = new Bundle(); 1304 bundle.putBoolean(SatelliteManager.KEY_DEMO_MODE_ENABLED, mIsDemoModeEnabled); 1305 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle); 1306 } 1307 1308 /** 1309 * Get whether the satellite service demo mode is enabled. 1310 * 1311 * @return {@code true} if the satellite demo mode is enabled and {@code false} otherwise. 1312 */ isDemoModeEnabled()1313 public boolean isDemoModeEnabled() { 1314 return mIsDemoModeEnabled; 1315 } 1316 1317 /** 1318 * Request to get whether the satellite service is supported on the device. 1319 * 1320 * @param subId The subId of the subscription to check satellite service support for. 1321 * @param result The result receiver that returns whether the satellite service is supported on 1322 * the device if the request is successful or an error code if the request failed. 1323 */ requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result)1324 public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) { 1325 synchronized (mIsSatelliteSupportedLock) { 1326 if (mIsSatelliteSupported != null) { 1327 /* We have already successfully queried the satellite modem. */ 1328 Bundle bundle = new Bundle(); 1329 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported); 1330 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle); 1331 return; 1332 } 1333 } 1334 1335 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, result, SatelliteServiceUtils.getPhone()); 1336 } 1337 1338 /** 1339 * Request to get the {@link SatelliteCapabilities} of the satellite service. 1340 * 1341 * @param subId The subId of the subscription to get the satellite capabilities for. 1342 * @param result The result receiver that returns the {@link SatelliteCapabilities} 1343 * if the request is successful or an error code if the request failed. 1344 */ requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result)1345 public void requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result) { 1346 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1347 if (satelliteSupported == null) { 1348 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1349 return; 1350 } 1351 if (!satelliteSupported) { 1352 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null); 1353 return; 1354 } 1355 1356 synchronized (mSatelliteCapabilitiesLock) { 1357 if (mSatelliteCapabilities != null) { 1358 Bundle bundle = new Bundle(); 1359 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES, 1360 mSatelliteCapabilities); 1361 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle); 1362 return; 1363 } 1364 } 1365 1366 sendRequestAsync(CMD_GET_SATELLITE_CAPABILITIES, result, SatelliteServiceUtils.getPhone()); 1367 } 1368 1369 /** 1370 * Start receiving satellite transmission updates. 1371 * This can be called by the pointing UI when the user starts pointing to the satellite. 1372 * Modem should continue to report the pointing input as the device or satellite moves. 1373 * 1374 * @param subId The subId of the subscription to start satellite transmission updates for. 1375 * @param errorCallback The callback to get the error code of the request. 1376 * @param callback The callback to notify of satellite transmission updates. 1377 */ startSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback, @NonNull ISatelliteTransmissionUpdateCallback callback)1378 public void startSatelliteTransmissionUpdates(int subId, 1379 @NonNull IIntegerConsumer errorCallback, 1380 @NonNull ISatelliteTransmissionUpdateCallback callback) { 1381 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept); 1382 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1383 if (satelliteSupported == null) { 1384 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1385 return; 1386 } 1387 if (!satelliteSupported) { 1388 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED); 1389 return; 1390 } 1391 1392 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1393 if (satelliteProvisioned == null) { 1394 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1395 return; 1396 } 1397 if (!satelliteProvisioned) { 1398 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED); 1399 return; 1400 } 1401 1402 Phone phone = SatelliteServiceUtils.getPhone(); 1403 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1404 mPointingAppController.registerForSatelliteTransmissionUpdates(validSubId, callback, phone); 1405 sendRequestAsync(CMD_START_SATELLITE_TRANSMISSION_UPDATES, 1406 new SatelliteTransmissionUpdateArgument(result, callback, validSubId), phone); 1407 } 1408 1409 /** 1410 * Stop receiving satellite transmission updates. 1411 * This can be called by the pointing UI when the user stops pointing to the satellite. 1412 * 1413 * @param subId The subId of the subscription to stop satellite transmission updates for. 1414 * @param errorCallback The callback to get the error code of the request. 1415 * @param callback The callback that was passed to {@link #startSatelliteTransmissionUpdates( 1416 * int, IIntegerConsumer, ISatelliteTransmissionUpdateCallback)}. 1417 */ stopSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback, @NonNull ISatelliteTransmissionUpdateCallback callback)1418 public void stopSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback, 1419 @NonNull ISatelliteTransmissionUpdateCallback callback) { 1420 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept); 1421 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1422 if (satelliteSupported == null) { 1423 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1424 return; 1425 } 1426 if (!satelliteSupported) { 1427 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED); 1428 return; 1429 } 1430 1431 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1432 if (satelliteProvisioned == null) { 1433 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1434 return; 1435 } 1436 if (!satelliteProvisioned) { 1437 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED); 1438 return; 1439 } 1440 1441 Phone phone = SatelliteServiceUtils.getPhone(); 1442 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1443 mPointingAppController.unregisterForSatelliteTransmissionUpdates( 1444 validSubId, result, callback, phone); 1445 1446 // Even if handler is null - which means there are no listeners, the modem command to stop 1447 // satellite transmission updates might have failed. The callers might want to retry 1448 // sending the command. Thus, we always need to send this command to the modem. 1449 sendRequestAsync(CMD_STOP_SATELLITE_TRANSMISSION_UPDATES, result, phone); 1450 } 1451 1452 /** 1453 * Register the subscription with a satellite provider. 1454 * This is needed to register the subscription if the provider allows dynamic registration. 1455 * 1456 * @param subId The subId of the subscription to be provisioned. 1457 * @param token The token to be used as a unique identifier for provisioning with satellite 1458 * gateway. 1459 * @param provisionData Data from the provisioning app that can be used by provisioning server 1460 * @param callback The callback to get the error code of the request. 1461 * 1462 * @return The signal transport used by the caller to cancel the provision request, 1463 * or {@code null} if the request failed. 1464 */ provisionSatelliteService(int subId, @NonNull String token, @NonNull byte[] provisionData, @NonNull IIntegerConsumer callback)1465 @Nullable public ICancellationSignal provisionSatelliteService(int subId, 1466 @NonNull String token, @NonNull byte[] provisionData, 1467 @NonNull IIntegerConsumer callback) { 1468 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1469 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1470 if (satelliteSupported == null) { 1471 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1472 return null; 1473 } 1474 if (!satelliteSupported) { 1475 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED); 1476 return null; 1477 } 1478 1479 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1480 if (mSatelliteProvisionCallbacks.containsKey(validSubId)) { 1481 result.accept(SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS); 1482 return null; 1483 } 1484 1485 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1486 if (satelliteProvisioned != null && satelliteProvisioned) { 1487 result.accept(SatelliteManager.SATELLITE_ERROR_NONE); 1488 return null; 1489 } 1490 1491 Phone phone = SatelliteServiceUtils.getPhone(); 1492 sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE, 1493 new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId), 1494 phone); 1495 1496 ICancellationSignal cancelTransport = CancellationSignal.createTransport(); 1497 CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> { 1498 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE, 1499 new ProvisionSatelliteServiceArgument(token, provisionData, null, 1500 validSubId), phone); 1501 mProvisionMetricsStats.setIsCanceled(true); 1502 }); 1503 return cancelTransport; 1504 } 1505 1506 /** 1507 * Unregister the device/subscription with the satellite provider. 1508 * This is needed if the provider allows dynamic registration. Once deprovisioned, 1509 * {@link android.telephony.satellite.SatelliteProvisionStateCallback 1510 * #onSatelliteProvisionStateChanged(boolean)} 1511 * should report as deprovisioned. 1512 * 1513 * @param subId The subId of the subscription to be deprovisioned. 1514 * @param token The token of the device/subscription to be deprovisioned. 1515 * @param callback The callback to get the error code of the request. 1516 */ deprovisionSatelliteService(int subId, @NonNull String token, @NonNull IIntegerConsumer callback)1517 public void deprovisionSatelliteService(int subId, 1518 @NonNull String token, @NonNull IIntegerConsumer callback) { 1519 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1520 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1521 if (satelliteSupported == null) { 1522 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1523 return; 1524 } 1525 if (!satelliteSupported) { 1526 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED); 1527 return; 1528 } 1529 1530 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1531 if (satelliteProvisioned == null) { 1532 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1533 return; 1534 } 1535 if (!satelliteProvisioned) { 1536 result.accept(SatelliteManager.SATELLITE_ERROR_NONE); 1537 return; 1538 } 1539 1540 Phone phone = SatelliteServiceUtils.getPhone(); 1541 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1542 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE, 1543 new ProvisionSatelliteServiceArgument(token, null, result, validSubId), 1544 phone); 1545 } 1546 1547 /** 1548 * Registers for the satellite provision state changed. 1549 * 1550 * @param subId The subId of the subscription to register for provision state changed. 1551 * @param callback The callback to handle the satellite provision state changed event. 1552 * 1553 * @return The {@link SatelliteManager.SatelliteError} result of the operation. 1554 */ registerForSatelliteProvisionStateChanged(int subId, @NonNull ISatelliteProvisionStateCallback callback)1555 @SatelliteManager.SatelliteError public int registerForSatelliteProvisionStateChanged(int subId, 1556 @NonNull ISatelliteProvisionStateCallback callback) { 1557 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1558 if (satelliteSupported == null) { 1559 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 1560 } 1561 if (!satelliteSupported) { 1562 return SatelliteManager.SATELLITE_NOT_SUPPORTED; 1563 } 1564 1565 mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback); 1566 return SatelliteManager.SATELLITE_ERROR_NONE; 1567 } 1568 1569 /** 1570 * Unregisters for the satellite provision state changed. 1571 * If callback was not registered before, the request will be ignored. 1572 * 1573 * @param subId The subId of the subscription to unregister for provision state changed. 1574 * @param callback The callback that was passed to 1575 * {@link #registerForSatelliteProvisionStateChanged(int, ISatelliteProvisionStateCallback)}. 1576 */ unregisterForSatelliteProvisionStateChanged( int subId, @NonNull ISatelliteProvisionStateCallback callback)1577 public void unregisterForSatelliteProvisionStateChanged( 1578 int subId, @NonNull ISatelliteProvisionStateCallback callback) { 1579 mSatelliteProvisionStateChangedListeners.remove(callback.asBinder()); 1580 } 1581 1582 /** 1583 * Request to get whether the device is provisioned with a satellite provider. 1584 * 1585 * @param subId The subId of the subscription to get whether the device is provisioned for. 1586 * @param result The result receiver that returns whether the device is provisioned with a 1587 * satellite provider if the request is successful or an error code if the 1588 * request failed. 1589 */ requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result)1590 public void requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result) { 1591 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1592 if (satelliteSupported == null) { 1593 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1594 return; 1595 } 1596 if (!satelliteSupported) { 1597 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null); 1598 return; 1599 } 1600 1601 synchronized (mIsSatelliteProvisionedLock) { 1602 if (mIsSatelliteProvisioned != null) { 1603 Bundle bundle = new Bundle(); 1604 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, 1605 mIsSatelliteProvisioned); 1606 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle); 1607 return; 1608 } 1609 } 1610 1611 sendRequestAsync(CMD_IS_SATELLITE_PROVISIONED, result, SatelliteServiceUtils.getPhone()); 1612 } 1613 1614 /** 1615 * Registers for modem state changed from satellite modem. 1616 * 1617 * @param subId The subId of the subscription to register for satellite modem state changed. 1618 * @param callback The callback to handle the satellite modem state changed event. 1619 * 1620 * @return The {@link SatelliteManager.SatelliteError} result of the operation. 1621 */ registerForSatelliteModemStateChanged(int subId, @NonNull ISatelliteStateCallback callback)1622 @SatelliteManager.SatelliteError public int registerForSatelliteModemStateChanged(int subId, 1623 @NonNull ISatelliteStateCallback callback) { 1624 if (mSatelliteSessionController != null) { 1625 mSatelliteSessionController.registerForSatelliteModemStateChanged(callback); 1626 } else { 1627 loge("registerForSatelliteModemStateChanged: mSatelliteSessionController" 1628 + " is not initialized yet"); 1629 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE; 1630 } 1631 return SatelliteManager.SATELLITE_ERROR_NONE; 1632 } 1633 1634 /** 1635 * Unregisters for modem state changed from satellite modem. 1636 * If callback was not registered before, the request will be ignored. 1637 * 1638 * @param subId The subId of the subscription to unregister for satellite modem state changed. 1639 * @param callback The callback that was passed to 1640 * {@link #registerForSatelliteModemStateChanged(int, ISatelliteStateCallback)}. 1641 */ unregisterForSatelliteModemStateChanged(int subId, @NonNull ISatelliteStateCallback callback)1642 public void unregisterForSatelliteModemStateChanged(int subId, 1643 @NonNull ISatelliteStateCallback callback) { 1644 if (mSatelliteSessionController != null) { 1645 mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback); 1646 } else { 1647 loge("registerForSatelliteModemStateChanged: mSatelliteSessionController" 1648 + " is not initialized yet"); 1649 } 1650 } 1651 1652 /** 1653 * Register to receive incoming datagrams over satellite. 1654 * 1655 * @param subId The subId of the subscription to register for incoming satellite datagrams. 1656 * @param callback The callback to handle incoming datagrams over satellite. 1657 * 1658 * @return The {@link SatelliteManager.SatelliteError} result of the operation. 1659 */ registerForSatelliteDatagram(int subId, @NonNull ISatelliteDatagramCallback callback)1660 @SatelliteManager.SatelliteError public int registerForSatelliteDatagram(int subId, 1661 @NonNull ISatelliteDatagramCallback callback) { 1662 return mDatagramController.registerForSatelliteDatagram(subId, callback); 1663 } 1664 1665 /** 1666 * Unregister to stop receiving incoming datagrams over satellite. 1667 * If callback was not registered before, the request will be ignored. 1668 * 1669 * @param subId The subId of the subscription to unregister for incoming satellite datagrams. 1670 * @param callback The callback that was passed to 1671 * {@link #registerForSatelliteDatagram(int, ISatelliteDatagramCallback)}. 1672 */ unregisterForSatelliteDatagram(int subId, @NonNull ISatelliteDatagramCallback callback)1673 public void unregisterForSatelliteDatagram(int subId, 1674 @NonNull ISatelliteDatagramCallback callback) { 1675 mDatagramController.unregisterForSatelliteDatagram(subId, callback); 1676 } 1677 1678 /** 1679 * Poll pending satellite datagrams over satellite. 1680 * 1681 * This method requests modem to check if there are any pending datagrams to be received over 1682 * satellite. If there are any incoming datagrams, they will be received via 1683 * {@link android.telephony.satellite.SatelliteDatagramCallback#onSatelliteDatagramReceived( 1684 * long, SatelliteDatagram, int, Consumer)} 1685 * 1686 * @param subId The subId of the subscription used for receiving datagrams. 1687 * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request. 1688 */ pollPendingSatelliteDatagrams(int subId, @NonNull IIntegerConsumer callback)1689 public void pollPendingSatelliteDatagrams(int subId, @NonNull IIntegerConsumer callback) { 1690 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1691 1692 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1693 if (satelliteProvisioned == null) { 1694 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1695 return; 1696 } 1697 if (!satelliteProvisioned) { 1698 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED); 1699 return; 1700 } 1701 1702 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1703 mDatagramController.pollPendingSatelliteDatagrams(validSubId, result); 1704 } 1705 1706 /** 1707 * Send datagram over satellite. 1708 * 1709 * Gateway encodes SOS message or location sharing message into a datagram and passes it as 1710 * input to this method. Datagram received here will be passed down to modem without any 1711 * encoding or encryption. 1712 * 1713 * @param subId The subId of the subscription to send satellite datagrams for. 1714 * @param datagramType datagram type indicating whether the datagram is of type 1715 * SOS_SMS or LOCATION_SHARING. 1716 * @param datagram encoded gateway datagram which is encrypted by the caller. 1717 * Datagram will be passed down to modem without any encoding or encryption. 1718 * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in 1719 * full screen mode. 1720 * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request. 1721 */ sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType, SatelliteDatagram datagram, boolean needFullScreenPointingUI, @NonNull IIntegerConsumer callback)1722 public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType, 1723 SatelliteDatagram datagram, boolean needFullScreenPointingUI, 1724 @NonNull IIntegerConsumer callback) { 1725 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept); 1726 1727 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1728 if (satelliteProvisioned == null) { 1729 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 1730 return; 1731 } 1732 if (!satelliteProvisioned) { 1733 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED); 1734 return; 1735 } 1736 1737 /** 1738 * TODO for NTN-based satellites: Check if satellite is acquired. 1739 */ 1740 if (mNeedsSatellitePointing) { 1741 mPointingAppController.startPointingUI(needFullScreenPointingUI); 1742 } 1743 1744 final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext); 1745 mDatagramController.sendSatelliteDatagram(validSubId, datagramType, datagram, 1746 needFullScreenPointingUI, result); 1747 } 1748 1749 /** 1750 * Request to get whether satellite communication is allowed for the current location. 1751 * 1752 * @param subId The subId of the subscription to check whether satellite communication is 1753 * allowed for the current location for. 1754 * @param result The result receiver that returns whether satellite communication is allowed 1755 * for the current location if the request is successful or an error code 1756 * if the request failed. 1757 */ requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId, @NonNull ResultReceiver result)1758 public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId, 1759 @NonNull ResultReceiver result) { 1760 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1761 if (satelliteSupported == null) { 1762 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1763 return; 1764 } 1765 if (!satelliteSupported) { 1766 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null); 1767 return; 1768 } 1769 1770 sendRequestAsync( 1771 CMD_IS_SATELLITE_COMMUNICATION_ALLOWED, result, SatelliteServiceUtils.getPhone()); 1772 } 1773 1774 /** 1775 * Request to get the time after which the satellite will be visible. 1776 * 1777 * @param subId The subId to get the time after which the satellite will be visible for. 1778 * @param result The result receiver that returns the time after which the satellite will 1779 * be visible if the request is successful or an error code if the request failed. 1780 */ requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result)1781 public void requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result) { 1782 Boolean satelliteSupported = isSatelliteSupportedInternal(); 1783 if (satelliteSupported == null) { 1784 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1785 return; 1786 } 1787 if (!satelliteSupported) { 1788 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null); 1789 return; 1790 } 1791 1792 Boolean satelliteProvisioned = isSatelliteProvisioned(); 1793 if (satelliteProvisioned == null) { 1794 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null); 1795 return; 1796 } 1797 if (!satelliteProvisioned) { 1798 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null); 1799 return; 1800 } 1801 1802 Phone phone = SatelliteServiceUtils.getPhone(); 1803 sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, phone); 1804 } 1805 1806 /** 1807 * Inform whether the device is aligned with satellite for demo mode. 1808 * 1809 * @param subId The subId of the subscription. 1810 * @param isAligned {@true} means device is aligned with the satellite, otherwise {@false}. 1811 */ onDeviceAlignedWithSatellite(@onNull int subId, @NonNull boolean isAligned)1812 public void onDeviceAlignedWithSatellite(@NonNull int subId, @NonNull boolean isAligned) { 1813 mDatagramController.onDeviceAlignedWithSatellite(isAligned); 1814 } 1815 1816 /** 1817 * This API can be used by only CTS to update satellite vendor service package name. 1818 * 1819 * @param servicePackageName The package name of the satellite vendor service. 1820 * @return {@code true} if the satellite vendor service is set successfully, 1821 * {@code false} otherwise. 1822 */ setSatelliteServicePackageName(@ullable String servicePackageName)1823 public boolean setSatelliteServicePackageName(@Nullable String servicePackageName) { 1824 if (!isMockModemAllowed()) return false; 1825 1826 // Cached states need to be cleared whenever switching satellite vendor services. 1827 logd("setSatelliteServicePackageName: Resetting cached states"); 1828 synchronized (mIsSatelliteSupportedLock) { 1829 mIsSatelliteSupported = null; 1830 } 1831 synchronized (mIsSatelliteProvisionedLock) { 1832 mIsSatelliteProvisioned = null; 1833 } 1834 synchronized (mIsSatelliteEnabledLock) { 1835 mIsSatelliteEnabled = null; 1836 } 1837 synchronized (mSatelliteCapabilitiesLock) { 1838 mSatelliteCapabilities = null; 1839 } 1840 mSatelliteModemInterface.setSatelliteServicePackageName(servicePackageName); 1841 return true; 1842 } 1843 1844 /** 1845 * This API can be used by only CTS to update the timeout duration in milliseconds that 1846 * satellite should stay at listening mode to wait for the next incoming page before disabling 1847 * listening mode. 1848 * 1849 * @param timeoutMillis The timeout duration in millisecond. 1850 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 1851 */ setSatelliteListeningTimeoutDuration(long timeoutMillis)1852 public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) { 1853 if (mSatelliteSessionController == null) { 1854 loge("mSatelliteSessionController is not initialized yet"); 1855 return false; 1856 } 1857 return mSatelliteSessionController.setSatelliteListeningTimeoutDuration(timeoutMillis); 1858 } 1859 1860 /** 1861 * This API can be used by only CTS to update the timeout duration in milliseconds whether 1862 * the device is aligned with the satellite for demo mode 1863 * 1864 * @param timeoutMillis The timeout duration in millisecond. 1865 * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise. 1866 */ setSatelliteDeviceAlignedTimeoutDuration(long timeoutMillis)1867 public boolean setSatelliteDeviceAlignedTimeoutDuration(long timeoutMillis) { 1868 return mDatagramController.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis); 1869 } 1870 1871 /** 1872 * This API can be used by only CTS to update satellite gateway service package name. 1873 * 1874 * @param servicePackageName The package name of the satellite gateway service. 1875 * @return {@code true} if the satellite gateway service is set successfully, 1876 * {@code false} otherwise. 1877 */ setSatelliteGatewayServicePackageName(@ullable String servicePackageName)1878 public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) { 1879 if (mSatelliteSessionController == null) { 1880 loge("mSatelliteSessionController is not initialized yet"); 1881 return false; 1882 } 1883 return mSatelliteSessionController.setSatelliteGatewayServicePackageName( 1884 servicePackageName); 1885 } 1886 1887 /** 1888 * This API can be used by only CTS to update satellite pointing UI app package and class names. 1889 * 1890 * @param packageName The package name of the satellite pointing UI app. 1891 * @param className The class name of the satellite pointing UI app. 1892 * @return {@code true} if the satellite pointing UI app package and class is set successfully, 1893 * {@code false} otherwise. 1894 */ setSatellitePointingUiClassName( @ullable String packageName, @Nullable String className)1895 public boolean setSatellitePointingUiClassName( 1896 @Nullable String packageName, @Nullable String className) { 1897 return mPointingAppController.setSatellitePointingUiClassName(packageName, className); 1898 } 1899 1900 /** 1901 * This function is used by {@link SatelliteModemInterface} to notify 1902 * {@link SatelliteController} that the satellite vendor service was just connected. 1903 * <p> 1904 * {@link SatelliteController} will send requests to satellite modem to check whether it support 1905 * satellite and whether it is provisioned. {@link SatelliteController} will use these cached 1906 * values to serve requests from its clients. 1907 * <p> 1908 * Because satellite vendor service might have just come back from a crash, we need to disable 1909 * the satellite modem so that resources will be cleaned up and internal states will be reset. 1910 */ 1911 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) onSatelliteServiceConnected()1912 public void onSatelliteServiceConnected() { 1913 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 1914 synchronized (mIsSatelliteSupportedLock) { 1915 if (mIsSatelliteSupported == null) { 1916 ResultReceiver receiver = new ResultReceiver(this) { 1917 @Override 1918 protected void onReceiveResult( 1919 int resultCode, Bundle resultData) { 1920 logd("requestIsSatelliteSupported: resultCode=" 1921 + resultCode); 1922 } 1923 }; 1924 requestIsSatelliteSupported( 1925 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, receiver); 1926 } 1927 } 1928 } else { 1929 logd("onSatelliteServiceConnected: Satellite vendor service is not supported." 1930 + " Ignored the event"); 1931 } 1932 } 1933 1934 /** 1935 * @return {@code true} is satellite is supported on the device, {@code false} otherwise. 1936 */ isSatelliteSupported()1937 public boolean isSatelliteSupported() { 1938 Boolean supported = isSatelliteSupportedInternal(); 1939 return (supported != null ? supported : false); 1940 } 1941 1942 /** 1943 * @return The list of satellite PLMNs used for connecting to satellite networks. 1944 */ 1945 @NonNull getSatellitePlmnList()1946 public List<String> getSatellitePlmnList() { 1947 return new ArrayList<>(mSatellitePlmnList); 1948 } 1949 1950 /** 1951 * @param subId Subscription ID. 1952 * @param plmn The satellite roaming plmn. 1953 * @return The list of services supported by the carrier associated with the {@code subId} for 1954 * the satellite network {@code plmn}. 1955 */ 1956 @NonNull getSupportedSatelliteServices(int subId, String plmn)1957 public List<Integer> getSupportedSatelliteServices(int subId, String plmn) { 1958 synchronized (mSupportedSatelliteServicesLock) { 1959 if (mSupportedSatelliteServices.containsKey(subId)) { 1960 Map<String, Set<Integer>> supportedServices = 1961 mSupportedSatelliteServices.get(subId); 1962 if (supportedServices != null && supportedServices.containsKey(plmn)) { 1963 return new ArrayList<>(supportedServices.get(plmn)); 1964 } else { 1965 loge("getSupportedSatelliteServices: subId=" + subId + ", supportedServices " 1966 + "does not contain key plmn=" + plmn); 1967 } 1968 } else { 1969 loge("getSupportedSatelliteServices: mSupportedSatelliteServices does contain key" 1970 + " subId=" + subId); 1971 } 1972 return new ArrayList<>(); 1973 } 1974 } 1975 1976 /** 1977 * If we have not successfully queried the satellite modem for its satellite service support, 1978 * we will retry the query one more time. Otherwise, we will return the cached result. 1979 */ isSatelliteSupportedInternal()1980 private Boolean isSatelliteSupportedInternal() { 1981 synchronized (mIsSatelliteSupportedLock) { 1982 if (mIsSatelliteSupported != null) { 1983 /* We have already successfully queried the satellite modem. */ 1984 return mIsSatelliteSupported; 1985 } 1986 } 1987 /** 1988 * We have not successfully checked whether the modem supports satellite service. 1989 * Thus, we need to retry it now. 1990 */ 1991 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 1992 new ResultReceiver(this) { 1993 @Override 1994 protected void onReceiveResult(int resultCode, Bundle resultData) { 1995 logd("requestIsSatelliteSupported: resultCode=" + resultCode); 1996 } 1997 }); 1998 return null; 1999 } 2000 handleEventProvisionSatelliteServiceDone( @onNull ProvisionSatelliteServiceArgument arg, @SatelliteManager.SatelliteError int result)2001 private void handleEventProvisionSatelliteServiceDone( 2002 @NonNull ProvisionSatelliteServiceArgument arg, 2003 @SatelliteManager.SatelliteError int result) { 2004 logd("handleEventProvisionSatelliteServiceDone: result=" 2005 + result + ", subId=" + arg.subId); 2006 2007 Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId); 2008 if (callback == null) { 2009 loge("handleEventProvisionSatelliteServiceDone: callback is null for subId=" 2010 + arg.subId); 2011 mProvisionMetricsStats 2012 .setResultCode(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE) 2013 .setIsProvisionRequest(true) 2014 .reportProvisionMetrics(); 2015 mControllerMetricsStats.reportProvisionCount( 2016 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 2017 return; 2018 } 2019 callback.accept(result); 2020 } 2021 handleEventDeprovisionSatelliteServiceDone( @onNull ProvisionSatelliteServiceArgument arg, @SatelliteManager.SatelliteError int result)2022 private void handleEventDeprovisionSatelliteServiceDone( 2023 @NonNull ProvisionSatelliteServiceArgument arg, 2024 @SatelliteManager.SatelliteError int result) { 2025 if (arg == null) { 2026 loge("handleEventDeprovisionSatelliteServiceDone: arg is null"); 2027 return; 2028 } 2029 logd("handleEventDeprovisionSatelliteServiceDone: result=" 2030 + result + ", subId=" + arg.subId); 2031 2032 if (arg.callback != null) { 2033 arg.callback.accept(result); 2034 mProvisionMetricsStats.setResultCode(result) 2035 .setIsProvisionRequest(false) 2036 .reportProvisionMetrics(); 2037 mControllerMetricsStats.reportDeprovisionCount(result); 2038 } 2039 } 2040 handleStartSatelliteTransmissionUpdatesDone(@onNull AsyncResult ar)2041 private void handleStartSatelliteTransmissionUpdatesDone(@NonNull AsyncResult ar) { 2042 SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj; 2043 SatelliteTransmissionUpdateArgument arg = 2044 (SatelliteTransmissionUpdateArgument) request.argument; 2045 int errorCode = SatelliteServiceUtils.getSatelliteError(ar, 2046 "handleStartSatelliteTransmissionUpdatesDone"); 2047 arg.errorCallback.accept(errorCode); 2048 2049 if (errorCode != SatelliteManager.SATELLITE_ERROR_NONE) { 2050 mPointingAppController.setStartedSatelliteTransmissionUpdates(false); 2051 // We need to remove the callback from our listener list since the caller might not call 2052 // stopSatelliteTransmissionUpdates to unregister the callback in case of failure. 2053 mPointingAppController.unregisterForSatelliteTransmissionUpdates(arg.subId, 2054 arg.errorCallback, arg.callback, request.phone); 2055 } else { 2056 mPointingAppController.setStartedSatelliteTransmissionUpdates(true); 2057 } 2058 } 2059 2060 /** 2061 * Posts the specified command to be executed on the main thread and returns immediately. 2062 * 2063 * @param command command to be executed on the main thread 2064 * @param argument additional parameters required to perform of the operation 2065 * @param phone phone object used to perform the operation. 2066 */ sendRequestAsync(int command, @NonNull Object argument, @Nullable Phone phone)2067 private void sendRequestAsync(int command, @NonNull Object argument, @Nullable Phone phone) { 2068 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 2069 argument, phone); 2070 Message msg = this.obtainMessage(command, request); 2071 msg.sendToTarget(); 2072 } 2073 2074 /** 2075 * Posts the specified command to be executed on the main thread. As this is a synchronous 2076 * request, it waits until the request is complete and then return the result. 2077 * 2078 * @param command command to be executed on the main thread 2079 * @param argument additional parameters required to perform of the operation 2080 * @param phone phone object used to perform the operation. 2081 * @return result of the operation 2082 */ sendRequest(int command, @NonNull Object argument, @Nullable Phone phone)2083 private @Nullable Object sendRequest(int command, @NonNull Object argument, 2084 @Nullable Phone phone) { 2085 if (Looper.myLooper() == this.getLooper()) { 2086 throw new RuntimeException("This method will deadlock if called from the main thread"); 2087 } 2088 2089 SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest( 2090 argument, phone); 2091 Message msg = this.obtainMessage(command, request); 2092 msg.sendToTarget(); 2093 2094 synchronized (request) { 2095 while(request.result == null) { 2096 try { 2097 request.wait(); 2098 } catch (InterruptedException e) { 2099 // Do nothing, go back and wait until the request is complete. 2100 } 2101 } 2102 } 2103 return request.result; 2104 } 2105 2106 /** 2107 * Check if satellite is provisioned for a subscription on the device. 2108 * @return true if satellite is provisioned on the given subscription else return false. 2109 */ 2110 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) isSatelliteProvisioned()2111 protected Boolean isSatelliteProvisioned() { 2112 synchronized (mIsSatelliteProvisionedLock) { 2113 if (mIsSatelliteProvisioned != null) { 2114 return mIsSatelliteProvisioned; 2115 } 2116 } 2117 2118 requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 2119 new ResultReceiver(this) { 2120 @Override 2121 protected void onReceiveResult(int resultCode, Bundle resultData) { 2122 logd("requestIsSatelliteProvisioned: resultCode=" + resultCode); 2123 } 2124 }); 2125 return null; 2126 } 2127 handleSatelliteEnabled(SatelliteControllerHandlerRequest request)2128 private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) { 2129 RequestSatelliteEnabledArgument argument = 2130 (RequestSatelliteEnabledArgument) request.argument; 2131 Phone phone = request.phone; 2132 2133 if (!argument.enableSatellite && (mSatelliteModemInterface.isSatelliteServiceSupported() 2134 || phone != null)) { 2135 synchronized (mIsSatelliteEnabledLock) { 2136 mWaitingForDisableSatelliteModemResponse = true; 2137 mWaitingForSatelliteModemOff = true; 2138 } 2139 } 2140 2141 Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request); 2142 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 2143 mSatelliteModemInterface.requestSatelliteEnabled(argument.enableSatellite, 2144 argument.enableDemoMode, onCompleted); 2145 return; 2146 } 2147 2148 if (phone != null) { 2149 phone.setSatellitePower(onCompleted, argument.enableSatellite); 2150 } else { 2151 loge("requestSatelliteEnabled: No phone object"); 2152 argument.callback.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE); 2153 } 2154 } 2155 updateSatelliteSupportedStateWhenSatelliteServiceConnected(boolean supported)2156 private void updateSatelliteSupportedStateWhenSatelliteServiceConnected(boolean supported) { 2157 synchronized (mIsSatelliteSupportedLock) { 2158 mIsSatelliteSupported = supported; 2159 } 2160 mSatelliteSessionController = SatelliteSessionController.make( 2161 mContext, getLooper(), supported); 2162 if (supported) { 2163 registerForSatelliteProvisionStateChanged(); 2164 registerForPendingDatagramCount(); 2165 registerForSatelliteModemStateChanged(); 2166 2167 requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 2168 new ResultReceiver(this) { 2169 @Override 2170 protected void onReceiveResult(int resultCode, Bundle resultData) { 2171 logd("requestIsSatelliteProvisioned: resultCode=" + resultCode); 2172 requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 2173 false, false, 2174 new IIntegerConsumer.Stub() { 2175 @Override 2176 public void accept(int result) { 2177 logd("requestSatelliteEnabled: result=" + result); 2178 } 2179 }); 2180 } 2181 }); 2182 requestSatelliteCapabilities(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, 2183 new ResultReceiver(this) { 2184 @Override 2185 protected void onReceiveResult(int resultCode, Bundle resultData) { 2186 logd("requestSatelliteCapabilities: resultCode=" + resultCode); 2187 } 2188 }); 2189 } 2190 } 2191 updateSatelliteEnabledState(boolean enabled, String caller)2192 private void updateSatelliteEnabledState(boolean enabled, String caller) { 2193 synchronized (mIsSatelliteEnabledLock) { 2194 mIsSatelliteEnabled = enabled; 2195 } 2196 if (mSatelliteSessionController != null) { 2197 mSatelliteSessionController.onSatelliteEnabledStateChanged(enabled); 2198 mSatelliteSessionController.setDemoMode(mIsDemoModeEnabled); 2199 } else { 2200 loge(caller + ": mSatelliteSessionController is not initialized yet"); 2201 } 2202 } 2203 registerForSatelliteProvisionStateChanged()2204 private void registerForSatelliteProvisionStateChanged() { 2205 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 2206 if (!mRegisteredForProvisionStateChangedWithSatelliteService.get()) { 2207 mSatelliteModemInterface.registerForSatelliteProvisionStateChanged( 2208 this, EVENT_SATELLITE_PROVISION_STATE_CHANGED, null); 2209 mRegisteredForProvisionStateChangedWithSatelliteService.set(true); 2210 } 2211 } else { 2212 Phone phone = SatelliteServiceUtils.getPhone(); 2213 if (phone == null) { 2214 loge("registerForSatelliteProvisionStateChanged: phone is null"); 2215 } else if (!mRegisteredForProvisionStateChangedWithPhone.get()) { 2216 phone.registerForSatelliteProvisionStateChanged( 2217 this, EVENT_SATELLITE_PROVISION_STATE_CHANGED, null); 2218 mRegisteredForProvisionStateChangedWithPhone.set(true); 2219 } 2220 } 2221 } 2222 registerForPendingDatagramCount()2223 private void registerForPendingDatagramCount() { 2224 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 2225 if (!mRegisteredForPendingDatagramCountWithSatelliteService.get()) { 2226 mSatelliteModemInterface.registerForPendingDatagrams( 2227 this, EVENT_PENDING_DATAGRAMS, null); 2228 mRegisteredForPendingDatagramCountWithSatelliteService.set(true); 2229 } 2230 } else { 2231 Phone phone = SatelliteServiceUtils.getPhone(); 2232 if (phone == null) { 2233 loge("registerForPendingDatagramCount: satellite phone is " 2234 + "not initialized yet"); 2235 } else if (!mRegisteredForPendingDatagramCountWithPhone.get()) { 2236 phone.registerForPendingDatagramCount(this, EVENT_PENDING_DATAGRAMS, null); 2237 mRegisteredForPendingDatagramCountWithPhone.set(true); 2238 } 2239 } 2240 } 2241 registerForSatelliteModemStateChanged()2242 private void registerForSatelliteModemStateChanged() { 2243 if (mSatelliteModemInterface.isSatelliteServiceSupported()) { 2244 if (!mRegisteredForSatelliteModemStateChangedWithSatelliteService.get()) { 2245 mSatelliteModemInterface.registerForSatelliteModemStateChanged( 2246 this, EVENT_SATELLITE_MODEM_STATE_CHANGED, null); 2247 mRegisteredForSatelliteModemStateChangedWithSatelliteService.set(true); 2248 } 2249 } else { 2250 Phone phone = SatelliteServiceUtils.getPhone(); 2251 if (phone == null) { 2252 loge("registerForSatelliteModemStateChanged: satellite phone is " 2253 + "not initialized yet"); 2254 } else if (!mRegisteredForSatelliteModemStateChangedWithPhone.get()) { 2255 phone.registerForSatelliteModemStateChanged( 2256 this, EVENT_SATELLITE_MODEM_STATE_CHANGED, null); 2257 mRegisteredForSatelliteModemStateChangedWithPhone.set(true); 2258 } 2259 } 2260 } 2261 handleEventSatelliteProvisionStateChanged(boolean provisioned)2262 private void handleEventSatelliteProvisionStateChanged(boolean provisioned) { 2263 logd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned); 2264 2265 synchronized (mIsSatelliteProvisionedLock) { 2266 mIsSatelliteProvisioned = provisioned; 2267 } 2268 2269 List<ISatelliteProvisionStateCallback> toBeRemoved = new ArrayList<>(); 2270 mSatelliteProvisionStateChangedListeners.values().forEach(listener -> { 2271 try { 2272 listener.onSatelliteProvisionStateChanged(provisioned); 2273 } catch (RemoteException e) { 2274 logd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e); 2275 toBeRemoved.add(listener); 2276 } 2277 }); 2278 toBeRemoved.forEach(listener -> { 2279 mSatelliteProvisionStateChangedListeners.remove(listener.asBinder()); 2280 }); 2281 } 2282 handleEventSatelliteModemStateChanged( @atelliteManager.SatelliteModemState int state)2283 private void handleEventSatelliteModemStateChanged( 2284 @SatelliteManager.SatelliteModemState int state) { 2285 logd("handleEventSatelliteModemStateChanged: state=" + state); 2286 if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE 2287 || state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) { 2288 synchronized (mIsSatelliteEnabledLock) { 2289 if ((state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) 2290 || ((mIsSatelliteEnabled == null || isSatelliteEnabled()) 2291 && !mWaitingForDisableSatelliteModemResponse)) { 2292 int error = (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) 2293 ? SatelliteManager.SATELLITE_ERROR_NONE 2294 : SatelliteManager.SATELLITE_INVALID_MODEM_STATE; 2295 Consumer<Integer> callback = null; 2296 synchronized (mSatelliteEnabledRequestLock) { 2297 if (mSatelliteEnabledRequest != null) { 2298 callback = mSatelliteEnabledRequest.callback; 2299 } 2300 } 2301 moveSatelliteToOffStateAndCleanUpResources(error, callback); 2302 } else { 2303 logd("Either waiting for the response of disabling satellite modem or the event" 2304 + " should be ignored because isSatelliteEnabled=" 2305 + isSatelliteEnabled() 2306 + ", mIsSatelliteEnabled=" + mIsSatelliteEnabled); 2307 } 2308 mWaitingForSatelliteModemOff = false; 2309 } 2310 } 2311 mDatagramController.onSatelliteModemStateChanged(state); 2312 } 2313 2314 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setSettingsKeyForSatelliteMode(int val)2315 protected void setSettingsKeyForSatelliteMode(int val) { 2316 logd("setSettingsKeyForSatelliteMode val: " + val); 2317 Settings.Global.putInt(mContext.getContentResolver(), 2318 Settings.Global.SATELLITE_MODE_ENABLED, val); 2319 } 2320 2321 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) areAllRadiosDisabled()2322 protected boolean areAllRadiosDisabled() { 2323 synchronized (mRadioStateLock) { 2324 if ((mDisableBTOnSatelliteEnabled && mBTStateEnabled) 2325 || (mDisableNFCOnSatelliteEnabled && mNfcStateEnabled) 2326 || (mDisableWifiOnSatelliteEnabled && mWifiStateEnabled) 2327 || (mDisableUWBOnSatelliteEnabled && mUwbStateEnabled)) { 2328 logd("All radios are not disabled yet."); 2329 return false; 2330 } 2331 logd("All radios are disabled."); 2332 return true; 2333 } 2334 } 2335 evaluateToSendSatelliteEnabledSuccess()2336 private void evaluateToSendSatelliteEnabledSuccess() { 2337 logd("evaluateToSendSatelliteEnabledSuccess"); 2338 synchronized (mSatelliteEnabledRequestLock) { 2339 if (areAllRadiosDisabled() && (mSatelliteEnabledRequest != null) 2340 && mWaitingForRadioDisabled) { 2341 logd("Sending success to callback that sent enable satellite request"); 2342 setDemoModeEnabled(mSatelliteEnabledRequest.enableDemoMode); 2343 synchronized (mIsSatelliteEnabledLock) { 2344 mIsSatelliteEnabled = mSatelliteEnabledRequest.enableSatellite; 2345 } 2346 mSatelliteEnabledRequest.callback.accept(SatelliteManager.SATELLITE_ERROR_NONE); 2347 updateSatelliteEnabledState( 2348 mSatelliteEnabledRequest.enableSatellite, 2349 "EVENT_SET_SATELLITE_ENABLED_DONE"); 2350 mSatelliteEnabledRequest = null; 2351 mWaitingForRadioDisabled = false; 2352 } 2353 } 2354 } 2355 resetSatelliteEnabledRequest()2356 private void resetSatelliteEnabledRequest() { 2357 logd("resetSatelliteEnabledRequest"); 2358 synchronized (mSatelliteEnabledRequestLock) { 2359 mSatelliteEnabledRequest = null; 2360 mWaitingForRadioDisabled = false; 2361 } 2362 } 2363 moveSatelliteToOffStateAndCleanUpResources( @atelliteManager.SatelliteError int error, @Nullable Consumer<Integer> callback)2364 private void moveSatelliteToOffStateAndCleanUpResources( 2365 @SatelliteManager.SatelliteError int error, @Nullable Consumer<Integer> callback) { 2366 logd("moveSatelliteToOffStateAndCleanUpResources"); 2367 synchronized (mIsSatelliteEnabledLock) { 2368 resetSatelliteEnabledRequest(); 2369 setDemoModeEnabled(false); 2370 mIsSatelliteEnabled = false; 2371 setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE); 2372 if (callback != null) callback.accept(error); 2373 updateSatelliteEnabledState( 2374 false, "moveSatelliteToOffStateAndCleanUpResources"); 2375 } 2376 } 2377 setDemoModeEnabled(boolean enabled)2378 private void setDemoModeEnabled(boolean enabled) { 2379 mIsDemoModeEnabled = enabled; 2380 mDatagramController.setDemoMode(mIsDemoModeEnabled); 2381 } 2382 isMockModemAllowed()2383 private boolean isMockModemAllowed() { 2384 return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); 2385 } 2386 updateSupportedSatelliteServicesForActiveSubscriptions()2387 private void updateSupportedSatelliteServicesForActiveSubscriptions() { 2388 synchronized (mSupportedSatelliteServicesLock) { 2389 mSupportedSatelliteServices.clear(); 2390 int[] activeSubIds = SubscriptionManagerService.getInstance().getActiveSubIdList(true); 2391 if (activeSubIds != null) { 2392 for (int subId : activeSubIds) { 2393 updateSupportedSatelliteServices(subId); 2394 } 2395 } else { 2396 loge("updateSupportedSatelliteServicesForActiveSubscriptions: " 2397 + "activeSubIds is null"); 2398 } 2399 } 2400 } 2401 updateSupportedSatelliteServices(int subId)2402 private void updateSupportedSatelliteServices(int subId) { 2403 Map<String, Set<Integer>> carrierSupportedSatelliteServicesPerPlmn = 2404 readSupportedSatelliteServicesFromCarrierConfig(subId); 2405 synchronized (mSupportedSatelliteServicesLock) { 2406 mSupportedSatelliteServices.put(subId, 2407 SatelliteServiceUtils.mergeSupportedSatelliteServices( 2408 mSatelliteServicesSupportedByProviders, 2409 carrierSupportedSatelliteServicesPerPlmn)); 2410 } 2411 } 2412 2413 @NonNull readSupportedSatelliteServicesFromOverlayConfig()2414 private Map<String, Set<Integer>> readSupportedSatelliteServicesFromOverlayConfig() { 2415 String[] supportedServices = readStringArrayFromOverlayConfig( 2416 R.array.config_satellite_services_supported_by_providers); 2417 return SatelliteServiceUtils.parseSupportedSatelliteServices(supportedServices); 2418 } 2419 2420 @NonNull readSupportedSatelliteServicesFromCarrierConfig(int subId)2421 private Map<String, Set<Integer>> readSupportedSatelliteServicesFromCarrierConfig(int subId) { 2422 synchronized (mCarrierConfigArrayLock) { 2423 PersistableBundle config = mCarrierConfigArray.get(subId); 2424 if (config == null) { 2425 config = getConfigForSubId(subId); 2426 mCarrierConfigArray.put(subId, config); 2427 } 2428 return SatelliteServiceUtils.parseSupportedSatelliteServices( 2429 config.getPersistableBundle(CarrierConfigManager 2430 .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE)); 2431 } 2432 } 2433 getConfigForSubId(int subId)2434 @NonNull private PersistableBundle getConfigForSubId(int subId) { 2435 PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId, 2436 CarrierConfigManager 2437 .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE); 2438 if (config == null || config.isEmpty()) { 2439 config = CarrierConfigManager.getDefaultConfig(); 2440 } 2441 return config; 2442 } 2443 handleCarrierConfigChanged(int slotIndex, int subId, int carrierId, int specificCarrierId)2444 private void handleCarrierConfigChanged(int slotIndex, int subId, int carrierId, 2445 int specificCarrierId) { 2446 logd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId(" 2447 + subId + "), carrierId(" + carrierId + "), specificCarrierId(" 2448 + specificCarrierId + ")"); 2449 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 2450 return; 2451 } 2452 2453 updateCarrierConfig(subId); 2454 updateSupportedSatelliteServicesForActiveSubscriptions(); 2455 } 2456 updateCarrierConfig(int subId)2457 private void updateCarrierConfig(int subId) { 2458 synchronized (mCarrierConfigArrayLock) { 2459 mCarrierConfigArray.put(subId, getConfigForSubId(subId)); 2460 } 2461 } 2462 2463 @NonNull readStringArrayFromOverlayConfig(@rrayRes int id)2464 private String[] readStringArrayFromOverlayConfig(@ArrayRes int id) { 2465 String[] strArray = null; 2466 try { 2467 strArray = mContext.getResources().getStringArray(id); 2468 } catch (Resources.NotFoundException ex) { 2469 loge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex); 2470 } 2471 if (strArray == null) { 2472 strArray = new String[0]; 2473 } 2474 return strArray; 2475 } 2476 logd(@onNull String log)2477 private static void logd(@NonNull String log) { 2478 Rlog.d(TAG, log); 2479 } 2480 loge(@onNull String log)2481 private static void loge(@NonNull String log) { 2482 Rlog.e(TAG, log); 2483 } 2484 } 2485