summaryrefslogtreecommitdiff
path: root/com/android/server/wifi/WifiServiceImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'com/android/server/wifi/WifiServiceImpl.java')
-rw-r--r--com/android/server/wifi/WifiServiceImpl.java403
1 files changed, 288 insertions, 115 deletions
diff --git a/com/android/server/wifi/WifiServiceImpl.java b/com/android/server/wifi/WifiServiceImpl.java
index ce49e559..d4bd12e5 100644
--- a/com/android/server/wifi/WifiServiceImpl.java
+++ b/com/android/server/wifi/WifiServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.server.wifi;
+import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
@@ -30,18 +31,15 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
-import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED;
import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
-import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED;
import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
-import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
-import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
import static com.android.server.wifi.WifiController.CMD_SET_AP;
import static com.android.server.wifi.WifiController.CMD_USER_PRESENT;
import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
import android.Manifest;
+import android.annotation.CheckResult;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AppOpsManager;
@@ -62,16 +60,15 @@ import android.net.NetworkUtils;
import android.net.StaticIpConfiguration;
import android.net.Uri;
import android.net.ip.IpClient;
+import android.net.wifi.ISoftApCallback;
import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
import android.net.wifi.ScanSettings;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConnectionStatistics;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
-import android.net.wifi.WifiScanner;
import android.net.wifi.hotspot2.IProvisioningCallback;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -102,6 +99,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.PowerProfile;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
@@ -128,6 +126,7 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -150,6 +149,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
final WifiStateMachine mWifiStateMachine;
+ final ScanRequestProxy mScanRequestProxy;
private final Context mContext;
private final FrameworkFacade mFacade;
@@ -179,7 +179,6 @@ public class WifiServiceImpl extends IWifiManager.Stub {
// Map of package name of background scan apps and last scan timestamp.
private final ArrayMap<String, Long> mLastScanTimestamps;
- private WifiScanner mWifiScanner;
private WifiLog mLog;
/**
@@ -199,6 +198,11 @@ public class WifiServiceImpl extends IWifiManager.Stub {
@GuardedBy("mLocalOnlyHotspotRequests")
private final ConcurrentHashMap<String, Integer> mIfaceIpModes;
+ /* Limit on number of registered soft AP callbacks to track and prevent potential memory leak */
+ private static final int NUM_SOFT_AP_CALLBACKS_WARN_LIMIT = 10;
+ private static final int NUM_SOFT_AP_CALLBACKS_WTF_LIMIT = 20;
+ private final HashMap<Integer, ISoftApCallback> mRegisteredSoftApCallbacks;
+
/**
* One of: {@link WifiManager#WIFI_AP_STATE_DISABLED},
* {@link WifiManager#WIFI_AP_STATE_DISABLING},
@@ -208,8 +212,17 @@ public class WifiServiceImpl extends IWifiManager.Stub {
*
* Access/maintenance MUST be done on the wifi service thread
*/
+ // TODO: (b/71714381) Remove mWifiApState and broadcast mechanism, keep mSoftApState as the only
+ // field to store soft AP state. Then rename mSoftApState and mSoftApNumClients to
+ // mWifiApState and mWifiApNumClients, to match the constants (i.e. WIFI_AP_STATE_*)
private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
+ private int mSoftApState = WifiManager.WIFI_AP_STATE_DISABLED;
+ private int mSoftApNumClients = 0;
+ /**
+ * Power profile
+ */
+ PowerProfile mPowerProfile;
/**
* Callback for use with LocalOnlyHotspot to unregister requesting applications upon death.
@@ -440,6 +453,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
mCountryCode = mWifiInjector.getWifiCountryCode();
mWifiStateMachine = mWifiInjector.getWifiStateMachine();
mWifiStateMachine.enableRssiPolling(true);
+ mScanRequestProxy = mWifiInjector.getScanRequestProxy();
mSettingsStore = mWifiInjector.getWifiSettingsStore();
mPowerManager = mContext.getSystemService(PowerManager.class);
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -464,6 +478,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
mIfaceIpModes = new ConcurrentHashMap<>();
mLocalOnlyHotspotRequests = new HashMap<>();
enableVerboseLoggingInternal(getVerboseLoggingLevel());
+ mRegisteredSoftApCallbacks = new HashMap<>();
+
+ mWifiInjector.getWifiStateMachinePrime().registerSoftApCallback(new SoftApCallbackImpl());
+ mPowerProfile = mWifiInjector.getPowerProfile();
}
/**
@@ -591,12 +609,16 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @param settings If null, use default parameter, i.e. full scan.
* @param workSource If null, all blame is given to the calling uid.
* @param packageName Package name of the app that requests wifi scan.
+ * TODO(b/68388459): Remove |settings| & |worksource|
*/
@Override
public void startScan(ScanSettings settings, WorkSource workSource, String packageName) {
- enforceChangePermission();
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
- mLog.info("startScan uid=%").c(Binder.getCallingUid()).flush();
+ int callingUid = Binder.getCallingUid();
+ mLog.info("startScan uid=%").c(callingUid).flush();
// Check and throttle background apps for wifi scan.
if (isRequestFromBackground(packageName)) {
long lastScanMs = mLastScanTimestamps.getOrDefault(packageName, 0L);
@@ -610,9 +632,6 @@ public class WifiServiceImpl extends IWifiManager.Stub {
mLastScanTimestamps.put(packageName, elapsedRealtime);
}
synchronized (this) {
- if (mWifiScanner == null) {
- mWifiScanner = mWifiInjector.getWifiScanner();
- }
if (mInIdleMode) {
// Need to send an immediate scan result broadcast in case the
// caller is waiting for a result ..
@@ -626,24 +645,15 @@ public class WifiServiceImpl extends IWifiManager.Stub {
return;
}
}
- if (settings != null) {
- settings = new ScanSettings(settings);
- if (!settings.isValid()) {
- Slog.e(TAG, "invalid scan setting");
- return;
+ boolean success = mWifiInjector.getWifiStateMachineHandler().runWithScissors(() -> {
+ if (!mScanRequestProxy.startScan(callingUid)) {
+ Log.e(TAG, "Failed to start scan");
}
+ }, 0);
+ if (!success) {
+ Log.e(TAG, "Failed to post runnable to start scan");
+ sendFailedScanBroadcast();
}
- if (workSource != null) {
- enforceWorkSourcePermission();
- // WifiManager currently doesn't use names, so need to clear names out of the
- // supplied WorkSource to allow future WorkSource combining.
- workSource.clearNames();
- }
- if (workSource == null && Binder.getCallingUid() >= 0) {
- workSource = new WorkSource(Binder.getCallingUid());
- }
- mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++,
- settings, workSource);
}
// Send a failed scan broadcast to indicate the current scan request failed.
@@ -713,8 +723,9 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
if (doScan) {
// Someone requested a scan while we were idle; do a full scan now.
- // The package name doesn't matter as the request comes from System UID.
- startScan(null, null, "");
+ // A security check of the caller's identity was made when the request arrived via
+ // Binder.
+ startScan(null, null, mContext.getOpPackageName());
}
}
@@ -738,9 +749,21 @@ public class WifiServiceImpl extends IWifiManager.Stub {
"WifiService");
}
- private void enforceChangePermission() {
+ /**
+ * Checks whether the caller can change the wifi state.
+ * Possible results:
+ * 1. Operation is allowed. No exception thrown, and AppOpsManager.MODE_ALLOWED returned.
+ * 2. Operation is not allowed, and caller must be told about this. SecurityException is thrown.
+ * 3. Operation is not allowed, and caller must not be told about this (i.e. must silently
+ * ignore the operation). No exception is thrown, and AppOpsManager.MODE_IGNORED returned.
+ */
+ @CheckResult
+ private int enforceChangePermission(String callingPackage) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
"WifiService");
+
+ return mAppOps.noteOp(
+ AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Binder.getCallingUid(), callingPackage);
}
private void enforceLocationHardwarePermission() {
@@ -784,7 +807,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
@Override
public synchronized boolean setWifiEnabled(String packageName, boolean enable)
throws RemoteException {
- enforceChangePermission();
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
+
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid() + ", package=" + packageName);
mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
@@ -1038,6 +1064,141 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
/**
+ * Callback to use with WifiStateMachine to receive events from WifiStateMachine
+ *
+ * @hide
+ */
+ private final class SoftApCallbackImpl implements WifiManager.SoftApCallback {
+ /**
+ * Called when soft AP state changes.
+ *
+ * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED},
+ * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
+ * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
+ * @param failureReason reason when in failed state. One of
+ * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL}
+ */
+ @Override
+ public void onStateChanged(int state, int failureReason) {
+ mSoftApState = state;
+ mSoftApNumClients = 0;
+
+ Iterator<ISoftApCallback> iterator = mRegisteredSoftApCallbacks.values().iterator();
+ while (iterator.hasNext()) {
+ ISoftApCallback callback = iterator.next();
+ try {
+ callback.onStateChanged(state, failureReason);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onStateChanged: remote exception -- " + e);
+ iterator.remove();
+ }
+ }
+ }
+
+ /**
+ * Called when number of connected clients to soft AP changes.
+ *
+ * @param numClients number of connected clients to soft AP
+ */
+ @Override
+ public void onNumClientsChanged(int numClients) {
+ mSoftApNumClients = numClients;
+
+ Iterator<ISoftApCallback> iterator = mRegisteredSoftApCallbacks.values().iterator();
+ while (iterator.hasNext()) {
+ ISoftApCallback callback = iterator.next();
+ try {
+ callback.onNumClientsChanged(numClients);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onNumClientsChanged: remote exception -- " + e);
+ iterator.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * see {@link android.net.wifi.WifiManager#registerSoftApCallback(SoftApCallback, Handler)}
+ *
+ * @param binder IBinder instance to allow cleanup if the app dies
+ * @param callback Soft AP callback to register
+ * @param callbackIdentifier Unique ID of the registering callback. This ID will be used to
+ * unregister the callback. See {@link unregisterSoftApCallback(int)}
+ *
+ * @throws SecurityException if the caller does not have permission to register a callback
+ * @throws RemoteException if remote exception happens
+ * @throws IllegalArgumentException if the arguments are null or invalid
+ */
+ @Override
+ public void registerSoftApCallback(IBinder binder, ISoftApCallback callback,
+ int callbackIdentifier) {
+ // verify arguments
+ if (binder == null) {
+ throw new IllegalArgumentException("Binder must not be null");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("Callback must not be null");
+ }
+
+ enforceNetworkSettingsPermission();
+
+ // register for binder death
+ IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ binder.unlinkToDeath(this, 0);
+ mClientHandler.post(() -> {
+ mRegisteredSoftApCallbacks.remove(callbackIdentifier);
+ });
+ }
+ };
+ try {
+ binder.linkToDeath(dr, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error on linkToDeath - " + e);
+ return;
+ }
+
+ // post operation to handler thread
+ mClientHandler.post(() -> {
+ mRegisteredSoftApCallbacks.put(callbackIdentifier, callback);
+
+ if (mRegisteredSoftApCallbacks.size() > NUM_SOFT_AP_CALLBACKS_WTF_LIMIT) {
+ Log.wtf(TAG, "Too many soft AP callbacks: " + mRegisteredSoftApCallbacks.size());
+ } else if (mRegisteredSoftApCallbacks.size() > NUM_SOFT_AP_CALLBACKS_WARN_LIMIT) {
+ Log.w(TAG, "Too many soft AP callbacks: " + mRegisteredSoftApCallbacks.size());
+ }
+
+ // Update the client about the current state immediately after registering the callback
+ try {
+ callback.onStateChanged(mSoftApState, 0);
+ callback.onNumClientsChanged(mSoftApNumClients);
+ } catch (RemoteException e) {
+ Log.e(TAG, "registerSoftApCallback: remote exception -- " + e);
+ }
+
+ });
+ }
+
+ /**
+ * see {@link android.net.wifi.WifiManager#unregisterSoftApCallback(SoftApCallback)}
+ *
+ * @param callbackIdentifier Unique ID of the callback to be unregistered.
+ *
+ * @throws SecurityException if the caller does not have permission to register a callback
+ */
+ @Override
+ public void unregisterSoftApCallback(int callbackIdentifier) {
+
+ enforceNetworkSettingsPermission();
+
+ // post operation to handler thread
+ mClientHandler.post(() -> {
+ mRegisteredSoftApCallbacks.remove(callbackIdentifier);
+ });
+ }
+
+ /**
* Private method to handle SoftAp state changes
*
* <p> MUST be called from the WifiStateMachine thread.
@@ -1188,7 +1349,9 @@ public class WifiServiceImpl extends IWifiManager.Stub {
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
- enforceChangePermission();
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return LocalOnlyHotspotCallback.ERROR_GENERIC;
+ }
enforceLocationPermission(packageName, uid);
// also need to verify that Locations services are enabled.
if (mSettingsStore.getLocationModeSetting(mContext) == Settings.Secure.LOCATION_MODE_OFF) {
@@ -1261,8 +1424,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
*/
@Override
public void stopLocalOnlyHotspot() {
- // first check if the caller has permission to stop a local only hotspot
- enforceChangePermission();
+ // don't do a permission check here. if the app has their permission to change the wifi
+ // state revoked, we still want them to be able to stop a previously created hotspot
+ // (otherwise it could cost the user money). When the app created the hotspot, its
+ // permission was checked.
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
@@ -1320,8 +1485,6 @@ public class WifiServiceImpl extends IWifiManager.Stub {
*/
@Override
public void startWatchLocalOnlyHotspot(Messenger messenger, IBinder binder) {
- final String packageName = mContext.getOpPackageName();
-
// NETWORK_SETTINGS is a signature only permission.
enforceNetworkSettingsPermission();
@@ -1364,8 +1527,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @throws SecurityException if the caller does not have permission to write the sotap config
*/
@Override
- public void setWifiApConfiguration(WifiConfiguration wifiConfig) {
- enforceChangePermission();
+ public void setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
int uid = Binder.getCallingUid();
// only allow Settings UI to write the stored SoftApConfig
if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) {
@@ -1397,8 +1562,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* see {@link android.net.wifi.WifiManager#disconnect()}
*/
@Override
- public void disconnect() {
- enforceChangePermission();
+ public void disconnect(String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
mLog.info("disconnect uid=%").c(Binder.getCallingUid()).flush();
mWifiStateMachine.disconnectCommand();
}
@@ -1407,8 +1574,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* see {@link android.net.wifi.WifiManager#reconnect()}
*/
@Override
- public void reconnect() {
- enforceChangePermission();
+ public void reconnect(String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
mLog.info("reconnect uid=%").c(Binder.getCallingUid()).flush();
mWifiStateMachine.reconnectCommand(new WorkSource(Binder.getCallingUid()));
}
@@ -1417,8 +1586,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* see {@link android.net.wifi.WifiManager#reassociate()}
*/
@Override
- public void reassociate() {
- enforceChangePermission();
+ public void reassociate(String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
mLog.info("reassociate uid=%").c(Binder.getCallingUid()).flush();
mWifiStateMachine.reassociateCommand();
}
@@ -1461,16 +1632,14 @@ public class WifiServiceImpl extends IWifiManager.Stub {
if (mWifiStateMachineChannel != null) {
stats = mWifiStateMachine.syncGetLinkLayerStats(mWifiStateMachineChannel);
if (stats != null) {
- final long rxIdleCurrent = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_idle_receive_cur_ma);
- final long rxCurrent = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_active_rx_cur_ma);
- final long txCurrent = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_tx_cur_ma);
- final double voltage = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_wifi_operating_voltage_mv)
- / 1000.0;
-
+ final double rxIdleCurrent = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
+ final double rxCurrent = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_RX);
+ final double txCurrent = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_TX);
+ final double voltage = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
final long rxIdleTime = stats.on_time - stats.tx_time - stats.rx_time;
final long[] txTimePerLevel;
if (stats.tx_time_per_level != null) {
@@ -1487,7 +1656,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
stats.rx_time * rxCurrent +
rxIdleTime * rxIdleCurrent) * voltage);
if (VDBG || rxIdleTime < 0 || stats.on_time < 0 || stats.tx_time < 0 ||
- stats.rx_time < 0 || energyUsed < 0) {
+ stats.rx_time < 0 || stats.on_time_scan < 0 || energyUsed < 0) {
StringBuilder sb = new StringBuilder();
sb.append(" rxIdleCur=" + rxIdleCurrent);
sb.append(" rxCur=" + rxCurrent);
@@ -1498,6 +1667,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
sb.append(" tx_time_per_level=" + Arrays.toString(txTimePerLevel));
sb.append(" rx_time=" + stats.rx_time);
sb.append(" rxIdleTime=" + rxIdleTime);
+ sb.append(" scan_time=" + stats.on_time_scan);
sb.append(" energy=" + energyUsed);
Log.d(TAG, " reportActivityInfo: " + sb.toString());
}
@@ -1505,7 +1675,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
// Convert the LinkLayerStats into EnergyActivity
energyInfo = new WifiActivityEnergyInfo(mClock.getElapsedSinceBootMillis(),
WifiActivityEnergyInfo.STACK_STATE_STATE_IDLE, stats.tx_time,
- txTimePerLevel, stats.rx_time, rxIdleTime, energyUsed);
+ txTimePerLevel, stats.rx_time, stats.on_time_scan, rxIdleTime, energyUsed);
}
if (energyInfo != null && energyInfo.isValid()) {
return energyInfo;
@@ -1619,8 +1789,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* network if the operation succeeds, or {@code -1} if it fails
*/
@Override
- public int addOrUpdateNetwork(WifiConfiguration config) {
- enforceChangePermission();
+ public int addOrUpdateNetwork(WifiConfiguration config, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return -1;
+ }
mLog.info("addOrUpdateNetwork uid=%").c(Binder.getCallingUid()).flush();
// Previously, this API is overloaded for installing Passpoint profiles. Now
@@ -1639,7 +1811,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
config.enterpriseConfig.getClientCertificateChain());
passpointConfig.getCredential().setClientPrivateKey(
config.enterpriseConfig.getClientPrivateKey());
- if (!addOrUpdatePasspointConfiguration(passpointConfig)) {
+ if (!addOrUpdatePasspointConfiguration(passpointConfig, packageName)) {
Slog.e(TAG, "Failed to add Passpoint profile");
return -1;
}
@@ -1690,8 +1862,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @return {@code true} if the operation succeeded
*/
@Override
- public boolean removeNetwork(int netId) {
- enforceChangePermission();
+ public boolean removeNetwork(int netId, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
mLog.info("removeNetwork uid=%").c(Binder.getCallingUid()).flush();
// TODO Add private logging for netId b/33807876
if (mWifiStateMachineChannel != null) {
@@ -1710,8 +1884,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @return {@code true} if the operation succeeded
*/
@Override
- public boolean enableNetwork(int netId, boolean disableOthers) {
- enforceChangePermission();
+ public boolean enableNetwork(int netId, boolean disableOthers, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
// TODO b/33807876 Log netId
mLog.info("enableNetwork uid=% disableOthers=%")
.c(Binder.getCallingUid())
@@ -1733,8 +1909,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @return {@code true} if the operation succeeded
*/
@Override
- public boolean disableNetwork(int netId) {
- enforceChangePermission();
+ public boolean disableNetwork(int netId, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
// TODO b/33807876 Log netId
mLog.info("disableNetwork uid=%").c(Binder.getCallingUid()).flush();
@@ -1779,14 +1957,19 @@ public class WifiServiceImpl extends IWifiManager.Stub {
int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
+ // TODO: Remove the bypass for apps targeting older SDK's (< M).
if (!mWifiPermissionsUtil.canAccessScanResults(callingPackage,
uid, Build.VERSION_CODES.M)) {
return new ArrayList<ScanResult>();
}
- if (mWifiScanner == null) {
- mWifiScanner = mWifiInjector.getWifiScanner();
+ final List<ScanResult> scanResults = new ArrayList<>();
+ boolean success = mWifiInjector.getWifiStateMachineHandler().runWithScissors(() -> {
+ scanResults.addAll(mScanRequestProxy.getScanResults());
+ }, 0);
+ if (!success) {
+ Log.e(TAG, "Failed to post runnable to fetch scan results");
}
- return mWifiScanner.getSingleScanResults();
+ return scanResults;
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1799,8 +1982,11 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @return true on success or false on failure
*/
@Override
- public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
- enforceChangePermission();
+ public boolean addOrUpdatePasspointConfiguration(
+ PasspointConfiguration config, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
mLog.info("addorUpdatePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush();
if (!mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_PASSPOINT)) {
@@ -1817,8 +2003,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* @return true on success or false on failure
*/
@Override
- public boolean removePasspointConfiguration(String fqdn) {
- enforceChangePermission();
+ public boolean removePasspointConfiguration(String fqdn, String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
mLog.info("removePasspointConfiguration uid=%").c(Binder.getCallingUid()).flush();
if (!mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_PASSPOINT)) {
@@ -1890,8 +2078,10 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* TODO: deprecate this
*/
@Override
- public boolean saveConfiguration() {
- enforceChangePermission();
+ public boolean saveConfiguration(String packageName) {
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return false;
+ }
mLog.info("saveConfiguration uid=%").c(Binder.getCallingUid()).flush();
if (mWifiStateMachineChannel != null) {
return mWifiStateMachine.syncSaveConfig(mWifiStateMachineChannel);
@@ -2087,9 +2277,13 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* an AsyncChannel communication with WifiService
*/
@Override
- public Messenger getWifiServiceMessenger() {
+ public Messenger getWifiServiceMessenger(String packageName) throws RemoteException {
enforceAccessPermission();
- enforceChangePermission();
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ // We don't have a good way of creating a fake Messenger, and returning null would
+ // immediately break callers.
+ throw new SecurityException("Could not create wifi service messenger");
+ }
mLog.info("getWifiServiceMessenger uid=%").c(Binder.getCallingUid()).flush();
return new Messenger(mClientHandler);
}
@@ -2098,9 +2292,11 @@ public class WifiServiceImpl extends IWifiManager.Stub {
* Disable an ephemeral network, i.e. network that is created thru a WiFi Scorer
*/
@Override
- public void disableEphemeralNetwork(String SSID) {
+ public void disableEphemeralNetwork(String SSID, String packageName) {
enforceAccessPermission();
- enforceChangePermission();
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
mLog.info("disableEphemeralNetwork uid=%").c(Binder.getCallingUid()).flush();
mWifiStateMachine.disableEphemeralNetwork(SSID);
}
@@ -2109,15 +2305,8 @@ public class WifiServiceImpl extends IWifiManager.Stub {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(Intent.ACTION_SCREEN_ON)) {
- mWifiController.sendMessage(CMD_SCREEN_ON);
- } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+ if (action.equals(Intent.ACTION_USER_PRESENT)) {
mWifiController.sendMessage(CMD_USER_PRESENT);
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- mWifiController.sendMessage(CMD_SCREEN_OFF);
- } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
} else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
@@ -2226,10 +2415,7 @@ public class WifiServiceImpl extends IWifiManager.Stub {
private void registerForBroadcasts() {
IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
@@ -2335,13 +2521,18 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
}
+ /**
+ * NOTE: WifiLocks do not serve a useful purpose in their current impl and will be removed
+ * (including the methods below).
+ *
+ * TODO: b/71548157
+ */
@Override
public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) {
mLog.info("acquireWifiLock uid=% lockMode=%")
.c(Binder.getCallingUid())
.c(lockMode).flush();
if (mWifiLockManager.acquireWifiLock(lockMode, tag, binder, ws)) {
- mWifiController.sendMessage(CMD_LOCKS_CHANGED);
return true;
}
return false;
@@ -2357,7 +2548,6 @@ public class WifiServiceImpl extends IWifiManager.Stub {
public boolean releaseWifiLock(IBinder binder) {
mLog.info("releaseWifiLock uid=%").c(Binder.getCallingUid()).flush();
if (mWifiLockManager.releaseWifiLock(binder)) {
- mWifiController.sendMessage(CMD_LOCKS_CHANGED);
return true;
}
return false;
@@ -2435,23 +2625,12 @@ public class WifiServiceImpl extends IWifiManager.Stub {
return mWifiStateMachine.getAggressiveHandover();
}
- /* Return the Wifi Connection statistics object */
@Override
- public WifiConnectionStatistics getConnectionStatistics() {
- enforceAccessPermission();
- enforceReadCredentialPermission();
- mLog.info("getConnectionStatistics uid=%").c(Binder.getCallingUid()).flush();
- if (mWifiStateMachineChannel != null) {
- return mWifiStateMachine.syncGetConnectionStatistics(mWifiStateMachineChannel);
- } else {
- Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
- return null;
- }
- }
-
- @Override
- public void factoryReset() {
+ public void factoryReset(String packageName) {
enforceConnectivityInternalPermission();
+ if (enforceChangePermission(packageName) != MODE_ALLOWED) {
+ return;
+ }
mLog.info("factoryReset uid=%").c(Binder.getCallingUid()).flush();
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
return;
@@ -2464,21 +2643,15 @@ public class WifiServiceImpl extends IWifiManager.Stub {
}
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI)) {
- // Enable wifi
- try {
- setWifiEnabled(mContext.getOpPackageName(), true);
- } catch (RemoteException e) {
- /* ignore - local call */
- }
// Delete all Wifi SSIDs
if (mWifiStateMachineChannel != null) {
List<WifiConfiguration> networks = mWifiStateMachine.syncGetConfiguredNetworks(
Binder.getCallingUid(), mWifiStateMachineChannel);
if (networks != null) {
for (WifiConfiguration config : networks) {
- removeNetwork(config.networkId);
+ removeNetwork(config.networkId, packageName);
}
- saveConfiguration();
+ saveConfiguration(packageName);
}
}
}