1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.wifi; 18 19 import android.content.Context; 20 import android.net.wifi.WifiManager; 21 import android.os.Handler; 22 import android.os.HandlerThread; 23 import android.os.Looper; 24 import android.os.PersistableBundle; 25 import android.os.Process; 26 import android.os.SimpleClock; 27 import android.os.SystemClock; 28 import android.telephony.CarrierConfigManager; 29 import android.util.Log; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 import androidx.lifecycle.Lifecycle; 34 import androidx.lifecycle.LifecycleObserver; 35 import androidx.lifecycle.OnLifecycleEvent; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.settings.network.CarrierConfigCache; 39 import com.android.settings.overlay.FeatureFactory; 40 import com.android.wifitrackerlib.MergedCarrierEntry; 41 import com.android.wifitrackerlib.WifiEntry; 42 import com.android.wifitrackerlib.WifiPickerTracker; 43 44 import java.time.Clock; 45 import java.time.ZoneOffset; 46 47 public class WifiPickerTrackerHelper implements LifecycleObserver { 48 49 private static final String TAG = "WifiPickerTrackerHelper"; 50 51 // Max age of tracked WifiEntries 52 private static final long MAX_SCAN_AGE_MILLIS = 15_000; 53 // Interval between initiating WifiPickerTracker scans 54 private static final long SCAN_INTERVAL_MILLIS = 10_000; 55 // Clock used for evaluating the age of scans 56 private static final Clock ELAPSED_REALTIME_CLOCK = new SimpleClock(ZoneOffset.UTC) { 57 @Override 58 public long millis() { 59 return SystemClock.elapsedRealtime(); 60 } 61 }; 62 63 protected WifiPickerTracker mWifiPickerTracker; 64 // Worker thread used for WifiPickerTracker work 65 protected HandlerThread mWorkerThread; 66 67 protected final WifiManager mWifiManager; 68 protected final CarrierConfigCache mCarrierConfigCache; 69 WifiPickerTrackerHelper(@onNull Lifecycle lifecycle, @NonNull Context context, @Nullable WifiPickerTracker.WifiPickerTrackerCallback listener)70 public WifiPickerTrackerHelper(@NonNull Lifecycle lifecycle, @NonNull Context context, 71 @Nullable WifiPickerTracker.WifiPickerTrackerCallback listener) { 72 if (lifecycle == null) { 73 throw new IllegalArgumentException("lifecycle must be non-null."); 74 } 75 lifecycle.addObserver(this); 76 mWorkerThread = new HandlerThread(TAG 77 + "{" + Integer.toHexString(System.identityHashCode(this)) + "}", 78 Process.THREAD_PRIORITY_BACKGROUND); 79 mWorkerThread.start(); 80 81 mWifiPickerTracker = FeatureFactory.getFeatureFactory() 82 .getWifiTrackerLibProvider() 83 .createWifiPickerTracker(lifecycle, context, 84 new Handler(Looper.getMainLooper()), 85 mWorkerThread.getThreadHandler(), 86 ELAPSED_REALTIME_CLOCK, 87 MAX_SCAN_AGE_MILLIS, 88 SCAN_INTERVAL_MILLIS, 89 listener); 90 91 mWifiManager = context.getSystemService(WifiManager.class); 92 mCarrierConfigCache = CarrierConfigCache.getInstance(context); 93 } 94 95 /** @OnLifecycleEvent(ON_DESTROY) */ 96 @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) onDestroy()97 public void onDestroy() { 98 mWorkerThread.quit(); 99 } 100 101 /** Return the WifiPickerTracker class */ getWifiPickerTracker()102 public @NonNull WifiPickerTracker getWifiPickerTracker() { 103 return mWifiPickerTracker; 104 } 105 106 /** Return the enabled/disabled state of the carrier network provision */ isCarrierNetworkProvisionEnabled(int subId)107 public boolean isCarrierNetworkProvisionEnabled(int subId) { 108 final PersistableBundle config = mCarrierConfigCache.getConfigForSubId(subId); 109 if (config == null) { 110 Log.e(TAG, "Could not get carrier config, subId:" + subId); 111 return false; 112 } 113 final boolean enabled = config.getBoolean( 114 CarrierConfigManager.KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL); 115 Log.i(TAG, "isCarrierNetworkProvisionEnabled:" + enabled); 116 return enabled; 117 } 118 119 /** Return the enabled/disabled state of the carrier network */ isCarrierNetworkEnabled()120 public boolean isCarrierNetworkEnabled() { 121 final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); 122 if (mergedCarrierEntry == null) { 123 Log.e(TAG, "Failed to get MergedCarrierEntry to query enabled status"); 124 return false; 125 } 126 final boolean isCarrierNetworkEnabled = mergedCarrierEntry.isEnabled(); 127 Log.i(TAG, "isCarrierNetworkEnabled:" + isCarrierNetworkEnabled); 128 return isCarrierNetworkEnabled; 129 } 130 131 /** Enables/disables the carrier network */ setCarrierNetworkEnabled(boolean enabled)132 public void setCarrierNetworkEnabled(boolean enabled) { 133 final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); 134 if (mergedCarrierEntry == null) { 135 Log.e(TAG, "Unable to get MergedCarrierEntry to set enabled status"); 136 return; 137 } 138 Log.i(TAG, "setCarrierNetworkEnabled:" + enabled); 139 mergedCarrierEntry.setEnabled(enabled); 140 } 141 142 /** Connect to the carrier network */ connectCarrierNetwork(@ullable WifiEntry.ConnectCallback callback)143 public boolean connectCarrierNetwork(@Nullable WifiEntry.ConnectCallback callback) { 144 final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); 145 if (mergedCarrierEntry == null || !mergedCarrierEntry.canConnect()) { 146 return false; 147 } 148 mergedCarrierEntry.connect(callback); 149 return true; 150 } 151 152 /** Confirms connection of the carrier network connected with the internet access */ isCarrierNetworkActive()153 public boolean isCarrierNetworkActive() { 154 final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); 155 return (mergedCarrierEntry != null && mergedCarrierEntry.isDefaultNetwork()); 156 } 157 158 /** Return the carrier network ssid */ getCarrierNetworkSsid()159 public String getCarrierNetworkSsid() { 160 final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); 161 if (mergedCarrierEntry == null) { 162 return null; 163 } 164 return mergedCarrierEntry.getSsid(); 165 } 166 167 /** Return the carrier network level */ getCarrierNetworkLevel()168 public int getCarrierNetworkLevel() { 169 final MergedCarrierEntry mergedCarrierEntry = mWifiPickerTracker.getMergedCarrierEntry(); 170 if (mergedCarrierEntry == null) return WifiEntry.WIFI_LEVEL_MIN; 171 172 int level = mergedCarrierEntry.getLevel(); 173 // To avoid icons not found with WIFI_LEVEL_UNREACHABLE(-1), use WIFI_LEVEL_MIN(0) instead. 174 if (level < WifiEntry.WIFI_LEVEL_MIN) level = WifiEntry.WIFI_LEVEL_MIN; 175 return level; 176 } 177 178 @VisibleForTesting setWifiPickerTracker(@onNull WifiPickerTracker wifiPickerTracker)179 void setWifiPickerTracker(@NonNull WifiPickerTracker wifiPickerTracker) { 180 mWifiPickerTracker = wifiPickerTracker; 181 } 182 183 @VisibleForTesting setWorkerThread(@onNull HandlerThread workerThread)184 void setWorkerThread(@NonNull HandlerThread workerThread) { 185 mWorkerThread = workerThread; 186 } 187 } 188