• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.phone.testapps.satellitetestapp;
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.ISatelliteCapabilitiesConsumer;
30 import android.telephony.satellite.stub.ISatelliteListener;
31 import android.telephony.satellite.stub.NTRadioTechnology;
32 import android.telephony.satellite.stub.PointingInfo;
33 import android.telephony.satellite.stub.SatelliteCapabilities;
34 import android.telephony.satellite.stub.SatelliteDatagram;
35 import android.telephony.satellite.stub.SatelliteImplBase;
36 import android.telephony.satellite.stub.SatelliteModemState;
37 import android.telephony.satellite.stub.SatelliteResult;
38 import android.telephony.satellite.stub.SatelliteService;
39 import android.telephony.satellite.stub.SystemSelectionSpecifier;
40 import android.util.Log;
41 
42 import com.android.internal.util.FunctionalUtils;
43 import com.android.telephony.Rlog;
44 
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.concurrent.Executor;
50 import java.util.concurrent.atomic.AtomicBoolean;
51 
52 /**
53  * Test service for Satellite to verify end to end flow via testapp.
54  */
55 public class TestSatelliteService extends SatelliteImplBase {
56     private static final String TAG = "TestSatelliteService";
57 
58     // Hardcoded values below
59     private static final int SATELLITE_ALWAYS_VISIBLE = 0;
60     /** SatelliteCapabilities constant indicating that the radio technology is proprietary. */
61     private static final int[] SUPPORTED_RADIO_TECHNOLOGIES =
62             new int[]{NTRadioTechnology.PROPRIETARY};
63     /** SatelliteCapabilities constant indicating that pointing to satellite is required. */
64     private static final boolean POINTING_TO_SATELLITE_REQUIRED = true;
65     /** SatelliteCapabilities constant indicating the maximum number of characters per datagram. */
66     private static final int MAX_BYTES_PER_DATAGRAM = 339;
67     /** SatelliteCapabilities constant keys which are used to fill mAntennaPositionMap. */
68     private static final int[] ANTENNA_POSITION_KEYS = new int[]{
69             SatelliteManager.DISPLAY_MODE_OPENED, SatelliteManager.DISPLAY_MODE_CLOSED};
70     /** SatelliteCapabilities constant values which are used to fill mAntennaPositionMap. */
71     private static final AntennaPosition[] ANTENNA_POSITION_VALUES = new AntennaPosition[] {
72             new AntennaPosition(new AntennaDirection(1, 1, 1),
73                     SatelliteManager.DEVICE_HOLD_POSITION_PORTRAIT),
74             new AntennaPosition(new AntennaDirection(2, 2, 2),
75                     SatelliteManager.DEVICE_HOLD_POSITION_LANDSCAPE_LEFT)
76     };
77 
78     @NonNull
79     private final Map<IBinder, ISatelliteListener> mRemoteListeners = new HashMap<>();
80     @Nullable private ILocalSatelliteListener mLocalListener;
81     private final LocalBinder mBinder = new LocalBinder();
82     @SatelliteResult
83     private int mErrorCode = SatelliteResult.SATELLITE_RESULT_SUCCESS;
84     private final AtomicBoolean mShouldNotifyRemoteServiceConnected =
85             new AtomicBoolean(false);
86 
87     // For local access of this Service.
88     class LocalBinder extends Binder {
getService()89         TestSatelliteService getService() {
90             return TestSatelliteService.this;
91         }
92     }
93 
94     private boolean mIsCommunicationAllowedInLocation;
95     private boolean mIsEnabled;
96     private boolean mIsProvisioned;
97     private boolean mIsSupported;
98     private int mModemState;
99     private boolean mIsCellularModemEnabledMode;
100     private List<String> mCarrierPlmnList = new ArrayList<>();
101     private List<String> mAllPlmnList = new ArrayList<>();
102     private boolean mIsSatelliteEnabledForCarrier;
103     private boolean mIsRequestIsSatelliteEnabledForCarrier;
104     private boolean mIsEmergnecy;
105 
106     /**
107      * Create TestSatelliteService using the Executor specified for methods being called from
108      * the framework.
109      *
110      * @param executor The executor for the framework to use when executing satellite methods.
111      */
TestSatelliteService(@onNull Executor executor)112     public TestSatelliteService(@NonNull Executor executor) {
113         super(executor);
114         mIsCommunicationAllowedInLocation = true;
115         mIsEnabled = false;
116         mIsProvisioned = false;
117         mIsSupported = true;
118         mModemState = SatelliteModemState.SATELLITE_MODEM_STATE_OFF;
119         mIsCellularModemEnabledMode = false;
120         mIsSatelliteEnabledForCarrier = false;
121         mIsRequestIsSatelliteEnabledForCarrier = false;
122         mIsEmergnecy = false;
123     }
124 
125     /**
126      * Zero-argument constructor to prevent service binding exception.
127      */
TestSatelliteService()128     public TestSatelliteService() {
129         this(Runnable::run);
130     }
131 
132     @Override
onBind(Intent intent)133     public IBinder onBind(Intent intent) {
134         if (SatelliteService.SERVICE_INTERFACE.equals(intent.getAction())) {
135             logd("Remote service bound");
136             return getBinder();
137         }
138         logd("Local service bound");
139         return mBinder;
140     }
141 
142     @Override
onCreate()143     public void onCreate() {
144         super.onCreate();
145         logd("onCreate");
146     }
147 
148     @Override
onDestroy()149     public void onDestroy() {
150         super.onDestroy();
151         logd("onDestroy");
152     }
153 
154     @Override
setSatelliteListener(@onNull ISatelliteListener listener)155     public void setSatelliteListener(@NonNull ISatelliteListener listener) {
156         logd("setSatelliteListener");
157         mRemoteListeners.put(listener.asBinder(), listener);
158         notifyRemoteServiceConnected();
159     }
160 
161     @Override
requestSatelliteListeningEnabled(boolean enabled, int timeout, @NonNull IIntegerConsumer errorCallback)162     public void requestSatelliteListeningEnabled(boolean enabled, int timeout,
163             @NonNull IIntegerConsumer errorCallback) {
164         logd("requestSatelliteListeningEnabled: mErrorCode=" + mErrorCode);
165 
166         if (mLocalListener != null) {
167             runWithExecutor(() -> mLocalListener.onSatelliteListeningEnabled(enabled));
168         } else {
169             loge("requestSatelliteListeningEnabled: mLocalListener is null");
170         }
171 
172         if (!verifySatelliteModemState(errorCallback)) {
173             return;
174         }
175         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
176             runWithExecutor(() -> errorCallback.accept(mErrorCode));
177             return;
178         }
179 
180         if (enabled) {
181             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_LISTENING);
182         } else {
183             updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
184         }
185         runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
186     }
187 
188     @Override
requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode, boolean isEmergency, @NonNull IIntegerConsumer errorCallback)189     public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
190             boolean isEmergency, @NonNull IIntegerConsumer errorCallback) {
191         logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode + " enable = " + enableSatellite
192                 + " isEmergency=" + isEmergency);
193         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
194             runWithExecutor(() -> errorCallback.accept(mErrorCode));
195             return;
196         }
197 
198         if (enableSatellite) {
199             enableSatellite(errorCallback);
200         } else {
201             disableSatellite(errorCallback);
202         }
203         mIsEmergnecy = isEmergency;
204     }
205 
enableSatellite(@onNull IIntegerConsumer errorCallback)206     private void enableSatellite(@NonNull IIntegerConsumer errorCallback) {
207         mIsEnabled = true;
208         updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
209         runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
210     }
211 
disableSatellite(@onNull IIntegerConsumer errorCallback)212     private void disableSatellite(@NonNull IIntegerConsumer errorCallback) {
213         mIsEnabled = false;
214         updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_OFF);
215         runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
216     }
217 
218     @Override
requestIsSatelliteEnabled(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)219     public void requestIsSatelliteEnabled(@NonNull IIntegerConsumer errorCallback,
220             @NonNull IBooleanConsumer callback) {
221         logd("requestIsSatelliteEnabled: mErrorCode=" + mErrorCode);
222         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
223             runWithExecutor(() -> errorCallback.accept(mErrorCode));
224             return;
225         }
226         runWithExecutor(() -> callback.accept(mIsEnabled));
227     }
228 
229     @Override
requestIsSatelliteSupported(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)230     public void requestIsSatelliteSupported(@NonNull IIntegerConsumer errorCallback,
231             @NonNull IBooleanConsumer callback) {
232         logd("requestIsSatelliteSupported");
233         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
234             runWithExecutor(() -> errorCallback.accept(mErrorCode));
235             return;
236         }
237         runWithExecutor(() -> callback.accept(mIsSupported));
238     }
239 
240     @Override
requestSatelliteCapabilities(@onNull IIntegerConsumer errorCallback, @NonNull ISatelliteCapabilitiesConsumer callback)241     public void requestSatelliteCapabilities(@NonNull IIntegerConsumer errorCallback,
242             @NonNull ISatelliteCapabilitiesConsumer callback) {
243         logd("requestSatelliteCapabilities: mErrorCode=" + mErrorCode);
244         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
245             runWithExecutor(() -> errorCallback.accept(mErrorCode));
246             return;
247         }
248 
249         SatelliteCapabilities capabilities = new SatelliteCapabilities();
250         capabilities.supportedRadioTechnologies = SUPPORTED_RADIO_TECHNOLOGIES;
251         capabilities.isPointingRequired = POINTING_TO_SATELLITE_REQUIRED;
252         capabilities.maxBytesPerOutgoingDatagram = MAX_BYTES_PER_DATAGRAM;
253         capabilities.antennaPositionKeys = ANTENNA_POSITION_KEYS;
254         capabilities.antennaPositionValues = ANTENNA_POSITION_VALUES;
255         runWithExecutor(() -> callback.accept(capabilities));
256     }
257 
258     @Override
startSendingSatellitePointingInfo(@onNull IIntegerConsumer errorCallback)259     public void startSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) {
260         logd("startSendingSatellitePointingInfo: mErrorCode=" + mErrorCode);
261         if (!verifySatelliteModemState(errorCallback)) {
262             if (mLocalListener != null) {
263                 runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo());
264             } else {
265                 loge("startSendingSatellitePointingInfo: mLocalListener is null");
266             }
267             return;
268         }
269 
270         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
271             runWithExecutor(() -> errorCallback.accept(mErrorCode));
272         } else {
273             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
274         }
275 
276         if (mLocalListener != null) {
277             runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo());
278         } else {
279             loge("startSendingSatellitePointingInfo: mLocalListener is null");
280         }
281     }
282 
283     @Override
stopSendingSatellitePointingInfo(@onNull IIntegerConsumer errorCallback)284     public void stopSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) {
285         logd("stopSendingSatellitePointingInfo: mErrorCode=" + mErrorCode);
286         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
287             runWithExecutor(() -> errorCallback.accept(mErrorCode));
288         } else {
289             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
290         }
291 
292         if (mLocalListener != null) {
293             runWithExecutor(() -> mLocalListener.onStopSendingSatellitePointingInfo());
294         } else {
295             loge("stopSendingSatellitePointingInfo: mLocalListener is null");
296         }
297     }
298 
299     @Override
provisionSatelliteService(@onNull String token, @NonNull byte[] provisionData, @NonNull IIntegerConsumer errorCallback)300     public void provisionSatelliteService(@NonNull String token, @NonNull byte[] provisionData,
301             @NonNull IIntegerConsumer errorCallback) {
302         logd("provisionSatelliteService: mErrorCode=" + mErrorCode);
303         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
304             runWithExecutor(() -> errorCallback.accept(mErrorCode));
305             return;
306         }
307         runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
308         updateSatelliteProvisionState(true);
309     }
310 
311     @Override
deprovisionSatelliteService(@onNull String token, @NonNull IIntegerConsumer errorCallback)312     public void deprovisionSatelliteService(@NonNull String token,
313             @NonNull IIntegerConsumer errorCallback) {
314         logd("deprovisionSatelliteService: mErrorCode=" + mErrorCode);
315         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
316             runWithExecutor(() -> errorCallback.accept(mErrorCode));
317             return;
318         }
319         runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
320         updateSatelliteProvisionState(false);
321     }
322 
323     @Override
requestIsSatelliteProvisioned(@onNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback)324     public void requestIsSatelliteProvisioned(@NonNull IIntegerConsumer errorCallback,
325             @NonNull IBooleanConsumer callback) {
326         logd("requestIsSatelliteProvisioned: mErrorCode=" + mErrorCode);
327         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
328             runWithExecutor(() -> errorCallback.accept(mErrorCode));
329             return;
330         }
331         runWithExecutor(() -> callback.accept(mIsProvisioned));
332     }
333 
334     @Override
pollPendingSatelliteDatagrams(@onNull IIntegerConsumer errorCallback)335     public void pollPendingSatelliteDatagrams(@NonNull IIntegerConsumer errorCallback) {
336         logd("pollPendingSatelliteDatagrams: mErrorCode=" + mErrorCode);
337         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
338             runWithExecutor(() -> errorCallback.accept(mErrorCode));
339         } else {
340             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
341         }
342 
343         if (mLocalListener != null) {
344             runWithExecutor(() -> mLocalListener.onPollPendingSatelliteDatagrams());
345         } else {
346             loge("pollPendingDatagrams: mLocalListener is null");
347         }
348     }
349 
350     @Override
sendSatelliteDatagram(@onNull SatelliteDatagram datagram, boolean isEmergency, @NonNull IIntegerConsumer errorCallback)351     public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
352             @NonNull IIntegerConsumer errorCallback) {
353         logd("sendDatagram: mErrorCode=" + mErrorCode);
354         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
355             runWithExecutor(() -> errorCallback.accept(mErrorCode));
356         } else {
357             runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
358         }
359 
360         if (mLocalListener != null) {
361             runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram(datagram, isEmergency));
362         } else {
363             loge("sendDatagram: mLocalListener is null");
364         }
365     }
366 
367     @Override
requestSatelliteModemState(@onNull IIntegerConsumer errorCallback, @NonNull IIntegerConsumer callback)368     public void requestSatelliteModemState(@NonNull IIntegerConsumer errorCallback,
369             @NonNull IIntegerConsumer callback) {
370         logd("requestSatelliteModemState: mErrorCode=" + mErrorCode);
371         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
372             runWithExecutor(() -> errorCallback.accept(mErrorCode));
373             return;
374         }
375         runWithExecutor(() -> callback.accept(mModemState));
376     }
377 
378     @Override
requestTimeForNextSatelliteVisibility(@onNull IIntegerConsumer errorCallback, @NonNull IIntegerConsumer callback)379     public void requestTimeForNextSatelliteVisibility(@NonNull IIntegerConsumer errorCallback,
380             @NonNull IIntegerConsumer callback) {
381         logd("requestTimeForNextSatelliteVisibility: mErrorCode=" + mErrorCode);
382         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
383             runWithExecutor(() -> errorCallback.accept(mErrorCode));
384             return;
385         }
386         runWithExecutor(() -> callback.accept(SATELLITE_ALWAYS_VISIBLE));
387     }
388 
389     @Override
setSatellitePlmn(int simLogicalSlotIndex, List<String> carrierPlmnList, List<String> allSatellitePlmnList, IIntegerConsumer resultCallback)390     public void setSatellitePlmn(int simLogicalSlotIndex, List<String> carrierPlmnList,
391             List<String> allSatellitePlmnList, IIntegerConsumer resultCallback) {
392         logd("setSatellitePlmn: simLogicalSlotIndex=" + simLogicalSlotIndex + " , carrierPlmnList="
393                 + carrierPlmnList + " , allSatellitePlmnList=" + allSatellitePlmnList);
394         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
395             runWithExecutor(() -> resultCallback.accept(mErrorCode));
396             return;
397         }
398         runWithExecutor(() -> resultCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
399 
400         mCarrierPlmnList = carrierPlmnList;
401         mAllPlmnList = allSatellitePlmnList;
402 
403         if (mLocalListener != null) {
404             runWithExecutor(() -> mLocalListener.onSetSatellitePlmn());
405         } else {
406             loge("setSatellitePlmn: mLocalListener is null");
407         }
408     }
409 
410     @Override
setSatelliteEnabledForCarrier(int simLogicalSlotIndex, boolean satelliteEnabled, IIntegerConsumer callback)411     public void setSatelliteEnabledForCarrier(int simLogicalSlotIndex, boolean satelliteEnabled,
412             IIntegerConsumer callback) {
413         logd("setSatelliteEnabledForCarrier: simLogicalSlotIndex=" + simLogicalSlotIndex
414                 + ", satelliteEnabled=" + satelliteEnabled);
415         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
416             runWithExecutor(() -> callback.accept(mErrorCode));
417             return;
418         }
419 
420         mIsSatelliteEnabledForCarrier = satelliteEnabled;
421         runWithExecutor(() -> callback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
422     }
423 
424     @Override
requestIsSatelliteEnabledForCarrier(int simLogicalSlotIndex, IIntegerConsumer resultCallback, IBooleanConsumer callback)425     public void requestIsSatelliteEnabledForCarrier(int simLogicalSlotIndex,
426             IIntegerConsumer resultCallback, IBooleanConsumer callback) {
427         logd("requestIsSatelliteEnabledForCarrier: simLogicalSlotIndex=" + simLogicalSlotIndex);
428         if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
429             runWithExecutor(() -> resultCallback.accept(mErrorCode));
430             mIsRequestIsSatelliteEnabledForCarrier = false;
431             return;
432         }
433 
434         runWithExecutor(() -> callback.accept(mIsSatelliteEnabledForCarrier));
435         mIsRequestIsSatelliteEnabledForCarrier = true;
436     }
437 
438     @Override
updateSatelliteSubscription(@onNull String iccId, @NonNull IIntegerConsumer resultCallback)439     public void updateSatelliteSubscription(@NonNull String iccId,
440             @NonNull IIntegerConsumer resultCallback) {
441         logd("updateSatelliteSubscription: iccId=" + iccId + " mErrorCode=" + mErrorCode);
442         runWithExecutor(() -> resultCallback.accept(mErrorCode));
443     }
444 
445     @Override
updateSystemSelectionChannels( @onNull List<SystemSelectionSpecifier> systemSelectionSpecifiers, @NonNull IIntegerConsumer resultCallback)446     public void updateSystemSelectionChannels(
447             @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
448             @NonNull IIntegerConsumer resultCallback) {
449         logd(" updateSystemSelectionChannels: "
450                 + "systemSelectionSpecifiers=" + systemSelectionSpecifiers
451                 + " mErrorCode=" + mErrorCode);
452         runWithExecutor(() -> resultCallback.accept(mErrorCode));
453     }
454 
setLocalSatelliteListener(@onNull ILocalSatelliteListener listener)455     public void setLocalSatelliteListener(@NonNull ILocalSatelliteListener listener) {
456         logd("setLocalSatelliteListener: listener=" + listener);
457         mLocalListener = listener;
458         if (mShouldNotifyRemoteServiceConnected.get()) {
459             notifyRemoteServiceConnected();
460         }
461     }
462 
setErrorCode(@atelliteResult int errorCode)463     public void setErrorCode(@SatelliteResult int errorCode) {
464         logd("setErrorCode: errorCode=" + errorCode);
465         mErrorCode = errorCode;
466     }
467 
setSatelliteSupport(boolean supported)468     public void setSatelliteSupport(boolean supported) {
469         logd("setSatelliteSupport: supported=" + supported);
470         mIsSupported = supported;
471     }
472 
sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount)473     public void sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount) {
474         logd("sendOnSatelliteDatagramReceived");
475         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
476                 listener.onSatelliteDatagramReceived(datagram, pendingCount)));
477     }
478 
sendOnPendingDatagrams()479     public void sendOnPendingDatagrams() {
480         logd("sendOnPendingDatagrams");
481         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
482                 listener.onPendingDatagrams()));
483     }
484 
sendOnSatellitePositionChanged(PointingInfo pointingInfo)485     public void sendOnSatellitePositionChanged(PointingInfo pointingInfo) {
486         logd("sendOnSatellitePositionChanged");
487         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
488                 listener.onSatellitePositionChanged(pointingInfo)));
489     }
490 
491     /**
492      * Helper method to report satellite supported from modem side for testing purpose.
493      * @param supported whether satellite is supported from modem or not.
494      */
sendOnSatelliteSupportedStateChanged(boolean supported)495     public void sendOnSatelliteSupportedStateChanged(boolean supported) {
496         logd("sendOnSatelliteSupportedStateChanged: supported=" + supported);
497         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
498                 listener.onSatelliteSupportedStateChanged(supported)));
499     }
500 
501     /**
502      * Helper method to verify that the satellite modem is properly configured to receive
503      * requests.
504      *
505      * @param errorCallback The callback to notify of any errors preventing satellite requests.
506      * @return {@code true} if the satellite modem is configured to receive requests and
507      * {@code false} if it is not.
508      */
verifySatelliteModemState(@onNull IIntegerConsumer errorCallback)509     private boolean verifySatelliteModemState(@NonNull IIntegerConsumer errorCallback) {
510         if (!mIsSupported) {
511             runWithExecutor(() -> errorCallback.accept(
512                     SatelliteResult.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED));
513             return false;
514         }
515         if (!mIsProvisioned) {
516             runWithExecutor(() -> errorCallback.accept(
517                     SatelliteResult.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED));
518             return false;
519         }
520         if (!mIsEnabled) {
521             runWithExecutor(() -> errorCallback.accept(
522                     SatelliteResult.SATELLITE_RESULT_INVALID_MODEM_STATE));
523             return false;
524         }
525         return true;
526     }
527 
528     /**
529      * Update the satellite modem state and notify listeners if it changed.
530      *
531      * @param modemState The {@link SatelliteModemState} to update.
532      */
updateSatelliteModemState(int modemState)533     private void updateSatelliteModemState(int modemState) {
534         if (modemState == mModemState) {
535             return;
536         }
537         if (mIsCellularModemEnabledMode
538                 && modemState == SatelliteModemState.SATELLITE_MODEM_STATE_OFF) {
539             logd("Not updating the Modem state to Off as it is in CellularModemEnabledMode");
540             return;
541         }
542         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
543                 listener.onSatelliteModemStateChanged(modemState)));
544         mModemState = modemState;
545     }
546 
547     /**
548      * Update the satellite provision state and notify listeners if it changed.
549      *
550      * @param isProvisioned {@code true} if the satellite is currently provisioned and
551      *                      {@code false} if it is not.
552      */
updateSatelliteProvisionState(boolean isProvisioned)553     private void updateSatelliteProvisionState(boolean isProvisioned) {
554         logd("updateSatelliteProvisionState: isProvisioned=" + isProvisioned
555                 + ", mIsProvisioned=" + mIsProvisioned);
556         if (isProvisioned == mIsProvisioned) {
557             return;
558         }
559         mIsProvisioned = isProvisioned;
560         logd("updateSatelliteProvisionState: mRemoteListeners.size=" + mRemoteListeners.size());
561         mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
562                 listener.onSatelliteProvisionStateChanged(mIsProvisioned)));
563     }
564 
565     /**
566      * Execute the given runnable using the executor that this service was created with.
567      *
568      * @param r A runnable that can throw an exception.
569      */
runWithExecutor(@onNull FunctionalUtils.ThrowingRunnable r)570     private void runWithExecutor(@NonNull FunctionalUtils.ThrowingRunnable r) {
571         mExecutor.execute(() -> Binder.withCleanCallingIdentity(r));
572     }
573 
notifyRemoteServiceConnected()574     private void notifyRemoteServiceConnected() {
575         logd("notifyRemoteServiceConnected");
576         if (mLocalListener != null) {
577             runWithExecutor(() -> mLocalListener.onRemoteServiceConnected());
578             mShouldNotifyRemoteServiceConnected.set(false);
579         } else {
580             mShouldNotifyRemoteServiceConnected.set(true);
581         }
582     }
583 
getCarrierPlmnList()584     public List<String> getCarrierPlmnList() {
585         return mCarrierPlmnList;
586     }
587 
getAllSatellitePlmnList()588     public List<String> getAllSatellitePlmnList() {
589         return mAllPlmnList;
590     }
591 
isSatelliteEnabledForCarrier()592     public boolean isSatelliteEnabledForCarrier() {
593         return mIsSatelliteEnabledForCarrier;
594     }
595 
isRequestIsSatelliteEnabledForCarrier()596     public boolean isRequestIsSatelliteEnabledForCarrier() {
597         return mIsRequestIsSatelliteEnabledForCarrier;
598     }
599 
getIsEmergency()600     public boolean getIsEmergency() {
601         return mIsEmergnecy;
602     }
603 
604     /**
605      * Helper methoid to provide a way to set supported state from test application to mock modem.
606      * @param supported whether satellite is supported by modem or not.
607      */
updateSatelliteSupportedState(boolean supported)608     public void updateSatelliteSupportedState(boolean  supported) {
609         logd("updateSatelliteSupportedState: supported=" + supported);
610         mIsSupported = supported;
611         mRemoteListeners.values().forEach(listener -> runWithExecutor(
612                 () -> listener.onSatelliteSupportedStateChanged(mIsSupported)));
613 
614     }
615 
getSatelliteSupportedState()616     public boolean getSatelliteSupportedState() {
617         return mIsSupported;
618     }
619 
620     /**
621      * Log the message to the radio buffer with {@code DEBUG} priority.
622      *
623      * @param log The message to log.
624      */
logd(@onNull String log)625     private static void logd(@NonNull String log) {
626         Rlog.d(TAG, log);
627     }
628 
629     /**
630      * Log with error attribute
631      *
632      * @param s is string log
633      */
loge(@onNull String s)634     protected void loge(@NonNull String s) {
635         Log.e(TAG, s);
636     }
637 }
638