• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.NonNull;
20 import android.annotation.Nullable;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.ServiceConnection;
25 import android.os.AsyncResult;
26 import android.os.Binder;
27 import android.os.Handler;
28 import android.os.IBinder;
29 import android.os.Looper;
30 import android.os.Message;
31 import android.os.RegistrantList;
32 import android.os.RemoteException;
33 import android.telephony.IBooleanConsumer;
34 import android.telephony.IIntegerConsumer;
35 import android.telephony.PersistentLogger;
36 import android.telephony.satellite.NtnSignalStrength;
37 import android.telephony.satellite.SatelliteCapabilities;
38 import android.telephony.satellite.SatelliteDatagram;
39 import android.telephony.satellite.SatelliteManager;
40 import android.telephony.satellite.SatelliteManager.SatelliteException;
41 import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
42 import android.telephony.satellite.SystemSelectionSpecifier;
43 import android.telephony.satellite.stub.INtnSignalStrengthConsumer;
44 import android.telephony.satellite.stub.ISatellite;
45 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
46 import android.telephony.satellite.stub.ISatelliteListener;
47 import android.telephony.satellite.stub.SatelliteModemState;
48 import android.telephony.satellite.stub.SatelliteService;
49 import android.text.TextUtils;
50 import android.util.Log;
51 import android.util.Pair;
52 
53 import com.android.internal.R;
54 import com.android.internal.annotations.VisibleForTesting;
55 import com.android.internal.telephony.ExponentialBackoff;
56 import com.android.internal.telephony.flags.FeatureFlags;
57 
58 import java.util.Arrays;
59 import java.util.List;
60 
61 /**
62  * Satellite modem interface to manage connections with the satellite service and HAL interface.
63  */
64 public class SatelliteModemInterface {
65     private static final String TAG = "SatelliteModemInterface";
66     private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
67     private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
68     private static final int REBIND_MULTIPLIER = 2;
69 
70     @NonNull private static SatelliteModemInterface sInstance;
71     @NonNull private final Context mContext;
72     @NonNull private final DemoSimulator mDemoSimulator;
73     @NonNull private final SatelliteListener mVendorListener;
74     @NonNull private final SatelliteListener mDemoListener;
75     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
76     @NonNull protected final ExponentialBackoff mExponentialBackoff;
77     @NonNull private final Object mLock = new Object();
78     @NonNull private final SatelliteController mSatelliteController;
79     /**
80      * {@code true} to use the vendor satellite service and {@code false} to use the HAL.
81      */
82     private boolean mIsSatelliteServiceSupported;
83     @Nullable private ISatellite mSatelliteService;
84     @Nullable private SatelliteServiceConnection mSatelliteServiceConnection;
85     @NonNull private String mVendorSatellitePackageName = "";
86     private boolean mIsBound;
87     private boolean mIsBinding;
88     @Nullable private PersistentLogger mPersistentLogger = null;
89 
90     @NonNull private final RegistrantList mSatellitePositionInfoChangedRegistrants =
91             new RegistrantList();
92     @NonNull private final RegistrantList mDatagramTransferStateChangedRegistrants =
93             new RegistrantList();
94     @NonNull private final RegistrantList mSatelliteModemStateChangedRegistrants =
95             new RegistrantList();
96     @NonNull private final RegistrantList mPendingDatagramsRegistrants = new RegistrantList();
97     @NonNull private final RegistrantList mSatelliteDatagramsReceivedRegistrants =
98             new RegistrantList();
99     @NonNull private final RegistrantList mNtnSignalStrengthChangedRegistrants =
100             new RegistrantList();
101     @NonNull private final RegistrantList mSatelliteCapabilitiesChangedRegistrants =
102             new RegistrantList();
103     @NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants =
104             new RegistrantList();
105     @NonNull private final RegistrantList mSatelliteRegistrationFailureRegistrants =
106             new RegistrantList();
107     @NonNull private final RegistrantList mTerrestrialNetworkAvailableChangedRegistrants =
108             new RegistrantList();
109 
110     private class SatelliteListener extends ISatelliteListener.Stub {
111 
112         private final boolean mIsDemoListener;
113 
SatelliteListener(boolean isDemoListener)114         SatelliteListener(boolean isDemoListener) {
115             mIsDemoListener = isDemoListener;
116         }
117 
118         @Override
onSatelliteDatagramReceived( android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount)119         public void onSatelliteDatagramReceived(
120                 android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) {
121             if (notifyResultIfExpectedListener()) {
122                 plogd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
123                 mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>(
124                         SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount));
125             }
126         }
127 
128         @Override
onPendingDatagrams()129         public void onPendingDatagrams() {
130             if (notifyResultIfExpectedListener()) {
131                 plogd("onPendingDatagrams");
132                 mPendingDatagramsRegistrants.notifyResult(null);
133             }
134         }
135 
136         @Override
onSatellitePositionChanged( android.telephony.satellite.stub.PointingInfo pointingInfo)137         public void onSatellitePositionChanged(
138                 android.telephony.satellite.stub.PointingInfo pointingInfo) {
139             mSatellitePositionInfoChangedRegistrants.notifyResult(
140                     SatelliteServiceUtils.fromPointingInfo(pointingInfo));
141         }
142 
143         @Override
onSatelliteModemStateChanged(int state)144         public void onSatelliteModemStateChanged(int state) {
145             if (notifyModemStateChanged(state)) {
146                 mSatelliteModemStateChangedRegistrants.notifyResult(
147                         SatelliteServiceUtils.fromSatelliteModemState(state));
148                 int datagramTransferState =
149                         SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN;
150                 switch (state) {
151                     case SatelliteManager.SATELLITE_MODEM_STATE_IDLE:
152                         datagramTransferState =
153                                 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
154                         break;
155                     case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING:
156                         datagramTransferState =
157                                 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
158                         break;
159                     case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
160                         datagramTransferState =
161                                 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
162                         break;
163                     case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
164                         // keep previous state as this could be retrying sending or receiving
165                         break;
166                 }
167                 mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState);
168             }
169         }
170 
171         @Override
onNtnSignalStrengthChanged( android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength)172         public void onNtnSignalStrengthChanged(
173                 android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) {
174             if (notifyResultIfExpectedListener()) {
175                 mNtnSignalStrengthChangedRegistrants.notifyResult(
176                         SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength));
177             }
178         }
179 
180         @Override
onSatelliteCapabilitiesChanged( android.telephony.satellite.stub.SatelliteCapabilities satelliteCapabilities)181         public void onSatelliteCapabilitiesChanged(
182                 android.telephony.satellite.stub.SatelliteCapabilities satelliteCapabilities) {
183             mSatelliteCapabilitiesChangedRegistrants.notifyResult(
184                     SatelliteServiceUtils.fromSatelliteCapabilities(satelliteCapabilities));
185         }
186 
187         @Override
onSatelliteSupportedStateChanged(boolean supported)188         public void onSatelliteSupportedStateChanged(boolean supported) {
189             mSatelliteSupportedStateChangedRegistrants.notifyResult(supported);
190         }
191 
192         @Override
onRegistrationFailure(int causeCode)193         public void onRegistrationFailure(int causeCode) {
194             mSatelliteRegistrationFailureRegistrants.notifyResult(causeCode);
195         }
196 
197         @Override
onTerrestrialNetworkAvailableChanged(boolean isAvailable)198         public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
199             mTerrestrialNetworkAvailableChangedRegistrants.notifyResult(isAvailable);
200         }
201 
notifyResultIfExpectedListener()202         private boolean notifyResultIfExpectedListener() {
203             // Demo listener should notify results only during demo mode
204             // Vendor listener should notify result only during real mode
205             return mIsDemoListener == mSatelliteController.isDemoModeEnabled();
206         }
207 
notifyModemStateChanged(int state)208         private boolean notifyModemStateChanged(int state) {
209             if (notifyResultIfExpectedListener()) {
210                 return true;
211             }
212 
213             return state == SatelliteModemState.SATELLITE_MODEM_STATE_OFF
214                     || state == SatelliteModemState.SATELLITE_MODEM_STATE_UNAVAILABLE;
215         }
216     }
217 
218     /**
219      * @return The singleton instance of SatelliteModemInterface.
220      */
getInstance()221     public static SatelliteModemInterface getInstance() {
222         if (sInstance == null) {
223             loge("SatelliteModemInterface was not yet initialized.");
224         }
225         return sInstance;
226     }
227 
228     /**
229      * Create the SatelliteModemInterface singleton instance.
230      * @param context The Context to use to create the SatelliteModemInterface.
231      * @param satelliteController The singleton instance of SatelliteController.
232      * @param featureFlags The telephony feature flags.
233      * @return The singleton instance of SatelliteModemInterface.
234      */
make(@onNull Context context, SatelliteController satelliteController, @NonNull FeatureFlags featureFlags)235     public static SatelliteModemInterface make(@NonNull Context context,
236             SatelliteController satelliteController,
237             @NonNull FeatureFlags featureFlags) {
238         if (sInstance == null) {
239             sInstance = new SatelliteModemInterface(
240                     context, satelliteController, Looper.getMainLooper(), featureFlags);
241         }
242         return sInstance;
243     }
244 
245     /**
246      * Create a SatelliteModemInterface to manage connections to the SatelliteService.
247      *
248      * @param context The Context for the SatelliteModemInterface.
249      * @param featureFlags The telephony feature flags.
250      * @param looper The Looper to run binding retry on.
251      */
252     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
SatelliteModemInterface(@onNull Context context, SatelliteController satelliteController, @NonNull Looper looper, @NonNull FeatureFlags featureFlags)253     protected SatelliteModemInterface(@NonNull Context context,
254             SatelliteController satelliteController,
255             @NonNull Looper looper,
256             @NonNull FeatureFlags featureFlags) {
257         mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
258         mContext = context;
259         mDemoSimulator = DemoSimulator.make(context, satelliteController);
260         mVendorListener = new SatelliteListener(false);
261         mDemoListener = new SatelliteListener(true);
262         mIsSatelliteServiceSupported = getSatelliteServiceSupport();
263         mSatelliteController = satelliteController;
264         mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY,
265                 REBIND_MULTIPLIER, looper, () -> {
266             synchronized (mLock) {
267                 if ((mIsBound && mSatelliteService != null) || mIsBinding) {
268                     return;
269                 }
270             }
271             if (mSatelliteServiceConnection != null) {
272                 synchronized (mLock) {
273                     mIsBound = false;
274                     mIsBinding = false;
275                 }
276                 unbindService();
277             }
278             bindService();
279         });
280         mExponentialBackoff.start();
281         plogd("Created SatelliteModemInterface. Attempting to bind to SatelliteService.");
282         bindService();
283     }
284 
285     /**
286      * Get the SatelliteService interface, if it exists.
287      *
288      * @return The bound ISatellite, or {@code null} if it is not yet connected.
289      */
getService()290     @Nullable public ISatellite getService() {
291         return mSatelliteService;
292     }
293 
getSatellitePackageName()294     @NonNull private String getSatellitePackageName() {
295         if (!TextUtils.isEmpty(mVendorSatellitePackageName)) {
296             return mVendorSatellitePackageName;
297         }
298         return TextUtils.emptyIfNull(mContext.getResources().getString(
299                 R.string.config_satellite_service_package));
300     }
301 
getSatelliteServiceSupport()302     private boolean getSatelliteServiceSupport() {
303         return !TextUtils.isEmpty(getSatellitePackageName());
304     }
305 
306     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
bindService()307     protected void bindService() {
308         synchronized (mLock) {
309             if (mIsBinding || mIsBound) return;
310             mIsBinding = true;
311         }
312         String packageName = getSatellitePackageName();
313         if (TextUtils.isEmpty(packageName)) {
314             ploge("Unable to bind to the satellite service because the package is undefined.");
315             // Since the package name comes from static device configs, stop retry because
316             // rebind will continue to fail without a valid package name.
317             synchronized (mLock) {
318                 mIsBinding = false;
319             }
320             mExponentialBackoff.stop();
321             return;
322         }
323         Intent intent = new Intent(SatelliteService.SERVICE_INTERFACE);
324         intent.setPackage(packageName);
325 
326         mSatelliteServiceConnection = new SatelliteServiceConnection();
327         plogd("Binding to " + packageName);
328         try {
329             boolean success = mContext.bindService(
330                     intent, mSatelliteServiceConnection, Context.BIND_AUTO_CREATE);
331             if (success) {
332                 plogd("Successfully bound to the satellite service.");
333             } else {
334                 synchronized (mLock) {
335                     mIsBinding = false;
336                 }
337                 mExponentialBackoff.notifyFailed();
338                 ploge("Error binding to the satellite service. Retrying in "
339                         + mExponentialBackoff.getCurrentDelay() + " ms.");
340             }
341         } catch (Exception e) {
342             synchronized (mLock) {
343                 mIsBinding = false;
344             }
345             mExponentialBackoff.notifyFailed();
346             ploge("Exception binding to the satellite service. Retrying in "
347                     + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e);
348         }
349     }
350 
351     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
unbindService()352     protected void unbindService() {
353         disconnectSatelliteService();
354         mContext.unbindService(mSatelliteServiceConnection);
355         mSatelliteServiceConnection = null;
356     }
357 
disconnectSatelliteService()358     private void disconnectSatelliteService() {
359         // TODO: clean up any listeners and return failed for pending callbacks
360         mSatelliteService = null;
361     }
362 
363     private class SatelliteServiceConnection implements ServiceConnection {
364         @Override
onServiceConnected(ComponentName name, IBinder service)365         public void onServiceConnected(ComponentName name, IBinder service) {
366             plogd("onServiceConnected: ComponentName=" + name);
367             synchronized (mLock) {
368                 mIsBound = true;
369                 mIsBinding = false;
370             }
371             mSatelliteService = ISatellite.Stub.asInterface(service);
372             mExponentialBackoff.stop();
373             try {
374                 mSatelliteService.setSatelliteListener(mVendorListener);
375                 mDemoSimulator.setSatelliteListener(mDemoListener);
376             } catch (RemoteException e) {
377                 // TODO: Retry setSatelliteListener
378                 plogd("setSatelliteListener: RemoteException " + e);
379             }
380             mSatelliteController.onSatelliteServiceConnected();
381         }
382 
383         @Override
onServiceDisconnected(ComponentName name)384         public void onServiceDisconnected(ComponentName name) {
385             ploge("onServiceDisconnected: Waiting for reconnect.");
386             synchronized (mLock) {
387                 mIsBinding = false;
388             }
389             // Since we are still technically bound, clear the service and wait for reconnect.
390             disconnectSatelliteService();
391         }
392 
393         @Override
onBindingDied(ComponentName name)394         public void onBindingDied(ComponentName name) {
395             ploge("onBindingDied: Unbinding and rebinding service.");
396             synchronized (mLock) {
397                 mIsBound = false;
398                 mIsBinding = false;
399             }
400             unbindService();
401             mExponentialBackoff.start();
402         }
403     }
404 
405     /**
406      * Registers for satellite position info changed from satellite modem.
407      *
408      * @param h Handler for notification message.
409      * @param what User-defined message code.
410      * @param obj User object.
411      */
registerForSatellitePositionInfoChanged( @onNull Handler h, int what, @Nullable Object obj)412     public void registerForSatellitePositionInfoChanged(
413             @NonNull Handler h, int what, @Nullable Object obj) {
414         mSatellitePositionInfoChangedRegistrants.add(h, what, obj);
415     }
416 
417     /**
418      * Unregisters for satellite position info changed from satellite modem.
419      *
420      * @param h Handler to be removed from the registrant list.
421      */
unregisterForSatellitePositionInfoChanged(@onNull Handler h)422     public void unregisterForSatellitePositionInfoChanged(@NonNull Handler h) {
423         mSatellitePositionInfoChangedRegistrants.remove(h);
424     }
425 
426     /**
427      * Registers for datagram transfer state changed.
428      *
429      * @param h Handler for notification message.
430      * @param what User-defined message code.
431      * @param obj User object.
432      */
registerForDatagramTransferStateChanged( @onNull Handler h, int what, @Nullable Object obj)433     public void registerForDatagramTransferStateChanged(
434             @NonNull Handler h, int what, @Nullable Object obj) {
435         mDatagramTransferStateChangedRegistrants.add(h, what, obj);
436     }
437 
438     /**
439      * Unregisters for datagram transfer state changed.
440      *
441      * @param h Handler to be removed from the registrant list.
442      */
unregisterForDatagramTransferStateChanged(@onNull Handler h)443     public void unregisterForDatagramTransferStateChanged(@NonNull Handler h) {
444         mDatagramTransferStateChangedRegistrants.remove(h);
445     }
446 
447     /**
448      * Registers for modem state changed from satellite modem.
449      *
450      * @param h Handler for notification message.
451      * @param what User-defined message code.
452      * @param obj User object.
453      */
registerForSatelliteModemStateChanged( @onNull Handler h, int what, @Nullable Object obj)454     public void registerForSatelliteModemStateChanged(
455             @NonNull Handler h, int what, @Nullable Object obj) {
456         mSatelliteModemStateChangedRegistrants.add(h, what, obj);
457     }
458 
459     /**
460      * Unregisters for modem state changed from satellite modem.
461      *
462      * @param h Handler to be removed from the registrant list.
463      */
unregisterForSatelliteModemStateChanged(@onNull Handler h)464     public void unregisterForSatelliteModemStateChanged(@NonNull Handler h) {
465         mSatelliteModemStateChangedRegistrants.remove(h);
466     }
467 
468     /**
469      * Registers for pending datagrams indication from satellite modem.
470      *
471      * @param h Handler for notification message.
472      * @param what User-defined message code.
473      * @param obj User object.
474      */
registerForPendingDatagrams(@onNull Handler h, int what, @Nullable Object obj)475     public void registerForPendingDatagrams(@NonNull Handler h, int what, @Nullable Object obj) {
476         mPendingDatagramsRegistrants.add(h, what, obj);
477     }
478 
479     /**
480      * Unregisters for pending datagrams indication from satellite modem.
481      *
482      * @param h Handler to be removed from the registrant list.
483      */
unregisterForPendingDatagrams(@onNull Handler h)484     public void unregisterForPendingDatagrams(@NonNull Handler h) {
485         mPendingDatagramsRegistrants.remove(h);
486     }
487 
488     /**
489      * Registers for new datagrams received from satellite modem.
490      *
491      * @param h Handler for notification message.
492      * @param what User-defined message code.
493      * @param obj User object.
494      */
registerForSatelliteDatagramsReceived( @onNull Handler h, int what, @Nullable Object obj)495     public void registerForSatelliteDatagramsReceived(
496             @NonNull Handler h, int what, @Nullable Object obj) {
497         mSatelliteDatagramsReceivedRegistrants.add(h, what, obj);
498     }
499 
500     /**
501      * Unregisters for new datagrams received from satellite modem.
502      *
503      * @param h Handler to be removed from the registrant list.
504      */
unregisterForSatelliteDatagramsReceived(@onNull Handler h)505     public void unregisterForSatelliteDatagramsReceived(@NonNull Handler h) {
506         mSatelliteDatagramsReceivedRegistrants.remove(h);
507     }
508 
509     /**
510      * Registers for non-terrestrial signal strength level changed.
511      *
512      * @param h Handler for notification message.
513      * @param what User-defined message code.
514      * @param obj User object.
515      */
registerForNtnSignalStrengthChanged( @onNull Handler h, int what, @Nullable Object obj)516     public void registerForNtnSignalStrengthChanged(
517             @NonNull Handler h, int what, @Nullable Object obj) {
518         mNtnSignalStrengthChangedRegistrants.add(h, what, obj);
519     }
520 
521     /**
522      * Unregisters for non-terrestrial signal strength level changed.
523      *
524      * @param h Handler to be removed from the registrant list.
525      */
unregisterForNtnSignalStrengthChanged(@onNull Handler h)526     public void unregisterForNtnSignalStrengthChanged(@NonNull Handler h) {
527         mNtnSignalStrengthChangedRegistrants.remove(h);
528     }
529 
530     /**
531      * Registers for satellite capabilities changed.
532      *
533      * @param h Handler for notification message.
534      * @param what User-defined message code.
535      * @param obj User object.
536      */
registerForSatelliteCapabilitiesChanged( @onNull Handler h, int what, @Nullable Object obj)537     public void registerForSatelliteCapabilitiesChanged(
538             @NonNull Handler h, int what, @Nullable Object obj) {
539         mSatelliteCapabilitiesChangedRegistrants.add(h, what, obj);
540     }
541 
542     /**
543      * Unregisters for satellite capabilities changed.
544      *
545      * @param h Handler to be removed from the registrant list.
546      */
unregisterForSatelliteCapabilitiesChanged(@onNull Handler h)547     public void unregisterForSatelliteCapabilitiesChanged(@NonNull Handler h) {
548         mSatelliteCapabilitiesChangedRegistrants.remove(h);
549     }
550 
551     /**
552      * Registers for the satellite supported state changed.
553      *
554      * @param h Handler for notification message.
555      * @param what User-defined message code.
556      * @param obj User object.
557      */
registerForSatelliteSupportedStateChanged( @onNull Handler h, int what, @Nullable Object obj)558     public void registerForSatelliteSupportedStateChanged(
559             @NonNull Handler h, int what, @Nullable Object obj) {
560         mSatelliteSupportedStateChangedRegistrants.add(h, what, obj);
561     }
562 
563     /**
564      * Unregisters for the satellite supported state changed.
565      *
566      * @param h Handler to be removed from the registrant list.
567      */
unregisterForSatelliteSupportedStateChanged(@onNull Handler h)568     public void unregisterForSatelliteSupportedStateChanged(@NonNull Handler h) {
569         mSatelliteSupportedStateChangedRegistrants.remove(h);
570     }
571 
572     /**
573      * Registers for the satellite registration failed.
574      *
575      * @param h Handler for notification message.
576      * @param what User-defined message code.
577      * @param obj User object.
578      */
registerForSatelliteRegistrationFailure( @onNull Handler h, int what, @Nullable Object obj)579     public void registerForSatelliteRegistrationFailure(
580             @NonNull Handler h, int what, @Nullable Object obj) {
581         mSatelliteRegistrationFailureRegistrants.add(h, what, obj);
582     }
583 
584     /**
585      * Unregisters for the satellite registration failed.
586      *
587      * @param h Handler to be removed from the registrant list.
588      */
unregisterForSatelliteRegistrationFailure(@onNull Handler h)589     public void unregisterForSatelliteRegistrationFailure(@NonNull Handler h) {
590         mSatelliteRegistrationFailureRegistrants.remove(h);
591     }
592 
593     /**
594      * Registers for the terrestrial network available changed.
595      *
596      * @param h Handler for notification message.
597      * @param what User-defined message code.
598      * @param obj User object.
599      */
registerForTerrestrialNetworkAvailableChanged( @onNull Handler h, int what, @Nullable Object obj)600     public void registerForTerrestrialNetworkAvailableChanged(
601             @NonNull Handler h, int what, @Nullable Object obj) {
602         mTerrestrialNetworkAvailableChangedRegistrants.add(h, what, obj);
603     }
604 
605     /**
606      * Unregisters for the terrestrial network available changed.
607      *
608      * @param h Handler to be removed from the registrant list.
609      */
unregisterForTerrestrialNetworkAvailableChanged(@onNull Handler h)610     public void unregisterForTerrestrialNetworkAvailableChanged(@NonNull Handler h) {
611         mTerrestrialNetworkAvailableChangedRegistrants.remove(h);
612     }
613 
614     /**
615      * Request to enable or disable the satellite service listening mode.
616      * Listening mode allows the satellite service to listen for incoming pages.
617      *
618      * @param enable True to enable satellite listening mode and false to disable.
619      * @param timeout How long the satellite modem should wait for the next incoming page before
620      *                disabling listening mode.
621      * @param message The Message to send to result of the operation to.
622      */
requestSatelliteListeningEnabled(boolean enable, int timeout, @Nullable Message message)623     public void requestSatelliteListeningEnabled(boolean enable, int timeout,
624             @Nullable Message message) {
625         if (mSatelliteService != null) {
626             try {
627                 mSatelliteService.requestSatelliteListeningEnabled(enable, timeout,
628                         new IIntegerConsumer.Stub() {
629                             @Override
630                             public void accept(int result) {
631                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
632                                 plogd("requestSatelliteListeningEnabled: " + error);
633                                 Binder.withCleanCallingIdentity(() -> {
634                                     if (message != null) {
635                                         sendMessageWithResult(message, null, error);
636                                     }
637                                 });
638                             }
639                         });
640             } catch (RemoteException e) {
641                 ploge("requestSatelliteListeningEnabled: RemoteException " + e);
642                 if (message != null) {
643                     sendMessageWithResult(
644                             message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
645                 }
646             }
647         } else {
648             ploge("requestSatelliteListeningEnabled: Satellite service is unavailable.");
649             if (message != null) {
650                 sendMessageWithResult(message, null,
651                         SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
652             }
653         }
654     }
655 
656     /**
657      * Allow cellular modem scanning while satellite mode is on.
658      * @param enabled  {@code true} to enable cellular modem while satellite mode is on
659      * and {@code false} to disable
660      * @param message The Message to send to result of the operation to.
661      */
enableCellularModemWhileSatelliteModeIsOn(boolean enabled, @Nullable Message message)662     public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled,
663             @Nullable Message message) {
664         if (mSatelliteService != null) {
665             try {
666                 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
667                     @Override
668                     public void accept(int result) {
669                         int error = SatelliteServiceUtils.fromSatelliteError(result);
670                         plogd("enableCellularModemWhileSatelliteModeIsOn: " + error);
671                         Binder.withCleanCallingIdentity(() -> {
672                             if (message != null) {
673                                 sendMessageWithResult(message, null, error);
674                             }
675                         });
676                     }
677                 };
678 
679                 if (mSatelliteController.isDemoModeEnabled()) {
680                     mDemoSimulator.enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
681                             enabled, errorCallback);
682                 } else {
683                     mSatelliteService.enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
684                             enabled, errorCallback);
685                 }
686             } catch (RemoteException e) {
687                 ploge("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: RemoteException " + e);
688                 if (message != null) {
689                     sendMessageWithResult(
690                             message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
691                 }
692             }
693         } else {
694             ploge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable.");
695             if (message != null) {
696                 sendMessageWithResult(message, null,
697                         SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
698             }
699         }
700     }
701     /**
702      * Request to enable or disable the satellite modem and demo mode. If the satellite modem
703      * is enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
704      * this may also re-enable the cellular modem.
705      *
706      * @param enableAttributes info needed to allow carrier to roam to satellite.
707      * @param message The Message to send to result of the operation to.
708      */
requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes, @NonNull Message message)709     public void requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes,
710             @NonNull Message message) {
711         if (mSatelliteService != null) {
712             try {
713                 mSatelliteService.requestSatelliteEnabled(SatelliteServiceUtils
714                         .toSatelliteModemEnableRequestAttributes(enableAttributes),
715                         new IIntegerConsumer.Stub() {
716                             @Override
717                             public void accept(int result) {
718                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
719                                 plogd("setSatelliteEnabled: " + error);
720                                 Binder.withCleanCallingIdentity(() ->
721                                 sendMessageWithResult(message, null, error));
722                     }
723                 });
724             } catch (RemoteException e) {
725                 ploge("setSatelliteEnabled: RemoteException " + e);
726                 sendMessageWithResult(message, null,
727                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
728             }
729         } else {
730             ploge("setSatelliteEnabled: Satellite service is unavailable.");
731             sendMessageWithResult(message, null,
732                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
733         }
734     }
735 
736     /**
737      * Request to get whether the satellite modem is enabled.
738      *
739      * @param message The Message to send to result of the operation to.
740      */
requestIsSatelliteEnabled(@onNull Message message)741     public void requestIsSatelliteEnabled(@NonNull Message message) {
742         if (mSatelliteService != null) {
743             try {
744                 mSatelliteService.requestIsSatelliteEnabled(new IIntegerConsumer.Stub() {
745                     @Override
746                     public void accept(int result) {
747                         int error = SatelliteServiceUtils.fromSatelliteError(result);
748                         plogd("requestIsSatelliteEnabled: " + error);
749                         Binder.withCleanCallingIdentity(() ->
750                                 sendMessageWithResult(message, null, error));
751                     }
752                 }, new IBooleanConsumer.Stub() {
753                     @Override
754                     public void accept(boolean result) {
755                         // Convert for compatibility with SatelliteResponse
756                         // TODO: This should just report result instead.
757                         int[] enabled = new int[] {result ? 1 : 0};
758                         plogd("requestIsSatelliteEnabled: " + Arrays.toString(enabled));
759                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
760                                 message, enabled, SatelliteManager.SATELLITE_RESULT_SUCCESS));
761                     }
762                 });
763             } catch (RemoteException e) {
764                 ploge("requestIsSatelliteEnabled: RemoteException " + e);
765                 sendMessageWithResult(message, null,
766                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
767             }
768         } else {
769             ploge("requestIsSatelliteEnabled: Satellite service is unavailable.");
770             sendMessageWithResult(message, null,
771                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
772         }
773     }
774 
775     /**
776      * Request to get whether the satellite service is supported on the device.
777      *
778      * @param message The Message to send to result of the operation to.
779      */
requestIsSatelliteSupported(@onNull Message message)780     public void requestIsSatelliteSupported(@NonNull Message message) {
781         if (mSatelliteService != null) {
782             try {
783                 mSatelliteService.requestIsSatelliteSupported(new IIntegerConsumer.Stub() {
784                     @Override
785                     public void accept(int result) {
786                         int error = SatelliteServiceUtils.fromSatelliteError(result);
787                         plogd("requestIsSatelliteSupported: " + error);
788                         Binder.withCleanCallingIdentity(() ->
789                                 sendMessageWithResult(message, null, error));
790                     }
791                 }, new IBooleanConsumer.Stub() {
792                     @Override
793                     public void accept(boolean result) {
794                         plogd("requestIsSatelliteSupported: " + result);
795                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
796                                 message, result, SatelliteManager.SATELLITE_RESULT_SUCCESS));
797                     }
798                 });
799             } catch (RemoteException e) {
800                 ploge("requestIsSatelliteSupported: RemoteException " + e);
801                 sendMessageWithResult(message, null,
802                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
803             }
804         } else {
805             ploge("requestIsSatelliteSupported: Satellite service is unavailable.");
806             sendMessageWithResult(
807                     message, null, SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
808         }
809     }
810 
811     /**
812      * Request to get the SatelliteCapabilities of the satellite service.
813      *
814      * @param message The Message to send to result of the operation to.
815      */
requestSatelliteCapabilities(@onNull Message message)816     public void requestSatelliteCapabilities(@NonNull Message message) {
817         if (mSatelliteService != null) {
818             try {
819                 mSatelliteService.requestSatelliteCapabilities(new IIntegerConsumer.Stub() {
820                     @Override
821                     public void accept(int result) {
822                         int error = SatelliteServiceUtils.fromSatelliteError(result);
823                         plogd("requestSatelliteCapabilities: " + error);
824                         Binder.withCleanCallingIdentity(() ->
825                                 sendMessageWithResult(message, null, error));
826                     }
827                 }, new ISatelliteCapabilitiesConsumer.Stub() {
828                     @Override
829                     public void accept(android.telephony.satellite.stub.SatelliteCapabilities
830                             result) {
831                         SatelliteCapabilities capabilities =
832                                 SatelliteServiceUtils.fromSatelliteCapabilities(result);
833                         plogd("requestSatelliteCapabilities: " + capabilities);
834                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
835                                 message, capabilities, SatelliteManager.SATELLITE_RESULT_SUCCESS));
836                     }
837                 });
838             } catch (RemoteException e) {
839                 ploge("requestSatelliteCapabilities: RemoteException " + e);
840                 sendMessageWithResult(message, null,
841                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
842             }
843         } else {
844             ploge("requestSatelliteCapabilities: Satellite service is unavailable.");
845             sendMessageWithResult(message, null,
846                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
847         }
848     }
849 
850     /**
851      * User started pointing to the satellite.
852      * The satellite service should report the satellite pointing info via
853      * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves.
854      *
855      * @param message The Message to send to result of the operation to.
856      */
startSendingSatellitePointingInfo(@onNull Message message)857     public void startSendingSatellitePointingInfo(@NonNull Message message) {
858         if (mSatelliteService != null) {
859             try {
860                 mSatelliteService.startSendingSatellitePointingInfo(new IIntegerConsumer.Stub() {
861                     @Override
862                     public void accept(int result) {
863                         int error = SatelliteServiceUtils.fromSatelliteError(result);
864                         plogd("startSendingSatellitePointingInfo: " + error);
865                         Binder.withCleanCallingIdentity(() ->
866                                 sendMessageWithResult(message, null, error));
867                     }
868                 });
869             } catch (RemoteException e) {
870                 ploge("startSendingSatellitePointingInfo: RemoteException " + e);
871                 sendMessageWithResult(message, null,
872                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
873             }
874         } else {
875             ploge("startSendingSatellitePointingInfo: Satellite service is unavailable.");
876             sendMessageWithResult(message, null,
877                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
878         }
879     }
880 
881     /**
882      * User stopped pointing to the satellite.
883      * The satellite service should stop reporting satellite pointing info to the framework.
884      *
885      * @param message The Message to send to result of the operation to.
886      */
stopSendingSatellitePointingInfo(@onNull Message message)887     public void stopSendingSatellitePointingInfo(@NonNull Message message) {
888         if (mSatelliteService != null) {
889             try {
890                 mSatelliteService.stopSendingSatellitePointingInfo(new IIntegerConsumer.Stub() {
891                     @Override
892                     public void accept(int result) {
893                         int error = SatelliteServiceUtils.fromSatelliteError(result);
894                         plogd("stopSendingSatellitePointingInfo: " + error);
895                         Binder.withCleanCallingIdentity(() ->
896                                 sendMessageWithResult(message, null, error));
897                     }
898                 });
899             } catch (RemoteException e) {
900                 ploge("stopSendingSatellitePointingInfo: RemoteException " + e);
901                 sendMessageWithResult(message, null,
902                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
903             }
904         } else {
905             ploge("stopSendingSatellitePointingInfo: Satellite service is unavailable.");
906             sendMessageWithResult(message, null,
907                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
908         }
909     }
910 
911     /**
912      * Poll the pending datagrams to be received over satellite.
913      * The satellite service should check if there are any pending datagrams to be received over
914      * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
915      *
916      * @param message The Message to send to result of the operation to.
917      */
pollPendingSatelliteDatagrams(@onNull Message message)918     public void pollPendingSatelliteDatagrams(@NonNull Message message) {
919         if (mSatelliteService != null) {
920             try {
921                 mSatelliteService.pollPendingSatelliteDatagrams(new IIntegerConsumer.Stub() {
922                     @Override
923                     public void accept(int result) {
924                         int error = SatelliteServiceUtils.fromSatelliteError(result);
925                         plogd("pollPendingDatagrams: " + error);
926                         Binder.withCleanCallingIdentity(() ->
927                                 sendMessageWithResult(message, null, error));
928                     }
929                 });
930             } catch (RemoteException e) {
931                 ploge("pollPendingDatagrams: RemoteException " + e);
932                 sendMessageWithResult(message, null,
933                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
934             }
935         } else {
936             ploge("pollPendingDatagrams: Satellite service is unavailable.");
937             sendMessageWithResult(message, null,
938                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
939         }
940     }
941 
942     /**
943      * Send datagram over satellite.
944      *
945      * @param datagram Datagram to send in byte format.
946      * @param isEmergency Whether this is an emergency datagram.
947      * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in
948      *                                 full screen mode.
949      * @param message The Message to send to result of the operation to.
950      */
sendSatelliteDatagram(@onNull SatelliteDatagram datagram, boolean isEmergency, boolean needFullScreenPointingUI, @NonNull Message message)951     public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
952             boolean needFullScreenPointingUI, @NonNull Message message) {
953         if (mSatelliteService != null) {
954             try {
955                 mSatelliteService.sendSatelliteDatagram(
956                         SatelliteServiceUtils.toSatelliteDatagram(datagram), isEmergency,
957                         new IIntegerConsumer.Stub() {
958                             @Override
959                             public void accept(int result) {
960                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
961                                 plogd("sendDatagram: " + error);
962                                 Binder.withCleanCallingIdentity(() ->
963                                         sendMessageWithResult(message, null, error));
964                             }
965                         });
966             } catch (RemoteException e) {
967                 ploge("sendDatagram: RemoteException " + e);
968                 sendMessageWithResult(message, null,
969                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
970             }
971         } else {
972             ploge("sendDatagram: Satellite service is unavailable.");
973             sendMessageWithResult(message, null,
974                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
975         }
976     }
977 
978     /**
979      * Request the current satellite modem state.
980      * The satellite service should report the current satellite modem state via
981      * ISatelliteListener#onSatelliteModemStateChanged.
982      *
983      * @param message The Message to send to result of the operation to.
984      */
requestSatelliteModemState(@onNull Message message)985     public void requestSatelliteModemState(@NonNull Message message) {
986         if (mSatelliteService != null) {
987             try {
988                 mSatelliteService.requestSatelliteModemState(new IIntegerConsumer.Stub() {
989                     @Override
990                     public void accept(int result) {
991                         int error = SatelliteServiceUtils.fromSatelliteError(result);
992                         plogd("requestSatelliteModemState: " + error);
993                         Binder.withCleanCallingIdentity(() ->
994                                 sendMessageWithResult(message, null, error));
995                     }
996                 }, new IIntegerConsumer.Stub() {
997                     @Override
998                     public void accept(int result) {
999                         // Convert SatelliteModemState from service to frameworks definition.
1000                         int modemState = SatelliteServiceUtils.fromSatelliteModemState(result);
1001                         plogd("requestSatelliteModemState: " + modemState);
1002                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
1003                                 message, modemState, SatelliteManager.SATELLITE_RESULT_SUCCESS));
1004                     }
1005                 });
1006             } catch (RemoteException e) {
1007                 ploge("requestSatelliteModemState: RemoteException " + e);
1008                 sendMessageWithResult(message, null,
1009                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1010             }
1011         } else {
1012             ploge("requestSatelliteModemState: Satellite service is unavailable.");
1013             sendMessageWithResult(message, null,
1014                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1015         }
1016     }
1017 
1018     /**
1019      * Request to get the time after which the satellite will be visible. This is an int
1020      * representing the duration in seconds after which the satellite will be visible.
1021      * This will return 0 if the satellite is currently visible.
1022      *
1023      * @param message The Message to send to result of the operation to.
1024      */
requestTimeForNextSatelliteVisibility(@onNull Message message)1025     public void requestTimeForNextSatelliteVisibility(@NonNull Message message) {
1026         if (mSatelliteService != null) {
1027             try {
1028                 mSatelliteService.requestTimeForNextSatelliteVisibility(
1029                         new IIntegerConsumer.Stub() {
1030                             @Override
1031                             public void accept(int result) {
1032                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1033                                 plogd("requestTimeForNextSatelliteVisibility: " + error);
1034                                 Binder.withCleanCallingIdentity(() ->
1035                                         sendMessageWithResult(message, null, error));
1036                             }
1037                         }, new IIntegerConsumer.Stub() {
1038                             @Override
1039                             public void accept(int result) {
1040                                 // Convert for compatibility with SatelliteResponse
1041                                 // TODO: This should just report result instead.
1042                                 int[] time = new int[] {result};
1043                                 plogd("requestTimeForNextSatelliteVisibility: "
1044                                         + Arrays.toString(time));
1045                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
1046                                         message, time, SatelliteManager.SATELLITE_RESULT_SUCCESS));
1047                             }
1048                         });
1049             } catch (RemoteException e) {
1050                 ploge("requestTimeForNextSatelliteVisibility: RemoteException " + e);
1051                 sendMessageWithResult(message, null,
1052                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1053             }
1054         } else {
1055             ploge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable.");
1056             sendMessageWithResult(message, null,
1057                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1058         }
1059     }
1060 
1061     /**
1062      * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
1063      * MCC/MNC broadcast by the non-terrestrial networks will not be included in OPLMNwACT file
1064      * on SIM profile.
1065      * Acquisition of satellite based system is deemed lower priority to terrestrial networks.
1066      * Even so, UE shall make all attempts to acquire terrestrial service prior to camping on
1067      * satellite LTE service.
1068      *
1069      * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
1070      *                this information to determine the relevant carrier.
1071      * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
1072      *                        supported by user subscription.
1073      * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
1074      *                             PLMNs that are not supported by the carrier and make sure not to
1075      *                             attach to them.
1076      * @param message The result receiver that returns whether the modem has
1077      *                successfully set the satellite PLMN
1078      */
setSatellitePlmn(@onNull int simSlot, @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList, @NonNull Message message)1079     public void setSatellitePlmn(@NonNull int simSlot, @NonNull List<String> carrierPlmnList,
1080             @NonNull List<String> allSatellitePlmnList, @NonNull Message message) {
1081         if (mSatelliteService != null) {
1082             try {
1083                 mSatelliteService.setSatellitePlmn(simSlot, carrierPlmnList, allSatellitePlmnList,
1084                         new IIntegerConsumer.Stub() {
1085                             @Override
1086                             public void accept(int result) {
1087                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1088                                 plogd("setSatellitePlmn: " + error);
1089                                 Binder.withCleanCallingIdentity(() ->
1090                                         sendMessageWithResult(message, null, error));
1091                             }
1092                         });
1093             } catch (RemoteException e) {
1094                 ploge("setSatellitePlmn: RemoteException " + e);
1095                 sendMessageWithResult(message, null,
1096                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1097             }
1098         } else {
1099             ploge("setSatellitePlmn: Satellite service is unavailable.");
1100             sendMessageWithResult(message, null,
1101                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1102         }
1103     }
1104 
1105     /**
1106      * Enable or disable satellite in the cellular modem associated with a carrier.
1107      * Refer setSatellitePlmn for the details of satellite PLMN scanning process.
1108      *
1109      * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
1110      *                this information to determine the relevant carrier.
1111      * @param enableSatellite True to enable the satellite modem and false to disable.
1112      * @param message The Message to send to result of the operation to.
1113      */
requestSetSatelliteEnabledForCarrier(@onNull int simSlot, @NonNull boolean enableSatellite, @NonNull Message message)1114     public void requestSetSatelliteEnabledForCarrier(@NonNull int simSlot,
1115             @NonNull boolean enableSatellite, @NonNull Message message) {
1116         if (mSatelliteService != null) {
1117             try {
1118                 mSatelliteService.setSatelliteEnabledForCarrier(simSlot, enableSatellite,
1119                         new IIntegerConsumer.Stub() {
1120                             @Override
1121                             public void accept(int result) {
1122                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1123                                 plogd("requestSetSatelliteEnabledForCarrier: " + error);
1124                                 Binder.withCleanCallingIdentity(() ->
1125                                         sendMessageWithResult(message, null, error));
1126                             }
1127                         });
1128             } catch (RemoteException e) {
1129                 ploge("requestSetSatelliteEnabledForCarrier: RemoteException " + e);
1130                 sendMessageWithResult(message, null,
1131                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1132             }
1133         } else {
1134             ploge("requestSetSatelliteEnabledForCarrier: Satellite service is unavailable.");
1135             sendMessageWithResult(message, null,
1136                     SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
1137         }
1138     }
1139 
1140     /**
1141      * Check whether satellite is enabled in the cellular modem associated with a carrier.
1142      *
1143      * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
1144      *                this information to determine the relevant carrier.
1145      * @param message The Message to send to result of the operation to.
1146      */
requestIsSatelliteEnabledForCarrier(@onNull int simSlot, @NonNull Message message)1147     public void requestIsSatelliteEnabledForCarrier(@NonNull int simSlot,
1148             @NonNull Message message) {
1149         if (mSatelliteService != null) {
1150             try {
1151                 mSatelliteService.requestIsSatelliteEnabledForCarrier(simSlot,
1152                         new IIntegerConsumer.Stub() {
1153                             @Override
1154                             public void accept(int result) {
1155                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1156                                 plogd("requestIsSatelliteEnabledForCarrier: " + error);
1157                                 Binder.withCleanCallingIdentity(() ->
1158                                         sendMessageWithResult(message, null, error));
1159                             }
1160                         }, new IBooleanConsumer.Stub() {
1161                             @Override
1162                             public void accept(boolean result) {
1163                                 plogd("requestIsSatelliteEnabledForCarrier: " + result);
1164                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
1165                                         message, result,
1166                                         SatelliteManager.SATELLITE_RESULT_SUCCESS));
1167                             }
1168                         });
1169             } catch (RemoteException e) {
1170                 ploge("requestIsSatelliteEnabledForCarrier: RemoteException " + e);
1171                 sendMessageWithResult(message, null,
1172                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1173             }
1174         } else {
1175             ploge("requestIsSatelliteEnabledForCarrier: Satellite service is unavailable.");
1176             sendMessageWithResult(message, null,
1177                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1178         }
1179     }
1180 
1181     /**
1182      * Request to get the signal strength of the satellite connection.
1183      *
1184      * @param message The Message to send to result of the operation to.
1185      */
requestNtnSignalStrength(@onNull Message message)1186     public void requestNtnSignalStrength(@NonNull Message message) {
1187         if (mSatelliteService != null) {
1188             try {
1189                 mSatelliteService.requestSignalStrength(
1190                         new IIntegerConsumer.Stub() {
1191                             @Override
1192                             public void accept(int result) {
1193                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1194                                 plogd("requestNtnSignalStrength: " + error);
1195                                 Binder.withCleanCallingIdentity(() ->
1196                                         sendMessageWithResult(message, null, error));
1197                             }
1198                         }, new INtnSignalStrengthConsumer.Stub() {
1199                             @Override
1200                             public void accept(
1201                                     android.telephony.satellite.stub.NtnSignalStrength result) {
1202                                 NtnSignalStrength ntnSignalStrength =
1203                                         SatelliteServiceUtils.fromNtnSignalStrength(result);
1204                                 plogd("requestNtnSignalStrength: " + ntnSignalStrength);
1205                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
1206                                         message, ntnSignalStrength,
1207                                         SatelliteManager.SATELLITE_RESULT_SUCCESS));
1208                             }
1209                         });
1210             } catch (RemoteException e) {
1211                 ploge("requestNtnSignalStrength: RemoteException " + e);
1212                 sendMessageWithResult(message, null,
1213                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1214             }
1215         } else {
1216             ploge("requestNtnSignalStrength: Satellite service is unavailable.");
1217             sendMessageWithResult(message, null,
1218                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1219         }
1220     }
1221 
1222     /**
1223      * The satellite service should report the NTN signal strength via
1224      * ISatelliteListener#onNtnSignalStrengthChanged when the NTN signal strength changes.
1225      *
1226      * @param message The Message to send to result of the operation to.
1227      */
startSendingNtnSignalStrength(@onNull Message message)1228     public void startSendingNtnSignalStrength(@NonNull Message message) {
1229         if (mSatelliteService != null) {
1230             try {
1231                 mSatelliteService.startSendingNtnSignalStrength(new IIntegerConsumer.Stub() {
1232                     @Override
1233                     public void accept(int result) {
1234                         int error = SatelliteServiceUtils.fromSatelliteError(result);
1235                         plogd("startSendingNtnSignalStrength: " + error);
1236                         Binder.withCleanCallingIdentity(() ->
1237                                 sendMessageWithResult(message, null, error));
1238                     }
1239                 });
1240             } catch (RemoteException e) {
1241                 ploge("startSendingNtnSignalStrength: RemoteException " + e);
1242                 sendMessageWithResult(message, null,
1243                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1244             }
1245         } else {
1246             ploge("startSendingNtnSignalStrength: Satellite service is unavailable.");
1247             sendMessageWithResult(message, null,
1248                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1249         }
1250     }
1251 
1252     /**
1253      * The satellite service should stop reporting NTN signal strength to the framework.
1254      *
1255      * @param message The Message to send to result of the operation to.
1256      */
stopSendingNtnSignalStrength(@onNull Message message)1257     public void stopSendingNtnSignalStrength(@NonNull Message message) {
1258         if (mSatelliteService != null) {
1259             try {
1260                 mSatelliteService.stopSendingNtnSignalStrength(new IIntegerConsumer.Stub() {
1261                     @Override
1262                     public void accept(int result) {
1263                         int error = SatelliteServiceUtils.fromSatelliteError(result);
1264                         plogd("stopSendingNtnSignalStrength: " + error);
1265                         Binder.withCleanCallingIdentity(() ->
1266                                 sendMessageWithResult(message, null, error));
1267                     }
1268                 });
1269             } catch (RemoteException e) {
1270                 ploge("stopSendingNtnSignalStrength: RemoteException " + e);
1271                 sendMessageWithResult(message, null,
1272                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1273             }
1274         } else {
1275             ploge("stopSendingNtnSignalStrength: Satellite service is unavailable.");
1276             sendMessageWithResult(message, null,
1277                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1278         }
1279     }
1280 
1281     /**
1282      * The satellite service should abort all datagram-sending requests.
1283      *
1284      * @param message The Message to send to result of the operation to.
1285      */
abortSendingSatelliteDatagrams(@onNull Message message)1286     public void abortSendingSatelliteDatagrams(@NonNull Message message) {
1287         if (mSatelliteService != null) {
1288             try {
1289                 mSatelliteService.abortSendingSatelliteDatagrams(new IIntegerConsumer.Stub() {
1290                     @Override
1291                     public void accept(int result) {
1292                         int error = SatelliteServiceUtils.fromSatelliteError(result);
1293                         plogd("abortSendingSatelliteDatagrams: " + error);
1294                         Binder.withCleanCallingIdentity(() ->
1295                                 sendMessageWithResult(message, null, error));
1296                     }
1297                 });
1298             } catch (RemoteException e) {
1299                 ploge("abortSendingSatelliteDatagrams: RemoteException " + e);
1300                 sendMessageWithResult(message, null,
1301                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1302             }
1303         } else {
1304             ploge("abortSendingSatelliteDatagrams: Satellite service is unavailable.");
1305             sendMessageWithResult(message, null,
1306                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1307         }
1308     }
1309 
isSatelliteServiceSupported()1310     public boolean isSatelliteServiceSupported() {
1311         return mIsSatelliteServiceSupported;
1312     }
1313 
1314     /** Check if vendor satellite service is connected */
isSatelliteServiceConnected()1315     public boolean isSatelliteServiceConnected() {
1316         synchronized (mLock) {
1317             return (mSatelliteService != null);
1318         }
1319     }
1320 
1321     /**
1322      * Provision UUID with a satellite provider.
1323      */
updateSatelliteSubscription(@onNull String iccId, @NonNull Message message)1324     public void updateSatelliteSubscription(@NonNull String iccId, @NonNull Message message) {
1325         if (mSatelliteService != null) {
1326             try {
1327                 mSatelliteService.updateSatelliteSubscription(iccId,
1328                         new IIntegerConsumer.Stub() {
1329                             @Override
1330                             public void accept(int result) {
1331                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1332                                 plogd("updateSatelliteSubscription: " + error);
1333                                 Binder.withCleanCallingIdentity(() ->
1334                                         sendMessageWithResult(message, null, error));
1335                             }
1336                         });
1337             } catch (RemoteException e) {
1338                 ploge("updateSatelliteSubscription: RemoteException " + e);
1339                 sendMessageWithResult(message, null,
1340                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1341             }
1342         } else {
1343             ploge("updateSatelliteSubscription: Satellite service is unavailable.");
1344             sendMessageWithResult(message, null,
1345                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1346         }
1347     }
1348 
1349     /**
1350      * This API can be used by only CTS to update satellite vendor service package name.
1351      *
1352      * @param servicePackageName The package name of the satellite vendor service.
1353      * @return {@code true} if the satellite vendor service is set successfully,
1354      * {@code false} otherwise.
1355      */
1356     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
setSatelliteServicePackageName(@ullable String servicePackageName)1357     public void setSatelliteServicePackageName(@Nullable String servicePackageName) {
1358         plogd("setSatelliteServicePackageName: config_satellite_service_package is "
1359                 + "updated, new packageName=" + servicePackageName);
1360         mExponentialBackoff.stop();
1361         if (mSatelliteServiceConnection != null) {
1362             synchronized (mLock) {
1363                 mIsBound = false;
1364                 mIsBinding = false;
1365             }
1366             unbindService();
1367         }
1368 
1369         if (servicePackageName == null || servicePackageName.equals("null")) {
1370             mVendorSatellitePackageName = "";
1371         } else {
1372             mVendorSatellitePackageName = servicePackageName;
1373         }
1374         mIsSatelliteServiceSupported = getSatelliteServiceSupport();
1375         bindService();
1376         mExponentialBackoff.start();
1377     }
1378 
1379     /**
1380      * Request to update system selection channels
1381      *
1382      * @param systemSelectionSpecifiers system selection specifiers
1383      * @param message The Message to send to result of the operation to.
1384      */
updateSystemSelectionChannels( @onNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, @Nullable Message message)1385     public void updateSystemSelectionChannels(
1386             @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
1387             @Nullable Message message) {
1388         plogd("updateSystemSelectionChannels: SystemSelectionSpecifier: "
1389                 + systemSelectionSpecifiers.toString());
1390         if (mSatelliteService != null) {
1391             try {
1392                 mSatelliteService.updateSystemSelectionChannels(SatelliteServiceUtils
1393                                 .toSystemSelectionSpecifier(systemSelectionSpecifiers),
1394                         new IIntegerConsumer.Stub() {
1395                             @Override
1396                             public void accept(int result) {
1397                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
1398                                 plogd("updateSystemSelectionChannels: " + error);
1399                                 Binder.withCleanCallingIdentity(() ->
1400                                         sendMessageWithResult(message, null, error));
1401                             }
1402                         });
1403             } catch (RemoteException e) {
1404                 ploge("updateSystemSelectionChannels: RemoteException " + e);
1405                 sendMessageWithResult(message, null,
1406                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
1407             }
1408         } else {
1409             ploge("updateSystemSelectionChannels: Satellite service is unavailable.");
1410             sendMessageWithResult(message, null,
1411                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
1412         }
1413     }
1414 
1415     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
sendMessageWithResult(@onNull Message message, @Nullable Object result, @SatelliteManager.SatelliteResult int error)1416     protected static void sendMessageWithResult(@NonNull Message message, @Nullable Object result,
1417             @SatelliteManager.SatelliteResult int error) {
1418         SatelliteException exception = error == SatelliteManager.SATELLITE_RESULT_SUCCESS
1419                 ? null : new SatelliteException(error);
1420         AsyncResult.forMessage(message, result, exception);
1421         message.sendToTarget();
1422     }
1423 
logd(@onNull String log)1424     private static void logd(@NonNull String log) {
1425         Log.d(TAG, log);
1426     }
1427 
loge(@onNull String log)1428     private static void loge(@NonNull String log) {
1429         Log.e(TAG, log);
1430     }
1431 
plogd(@onNull String log)1432     private void plogd(@NonNull String log) {
1433         Log.d(TAG, log);
1434         if (mPersistentLogger != null) {
1435             mPersistentLogger.debug(TAG, log);
1436         }
1437     }
1438 
ploge(@onNull String log)1439     private void ploge(@NonNull String log) {
1440         Log.e(TAG, log);
1441         if (mPersistentLogger != null) {
1442             mPersistentLogger.error(TAG, log);
1443         }
1444     }
1445 }
1446