[Thread] disable handling of airplane mode

This is basically a revert of aosp/3079292 to disable the handling of
the airplane mode. The cause is that there are a few reported ANR issues
on real devices and they points to the handlers here in Thread module.

Before we figure out the root cause, let's disable the airplane mode
handler in Thread to recover the presubmit tests.

Bug: 353115531
Bug: 352484437
Bug: 350586929
Bug: 352316041
Change-Id: I569ced2855658f965ddf51242600ee3c325781a7
This commit is contained in:
Kangping Dong 2024-07-15 15:41:38 +08:00
commit 14da81bc17
2 changed files with 1 additions and 173 deletions

View file

@ -111,7 +111,6 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
@ -211,7 +210,6 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
private final ThreadPersistentSettings mPersistentSettings;
private final UserManager mUserManager;
private boolean mUserRestricted;
private boolean mAirplaneModeOn;
private boolean mForceStopOtDaemonEnabled;
private BorderRouterConfigurationParcel mBorderRouterConfig;
@ -446,8 +444,6 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
requestThreadNetwork();
mUserRestricted = isThreadUserRestricted();
registerUserRestrictionsReceiver();
mAirplaneModeOn = isAirplaneModeOn();
registerAirplaneModeReceiver();
maybeInitializeOtDaemon();
});
}
@ -529,15 +525,6 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
// the otDaemon set enabled state operation succeeded or not, so that it can recover
// to the desired value after reboot.
mPersistentSettings.put(ThreadPersistentSettings.THREAD_ENABLED.key, isEnabled);
// Remember whether the user wanted to keep Thread enabled in airplane mode. If once
// the user disabled Thread again in airplane mode, the persistent settings state is
// reset (so that Thread will be auto-disabled again when airplane mode is turned on).
// This behavior is consistent with Wi-Fi and bluetooth.
if (mAirplaneModeOn) {
mPersistentSettings.put(
ThreadPersistentSettings.THREAD_ENABLED_IN_AIRPLANE_MODE.key, isEnabled);
}
}
try {
@ -676,74 +663,13 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
return mUserManager.hasUserRestriction(DISALLOW_THREAD_NETWORK);
}
private void registerAirplaneModeReceiver() {
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
onAirplaneModeChanged(isAirplaneModeOn());
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED),
null /* broadcastPermission */,
mHandler);
}
private void onAirplaneModeChanged(boolean newAirplaneModeOn) {
checkOnHandlerThread();
if (mAirplaneModeOn == newAirplaneModeOn) {
return;
}
Log.i(TAG, "Airplane mode changed: " + mAirplaneModeOn + " -> " + newAirplaneModeOn);
mAirplaneModeOn = newAirplaneModeOn;
final boolean shouldEnableThread = shouldEnableThread();
final IOperationReceiver receiver =
new IOperationReceiver.Stub() {
@Override
public void onSuccess() {
Log.d(
TAG,
(shouldEnableThread ? "Enabled" : "Disabled")
+ " Thread due to airplane mode change");
}
@Override
public void onError(int errorCode, String errorMessage) {
Log.e(
TAG,
"Failed to "
+ (shouldEnableThread ? "enable" : "disable")
+ " Thread for airplane mode change");
}
};
// Do not save the user restriction state to persistent settings so that the user
// configuration won't be overwritten
setEnabledInternal(
shouldEnableThread, false /* persist */, new OperationReceiverWrapper(receiver));
}
/** Returns {@code true} if Airplane mode has been turned on. */
private boolean isAirplaneModeOn() {
return Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0)
== 1;
}
/**
* Returns {@code true} if Thread should be enabled based on current settings, runtime user
* restriction and airplane mode state.
* restriction state.
*/
private boolean shouldEnableThread() {
final boolean enabledInAirplaneMode =
mPersistentSettings.get(ThreadPersistentSettings.THREAD_ENABLED_IN_AIRPLANE_MODE);
return !mForceStopOtDaemonEnabled
&& !mUserRestricted
// FIXME(b/340744397): Note that here we need to call `isAirplaneModeOn()` to get
// the latest state of airplane mode but can't use `mIsAirplaneMode`. This is for
// avoiding the race conditions described in b/340744397
&& (!isAirplaneModeOn() || enabledInAirplaneMode)
&& mPersistentSettings.get(ThreadPersistentSettings.THREAD_ENABLED);
}

View file

