Loading src/java/com/android/internal/telephony/satellite/DatagramController.java +68 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCC import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.os.Build; import android.os.Looper; import android.os.SystemProperties; Loading Loading @@ -69,6 +70,8 @@ public class DatagramController { public static final int TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE = 3; /** This type is used by CTS to override the time to datagram delay in demo mode */ public static final int TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE = 4; /** This type is used by CTS to override wait for device alignment in demo datagram boolean */ public static final int BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM = 1; private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; private static final boolean DEBUG = !"user".equals(Build.TYPE); Loading Loading @@ -101,6 +104,7 @@ public class DatagramController { private long mAlignTimeoutDuration = SATELLITE_ALIGN_TIMEOUT; private long mDatagramWaitTimeForConnectedState; private long mModemImageSwitchingDuration; private boolean mWaitForDeviceAlignmentInDemoDatagram; @GuardedBy("mLock") @SatelliteManager.SatelliteModemState private int mSatelltieModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN; Loading Loading @@ -155,6 +159,8 @@ public class DatagramController { mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis(); mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis(); mWaitForDeviceAlignmentInDemoDatagram = getWaitForDeviceAlignmentInDemoDatagramFromResources(); mDemoModeDatagramList = new ArrayList<>(); } Loading Loading @@ -492,6 +498,36 @@ public class DatagramController { return true; } /** * This API can be used by only CTS to override the boolean configs used by the * DatagramController module. * * @param enable Whether to enable or disable boolean config. * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. */ boolean setDatagramControllerBooleanConfig( boolean reset, int booleanType, boolean enable) { if (!isMockModemAllowed()) { loge("Updating boolean config is not allowed"); return false; } logd("setDatagramControllerTimeoutDuration: booleanType=" + booleanType + ", reset=" + reset + ", enable=" + enable); if (booleanType == BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM) { if (reset) { mWaitForDeviceAlignmentInDemoDatagram = getWaitForDeviceAlignmentInDemoDatagramFromResources(); } else { mWaitForDeviceAlignmentInDemoDatagram = enable; } } else { loge("Invalid boolean type " + booleanType); return false; } return true; } private boolean isMockModemAllowed() { return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); } Loading Loading @@ -546,6 +582,38 @@ public class DatagramController { } } /** * Get whether to wait for device alignment with satellite before sending datagrams. * * @param isAligned if the device is aligned with satellite or not * @return {@code true} if device is not aligned to satellite, * and it is required to wait for alignment else {@code false} */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean waitForAligningToSatellite(boolean isAligned) { if (isAligned) { return false; } return getWaitForDeviceAlignmentInDemoDatagram(); } private boolean getWaitForDeviceAlignmentInDemoDatagram() { return mWaitForDeviceAlignmentInDemoDatagram; } private boolean getWaitForDeviceAlignmentInDemoDatagramFromResources() { boolean waitForDeviceAlignmentInDemoDatagram = false; try { waitForDeviceAlignmentInDemoDatagram = mContext.getResources().getBoolean( R.bool.config_wait_for_device_alignment_in_demo_datagram); } catch (Resources.NotFoundException ex) { loge("getWaitForDeviceAlignmentInDemoDatagram: ex=" + ex); } return waitForDeviceAlignmentInDemoDatagram; } private static void logd(@NonNull String log) { Rlog.d(TAG, log); } Loading src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java +1 −1 Original line number Diff line number Diff line Loading @@ -239,7 +239,7 @@ public class DatagramDispatcher extends Handler { if (mIsDemoMode && (error == SatelliteManager.SATELLITE_RESULT_SUCCESS)) { if (argument.skipCheckingSatelliteAligned) { logd("Satellite was already aligned. No need to check alignment again"); } else if (!mIsAligned) { } else if (mDatagramController.waitForAligningToSatellite(mIsAligned)) { logd("Satellite is not aligned in demo mode, wait for the alignment."); startSatelliteAlignedTimer(request); break; Loading src/java/com/android/internal/telephony/satellite/DatagramReceiver.java +1 −1 Original line number Diff line number Diff line Loading @@ -620,7 +620,7 @@ public class DatagramReceiver extends Handler { DatagramReceiverHandlerRequest request = new DatagramReceiverHandlerRequest( callback, phone, subId); synchronized (mLock) { if (mIsAligned) { if (!mDatagramController.waitForAligningToSatellite(mIsAligned)) { Message msg = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE, request); AsyncResult.forMessage(msg, null, null); Loading src/java/com/android/internal/telephony/satellite/DemoSimulator.java 0 → 100644 +329 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony.satellite; import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.telephony.IIntegerConsumer; import android.telephony.satellite.stub.ISatelliteListener; import android.telephony.satellite.stub.NtnSignalStrength; import android.telephony.satellite.stub.SatelliteModemState; import android.telephony.satellite.stub.SatelliteResult; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.State; import com.android.internal.util.StateMachine; public class DemoSimulator extends StateMachine { private static final String TAG = "DemoSimulator"; private static final boolean DBG = true; private static final int EVENT_SATELLITE_MODE_ON = 1; private static final int EVENT_SATELLITE_MODE_OFF = 2; private static final int EVENT_DEVICE_ALIGNED_WITH_SATELLITE = 3; protected static final int EVENT_DEVICE_ALIGNED = 4; protected static final int EVENT_DEVICE_NOT_ALIGNED = 5; @NonNull private static DemoSimulator sInstance; @NonNull private final Context mContext; @NonNull private final SatelliteController mSatelliteController; @NonNull private final PowerOffState mPowerOffState = new PowerOffState(); @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState(); @NonNull private final ConnectedState mConnectedState = new ConnectedState(); @NonNull private final Object mLock = new Object(); @GuardedBy("mLock") private boolean mIsAligned = false; private ISatelliteListener mISatelliteListener; /** * @return The singleton instance of DemoSimulator. */ public static DemoSimulator getInstance() { if (sInstance == null) { Log.e(TAG, "DemoSimulator was not yet initialized."); } return sInstance; } /** * Create the DemoSimulator singleton instance. * * @param context The Context for the DemoSimulator. * @return The singleton instance of DemoSimulator. */ public static DemoSimulator make(@NonNull Context context, @NonNull SatelliteController satelliteController) { if (sInstance == null) { sInstance = new DemoSimulator(context, Looper.getMainLooper(), satelliteController); } return sInstance; } /** * Create a DemoSimulator. * * @param context The Context for the DemoSimulator. * @param looper The looper associated with the handler of this class. */ protected DemoSimulator(@NonNull Context context, @NonNull Looper looper, @NonNull SatelliteController satelliteController) { super(TAG, looper); mContext = context; mSatelliteController = satelliteController; addState(mPowerOffState); addState(mNotConnectedState); addState(mConnectedState); setInitialState(mPowerOffState); start(); } private class PowerOffState extends State { @Override public void enter() { logd("Entering PowerOffState"); } @Override public void exit() { logd("Exiting PowerOffState"); } @Override public boolean processMessage(Message msg) { if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what)); switch (msg.what) { case EVENT_SATELLITE_MODE_ON: transitionTo(mNotConnectedState); break; } // Ignore all unexpected events. return HANDLED; } } private class NotConnectedState extends State { @Override public void enter() { logd("Entering NotConnectedState"); try { NtnSignalStrength ntnSignalStrength = new NtnSignalStrength(); ntnSignalStrength.signalStrengthLevel = 0; mISatelliteListener.onSatelliteModemStateChanged( SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED); mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength); synchronized (mLock) { if (mIsAligned) { handleEventDeviceAlignedWithSatellite(true); } } } catch (RemoteException e) { loge("NotConnectedState: RemoteException " + e); } } @Override public void exit() { logd("Exiting NotConnectedState"); } @Override public boolean processMessage(Message msg) { if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what)); switch (msg.what) { case EVENT_SATELLITE_MODE_OFF: transitionTo(mPowerOffState); break; case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: handleEventDeviceAlignedWithSatellite((boolean) msg.obj); break; case EVENT_DEVICE_ALIGNED: transitionTo(mConnectedState); break; } // Ignore all unexpected events. return HANDLED; } private void handleEventDeviceAlignedWithSatellite(boolean isAligned) { if (isAligned && !hasMessages(EVENT_DEVICE_ALIGNED)) { long durationMillis = mSatelliteController.getDemoPointingAlignedDurationMillis(); logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=true." + " Send delayed EVENT_DEVICE_ALIGNED message in" + " durationMillis=" + durationMillis); sendMessageDelayed(EVENT_DEVICE_ALIGNED, durationMillis); } else if (!isAligned && hasMessages(EVENT_DEVICE_ALIGNED)) { logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=false." + " Remove EVENT_DEVICE_ALIGNED message."); removeMessages(EVENT_DEVICE_ALIGNED); } } } private class ConnectedState extends State { @Override public void enter() { logd("Entering ConnectedState"); try { NtnSignalStrength ntnSignalStrength = new NtnSignalStrength(); ntnSignalStrength.signalStrengthLevel = 2; mISatelliteListener.onSatelliteModemStateChanged( SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED); mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength); synchronized (mLock) { if (!mIsAligned) { handleEventDeviceAlignedWithSatellite(false); } } } catch (RemoteException e) { loge("ConnectedState: RemoteException " + e); } } @Override public void exit() { logd("Exiting ConnectedState"); } @Override public boolean processMessage(Message msg) { if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what)); switch (msg.what) { case EVENT_SATELLITE_MODE_OFF: transitionTo(mPowerOffState); break; case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: handleEventDeviceAlignedWithSatellite((boolean) msg.obj); break; case EVENT_DEVICE_NOT_ALIGNED: transitionTo(mNotConnectedState); break; } // Ignore all unexpected events. return HANDLED; } private void handleEventDeviceAlignedWithSatellite(boolean isAligned) { if (!isAligned && !hasMessages(EVENT_DEVICE_NOT_ALIGNED)) { long durationMillis = mSatelliteController.getDemoPointingNotAlignedDurationMillis(); logd("ConnectedState: handleEventAlignedWithSatellite isAligned=false." + " Send delayed EVENT_DEVICE_NOT_ALIGNED message" + " in durationMillis=" + durationMillis); sendMessageDelayed(EVENT_DEVICE_NOT_ALIGNED, durationMillis); } else if (isAligned && hasMessages(EVENT_DEVICE_NOT_ALIGNED)) { logd("ConnectedState: handleEventAlignedWithSatellite isAligned=true." + " Remove EVENT_DEVICE_NOT_ALIGNED message."); removeMessages(EVENT_DEVICE_NOT_ALIGNED); } } } /** * @return the string for msg.what */ @Override protected String getWhatToString(int what) { String whatString; switch (what) { case EVENT_SATELLITE_MODE_ON: whatString = "EVENT_SATELLITE_MODE_ON"; break; case EVENT_SATELLITE_MODE_OFF: whatString = "EVENT_SATELLITE_MODE_OFF"; break; case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: whatString = "EVENT_DEVICE_ALIGNED_WITH_SATELLITE"; break; case EVENT_DEVICE_ALIGNED: whatString = "EVENT_DEVICE_ALIGNED"; break; case EVENT_DEVICE_NOT_ALIGNED: whatString = "EVENT_DEVICE_NOT_ALIGNED"; break; default: whatString = "UNKNOWN EVENT " + what; } return whatString; } /** * Register the callback interface with satellite service. * * @param listener The callback interface to handle satellite service indications. */ public void setSatelliteListener(@NonNull ISatelliteListener listener) { mISatelliteListener = listener; } /** * Allow cellular modem scanning while satellite mode is on. * * @param enabled {@code true} to enable cellular modem while satellite mode is on * and {@code false} to disable * @param errorCallback The callback to receive the error code result of the operation. */ public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled, @NonNull IIntegerConsumer errorCallback) { try { errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS); } catch (RemoteException e) { loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e); } } /** * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator} * that satellite mode is ON. */ public void onSatelliteModeOn() { if (mSatelliteController.isDemoModeEnabled()) { sendMessage(EVENT_SATELLITE_MODE_ON); } } /** * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator} * that satellite mode is OFF. */ public void onSatelliteModeOff() { sendMessage(EVENT_SATELLITE_MODE_OFF); } /** * Set whether the device is aligned with the satellite. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void setDeviceAlignedWithSatellite(boolean isAligned) { synchronized (mLock) { if (mSatelliteController.isDemoModeEnabled()) { mIsAligned = isAligned; sendMessage(EVENT_DEVICE_ALIGNED_WITH_SATELLITE, isAligned); } } } } src/java/com/android/internal/telephony/satellite/SatelliteController.java +78 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,10 @@ public class SatelliteController extends Handler { * to enable satellite. */ public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1; /** This is used by CTS to override demo pointing aligned duration. */ public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2; /** This is used by CTS to override demo pointing not aligned duration. */ public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3; /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */ private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY = Loading Loading @@ -408,6 +412,8 @@ public class SatelliteController extends Handler { private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0); private long mWaitTimeForSatelliteEnablingResponse; private long mDemoPointingAlignedDurationMillis; private long mDemoPointingNotAlignedDurationMillis; /** Key used to read/write satellite system notification done in shared preferences. */ private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = Loading Loading @@ -537,6 +543,9 @@ public class SatelliteController extends Handler { null); loadSatelliteSharedPreferences(); mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis(); mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); mDemoPointingNotAlignedDurationMillis = getDemoPointingNotAlignedDurationMillisFromResources(); } /** Loading Loading @@ -2055,6 +2064,8 @@ public class SatelliteController extends Handler { logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled"); return; } DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned); mDatagramController.setDeviceAlignedWithSatellite(isAligned); } Loading Loading @@ -2384,6 +2395,25 @@ public class SatelliteController extends Handler { reset, timeoutType, timeoutMillis); } /** * This API can be used by only CTS to override the boolean configs used by the * DatagramController module. * * @param enable Whether to enable or disable boolean config. * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. */ public boolean setDatagramControllerBooleanConfig( boolean reset, int booleanType, boolean enable) { if (!mFeatureFlags.oemEnabledSatelliteFlag()) { logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled"); return false; } logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType=" + booleanType + ", enable=" + enable); return mDatagramController.setDatagramControllerBooleanConfig( reset, booleanType, enable); } /** * This API can be used by only CTS to override timeout durations used by SatelliteController * module. Loading Loading @@ -2411,6 +2441,20 @@ public class SatelliteController extends Handler { mWaitTimeForSatelliteEnablingResponse = timeoutMillis; } logd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse); } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) { if (reset) { mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); } else { mDemoPointingAlignedDurationMillis = timeoutMillis; } } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) { if (reset) { mDemoPointingNotAlignedDurationMillis = getDemoPointingNotAlignedDurationMillisFromResources(); } else { mDemoPointingNotAlignedDurationMillis = timeoutMillis; } } else { logw("Invalid timeoutType=" + timeoutType); return false; Loading Loading @@ -4618,6 +4662,40 @@ public class SatelliteController extends Handler { } } private long getDemoPointingAlignedDurationMillisFromResources() { long durationMillis = 15000L; try { durationMillis = mContext.getResources().getInteger( R.integer.config_demo_pointing_aligned_duration_millis); } catch (Resources.NotFoundException ex) { loge("getPointingAlignedDurationMillis: ex=" + ex); } return durationMillis; } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public long getDemoPointingAlignedDurationMillis() { return mDemoPointingAlignedDurationMillis; } private long getDemoPointingNotAlignedDurationMillisFromResources() { long durationMillis = 30000L; try { durationMillis = mContext.getResources().getInteger( R.integer.config_demo_pointing_not_aligned_duration_millis); } catch (Resources.NotFoundException ex) { loge("getPointingNotAlignedDurationMillis: ex=" + ex); } return durationMillis; } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public long getDemoPointingNotAlignedDurationMillis() { return mDemoPointingNotAlignedDurationMillis; } private static void logd(@NonNull String log) { Rlog.d(TAG, log); } Loading Loading
src/java/com/android/internal/telephony/satellite/DatagramController.java +68 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCC import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.os.Build; import android.os.Looper; import android.os.SystemProperties; Loading Loading @@ -69,6 +70,8 @@ public class DatagramController { public static final int TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE = 3; /** This type is used by CTS to override the time to datagram delay in demo mode */ public static final int TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE = 4; /** This type is used by CTS to override wait for device alignment in demo datagram boolean */ public static final int BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM = 1; private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; private static final boolean DEBUG = !"user".equals(Build.TYPE); Loading Loading @@ -101,6 +104,7 @@ public class DatagramController { private long mAlignTimeoutDuration = SATELLITE_ALIGN_TIMEOUT; private long mDatagramWaitTimeForConnectedState; private long mModemImageSwitchingDuration; private boolean mWaitForDeviceAlignmentInDemoDatagram; @GuardedBy("mLock") @SatelliteManager.SatelliteModemState private int mSatelltieModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN; Loading Loading @@ -155,6 +159,8 @@ public class DatagramController { mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis(); mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis(); mWaitForDeviceAlignmentInDemoDatagram = getWaitForDeviceAlignmentInDemoDatagramFromResources(); mDemoModeDatagramList = new ArrayList<>(); } Loading Loading @@ -492,6 +498,36 @@ public class DatagramController { return true; } /** * This API can be used by only CTS to override the boolean configs used by the * DatagramController module. * * @param enable Whether to enable or disable boolean config. * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. */ boolean setDatagramControllerBooleanConfig( boolean reset, int booleanType, boolean enable) { if (!isMockModemAllowed()) { loge("Updating boolean config is not allowed"); return false; } logd("setDatagramControllerTimeoutDuration: booleanType=" + booleanType + ", reset=" + reset + ", enable=" + enable); if (booleanType == BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM) { if (reset) { mWaitForDeviceAlignmentInDemoDatagram = getWaitForDeviceAlignmentInDemoDatagramFromResources(); } else { mWaitForDeviceAlignmentInDemoDatagram = enable; } } else { loge("Invalid boolean type " + booleanType); return false; } return true; } private boolean isMockModemAllowed() { return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)); } Loading Loading @@ -546,6 +582,38 @@ public class DatagramController { } } /** * Get whether to wait for device alignment with satellite before sending datagrams. * * @param isAligned if the device is aligned with satellite or not * @return {@code true} if device is not aligned to satellite, * and it is required to wait for alignment else {@code false} */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean waitForAligningToSatellite(boolean isAligned) { if (isAligned) { return false; } return getWaitForDeviceAlignmentInDemoDatagram(); } private boolean getWaitForDeviceAlignmentInDemoDatagram() { return mWaitForDeviceAlignmentInDemoDatagram; } private boolean getWaitForDeviceAlignmentInDemoDatagramFromResources() { boolean waitForDeviceAlignmentInDemoDatagram = false; try { waitForDeviceAlignmentInDemoDatagram = mContext.getResources().getBoolean( R.bool.config_wait_for_device_alignment_in_demo_datagram); } catch (Resources.NotFoundException ex) { loge("getWaitForDeviceAlignmentInDemoDatagram: ex=" + ex); } return waitForDeviceAlignmentInDemoDatagram; } private static void logd(@NonNull String log) { Rlog.d(TAG, log); } Loading
src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java +1 −1 Original line number Diff line number Diff line Loading @@ -239,7 +239,7 @@ public class DatagramDispatcher extends Handler { if (mIsDemoMode && (error == SatelliteManager.SATELLITE_RESULT_SUCCESS)) { if (argument.skipCheckingSatelliteAligned) { logd("Satellite was already aligned. No need to check alignment again"); } else if (!mIsAligned) { } else if (mDatagramController.waitForAligningToSatellite(mIsAligned)) { logd("Satellite is not aligned in demo mode, wait for the alignment."); startSatelliteAlignedTimer(request); break; Loading
src/java/com/android/internal/telephony/satellite/DatagramReceiver.java +1 −1 Original line number Diff line number Diff line Loading @@ -620,7 +620,7 @@ public class DatagramReceiver extends Handler { DatagramReceiverHandlerRequest request = new DatagramReceiverHandlerRequest( callback, phone, subId); synchronized (mLock) { if (mIsAligned) { if (!mDatagramController.waitForAligningToSatellite(mIsAligned)) { Message msg = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE, request); AsyncResult.forMessage(msg, null, null); Loading
src/java/com/android/internal/telephony/satellite/DemoSimulator.java 0 → 100644 +329 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony.satellite; import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.telephony.IIntegerConsumer; import android.telephony.satellite.stub.ISatelliteListener; import android.telephony.satellite.stub.NtnSignalStrength; import android.telephony.satellite.stub.SatelliteModemState; import android.telephony.satellite.stub.SatelliteResult; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.State; import com.android.internal.util.StateMachine; public class DemoSimulator extends StateMachine { private static final String TAG = "DemoSimulator"; private static final boolean DBG = true; private static final int EVENT_SATELLITE_MODE_ON = 1; private static final int EVENT_SATELLITE_MODE_OFF = 2; private static final int EVENT_DEVICE_ALIGNED_WITH_SATELLITE = 3; protected static final int EVENT_DEVICE_ALIGNED = 4; protected static final int EVENT_DEVICE_NOT_ALIGNED = 5; @NonNull private static DemoSimulator sInstance; @NonNull private final Context mContext; @NonNull private final SatelliteController mSatelliteController; @NonNull private final PowerOffState mPowerOffState = new PowerOffState(); @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState(); @NonNull private final ConnectedState mConnectedState = new ConnectedState(); @NonNull private final Object mLock = new Object(); @GuardedBy("mLock") private boolean mIsAligned = false; private ISatelliteListener mISatelliteListener; /** * @return The singleton instance of DemoSimulator. */ public static DemoSimulator getInstance() { if (sInstance == null) { Log.e(TAG, "DemoSimulator was not yet initialized."); } return sInstance; } /** * Create the DemoSimulator singleton instance. * * @param context The Context for the DemoSimulator. * @return The singleton instance of DemoSimulator. */ public static DemoSimulator make(@NonNull Context context, @NonNull SatelliteController satelliteController) { if (sInstance == null) { sInstance = new DemoSimulator(context, Looper.getMainLooper(), satelliteController); } return sInstance; } /** * Create a DemoSimulator. * * @param context The Context for the DemoSimulator. * @param looper The looper associated with the handler of this class. */ protected DemoSimulator(@NonNull Context context, @NonNull Looper looper, @NonNull SatelliteController satelliteController) { super(TAG, looper); mContext = context; mSatelliteController = satelliteController; addState(mPowerOffState); addState(mNotConnectedState); addState(mConnectedState); setInitialState(mPowerOffState); start(); } private class PowerOffState extends State { @Override public void enter() { logd("Entering PowerOffState"); } @Override public void exit() { logd("Exiting PowerOffState"); } @Override public boolean processMessage(Message msg) { if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what)); switch (msg.what) { case EVENT_SATELLITE_MODE_ON: transitionTo(mNotConnectedState); break; } // Ignore all unexpected events. return HANDLED; } } private class NotConnectedState extends State { @Override public void enter() { logd("Entering NotConnectedState"); try { NtnSignalStrength ntnSignalStrength = new NtnSignalStrength(); ntnSignalStrength.signalStrengthLevel = 0; mISatelliteListener.onSatelliteModemStateChanged( SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED); mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength); synchronized (mLock) { if (mIsAligned) { handleEventDeviceAlignedWithSatellite(true); } } } catch (RemoteException e) { loge("NotConnectedState: RemoteException " + e); } } @Override public void exit() { logd("Exiting NotConnectedState"); } @Override public boolean processMessage(Message msg) { if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what)); switch (msg.what) { case EVENT_SATELLITE_MODE_OFF: transitionTo(mPowerOffState); break; case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: handleEventDeviceAlignedWithSatellite((boolean) msg.obj); break; case EVENT_DEVICE_ALIGNED: transitionTo(mConnectedState); break; } // Ignore all unexpected events. return HANDLED; } private void handleEventDeviceAlignedWithSatellite(boolean isAligned) { if (isAligned && !hasMessages(EVENT_DEVICE_ALIGNED)) { long durationMillis = mSatelliteController.getDemoPointingAlignedDurationMillis(); logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=true." + " Send delayed EVENT_DEVICE_ALIGNED message in" + " durationMillis=" + durationMillis); sendMessageDelayed(EVENT_DEVICE_ALIGNED, durationMillis); } else if (!isAligned && hasMessages(EVENT_DEVICE_ALIGNED)) { logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=false." + " Remove EVENT_DEVICE_ALIGNED message."); removeMessages(EVENT_DEVICE_ALIGNED); } } } private class ConnectedState extends State { @Override public void enter() { logd("Entering ConnectedState"); try { NtnSignalStrength ntnSignalStrength = new NtnSignalStrength(); ntnSignalStrength.signalStrengthLevel = 2; mISatelliteListener.onSatelliteModemStateChanged( SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED); mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength); synchronized (mLock) { if (!mIsAligned) { handleEventDeviceAlignedWithSatellite(false); } } } catch (RemoteException e) { loge("ConnectedState: RemoteException " + e); } } @Override public void exit() { logd("Exiting ConnectedState"); } @Override public boolean processMessage(Message msg) { if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what)); switch (msg.what) { case EVENT_SATELLITE_MODE_OFF: transitionTo(mPowerOffState); break; case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: handleEventDeviceAlignedWithSatellite((boolean) msg.obj); break; case EVENT_DEVICE_NOT_ALIGNED: transitionTo(mNotConnectedState); break; } // Ignore all unexpected events. return HANDLED; } private void handleEventDeviceAlignedWithSatellite(boolean isAligned) { if (!isAligned && !hasMessages(EVENT_DEVICE_NOT_ALIGNED)) { long durationMillis = mSatelliteController.getDemoPointingNotAlignedDurationMillis(); logd("ConnectedState: handleEventAlignedWithSatellite isAligned=false." + " Send delayed EVENT_DEVICE_NOT_ALIGNED message" + " in durationMillis=" + durationMillis); sendMessageDelayed(EVENT_DEVICE_NOT_ALIGNED, durationMillis); } else if (isAligned && hasMessages(EVENT_DEVICE_NOT_ALIGNED)) { logd("ConnectedState: handleEventAlignedWithSatellite isAligned=true." + " Remove EVENT_DEVICE_NOT_ALIGNED message."); removeMessages(EVENT_DEVICE_NOT_ALIGNED); } } } /** * @return the string for msg.what */ @Override protected String getWhatToString(int what) { String whatString; switch (what) { case EVENT_SATELLITE_MODE_ON: whatString = "EVENT_SATELLITE_MODE_ON"; break; case EVENT_SATELLITE_MODE_OFF: whatString = "EVENT_SATELLITE_MODE_OFF"; break; case EVENT_DEVICE_ALIGNED_WITH_SATELLITE: whatString = "EVENT_DEVICE_ALIGNED_WITH_SATELLITE"; break; case EVENT_DEVICE_ALIGNED: whatString = "EVENT_DEVICE_ALIGNED"; break; case EVENT_DEVICE_NOT_ALIGNED: whatString = "EVENT_DEVICE_NOT_ALIGNED"; break; default: whatString = "UNKNOWN EVENT " + what; } return whatString; } /** * Register the callback interface with satellite service. * * @param listener The callback interface to handle satellite service indications. */ public void setSatelliteListener(@NonNull ISatelliteListener listener) { mISatelliteListener = listener; } /** * Allow cellular modem scanning while satellite mode is on. * * @param enabled {@code true} to enable cellular modem while satellite mode is on * and {@code false} to disable * @param errorCallback The callback to receive the error code result of the operation. */ public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled, @NonNull IIntegerConsumer errorCallback) { try { errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS); } catch (RemoteException e) { loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e); } } /** * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator} * that satellite mode is ON. */ public void onSatelliteModeOn() { if (mSatelliteController.isDemoModeEnabled()) { sendMessage(EVENT_SATELLITE_MODE_ON); } } /** * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator} * that satellite mode is OFF. */ public void onSatelliteModeOff() { sendMessage(EVENT_SATELLITE_MODE_OFF); } /** * Set whether the device is aligned with the satellite. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void setDeviceAlignedWithSatellite(boolean isAligned) { synchronized (mLock) { if (mSatelliteController.isDemoModeEnabled()) { mIsAligned = isAligned; sendMessage(EVENT_DEVICE_ALIGNED_WITH_SATELLITE, isAligned); } } } }
src/java/com/android/internal/telephony/satellite/SatelliteController.java +78 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,10 @@ public class SatelliteController extends Handler { * to enable satellite. */ public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1; /** This is used by CTS to override demo pointing aligned duration. */ public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2; /** This is used by CTS to override demo pointing not aligned duration. */ public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3; /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */ private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY = Loading Loading @@ -408,6 +412,8 @@ public class SatelliteController extends Handler { private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0); private long mWaitTimeForSatelliteEnablingResponse; private long mDemoPointingAlignedDurationMillis; private long mDemoPointingNotAlignedDurationMillis; /** Key used to read/write satellite system notification done in shared preferences. */ private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = Loading Loading @@ -537,6 +543,9 @@ public class SatelliteController extends Handler { null); loadSatelliteSharedPreferences(); mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis(); mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); mDemoPointingNotAlignedDurationMillis = getDemoPointingNotAlignedDurationMillisFromResources(); } /** Loading Loading @@ -2055,6 +2064,8 @@ public class SatelliteController extends Handler { logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled"); return; } DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned); mDatagramController.setDeviceAlignedWithSatellite(isAligned); } Loading Loading @@ -2384,6 +2395,25 @@ public class SatelliteController extends Handler { reset, timeoutType, timeoutMillis); } /** * This API can be used by only CTS to override the boolean configs used by the * DatagramController module. * * @param enable Whether to enable or disable boolean config. * @return {@code true} if the boolean config is set successfully, {@code false} otherwise. */ public boolean setDatagramControllerBooleanConfig( boolean reset, int booleanType, boolean enable) { if (!mFeatureFlags.oemEnabledSatelliteFlag()) { logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled"); return false; } logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType=" + booleanType + ", enable=" + enable); return mDatagramController.setDatagramControllerBooleanConfig( reset, booleanType, enable); } /** * This API can be used by only CTS to override timeout durations used by SatelliteController * module. Loading Loading @@ -2411,6 +2441,20 @@ public class SatelliteController extends Handler { mWaitTimeForSatelliteEnablingResponse = timeoutMillis; } logd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse); } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) { if (reset) { mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources(); } else { mDemoPointingAlignedDurationMillis = timeoutMillis; } } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) { if (reset) { mDemoPointingNotAlignedDurationMillis = getDemoPointingNotAlignedDurationMillisFromResources(); } else { mDemoPointingNotAlignedDurationMillis = timeoutMillis; } } else { logw("Invalid timeoutType=" + timeoutType); return false; Loading Loading @@ -4618,6 +4662,40 @@ public class SatelliteController extends Handler { } } private long getDemoPointingAlignedDurationMillisFromResources() { long durationMillis = 15000L; try { durationMillis = mContext.getResources().getInteger( R.integer.config_demo_pointing_aligned_duration_millis); } catch (Resources.NotFoundException ex) { loge("getPointingAlignedDurationMillis: ex=" + ex); } return durationMillis; } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public long getDemoPointingAlignedDurationMillis() { return mDemoPointingAlignedDurationMillis; } private long getDemoPointingNotAlignedDurationMillisFromResources() { long durationMillis = 30000L; try { durationMillis = mContext.getResources().getInteger( R.integer.config_demo_pointing_not_aligned_duration_millis); } catch (Resources.NotFoundException ex) { loge("getPointingNotAlignedDurationMillis: ex=" + ex); } return durationMillis; } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public long getDemoPointingNotAlignedDurationMillis() { return mDemoPointingNotAlignedDurationMillis; } private static void logd(@NonNull String log) { Rlog.d(TAG, log); } Loading