set the country code when initializing the ot-daemon
The country code is lost after the ot-daemon is restarted. This CL stores the country code to persistent settings and reads out the previously stored country code to set the country code when the ot-daemon is initialized. Bug: b/326021472 Test: atest ThreadNetworkUnitTests Change-Id: I6982a57ba4845f5a45f3366400c531398e82339e
This commit is contained in:
parent
abefbf0b9f
commit
4eab54b40e
9 changed files with 109 additions and 15 deletions
|
|
@ -182,6 +182,7 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
|
|||
private final NsdPublisher mNsdPublisher;
|
||||
private final OtDaemonCallbackProxy mOtDaemonCallbackProxy = new OtDaemonCallbackProxy();
|
||||
private final ConnectivityResources mResources;
|
||||
private final Supplier<String> mCountryCodeSupplier;
|
||||
|
||||
// This should not be directly used for calling IOtDaemon APIs because ot-daemon may die and
|
||||
// {@code mOtDaemon} will be set to {@code null}. Instead, use {@code getOtDaemon()}
|
||||
|
|
@ -215,7 +216,8 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
|
|||
ThreadPersistentSettings persistentSettings,
|
||||
NsdPublisher nsdPublisher,
|
||||
UserManager userManager,
|
||||
ConnectivityResources resources) {
|
||||
ConnectivityResources resources,
|
||||
Supplier<String> countryCodeSupplier) {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
mNetworkProvider = networkProvider;
|
||||
|
|
@ -230,10 +232,13 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
|
|||
mNsdPublisher = nsdPublisher;
|
||||
mUserManager = userManager;
|
||||
mResources = resources;
|
||||
mCountryCodeSupplier = countryCodeSupplier;
|
||||
}
|
||||
|
||||
public static ThreadNetworkControllerService newInstance(
|
||||
Context context, ThreadPersistentSettings persistentSettings) {
|
||||
Context context,
|
||||
ThreadPersistentSettings persistentSettings,
|
||||
Supplier<String> countryCodeSupplier) {
|
||||
HandlerThread handlerThread = new HandlerThread("ThreadHandlerThread");
|
||||
handlerThread.start();
|
||||
Handler handler = new Handler(handlerThread.getLooper());
|
||||
|
|
@ -251,7 +256,8 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
|
|||
persistentSettings,
|
||||
NsdPublisher.newInstance(context, handler),
|
||||
context.getSystemService(UserManager.class),
|
||||
new ConnectivityResources(context));
|
||||
new ConnectivityResources(context),
|
||||
countryCodeSupplier);
|
||||
}
|
||||
|
||||
private static Inet6Address bytesToInet6Address(byte[] addressBytes) {
|
||||
|
|
@ -347,7 +353,8 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
|
|||
isEnabled(),
|
||||
mNsdPublisher,
|
||||
getMeshcopTxtAttributes(mResources.get()),
|
||||
mOtDaemonCallbackProxy);
|
||||
mOtDaemonCallbackProxy,
|
||||
mCountryCodeSupplier.get());
|
||||
otDaemon.asBinder().linkToDeath(() -> mHandler.post(this::onOtDaemonDied), 0);
|
||||
mOtDaemon = otDaemon;
|
||||
return mOtDaemon;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.server.thread;
|
||||
|
||||
import static com.android.server.thread.ThreadPersistentSettings.THREAD_COUNTRY_CODE;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.StringDef;
|
||||
import android.annotation.TargetApi;
|
||||
|
|
@ -83,6 +85,7 @@ public class ThreadNetworkCountryCode {
|
|||
COUNTRY_CODE_SOURCE_TELEPHONY,
|
||||
COUNTRY_CODE_SOURCE_TELEPHONY_LAST,
|
||||
COUNTRY_CODE_SOURCE_WIFI,
|
||||
COUNTRY_CODE_SOURCE_SETTINGS,
|
||||
})
|
||||
private @interface CountryCodeSource {}
|
||||
|
||||
|
|
@ -93,6 +96,7 @@ public class ThreadNetworkCountryCode {
|
|||
private static final String COUNTRY_CODE_SOURCE_TELEPHONY = "Telephony";
|
||||
private static final String COUNTRY_CODE_SOURCE_TELEPHONY_LAST = "TelephonyLast";
|
||||
private static final String COUNTRY_CODE_SOURCE_WIFI = "Wifi";
|
||||
private static final String COUNTRY_CODE_SOURCE_SETTINGS = "Settings";
|
||||
|
||||
private static final CountryCodeInfo DEFAULT_COUNTRY_CODE_INFO =
|
||||
new CountryCodeInfo(DEFAULT_COUNTRY_CODE, COUNTRY_CODE_SOURCE_DEFAULT);
|
||||
|
|
@ -107,6 +111,7 @@ public class ThreadNetworkCountryCode {
|
|||
private final SubscriptionManager mSubscriptionManager;
|
||||
private final Map<Integer, TelephonyCountryCodeSlotInfo> mTelephonyCountryCodeSlotInfoMap =
|
||||
new ArrayMap();
|
||||
private final ThreadPersistentSettings mPersistentSettings;
|
||||
|
||||
@Nullable private CountryCodeInfo mCurrentCountryCodeInfo;
|
||||
@Nullable private CountryCodeInfo mLocationCountryCodeInfo;
|
||||
|
|
@ -215,7 +220,8 @@ public class ThreadNetworkCountryCode {
|
|||
Context context,
|
||||
TelephonyManager telephonyManager,
|
||||
SubscriptionManager subscriptionManager,
|
||||
@Nullable String oemCountryCode) {
|
||||
@Nullable String oemCountryCode,
|
||||
ThreadPersistentSettings persistentSettings) {
|
||||
mLocationManager = locationManager;
|
||||
mThreadNetworkControllerService = threadNetworkControllerService;
|
||||
mGeocoder = geocoder;
|
||||
|
|
@ -224,14 +230,19 @@ public class ThreadNetworkCountryCode {
|
|||
mContext = context;
|
||||
mTelephonyManager = telephonyManager;
|
||||
mSubscriptionManager = subscriptionManager;
|
||||
mPersistentSettings = persistentSettings;
|
||||
|
||||
if (oemCountryCode != null) {
|
||||
mOemCountryCodeInfo = new CountryCodeInfo(oemCountryCode, COUNTRY_CODE_SOURCE_OEM);
|
||||
}
|
||||
|
||||
mCurrentCountryCodeInfo = pickCountryCode();
|
||||
}
|
||||
|
||||
public static ThreadNetworkCountryCode newInstance(
|
||||
Context context, ThreadNetworkControllerService controllerService) {
|
||||
Context context,
|
||||
ThreadNetworkControllerService controllerService,
|
||||
ThreadPersistentSettings persistentSettings) {
|
||||
return new ThreadNetworkCountryCode(
|
||||
context.getSystemService(LocationManager.class),
|
||||
controllerService,
|
||||
|
|
@ -241,7 +252,8 @@ public class ThreadNetworkCountryCode {
|
|||
context,
|
||||
context.getSystemService(TelephonyManager.class),
|
||||
context.getSystemService(SubscriptionManager.class),
|
||||
ThreadNetworkProperties.country_code().orElse(null));
|
||||
ThreadNetworkProperties.country_code().orElse(null),
|
||||
persistentSettings);
|
||||
}
|
||||
|
||||
/** Sets up this country code module to listen to location country code changes. */
|
||||
|
|
@ -485,6 +497,11 @@ public class ThreadNetworkCountryCode {
|
|||
return mLocationCountryCodeInfo;
|
||||
}
|
||||
|
||||
String settingsCountryCode = mPersistentSettings.get(THREAD_COUNTRY_CODE);
|
||||
if (settingsCountryCode != null) {
|
||||
return new CountryCodeInfo(settingsCountryCode, COUNTRY_CODE_SOURCE_SETTINGS);
|
||||
}
|
||||
|
||||
if (mOemCountryCodeInfo != null) {
|
||||
return mOemCountryCodeInfo;
|
||||
}
|
||||
|
|
@ -498,6 +515,8 @@ public class ThreadNetworkCountryCode {
|
|||
public void onSuccess() {
|
||||
synchronized ("ThreadNetworkCountryCode.this") {
|
||||
mCurrentCountryCodeInfo = countryCodeInfo;
|
||||
mPersistentSettings.put(
|
||||
THREAD_COUNTRY_CODE.key, countryCodeInfo.getCountryCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -536,10 +555,9 @@ public class ThreadNetworkCountryCode {
|
|||
newOperationReceiver(countryCodeInfo));
|
||||
}
|
||||
|
||||
/** Returns the current country code or {@code null} if no country code is set. */
|
||||
@Nullable
|
||||
/** Returns the current country code. */
|
||||
public synchronized String getCountryCode() {
|
||||
return (mCurrentCountryCodeInfo != null) ? mCurrentCountryCodeInfo.getCountryCode() : null;
|
||||
return mCurrentCountryCodeInfo.getCountryCode();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -60,13 +60,16 @@ public class ThreadNetworkService extends IThreadNetworkManager.Stub {
|
|||
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
|
||||
mPersistentSettings.initialize();
|
||||
mControllerService =
|
||||
ThreadNetworkControllerService.newInstance(mContext, mPersistentSettings);
|
||||
ThreadNetworkControllerService.newInstance(
|
||||
mContext, mPersistentSettings, () -> mCountryCode.getCountryCode());
|
||||
mCountryCode =
|
||||
ThreadNetworkCountryCode.newInstance(
|
||||
mContext, mControllerService, mPersistentSettings);
|
||||
mControllerService.initialize();
|
||||
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
|
||||
// Country code initialization is delayed to the BOOT_COMPLETED phase because it will
|
||||
// call into Wi-Fi and Telephony service whose country code module is ready after
|
||||
// PHASE_ACTIVITY_MANAGER_READY and PHASE_THIRD_PARTY_APPS_CAN_START
|
||||
mCountryCode = ThreadNetworkCountryCode.newInstance(mContext, mControllerService);
|
||||
mCountryCode.initialize();
|
||||
mShellCommand =
|
||||
new ThreadNetworkShellCommand(requireNonNull(mControllerService), mCountryCode);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ public class ThreadPersistentSettings {
|
|||
/** Stores the Thread feature toggle state, true for enabled and false for disabled. */
|
||||
public static final Key<Boolean> THREAD_ENABLED = new Key<>("Thread_enabled", true);
|
||||
|
||||
/** Stores the Thread country code, null if no country code is stored. */
|
||||
public static final Key<String> THREAD_COUNTRY_CODE = new Key<>("thread_country_code", null);
|
||||
|
||||
/******** Thread persistent setting keys ***************/
|
||||
|
||||
@GuardedBy("mLock")
|
||||
|
|
@ -123,7 +126,9 @@ public class ThreadPersistentSettings {
|
|||
private <T> T getObject(String key, T defaultValue) {
|
||||
Object value;
|
||||
synchronized (mLock) {
|
||||
if (defaultValue instanceof Boolean) {
|
||||
if (defaultValue == null) {
|
||||
value = mSettings.getString(key, null);
|
||||
} else if (defaultValue instanceof Boolean) {
|
||||
value = mSettings.getBoolean(key, (Boolean) defaultValue);
|
||||
} else if (defaultValue instanceof Integer) {
|
||||
value = mSettings.getInt(key, (Integer) defaultValue);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import static android.net.thread.utils.IntegrationTestUtils.CALLBACK_TIMEOUT;
|
|||
import static android.net.thread.utils.IntegrationTestUtils.RESTART_JOIN_TIMEOUT;
|
||||
|
||||
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
|
||||
import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
|
||||
|
||||
import static com.google.common.io.BaseEncoding.base16;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
|
@ -140,6 +141,22 @@ public class ThreadIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void otDaemonRestart_latestCountryCodeIsSetToOtDaemon() throws Exception {
|
||||
runThreadCommand("force-country-code enabled CN");
|
||||
|
||||
runShellCommand("stop ot-daemon");
|
||||
// TODO(b/323331973): the sleep is needed to workaround the race conditions
|
||||
SystemClock.sleep(200);
|
||||
mController.waitForRole(DEVICE_ROLE_STOPPED, CALLBACK_TIMEOUT);
|
||||
|
||||
assertThat(mOtCtl.getCountryCode()).isEqualTo("CN");
|
||||
}
|
||||
|
||||
private static String runThreadCommand(String cmd) {
|
||||
return runShellCommandOrThrow("cmd thread_network " + cmd);
|
||||
}
|
||||
|
||||
// TODO (b/323300829): add more tests for integration with linux platform and
|
||||
// ConnectivityService
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,12 @@ public final class OtDaemonController {
|
|||
return (Inet6Address) InetAddresses.parseNumericAddress(addressStr);
|
||||
}
|
||||
|
||||
/** Returns the country code on ot-daemon. */
|
||||
public String getCountryCode() {
|
||||
String countryCodeStr = executeCommand("region").split("\n")[0].trim();
|
||||
return countryCodeStr;
|
||||
}
|
||||
|
||||
public String executeCommand(String cmd) {
|
||||
return SystemUtil.runShellCommand(OT_CTL + " " + cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import static android.net.thread.ThreadNetworkException.ERROR_THREAD_DISABLED;
|
|||
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.openthread.IOtDaemon.ErrorCode.OT_ERROR_INVALID_STATE;
|
||||
|
||||
import static com.google.common.io.BaseEncoding.base16;
|
||||
|
|
@ -182,7 +183,8 @@ public final class ThreadNetworkControllerServiceTest {
|
|||
mMockPersistentSettings,
|
||||
mMockNsdPublisher,
|
||||
mMockUserManager,
|
||||
mConnectivityResources);
|
||||
mConnectivityResources,
|
||||
() -> DEFAULT_COUNTRY_CODE);
|
||||
mService.setTestNetworkAgent(mMockNetworkAgent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package com.android.server.thread;
|
|||
import static android.net.thread.ThreadNetworkException.ERROR_INTERNAL_ERROR;
|
||||
|
||||
import static com.android.server.thread.ThreadNetworkCountryCode.DEFAULT_COUNTRY_CODE;
|
||||
import static com.android.server.thread.ThreadPersistentSettings.THREAD_COUNTRY_CODE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
|
|
@ -104,6 +105,7 @@ public class ThreadNetworkCountryCodeTest {
|
|||
@Mock List<SubscriptionInfo> mSubscriptionInfoList;
|
||||
@Mock SubscriptionInfo mSubscriptionInfo0;
|
||||
@Mock SubscriptionInfo mSubscriptionInfo1;
|
||||
@Mock ThreadPersistentSettings mPersistentSettings;
|
||||
|
||||
private ThreadNetworkCountryCode mThreadNetworkCountryCode;
|
||||
private boolean mErrorSetCountryCode;
|
||||
|
|
@ -164,7 +166,8 @@ public class ThreadNetworkCountryCodeTest {
|
|||
mContext,
|
||||
mTelephonyManager,
|
||||
mSubscriptionManager,
|
||||
oemCountryCode);
|
||||
oemCountryCode,
|
||||
mPersistentSettings);
|
||||
}
|
||||
|
||||
private static Address newAddress(String countryCode) {
|
||||
|
|
@ -449,6 +452,14 @@ public class ThreadNetworkCountryCodeTest {
|
|||
assertThat(mThreadNetworkCountryCode.getCountryCode()).isEqualTo(DEFAULT_COUNTRY_CODE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void settingsCountryCode_settingsCountryCodeIsActive_settingsCountryCodeIsUsed() {
|
||||
when(mPersistentSettings.get(THREAD_COUNTRY_CODE)).thenReturn(TEST_COUNTRY_CODE_CN);
|
||||
mThreadNetworkCountryCode.initialize();
|
||||
|
||||
assertThat(mThreadNetworkCountryCode.getCountryCode()).isEqualTo(TEST_COUNTRY_CODE_CN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dump_allCountryCodeInfoAreDumped() {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.server.thread;
|
||||
|
||||
import static com.android.server.thread.ThreadPersistentSettings.THREAD_COUNTRY_CODE;
|
||||
import static com.android.server.thread.ThreadPersistentSettings.THREAD_ENABLED;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
|
@ -54,6 +55,8 @@ import java.io.FileOutputStream;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class ThreadPersistentSettingsTest {
|
||||
private static final String TEST_COUNTRY_CODE = "CN";
|
||||
|
||||
@Mock private AtomicFile mAtomicFile;
|
||||
@Mock Resources mResources;
|
||||
@Mock ConnectivityResources mConnectivityResources;
|
||||
|
|
@ -131,6 +134,28 @@ public class ThreadPersistentSettingsTest {
|
|||
verify(mAtomicFile).finishWrite(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void put_ThreadCountryCodeString_returnsString() throws Exception {
|
||||
mThreadPersistentSettings.put(THREAD_COUNTRY_CODE.key, TEST_COUNTRY_CODE);
|
||||
|
||||
assertThat(mThreadPersistentSettings.get(THREAD_COUNTRY_CODE)).isEqualTo(TEST_COUNTRY_CODE);
|
||||
|
||||
// Confirm that file writes have been triggered.
|
||||
verify(mAtomicFile).startWrite();
|
||||
verify(mAtomicFile).finishWrite(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void put_ThreadCountryCodeNull_returnsNull() throws Exception {
|
||||
mThreadPersistentSettings.put(THREAD_COUNTRY_CODE.key, null);
|
||||
|
||||
assertThat(mThreadPersistentSettings.get(THREAD_COUNTRY_CODE)).isNull();
|
||||
|
||||
// Confirm that file writes have been triggered.
|
||||
verify(mAtomicFile).startWrite();
|
||||
verify(mAtomicFile).finishWrite(any());
|
||||
}
|
||||
|
||||
private byte[] createXmlForParsing(String key, Boolean value) throws Exception {
|
||||
PersistableBundle bundle = new PersistableBundle();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
|
|
|||
Loading…
Reference in a new issue