@ -26,7 +26,6 @@ import static android.net.thread.ThreadNetworkManager.DISALLOW_THREAD_NETWORK;
import static android.net.thread.ThreadNetworkManager.PERMISSION_THREAD_NETWORK_PRIVILEGED;
import static com.android.server.thread.ThreadNetworkCountryCode.DEFAULT_COUNTRY_CODE;
import static com.android.server.thread.ThreadPersistentSettings.THREAD_ENABLED_IN_AIRPLANE_MODE;
import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_INVALID_STATE;
import static com.google.common.io.BaseEncoding.base16;
@ -70,7 +69,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserManager;
import android.os.test.TestLooper;
import android.provider.Settings;
import android.util.AtomicFile;
import androidx.test.annotation.UiThreadTest;
@ -194,8 +192,6 @@ public final class ThreadNetworkControllerServiceTest {
when(mMockUserManager.hasUserRestriction(eq(DISALLOW_THREAD_NETWORK))).thenReturn(false);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
when(mConnectivityResources.get()).thenReturn(mResources);
when(mResources.getBoolean(eq(R.bool.config_thread_default_enabled))).thenReturn(true);
when(mResources.getString(eq(R.string.config_thread_vendor_name)))
@ -481,100 +477,6 @@ public final class ThreadNetworkControllerServiceTest {
assertThat(failure.getErrorCode()).isEqualTo(ERROR_FAILED_PRECONDITION);
}
@Test
public void airplaneMode_initWithAirplaneModeOn_otDaemonNotStarted() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
mService.initialize();
mTestLooper.dispatchAll();
assertThat(mFakeOtDaemon.isInitialized()).isFalse();
}
@Test
public void airplaneMode_initWithAirplaneModeOff_threadIsEnabled() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
mService.initialize();
mTestLooper.dispatchAll();
assertThat(mFakeOtDaemon.getEnabledState()).isEqualTo(STATE_ENABLED);
}
@Test
public void airplaneMode_changesFromOffToOn_stateIsDisabled() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
AtomicReference<BroadcastReceiver> receiverRef =
captureBroadcastReceiver(Intent.ACTION_AIRPLANE_MODE_CHANGED);
mService.initialize();
mTestLooper.dispatchAll();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
receiverRef.get().onReceive(mContext, new Intent());
mTestLooper.dispatchAll();
assertThat(mFakeOtDaemon.getEnabledState()).isEqualTo(STATE_DISABLED);
}
@Test
public void airplaneMode_changesFromOnToOff_stateIsEnabled() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
AtomicReference<BroadcastReceiver> receiverRef =
captureBroadcastReceiver(Intent.ACTION_AIRPLANE_MODE_CHANGED);
mService.initialize();
mTestLooper.dispatchAll();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
receiverRef.get().onReceive(mContext, new Intent());
mTestLooper.dispatchAll();
assertThat(mFakeOtDaemon.getEnabledState()).isEqualTo(STATE_ENABLED);
}
@Test
public void airplaneMode_setEnabledWhenAirplaneModeIsOn_WillNotAutoDisableSecondTime() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
AtomicReference<BroadcastReceiver> receiverRef =
captureBroadcastReceiver(Intent.ACTION_AIRPLANE_MODE_CHANGED);
CompletableFuture<Void> setEnabledFuture = new CompletableFuture<>();
mService.initialize();
mService.setEnabled(true, newOperationReceiver(setEnabledFuture));
mTestLooper.dispatchAll();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
receiverRef.get().onReceive(mContext, new Intent());
mTestLooper.dispatchAll();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
receiverRef.get().onReceive(mContext, new Intent());
mTestLooper.dispatchAll();
assertThat(mFakeOtDaemon.getEnabledState()).isEqualTo(STATE_ENABLED);
assertThat(mPersistentSettings.get(THREAD_ENABLED_IN_AIRPLANE_MODE)).isTrue();
}
@Test
public void airplaneMode_setDisabledWhenAirplaneModeIsOn_WillAutoDisableSecondTime() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
AtomicReference<BroadcastReceiver> receiverRef =
captureBroadcastReceiver(Intent.ACTION_AIRPLANE_MODE_CHANGED);
CompletableFuture<Void> setEnabledFuture = new CompletableFuture<>();
mService.initialize();
mService.setEnabled(true, newOperationReceiver(setEnabledFuture));
mTestLooper.dispatchAll();
mService.setEnabled(false, newOperationReceiver(setEnabledFuture));
mTestLooper.dispatchAll();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
receiverRef.get().onReceive(mContext, new Intent());
mTestLooper.dispatchAll();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
receiverRef.get().onReceive(mContext, new Intent());
mTestLooper.dispatchAll();
assertThat(mFakeOtDaemon.getEnabledState()).isEqualTo(STATE_DISABLED);
assertThat(mPersistentSettings.get(THREAD_ENABLED_IN_AIRPLANE_MODE)).isFalse();
}
private AtomicReference<BroadcastReceiver> captureBroadcastReceiver(String action) {
AtomicReference<BroadcastReceiver> receiverRef = new AtomicReference<>();