diff --git a/src/com/android/settings/wifi/helper/SavedWifiHelper.java b/src/com/android/settings/wifi/helper/SavedWifiHelper.java new file mode 100644 index 00000000000..ebc97286f2f --- /dev/null +++ b/src/com/android/settings/wifi/helper/SavedWifiHelper.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2022 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.settings.wifi.helper; + +import android.annotation.TestApi; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.GuardedBy; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Lifecycle; + +import com.android.wifitrackerlib.SavedNetworkTracker; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Helper for saved Wi-Fi networks tracker from WifiTrackerLib. + */ +public class SavedWifiHelper extends WifiTrackerBase { + private static final String TAG = "SavedWifiHelper"; + + private static final Object sInstanceLock = new Object(); + @TestApi + @GuardedBy("sInstanceLock") + private static Map sTestInstances; + + protected SavedNetworkTracker mSavedNetworkTracker; + + /** + * Static method to create a SavedWifiHelper class. + * + * @param context The Context this is associated with. + * @param lifecycle The lifecycle this is associated with. + * @return an instance of {@link SavedWifiHelper} object. + */ + public static SavedWifiHelper getInstance(@NonNull Context context, + @NonNull Lifecycle lifecycle) { + synchronized (sInstanceLock) { + if (sTestInstances != null && sTestInstances.containsKey(context)) { + SavedWifiHelper testInstance = sTestInstances.get(context); + Log.w(TAG, "The context owner use a test instance:" + testInstance); + return testInstance; + } + return new SavedWifiHelper(context, lifecycle); + } + } + + /** + * A convenience method to set pre-prepared instance or mock(SavedWifiHelper.class) for + * testing. + * + * @param context The Context this is associated with. + * @param instance of {@link SavedWifiHelper} object. + * @hide + */ + @TestApi + @VisibleForTesting + public static void setTestInstance(@NonNull Context context, SavedWifiHelper instance) { + synchronized (sInstanceLock) { + if (sTestInstances == null) sTestInstances = new ConcurrentHashMap<>(); + Log.w(TAG, "Set a test instance by context:" + context); + sTestInstances.put(context, instance); + } + } + + public SavedWifiHelper(@NonNull Context context, @NonNull Lifecycle lifecycle) { + this(context, lifecycle, null); + } + + @VisibleForTesting + protected SavedWifiHelper(@NonNull Context context, @NonNull Lifecycle lifecycle, + SavedNetworkTracker saveNetworkTracker) { + super(lifecycle); + mSavedNetworkTracker = (saveNetworkTracker != null) ? saveNetworkTracker + : createSavedNetworkTracker(context, lifecycle); + } + + @VisibleForTesting + protected SavedNetworkTracker createSavedNetworkTracker(@NonNull Context context, + @NonNull Lifecycle lifecycle) { + return new SavedNetworkTracker(lifecycle, context.getApplicationContext(), + context.getApplicationContext().getSystemService(WifiManager.class), + context.getApplicationContext().getSystemService(ConnectivityManager.class), + new Handler(Looper.getMainLooper()), + getWorkerThreadHandler(), + ELAPSED_REALTIME_CLOCK, + MAX_SCAN_AGE_MILLIS, + SCAN_INTERVAL_MILLIS, + null /* SavedNetworkTrackerCallback */); + } + + @Override + protected String getTag() { + return TAG; + } + + public SavedNetworkTracker getSavedNetworkTracker() { + return mSavedNetworkTracker; + } + + /** + * Returns true when the certificate is being used by a saved network or network suggestion. + */ + public boolean isCertificateInUse(String certAlias) { + return mSavedNetworkTracker.isCertificateRequired(certAlias); + } + + /** + * Returns a list of network names which is using the certificate alias. + * + * @return a list of network names. + */ + public List getCertificateNetworkNames(String certAlias) { + return mSavedNetworkTracker.getCertificateRequesterNames(certAlias); + } +} diff --git a/src/com/android/settings/wifi/helper/WifiTrackerBase.java b/src/com/android/settings/wifi/helper/WifiTrackerBase.java new file mode 100644 index 00000000000..19be76a013a --- /dev/null +++ b/src/com/android/settings/wifi/helper/WifiTrackerBase.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022 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.settings.wifi.helper; + +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; +import android.os.SimpleClock; +import android.os.SystemClock; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.DefaultLifecycleObserver; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleOwner; + +import java.time.Clock; +import java.time.ZoneOffset; + +/** + * Base class for the WifiTrackerLib related classes. + */ +public class WifiTrackerBase implements DefaultLifecycleObserver { + private static final String TAG = "WifiTrackerBase"; + + // Max age of tracked WifiEntries + protected static final long MAX_SCAN_AGE_MILLIS = 15_000; + // Interval between initiating Wi-Fi Tracker scans + protected static final long SCAN_INTERVAL_MILLIS = 10_000; + // Clock used for evaluating the age of scans + protected static final Clock ELAPSED_REALTIME_CLOCK = new SimpleClock(ZoneOffset.UTC) { + @Override + public long millis() { + return SystemClock.elapsedRealtime(); + } + }; + + @VisibleForTesting + protected HandlerThread mWorkerThread; + + public WifiTrackerBase(@NonNull Lifecycle lifecycle) { + this(lifecycle, null /* handlerThread */); + } + + @VisibleForTesting + protected WifiTrackerBase(@NonNull Lifecycle lifecycle, HandlerThread handlerThread) { + lifecycle.addObserver(this); + mWorkerThread = (handlerThread != null) ? handlerThread : + new HandlerThread(getTag() + + "{" + Integer.toHexString(System.identityHashCode(this)) + "}", + Process.THREAD_PRIORITY_BACKGROUND); + mWorkerThread.start(); + } + + protected String getTag() { + return TAG; + } + + @Override + public void onDestroy(@NonNull LifecycleOwner owner) { + mWorkerThread.quit(); + } + + /** Returns the worker thread handler. */ + public Handler getWorkerThreadHandler() { + return mWorkerThread.getThreadHandler(); + } +} diff --git a/tests/unit/src/com/android/settings/wifi/helper/SavedWifiHelperTest.java b/tests/unit/src/com/android/settings/wifi/helper/SavedWifiHelperTest.java new file mode 100644 index 00000000000..2ad77e19b59 --- /dev/null +++ b/tests/unit/src/com/android/settings/wifi/helper/SavedWifiHelperTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 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.settings.wifi.helper; + +import static org.mockito.Mockito.verify; + +import android.content.Context; + +import androidx.lifecycle.Lifecycle; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.wifitrackerlib.SavedNetworkTracker; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(AndroidJUnit4.class) +public class SavedWifiHelperTest { + static final String TEST_ALIAS = "test_alias"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + final Context mContext = ApplicationProvider.getApplicationContext(); + @Mock + Lifecycle mLifecycle; + @Mock + SavedNetworkTracker mSaveNetworkTracker; + + SavedWifiHelper mSavedWifiHelper; + + @Before + public void setUp() { + mSavedWifiHelper = new SavedWifiHelper(mContext, mLifecycle, mSaveNetworkTracker); + } + + @Test + public void isCertificateInUse_redirectToSavedNetworkTracker() { + mSavedWifiHelper.isCertificateInUse(TEST_ALIAS); + + verify(mSaveNetworkTracker).isCertificateRequired(TEST_ALIAS); + } + + @Test + public void getCertificateNetworkNames_redirectToSavedNetworkTracker() { + mSavedWifiHelper.getCertificateNetworkNames(TEST_ALIAS); + + verify(mSaveNetworkTracker).getCertificateRequesterNames(TEST_ALIAS); + } +} diff --git a/tests/unit/src/com/android/settings/wifi/helper/WifiTrackerBaseTest.java b/tests/unit/src/com/android/settings/wifi/helper/WifiTrackerBaseTest.java new file mode 100644 index 00000000000..159e2e2d87b --- /dev/null +++ b/tests/unit/src/com/android/settings/wifi/helper/WifiTrackerBaseTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 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.settings.wifi.helper; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.os.HandlerThread; + +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleOwner; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(AndroidJUnit4.class) +public class WifiTrackerBaseTest { + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + Lifecycle mLifecycle; + @Mock + HandlerThread mWorkerThread; + + WifiTrackerBase mWifiTrackerBase; + + @Before + public void setUp() { + mWifiTrackerBase = new WifiTrackerBase(mLifecycle, mWorkerThread); + } + + @Test + public void constructor_createWorkerThread() { + mWifiTrackerBase = new WifiTrackerBase(mLifecycle); + + assertThat(mWifiTrackerBase.mWorkerThread).isNotNull(); + } + + @Test + public void constructor_startWorkerThread() { + verify(mWorkerThread).start(); + } + + @Test + public void onDestroy_quitWorkerThread() { + mWifiTrackerBase.onDestroy(mock(LifecycleOwner.class)); + + verify(mWorkerThread).quit(); + } + + @Test + public void getWorkerThreadHandler_isNotNull() { + mWifiTrackerBase = new WifiTrackerBase(mLifecycle); + + assertThat(mWifiTrackerBase.getWorkerThreadHandler()).isNotNull(); + } +}