diff options
Diffstat (limited to 'com/android/server/wifi/WifiServiceImpl.java')
-rw-r--r-- | com/android/server/wifi/WifiServiceImpl.java | 403 |
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); } } } |