• 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 android.telephony.satellite.cts;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.Intent;
22 import android.os.Binder;
23 import android.os.IBinder;
24 import android.telephony.IBooleanConsumer;
25 import android.telephony.IIntegerConsumer;
26 import android.telephony.satellite.AntennaDirection;
27 import android.telephony.satellite.AntennaPosition;
28 import android.telephony.satellite.SatelliteManager;
29 import android.telephony.satellite.stub.INtnSignalStrengthConsumer;
30 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
31 import android.telephony.satellite.stub.ISatelliteListener;
32 import android.telephony.satellite.stub.NTRadioTechnology;
33 import android.telephony.satellite.stub.NtnSignalStrength;
34 import android.telephony.satellite.stub.PointingInfo;
35 import android.telephony.satellite.stub.SatelliteCapabilities;
36 import android.telephony.satellite.stub.SatelliteDatagram;
37 import android.telephony.satellite.stub.SatelliteImplBase;
38 import android.telephony.satellite.stub.SatelliteModemEnableRequestAttributes;
39 import android.telephony.satellite.stub.SatelliteModemState;
40 import android.telephony.satellite.stub.SatelliteResult;
41 import android.telephony.satellite.stub.SatelliteService;
42 import android.telephony.satellite.stub.SystemSelectionSpecifier;
43 import android.util.Log;
44 
45 import com.android.internal.util.FunctionalUtils;
46 
47 import java.util.ArrayList;
48 import java.util.HashMap;
49 import java.util.LinkedList;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.concurrent.Executor;
53 import java.util.concurrent.atomic.AtomicBoolean;
54 
55 public class MockSatelliteService extends SatelliteImplBase {
56     public static final int NOT_UPDATED_SATELLITE_MODEM_STATE = -1;
57     private static final String TAG = "MockSatelliteService";
58 
59     // Hardcoded values below
60     private static final int SATELLITE_ALWAYS_VISIBLE = 0;
61     /** SatelliteCapabilities constant indicating that the radio technology is proprietary. */
62     private static final int[] SUPPORTED_RADIO_TECHNOLOGIES =
63             new int[]{NTRadioTechnology.PROPRIETARY};
64     /** SatelliteCapabilities constant indicating that pointing to satellite is required. */
65     private static final boolean POINTING_TO_SATELLITE_REQUIRED = true;
66     /** SatelliteCapabilities constant indicating the maximum number of characters per datagram. */
67     private static final int MAX_BYTES_PER_DATAGRAM = 339;
68     /** SatelliteCapabilities constant keys which are used to fill mAntennaPositionMap. */
69     private static final int[] ANTENNA_POSITION_KEYS = new int[]{
70             SatelliteManager.DISPLAY_MODE_OPENED, SatelliteManager.DISPLAY_MODE_CLOSED};
71     /** SatelliteCapabilities constant values which are used to fill mAntennaPositionMap. */
72     private static final AntennaPosition[] ANTENNA_POSITION_VALUES = new AntennaPosition[] {
73             new AntennaPosition(new AntennaDirection(1,1,1),
74                     SatelliteManager.DEVICE_HOLD_POSITION_PORTRAIT),
75             new AntennaPosition(new AntennaDirection(2,2,2),
76                     SatelliteManager.DEVICE_HOLD_POSITION_LANDSCAPE_LEFT)
77     };
78 
79     @NonNull
80     private final Map<IBinder, ISatelliteListener> mRemoteListeners = new HashMap<>();
81     @Nullable private ILocalSatelliteListener mLocalListener;
82     private final LocalBinder mBinder = new LocalBinder();
83     @SatelliteResult
84     private int mErrorCode = SatelliteResult.SATELLITE_RESULT_SUCCESS;
85 
86     @SatelliteResult
87     private int mEnableCellularScanningErrorCode = SatelliteResult.SATELLITE_RESULT_SUCCESS;
88     // For local access of this Service.
89     class LocalBinder extends Binder {
getService()90         MockSatelliteService getService() {
91             return MockSatelliteService.this;
92         }
93     }
94 
95     private boolean mIsEnabled;
96     private boolean mIsSupported;
97     private int mModemState;
98     private final AtomicBoolean mWaitToSend = new AtomicBoolean(false);
99     private SatelliteDatagram mDatagramToBeSent;
100     private boolean mIsEmergencyDatagram;
101     private IIntegerConsumer mSendDatagramErrorCallback;
102     private Object mSendDatagramWithDelayLock = new Object();
103     private static final long TIMEOUT = 1000;
104     private final AtomicBoolean mShouldRespondTelephony = new AtomicBoolean(true);
105     private final AtomicBoolean mShouldRespondEnableRequest = new AtomicBoolean(true);
106     private final AtomicBoolean mShouldNotifyRemoteServiceConnected =
107             new AtomicBoolean(false);
108     @Nullable private List<String> mCarrierPlmnList;
109     @Nullable private List<String> mAllSatellitePlmnList;
110     private boolean mIsSatelliteEnabledForCarrier;
111     private android.telephony.satellite.stub.NtnSignalStrength mNtnSignalStrength;
112 
113     private int[] mSupportedRadioTechnologies;
114     private LinkedList<IIntegerConsumer>
115             mRequestSatelliteEnabledErrorCallbackQueue = new LinkedList<IIntegerConsumer>();
116     private LinkedList<IIntegerConsumer>
117             mRequestSatelliteDisabledErrorCallbackQueue = new LinkedList<IIntegerConsumer>();
118     private final Object mRequestSatelliteEnabledLock = new Object();
119     private boolean mIsEmergnecy;
120     private List<SystemSelectionSpecifier> mSystemSelectionSpecifierList = new ArrayList<>();
121 
122     /**
123      * Create MockSatelliteService using the Executor specified for methods being called from
124      * the framework.
125      *
126      * @param executor The executor for the framework to use when executing satellite methods.
127      */
MockSatelliteService(@onNull Executor executor)128     public MockSatelliteService(@NonNull Executor executor) {
129         super(executor);
130         mIsEnabled = false;
131         mIsSupported = true;
132         mModemState = SatelliteModemState.SATELLITE_MODEM_STATE_OFF;
133         mSupportedRadioTechnologies = SUPPORTED_RADIO_TECHNOLOGIES;
134         mIsEmergnecy = false;
135     }
136 
137     /**
138      * Zero-argument constructor to prevent service binding exception.
139      */
MockSatelliteService()140     public MockSatelliteService() {
141         this(Runnable::run);
142     }
143 
144     @Override
onBind(Intent intent)145     public IBinder onBind(Intent intent) {
146         if (SatelliteService.SERVICE_INTERFACE.equals(intent.getAction())) {
147             logd("Remote service bound");
148             return getBinder();
149         }
150         logd("Local service bound");
151         return mBinder;
152     }
153 
154     @Override
onCreate()155     public void onCreate() {
156         super.onCreate();
157         logd("onCreate");
158     }
159 
160     @Override
onDestroy()161     public void onDestroy() {
162         super.onDestroy();
163         logd("onDestroy");
164     }
165 
166     @Override
setSatelliteListener(@onNull ISatelliteListener listener)167     public void setSatelliteListener(@NonNull ISatelliteListener listener) {
168         logd("setSatelliteListener");
169         mRemoteListeners.put(listener.asBinder(), listener);
170         notifyRemoteServiceConnected();
171     }
172 
173     @Override
requestSatelliteListeningEnabled(boolean enabled, int timeout, @NonNull IIntegerConsumer errorCallback)174     public void requestSatelliteListeningEnabled(boolean enabled, int timeout,
175             @NonNull IIntegerConsumer errorCallback) {
176         logd("requestSatelliteListeningEnabled: mErrorCode=" + mErrorCode);
177 
178         if (mLocalListener != null) {
179             runWithExecutor(() -> mLocalListener.onSatelliteListeningEnabled(enabled));
180         } else {
181             loge("requestSatelliteListeningEnabled: mLocalListener is null");
182         }
183 
184         if (!verifySatelliteModemState(errorCallback)) {
185             return;
186         }
187         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
188             if (mShouldRespondTelephony.get()) {
189                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
190             }
191             return;
192         }
193 
194         if (mShouldRespondTelephony.get()) {
195             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
196         }
197         if (enabled) {
198             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_LISTENING);
199         } else {
200             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
201         }
202     }
203 
204     @Override
requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes, @NonNull IIntegerConsumer errorCallback)205     public void requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes,
206             @NonNull IIntegerConsumer errorCallback) {
207         logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode
208                 + ", isEnabled=" + enableAttributes.isEnabled
209                 + ", isDemoMode=" + enableAttributes.isDemoMode
210                 + ", isEmergency= " + enableAttributes.isEmergencyMode
211                 + ", iccId=" + enableAttributes.satelliteSubscriptionInfo.iccId
212                 + ", niddApn=" + enableAttributes.satelliteSubscriptionInfo.niddApn
213                 + ", mShouldRespondEnableRequest=" + mShouldRespondEnableRequest.get());
214         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
215             if (mShouldRespondEnableRequest.get()) {
216                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
217             }
218             return;
219         }
220 
221         if (enableAttributes.isEnabled) {
222             enableSatellite(errorCallback);
223         } else {
224             disableSatellite(errorCallback);
225         }
226         mIsEmergnecy = enableAttributes.isEmergencyMode;
227 
228         if (mLocalListener != null) {
229             runWithExecutor(() -> mLocalListener.onRequestSatelliteEnabled(
230                     enableAttributes.isEmergencyMode));
231         } else {
232             loge("requestSatelliteEnabled: mLocalListener is null");
233         }
234     }
235 
enableSatellite(@onNull IIntegerConsumer errorCallback)236     private void enableSatellite(@NonNull IIntegerConsumer errorCallback) {
237         if (mShouldRespondEnableRequest.get()) {
238             mIsEnabled = true;
239             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
240             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
241         } else {
242             synchronized (mRequestSatelliteEnabledLock) {
243                 mRequestSatelliteEnabledErrorCallbackQueue.addLast(errorCallback);
244             }
245         }
246     }
247 
disableSatellite(@onNull IIntegerConsumer errorCallback)248     private void disableSatellite(@NonNull IIntegerConsumer errorCallback) {
249         if (mShouldRespondEnableRequest.get()) {
250             mIsEnabled = false;
251             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
252             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_OFF);
253         } else {
254             synchronized (mRequestSatelliteEnabledLock) {
255                 mRequestSatelliteDisabledErrorCallbackQueue.addLast(errorCallback);
256             }
257         }
258     }
259 
260     @Override
requestIsSatelliteEnabled(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)261     public void requestIsSatelliteEnabled(@NonNull IIntegerConsumer errorCallback,
262             @NonNull IBooleanConsumer callback) {
263         logd("requestIsSatelliteEnabled: mErrorCode=" + mErrorCode);
264         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
265             if (mShouldRespondTelephony.get()) {
266                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
267             }
268             return;
269         }
270         if (mShouldRespondTelephony.get()) {
271             runWithExecutor(() -> callback.accept(mIsEnabled));
272         }
273     }
274 
275     @Override
requestIsSatelliteSupported(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)276     public void requestIsSatelliteSupported(@NonNull IIntegerConsumer errorCallback,
277             @NonNull IBooleanConsumer callback) {
278         logd("requestIsSatelliteSupported");
279         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
280             if (mShouldRespondTelephony.get()) {
281                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
282             }
283             return;
284         }
285         if (mShouldRespondTelephony.get()) {
286             runWithExecutor(() -> callback.accept(mIsSupported));
287         }
288     }
289 
290     @Override
requestSatelliteCapabilities(@onNull IIntegerConsumer errorCallback, @NonNull ISatelliteCapabilitiesConsumer callback)291     public void requestSatelliteCapabilities(@NonNull IIntegerConsumer errorCallback,
292             @NonNull ISatelliteCapabilitiesConsumer callback) {
293         logd("requestSatelliteCapabilities: mErrorCode=" + mErrorCode);
294         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
295             if (mShouldRespondTelephony.get()) {
296                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
297             }
298             return;
299         }
300 
301         if (mShouldRespondTelephony.get()) {
302             SatelliteCapabilities capabilities = new SatelliteCapabilities();
303             capabilities.supportedRadioTechnologies = mSupportedRadioTechnologies;
304             capabilities.isPointingRequired = POINTING_TO_SATELLITE_REQUIRED;
305             capabilities.maxBytesPerOutgoingDatagram = MAX_BYTES_PER_DATAGRAM;
306             capabilities.antennaPositionKeys = ANTENNA_POSITION_KEYS;
307             capabilities.antennaPositionValues = ANTENNA_POSITION_VALUES;
308             runWithExecutor(() -> callback.accept(capabilities));
309         }
310     }
311 
312     @Override
enableTerrestrialNetworkScanWhileSatelliteModeIsOn( boolean enabled, @NonNull IIntegerConsumer errorCallback)313     public void enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
314             boolean enabled, @NonNull IIntegerConsumer errorCallback) {
315         logd("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: enabled=" + enabled);
316         runWithExecutor(() -> errorCallback.accept(mEnableCellularScanningErrorCode));
317     }
318 
319     @Override
startSendingSatellitePointingInfo(@onNull IIntegerConsumer errorCallback)320     public void startSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) {
321         logd("startSendingSatellitePointingInfo: mErrorCode=" + mErrorCode);
322         if (!verifySatelliteModemState(errorCallback)) {
323             if (mLocalListener != null) {
324                 runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo());
325             } else {
326                 loge("startSendingSatellitePointingInfo: mLocalListener is null");
327             }
328             return;
329         }
330 
331         if (mShouldRespondTelephony.get()) {
332             if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
333                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
334             } else {
335                 runWithExecutor(() -> errorCallback.accept(
336                         SatelliteResult.SATELLITE_RESULT_SUCCESS));
337             }
338         }
339 
340         if (mLocalListener != null) {
341             runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo());
342         } else {
343             loge("startSendingSatellitePointingInfo: mLocalListener is null");
344         }
345     }
346 
347     @Override
stopSendingSatellitePointingInfo(@onNull IIntegerConsumer errorCallback)348     public void stopSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) {
349         logd("stopSendingSatellitePointingInfo: mErrorCode=" + mErrorCode);
350         if (mShouldRespondTelephony.get()) {
351             if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
352                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
353             } else {
354                 runWithExecutor(() -> errorCallback.accept(
355                         SatelliteResult.SATELLITE_RESULT_SUCCESS));
356             }
357         }
358 
359         if (mLocalListener != null) {
360             runWithExecutor(() -> mLocalListener.onStopSendingSatellitePointingInfo());
361         } else {
362             loge("stopSendingSatellitePointingInfo: mLocalListener is null");
363         }
364     }
365 
366     @Override
pollPendingSatelliteDatagrams(@onNull IIntegerConsumer errorCallback)367     public void pollPendingSatelliteDatagrams(@NonNull IIntegerConsumer errorCallback) {
368         logd("pollPendingSatelliteDatagrams: mErrorCode=" + mErrorCode);
369         updateSatelliteModemState(
370                 SatelliteModemState.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
371         if (mShouldRespondTelephony.get()) {
372             if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
373                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
374             } else {
375                 runWithExecutor(() -> errorCallback.accept(
376                         SatelliteResult.SATELLITE_RESULT_SUCCESS));
377             }
378         }
379 
380         if (mLocalListener != null) {
381             runWithExecutor(() -> mLocalListener.onPollPendingSatelliteDatagrams());
382         } else {
383             loge("pollPendingSatelliteDatagrams: mLocalListener is null");
384         }
385     }
386 
387     @Override
sendSatelliteDatagram(@onNull SatelliteDatagram datagram, boolean isEmergency, @NonNull IIntegerConsumer errorCallback)388     public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
389             @NonNull IIntegerConsumer errorCallback) {
390         logd("sendDatagram: mErrorCode=" + mErrorCode);
391 
392         if (mWaitToSend.get()) {
393             synchronized (mSendDatagramWithDelayLock) {
394                 // Save the datagram
395                 mDatagramToBeSent = datagram;
396                 mIsEmergencyDatagram = isEmergency;
397                 mSendDatagramErrorCallback = errorCallback;
398             }
399 
400             if (mLocalListener != null) {
401                 runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram(
402                         datagram, isEmergency));
403             } else {
404                 loge("sendDatagram: mLocalListener is null");
405             }
406         } else {
407             updateSatelliteModemState(
408                     SatelliteModemState.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
409             if (mShouldRespondTelephony.get()) {
410                 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
411                     runWithExecutor(() -> errorCallback.accept(mErrorCode));
412                 } else {
413                     runWithExecutor(() -> errorCallback.accept(
414                             SatelliteResult.SATELLITE_RESULT_SUCCESS));
415                 }
416             }
417 
418             if (mLocalListener != null) {
419                 runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram(
420                         datagram, isEmergency));
421             } else {
422                 loge("sendDatagram: mLocalListener is null");
423             }
424             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
425         }
426     }
427 
428     @Override
requestSatelliteModemState(@onNull IIntegerConsumer errorCallback, @NonNull IIntegerConsumer callback)429     public void requestSatelliteModemState(@NonNull IIntegerConsumer errorCallback,
430             @NonNull IIntegerConsumer callback) {
431         logd("requestSatelliteModemState: mErrorCode=" + mErrorCode);
432         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
433             if (mShouldRespondTelephony.get()) {
434                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
435             }
436             return;
437         }
438         if (mShouldRespondTelephony.get()) {
439             runWithExecutor(() -> callback.accept(mModemState));
440         }
441     }
442 
443     @Override
requestTimeForNextSatelliteVisibility(@onNull IIntegerConsumer errorCallback, @NonNull IIntegerConsumer callback)444     public void requestTimeForNextSatelliteVisibility(@NonNull IIntegerConsumer errorCallback,
445             @NonNull IIntegerConsumer callback) {
446         logd("requestTimeForNextSatelliteVisibility: mErrorCode=" + mErrorCode);
447         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
448             if (mShouldRespondTelephony.get()) {
449                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
450             }
451             return;
452         }
453         if (mShouldRespondTelephony.get()) {
454             runWithExecutor(() -> callback.accept(SATELLITE_ALWAYS_VISIBLE));
455         }
456     }
457 
458     @Override
setSatellitePlmn(@onNull int simLogicalSlotIndex, @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList, @NonNull IIntegerConsumer errorCallback)459     public void setSatellitePlmn(@NonNull int simLogicalSlotIndex,
460             @NonNull List<String> carrierPlmnList,
461             @NonNull List<String> allSatellitePlmnList,
462             @NonNull IIntegerConsumer errorCallback) {
463         logd("setSatellitePlmn: mErrorCode=" + mErrorCode);
464         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
465             if (mShouldRespondTelephony.get()) {
466                 runWithExecutor(() -> errorCallback.accept(mErrorCode));
467             }
468             return;
469         }
470         if (mShouldRespondTelephony.get()) {
471             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
472         }
473 
474         mCarrierPlmnList = carrierPlmnList;
475         mAllSatellitePlmnList = allSatellitePlmnList;
476 
477         if (mLocalListener != null) {
478             runWithExecutor(() -> mLocalListener.onSetSatellitePlmn());
479         } else {
480             loge("setSatellitePlmn: mLocalListener is null");
481         }
482     }
483 
484     @Override
setSatelliteEnabledForCarrier(@onNull int simLogicalSlotIndex, @NonNull boolean satelliteEnabled, @NonNull IIntegerConsumer callback)485     public void setSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex,
486             @NonNull boolean satelliteEnabled,
487             @NonNull IIntegerConsumer callback) {
488         logd("setSatelliteEnabledForCarrier: mErrorCode=" + mErrorCode
489                 + ", satelliteEnabled=" + satelliteEnabled
490                 + ", mShouldRespondTelephony=" + mShouldRespondTelephony.get());
491         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
492             if (mShouldRespondTelephony.get()) {
493                 runWithExecutor(() -> callback.accept(mErrorCode));
494             }
495             return;
496         }
497 
498         mIsSatelliteEnabledForCarrier = satelliteEnabled;
499         if (mShouldRespondTelephony.get()) {
500             runWithExecutor(() -> callback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
501         }
502     }
503 
504     @Override
requestIsSatelliteEnabledForCarrier(@onNull int simLogicalSlotIndex, @NonNull IIntegerConsumer resultCallback, @NonNull IBooleanConsumer callback)505     public void requestIsSatelliteEnabledForCarrier(@NonNull int simLogicalSlotIndex,
506             @NonNull IIntegerConsumer resultCallback, @NonNull IBooleanConsumer callback) {
507         logd("requestIsSatelliteEnabledForCarrier: mErrorCode=" + mErrorCode);
508         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
509             if (mShouldRespondTelephony.get()) {
510                 runWithExecutor(() -> resultCallback.accept(mErrorCode));
511             }
512             return;
513         }
514         if (mShouldRespondTelephony.get()) {
515             runWithExecutor(() -> callback.accept(mIsSatelliteEnabledForCarrier));
516         }
517     }
518 
519     @Override
requestSignalStrength(@onNull IIntegerConsumer resultCallback, INtnSignalStrengthConsumer callback)520     public void requestSignalStrength(@NonNull IIntegerConsumer resultCallback,
521             INtnSignalStrengthConsumer callback) {
522         logd("requestSignalStrength: mErrorCode=" + mErrorCode);
523         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
524             if (mShouldRespondTelephony.get()) {
525                 runWithExecutor(() -> resultCallback.accept(mErrorCode));
526             }
527             return;
528         }
529         if (mShouldRespondTelephony.get()) {
530             runWithExecutor(() -> callback.accept(mNtnSignalStrength));
531         }
532     }
533 
534     @Override
startSendingNtnSignalStrength(@onNull IIntegerConsumer resultCallback)535     public void startSendingNtnSignalStrength(@NonNull IIntegerConsumer resultCallback) {
536         logd("startSendingNtnSignalStrength: mErrorCode=" + mErrorCode);
537         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
538             if (mShouldRespondTelephony.get()) {
539                 runWithExecutor(() -> resultCallback.accept(mErrorCode));
540             }
541         }
542     }
543 
544     @Override
stopSendingNtnSignalStrength(@onNull IIntegerConsumer resultCallback)545     public void stopSendingNtnSignalStrength(@NonNull IIntegerConsumer resultCallback) {
546         logd("stopSendingNtnSignalStrength: mErrorCode=" + mErrorCode);
547         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
548             if (mShouldRespondTelephony.get()) {
549                 runWithExecutor(() -> resultCallback.accept(mErrorCode));
550             }
551         }
552     }
553 
554     @Override
updateSatelliteSubscription(@onNull String iccId, @NonNull IIntegerConsumer resultCallback)555     public void updateSatelliteSubscription(@NonNull String iccId,
556             @NonNull IIntegerConsumer resultCallback) {
557         logd("updateSatelliteSubscription: iccId=" + iccId + " mErrorCode=" + mErrorCode);
558 
559         if (mShouldRespondTelephony.get()) {
560             runWithExecutor(() -> resultCallback.accept(mErrorCode));
561         }
562     }
563 
564     @Override
updateSystemSelectionChannels( @onNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, @NonNull IIntegerConsumer resultCallback)565     public void updateSystemSelectionChannels(
566             @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
567             @NonNull IIntegerConsumer resultCallback) {
568         logd("updateSystemSelectionChannels: mErrorCode=" + mErrorCode
569                  + ", mShouldRespondTelephony=" + mShouldRespondTelephony.get());
570 
571         if (mErrorCode == SatelliteResult.SATELLITE_RESULT_SUCCESS) {
572             mSystemSelectionSpecifierList = new ArrayList<>(systemSelectionSpecifiers);
573         }
574 
575         if (mShouldRespondTelephony.get()) {
576             runWithExecutor(() -> resultCallback.accept(mErrorCode));
577         }
578     }
579 
580 
581     /**
582      * Returns the configured list of SystemSelectionSpecifiers.
583      *
584      * @return the list of configured system selection specifier.
585      */
getSystemSelectionChannels()586     public List<SystemSelectionSpecifier> getSystemSelectionChannels() {
587         logd("getSystemSelectionChannels: mSystemSelectionSpecifierList="
588                 + mSystemSelectionSpecifierList);
589         return mSystemSelectionSpecifierList;
590     }
591 
setLocalSatelliteListener(@onNull ILocalSatelliteListener listener)592     public void setLocalSatelliteListener(@NonNull ILocalSatelliteListener listener) {
593         logd("setLocalSatelliteListener: listener=" + listener);
594         mLocalListener = listener;
595         if (mShouldNotifyRemoteServiceConnected.get()) {
596             notifyRemoteServiceConnected();
597         }
598     }
599 
setErrorCode(@atelliteResult int errorCode)600     public void setErrorCode(@SatelliteResult int errorCode) {
601         logd("setErrorCode: errorCode=" + errorCode);
602         mErrorCode = errorCode;
603     }
604 
605     /**
606      * This API is used by CTS test cases to update current NTN signal strength of the mock
607      * satellite modem.
608      */
setNtnSignalStrength( android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength)609     public void setNtnSignalStrength(
610             android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) {
611         logd("setNtnSignalStrength: ntnSignalStrengthLevel="
612                 + ntnSignalStrength.signalStrengthLevel);
613         mNtnSignalStrength = ntnSignalStrength;
614     }
615 
616     /**
617      * This API is used by CTS test cases to set the error code returned when the mock satellite
618      * modem receives requests to enable or disable cellular scanning mode.
619      */
setEnableCellularScanningErrorCode(@atelliteResult int errorCode)620     public void setEnableCellularScanningErrorCode(@SatelliteResult int errorCode) {
621         logd("setEnableCellularScanningErrorCode: errorCode=" + errorCode);
622         mEnableCellularScanningErrorCode = errorCode;
623     }
624 
625     /**
626      * This API is used by CTS test cases to update supported NTN radio technologies of the
627      * mock satellite modem.
628      */
setSupportedRadioTechnologies(@onNull int[] supportedRadioTechnologies)629     public void setSupportedRadioTechnologies(@NonNull int[] supportedRadioTechnologies) {
630         logd("setSupportedRadioTechnologies: supportedRadioTechnologies="
631                 + supportedRadioTechnologies[0]);
632         mSupportedRadioTechnologies = supportedRadioTechnologies;
633     }
634 
setSatelliteSupport(boolean supported)635     public void setSatelliteSupport(boolean supported) {
636         logd("setSatelliteSupport: supported=" + supported);
637         mIsSupported = supported;
638     }
639 
setShouldRespondTelephony(boolean shouldRespondTelephony)640     public void setShouldRespondTelephony(boolean shouldRespondTelephony) {
641         mShouldRespondTelephony.set(shouldRespondTelephony);
642         logd("setShouldRespondTelephony: shouldRespondTelephony=" + shouldRespondTelephony);
643     }
644 
setShouldRespondEnableRequest(boolean shouldRespond)645     public void setShouldRespondEnableRequest(boolean shouldRespond) {
646         mShouldRespondEnableRequest.set(shouldRespond);
647         logd("setShouldRespondEnableRequest: shouldRespond=" + shouldRespond);
648     }
649 
sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount)650     public void sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount) {
651         logd("sendOnSatelliteDatagramReceived");
652         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
653                 listener.onSatelliteDatagramReceived(datagram, pendingCount)));
654         updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
655     }
656 
sendOnPendingDatagrams()657     public void sendOnPendingDatagrams() {
658         logd("sendOnPendingDatagrams");
659         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
660                 listener.onPendingDatagrams()));
661     }
662 
sendOnSatellitePositionChanged(PointingInfo pointingInfo)663     public void sendOnSatellitePositionChanged(PointingInfo pointingInfo) {
664         logd("sendOnSatellitePositionChanged");
665         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
666                 listener.onSatellitePositionChanged(pointingInfo)));
667     }
668 
669     /**
670      * This API is used by CTS test cases to update satellite modem state.
671      */
sendOnSatelliteModemStateChanged(int modemState)672     public void sendOnSatelliteModemStateChanged(int modemState) {
673         updateSatelliteModemState(modemState);
674     }
675 
676     /**
677      * Called when NTN signal strength changes.
678      * This API is used by CTS test cases to update NTN signal strength.
679      * @param ntnSignalStrength The new NTN signal strength.
680      */
sendOnNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength)681     public void sendOnNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
682         logd("sendOnNtnSignalStrengthChanged");
683         mNtnSignalStrength = ntnSignalStrength;
684         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
685                 listener.onNtnSignalStrengthChanged(ntnSignalStrength)));
686     }
687 
688     /**
689      * Called when satellite capabilities has changed.
690      * This API is used by CTS test cases to update satellite capabilities.
691      * @param satelliteCapabilities The new satellite capabilities.
692      */
sendOnSatelliteCapabilitiesChanged(SatelliteCapabilities satelliteCapabilities)693     public void sendOnSatelliteCapabilitiesChanged(SatelliteCapabilities satelliteCapabilities) {
694         logd("sendOnSatelliteCapabilitiesChanged");
695         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
696                 listener.onSatelliteCapabilitiesChanged(satelliteCapabilities)));
697     }
698 
699     /**
700      * This API is used by CTS test cases to update satellite supported state.
701      * @param supported The new satellite supported state.
702      */
sendOnSatelliteSupportedStateChanged(boolean supported)703     public void sendOnSatelliteSupportedStateChanged(boolean supported) {
704         logd("sendOnSatelliteSupportedStateChanged: supported=" + supported);
705         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
706                 listener.onSatelliteSupportedStateChanged(supported)));
707     }
708 
setWaitToSend(boolean wait)709     public void setWaitToSend(boolean wait) {
710         mWaitToSend.set(wait);
711     }
712 
sendSavedDatagram()713     public boolean sendSavedDatagram() {
714         synchronized (mSendDatagramWithDelayLock) {
715             logd("sendSavedDatagram");
716             if (mSendDatagramErrorCallback == null) {
717                 return false;
718             }
719 
720             if (mShouldRespondTelephony.get()) {
721                 if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
722                     runWithExecutor(() -> mSendDatagramErrorCallback.accept(mErrorCode));
723                 } else {
724                     runWithExecutor(() -> mSendDatagramErrorCallback.accept(
725                             SatelliteResult.SATELLITE_RESULT_SUCCESS));
726                 }
727             }
728             mSendDatagramErrorCallback = null;
729             return true;
730         }
731     }
732 
733     /**
734      * Respond to the oldest enable/disable request.
735      */
respondToRequestSatelliteEnabled(boolean isEnabled, int modemState)736     public boolean respondToRequestSatelliteEnabled(boolean isEnabled, int modemState) {
737         synchronized (mRequestSatelliteEnabledLock) {
738             if (isEnabled) {
739                 logd("respondToRequestSatelliteEnabled: isEnabled=true, "
740                         + "mRequestSatelliteEnabledErrorCallbackQueue="
741                         + mRequestSatelliteEnabledErrorCallbackQueue.size());
742                 if (mRequestSatelliteEnabledErrorCallbackQueue.isEmpty()) {
743                     return false;
744                 }
745                 runWithExecutor(() -> mRequestSatelliteEnabledErrorCallbackQueue
746                         .removeFirst().accept(mErrorCode));
747             } else {
748                 logd("respondToRequestSatelliteEnabled: isEnabled=false, "
749                         + "mRequestSatelliteDisabledErrorCallbackQueue="
750                         + mRequestSatelliteDisabledErrorCallbackQueue.size());
751                 if (mRequestSatelliteDisabledErrorCallbackQueue.isEmpty()) {
752                     return false;
753                 }
754                 runWithExecutor(() -> mRequestSatelliteDisabledErrorCallbackQueue
755                         .removeFirst().accept(mErrorCode));
756             }
757             if (modemState != NOT_UPDATED_SATELLITE_MODEM_STATE) {
758                 updateSatelliteModemState(modemState);
759             }
760             return true;
761         }
762     }
763 
764     /**
765      * Clear the enable request queues.
766      */
clearSatelliteEnableRequestQueues()767     public void clearSatelliteEnableRequestQueues() {
768         synchronized (mRequestSatelliteEnabledLock) {
769             logd("clearSatelliteEnableRequestQueues: isEnabled=true, "
770                     + "mRequestSatelliteEnabledErrorCallbackQueue="
771                     + mRequestSatelliteEnabledErrorCallbackQueue.size()
772                     + "mRequestSatelliteDisabledErrorCallbackQueue="
773                     + mRequestSatelliteDisabledErrorCallbackQueue.size());
774             mRequestSatelliteEnabledErrorCallbackQueue.clear();
775             mRequestSatelliteDisabledErrorCallbackQueue.clear();
776         }
777     }
778 
779 
780     /**
781      * Get the configured PLMN list supported by carrier.
782      */
getCarrierPlmnList()783     public List<String> getCarrierPlmnList() {
784         logd("getCarrierPlmnList");
785         return mCarrierPlmnList;
786     }
787 
788     /**
789      * Get the configured all satellite PLMN list.
790      */
getAllSatellitePlmnList()791     public List<String> getAllSatellitePlmnList() {
792         logd("getAllSatellitePlmnList");
793         return mAllSatellitePlmnList;
794     }
795 
getIsSatelliteEnabledForCarrier()796     public boolean getIsSatelliteEnabledForCarrier() {
797         logd("getIsSatelliteEnabledForCarrier");
798         return mIsSatelliteEnabledForCarrier;
799     }
800 
clearSatelliteEnabledForCarrier()801     public void clearSatelliteEnabledForCarrier() {
802         mIsSatelliteEnabledForCarrier = false;
803     }
804 
805     /**
806      * Helper method to verify that the satellite modem is properly configured to receive
807      * requests.
808      *
809      * @param errorCallback The callback to notify of any errors preventing satellite requests.
810      * @return {@code true} if the satellite modem is configured to receive requests and
811      * {@code false} if it is not.
812      */
verifySatelliteModemState(@onNull IIntegerConsumer errorCallback)813     private boolean verifySatelliteModemState(@NonNull IIntegerConsumer errorCallback) {
814         if (!mIsSupported) {
815             runWithExecutor(() -> errorCallback.accept(
816                     SatelliteResult.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED));
817             return false;
818         }
819         if (!mIsEnabled) {
820             runWithExecutor(() -> errorCallback.accept(
821                     SatelliteResult.SATELLITE_RESULT_INVALID_MODEM_STATE));
822             return false;
823         }
824         return true;
825     }
826 
827     /**
828      * Update the satellite modem state and notify listeners if it changed.
829      *
830      * @param modemState The {@link SatelliteModemState} to update.
831      */
updateSatelliteModemState(int modemState)832     private void updateSatelliteModemState(int modemState) {
833         logd("updateSatelliteModemState modemState=" + modemState);
834         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
835                 listener.onSatelliteModemStateChanged(modemState)));
836         mModemState = modemState;
837     }
838 
839     /**
840      * Get the emergency mode or not
841      */
getIsEmergency()842     public boolean getIsEmergency() {
843         logd("getIsEmergency: mIsEmergnecy=" + mIsEmergnecy);
844         return mIsEmergnecy;
845     }
846 
847     /**
848      * Execute the given runnable using the executor that this service was created with.
849      *
850      * @param r A runnable that can throw an exception.
851      */
runWithExecutor(@onNull FunctionalUtils.ThrowingRunnable r)852     private void runWithExecutor(@NonNull FunctionalUtils.ThrowingRunnable r) {
853         mExecutor.execute(() -> Binder.withCleanCallingIdentity(r));
854     }
855 
notifyRemoteServiceConnected()856     private void notifyRemoteServiceConnected() {
857         logd("notifyRemoteServiceConnected");
858         if (mLocalListener != null) {
859             runWithExecutor(() -> mLocalListener.onRemoteServiceConnected());
860             mShouldNotifyRemoteServiceConnected.set(false);
861         } else {
862             mShouldNotifyRemoteServiceConnected.set(true);
863         }
864     }
865 
866     /**
867      * Log the message to the radio buffer with {@code DEBUG} priority.
868      *
869      * @param log The message to log.
870      */
logd(@onNull String log)871     private static void logd(@NonNull String log) {
872         Log.d(TAG, log);
873     }
874 
875     /**
876      * Log with error attribute
877      *
878      * @param s is string log
879      */
loge(@onNull String s)880     protected void loge(@NonNull String s) {
881         Log.e(TAG, s);
882     }
883 }
884