blob: a0c2698da4b54f391a9de14b004173fda6d38745 [file] [log] [blame]
/*
* 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.settingslib.wifi;
import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.os.HandlerThread;
import android.os.Process;
import android.util.Log;
import androidx.annotation.GuardedBy;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* This is a singleton class for Wi-Fi state worker.
*/
public class WifiStateWorker {
private static final String TAG = "WifiStateWorker";
private static final Object sLock = new Object();
/**
* A singleton {@link WifiStateWorker} object is used to share with all sub-settings.
*/
@GuardedBy("sLock")
private static WifiStateWorker sInstance;
@TestApi
@GuardedBy("sLock")
private static Map<Context, WifiStateWorker> sTestInstances;
@VisibleForTesting
static WifiManager sWifiManager;
private static int sWifiState;
private static HandlerThread sWorkerThread;
/**
* Static method to create a singleton class for WifiStateWorker.
*
* @param context The Context this is associated with.
* @return an instance of {@link WifiStateWorker} object.
*/
@NonNull
@AnyThread
public static WifiStateWorker getInstance(@NonNull Context context) {
synchronized (sLock) {
if (sTestInstances != null && sTestInstances.containsKey(context)) {
WifiStateWorker testInstance = sTestInstances.get(context);
Log.w(TAG, "The context owner try to use a test instance:" + testInstance);
return testInstance;
}
if (sInstance != null) return sInstance;
sInstance = new WifiStateWorker();
sWorkerThread = new HandlerThread(
TAG + ":{" + context.getApplicationInfo().className + "}",
Process.THREAD_PRIORITY_DISPLAY);
sWorkerThread.start();
sWorkerThread.getThreadHandler().post(() -> init(context));
return sInstance;
}
}
/**
* A convenience method to set pre-prepared instance or mock(WifiStateWorker.class) for testing.
*
* @param context The Context this is associated with.
* @param instance of {@link WifiStateWorker} object.
* @hide
*/
@TestApi
@VisibleForTesting
public static void setTestInstance(@NonNull Context context, WifiStateWorker instance) {
synchronized (sLock) {
if (sTestInstances == null) sTestInstances = new ConcurrentHashMap<>();
Log.w(TAG, "Try to set a test instance by context:" + context);
sTestInstances.put(context, instance);
}
}
@WorkerThread
private static void init(@NonNull Context context) {
final Context appContext = context.getApplicationContext();
final IntentReceiver receiver = new IntentReceiver();
appContext.registerReceiver(receiver, new IntentFilter(WIFI_STATE_CHANGED_ACTION), null,
sWorkerThread.getThreadHandler());
sWifiManager = appContext.getSystemService(WifiManager.class);
refresh();
}
/**
* Refresh Wi-Fi state with WifiManager#getWifiState()
*/
@AnyThread
public static void refresh() {
if (sWifiManager == null) return;
Log.d(TAG, "Start calling WifiManager#getWifiState.");
sWifiState = sWifiManager.getWifiState();
Log.d(TAG, "WifiManager#getWifiState return state:" + sWifiState);
}
/**
* Gets the Wi-Fi enabled state.
*
* @return One of {@link WifiManager#WIFI_STATE_DISABLED},
* {@link WifiManager#WIFI_STATE_DISABLING}, {@link WifiManager#WIFI_STATE_ENABLED},
* {@link WifiManager#WIFI_STATE_ENABLING}, {@link WifiManager#WIFI_STATE_UNKNOWN}
* @see #isWifiEnabled()
*/
@AnyThread
public int getWifiState() {
return sWifiState;
}
/**
* Return whether Wi-Fi is enabled or disabled.
*
* @return {@code true} if Wi-Fi is enabled
* @see #getWifiState()
*/
@AnyThread
public boolean isWifiEnabled() {
return sWifiState == WIFI_STATE_ENABLED;
}
@WorkerThread
private static class IntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
sWifiState = intent.getIntExtra(EXTRA_WIFI_STATE, WIFI_STATE_DISABLED);
}
}
}
}