diff --git a/service/ServiceConnectivityResources/res/values/config_thread.xml b/service/ServiceConnectivityResources/res/values/config_thread.xml
index 14b54275c1..f7e47f552d 100644
--- a/service/ServiceConnectivityResources/res/values/config_thread.xml
+++ b/service/ServiceConnectivityResources/res/values/config_thread.xml
@@ -20,10 +20,15 @@
-->
+
+ true
+
true
-
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index f2c4d91534..d9af5a3983 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -46,6 +46,7 @@
+
diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkService.java b/thread/service/java/com/android/server/thread/ThreadNetworkService.java
index 5cf27f7f13..5664922f85 100644
--- a/thread/service/java/com/android/server/thread/ThreadNetworkService.java
+++ b/thread/service/java/com/android/server/thread/ThreadNetworkService.java
@@ -18,21 +18,16 @@ package com.android.server.thread;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ApexEnvironment;
import android.content.Context;
import android.net.thread.IThreadNetworkController;
import android.net.thread.IThreadNetworkManager;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
-import android.util.AtomicFile;
import com.android.server.SystemService;
-import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
@@ -51,12 +46,7 @@ public class ThreadNetworkService extends IThreadNetworkManager.Stub {
/** Creates a new {@link ThreadNetworkService} object. */
public ThreadNetworkService(Context context) {
mContext = context;
- mPersistentSettings =
- new ThreadPersistentSettings(
- new AtomicFile(
- new File(
- getOrCreateThreadnetworkDir(),
- ThreadPersistentSettings.FILE_NAME)));
+ mPersistentSettings = ThreadPersistentSettings.newInstance(context);
}
/**
@@ -123,19 +113,4 @@ public class ThreadNetworkService extends IThreadNetworkManager.Stub {
pw.println();
}
-
- /** Get device protected storage dir for the tethering apex. */
- private static File getOrCreateThreadnetworkDir() {
- final File threadnetworkDir;
- final File apexDataDir =
- ApexEnvironment.getApexEnvironment(TETHERING_MODULE_NAME)
- .getDeviceProtectedDataDir();
- threadnetworkDir = new File(apexDataDir, "thread");
-
- if (threadnetworkDir.exists() || threadnetworkDir.mkdirs()) {
- return threadnetworkDir;
- }
- throw new IllegalStateException(
- "Cannot write into thread network data directory: " + threadnetworkDir);
- }
}
diff --git a/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java b/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java
index d32f0bf028..aba4193da0 100644
--- a/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java
+++ b/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java
@@ -16,15 +16,23 @@
package com.android.server.thread;
+import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
+
import android.annotation.Nullable;
+import android.content.ApexEnvironment;
+import android.content.Context;
import android.os.PersistableBundle;
import android.util.AtomicFile;
import android.util.Log;
+import com.android.connectivity.resources.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.connectivity.ConnectivityResources;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -39,7 +47,7 @@ import java.io.InputStream;
public class ThreadPersistentSettings {
private static final String TAG = "ThreadPersistentSettings";
/** File name used for storing settings. */
- public static final String FILE_NAME = "ThreadPersistentSettings.xml";
+ private static final String FILE_NAME = "ThreadPersistentSettings.xml";
/** Current config store data version. This will be incremented for any additions. */
private static final int CURRENT_SETTINGS_STORE_DATA_VERSION = 1;
/**
@@ -62,16 +70,29 @@ public class ThreadPersistentSettings {
@GuardedBy("mLock")
private final PersistableBundle mSettings = new PersistableBundle();
- public ThreadPersistentSettings(AtomicFile atomicFile) {
+ private final ConnectivityResources mResources;
+
+ public static ThreadPersistentSettings newInstance(Context context) {
+ return new ThreadPersistentSettings(
+ new AtomicFile(new File(getOrCreateThreadNetworkDir(), FILE_NAME)),
+ new ConnectivityResources(context));
+ }
+
+ @VisibleForTesting
+ ThreadPersistentSettings(AtomicFile atomicFile, ConnectivityResources resources) {
mAtomicFile = atomicFile;
+ mResources = resources;
}
/** Initialize the settings by reading from the settings file. */
public void initialize() {
readFromStoreFile();
synchronized (mLock) {
- if (mSettings.isEmpty()) {
- put(THREAD_ENABLED.key, THREAD_ENABLED.defaultValue);
+ if (!mSettings.containsKey(THREAD_ENABLED.key)) {
+ Log.i(TAG, "\"thread_enabled\" is missing in settings file, using default value");
+ put(
+ THREAD_ENABLED.key,
+ mResources.get().getBoolean(R.bool.config_thread_default_enabled));
}
}
}
@@ -240,4 +261,19 @@ public class ThreadPersistentSettings {
throw e;
}
}
+
+ /** Get device protected storage dir for the tethering apex. */
+ private static File getOrCreateThreadNetworkDir() {
+ final File threadnetworkDir;
+ final File apexDataDir =
+ ApexEnvironment.getApexEnvironment(TETHERING_MODULE_NAME)
+ .getDeviceProtectedDataDir();
+ threadnetworkDir = new File(apexDataDir, "thread");
+
+ if (threadnetworkDir.exists() || threadnetworkDir.mkdirs()) {
+ return threadnetworkDir;
+ }
+ throw new IllegalStateException(
+ "Cannot write into thread network data directory: " + threadnetworkDir);
+ }
}
diff --git a/thread/tests/unit/src/android/net/thread/ThreadPersistentSettingsTest.java b/thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java
similarity index 67%
rename from thread/tests/unit/src/android/net/thread/ThreadPersistentSettingsTest.java
rename to thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java
index 11aabb803e..927b5aeda9 100644
--- a/thread/tests/unit/src/android/net/thread/ThreadPersistentSettingsTest.java
+++ b/thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java
@@ -23,18 +23,22 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.res.Resources;
import android.os.PersistableBundle;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.AtomicFile;
import androidx.test.runner.AndroidJUnit4;
+import com.android.connectivity.resources.R;
+import com.android.server.connectivity.ConnectivityResources;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -51,16 +55,22 @@ import java.io.FileOutputStream;
@SmallTest
public class ThreadPersistentSettingsTest {
@Mock private AtomicFile mAtomicFile;
+ @Mock Resources mResources;
+ @Mock ConnectivityResources mConnectivityResources;
- private ThreadPersistentSettings mThreadPersistentSetting;
+ private ThreadPersistentSettings mThreadPersistentSettings;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ when(mConnectivityResources.get()).thenReturn(mResources);
+ when(mResources.getBoolean(eq(R.bool.config_thread_default_enabled))).thenReturn(true);
+
FileOutputStream fos = mock(FileOutputStream.class);
when(mAtomicFile.startWrite()).thenReturn(fos);
- mThreadPersistentSetting = new ThreadPersistentSettings(mAtomicFile);
+ mThreadPersistentSettings =
+ new ThreadPersistentSettings(mAtomicFile, mConnectivityResources);
}
/** Called after each test */
@@ -70,10 +80,42 @@ public class ThreadPersistentSettingsTest {
}
@Test
- public void put_ThreadFeatureEnabledTrue_returnsTrue() throws Exception {
- mThreadPersistentSetting.put(THREAD_ENABLED.key, true);
+ public void initialize_readsFromFile() throws Exception {
+ byte[] data = createXmlForParsing(THREAD_ENABLED.key, false);
+ setupAtomicFileMockForRead(data);
- assertThat(mThreadPersistentSetting.get(THREAD_ENABLED)).isTrue();
+ mThreadPersistentSettings.initialize();
+
+ assertThat(mThreadPersistentSettings.get(THREAD_ENABLED)).isFalse();
+ }
+
+ @Test
+ public void initialize_ThreadDisabledInResources_returnsThreadDisabled() throws Exception {
+ when(mResources.getBoolean(eq(R.bool.config_thread_default_enabled))).thenReturn(false);
+ setupAtomicFileMockForRead(new byte[0]);
+
+ mThreadPersistentSettings.initialize();
+
+ assertThat(mThreadPersistentSettings.get(THREAD_ENABLED)).isFalse();
+ }
+
+ @Test
+ public void initialize_ThreadDisabledInResourcesButEnabledInXml_returnsThreadEnabled()
+ throws Exception {
+ when(mResources.getBoolean(eq(R.bool.config_thread_default_enabled))).thenReturn(false);
+ byte[] data = createXmlForParsing(THREAD_ENABLED.key, true);
+ setupAtomicFileMockForRead(data);
+
+ mThreadPersistentSettings.initialize();
+
+ assertThat(mThreadPersistentSettings.get(THREAD_ENABLED)).isTrue();
+ }
+
+ @Test
+ public void put_ThreadFeatureEnabledTrue_returnsTrue() throws Exception {
+ mThreadPersistentSettings.put(THREAD_ENABLED.key, true);
+
+ assertThat(mThreadPersistentSettings.get(THREAD_ENABLED)).isTrue();
// Confirm that file writes have been triggered.
verify(mAtomicFile).startWrite();
verify(mAtomicFile).finishWrite(any());
@@ -81,26 +123,14 @@ public class ThreadPersistentSettingsTest {
@Test
public void put_ThreadFeatureEnabledFalse_returnsFalse() throws Exception {
- mThreadPersistentSetting.put(THREAD_ENABLED.key, false);
+ mThreadPersistentSettings.put(THREAD_ENABLED.key, false);
- assertThat(mThreadPersistentSetting.get(THREAD_ENABLED)).isFalse();
+ assertThat(mThreadPersistentSettings.get(THREAD_ENABLED)).isFalse();
// Confirm that file writes have been triggered.
verify(mAtomicFile).startWrite();
verify(mAtomicFile).finishWrite(any());
}
- @Test
- public void initialize_readsFromFile() throws Exception {
- byte[] data = createXmlForParsing(THREAD_ENABLED.key, false);
- setupAtomicFileMockForRead(data);
-
- // Trigger file read.
- mThreadPersistentSetting.initialize();
-
- assertThat(mThreadPersistentSetting.get(THREAD_ENABLED)).isFalse();
- verify(mAtomicFile, never()).startWrite();
- }
-
private byte[] createXmlForParsing(String key, Boolean value) throws Exception {
PersistableBundle bundle = new PersistableBundle();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();