From 75f129e17b05e6d51080cf1ab9eb5cdddecdc734 Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Thu, 17 Mar 2016 09:40:28 -0700 Subject: [PATCH] WifiManager: Defer Async Channel init Now that WifiManager instances are separate and do not depend on a single static AsyncChannel for the entire process, all contexts within a process will create an async channel on init. Since creating this channel requires special permissions that some applications do not have, it is problematic for them all to request it in the process of getting a WifiManager instance. This CL defers AsyncChannel initialization until it is actually going to be used. This allows callers to create WifiManager instances without necessarily creating an AsyncChannel. Depending on what parts of the API will be used, some callers will never need one. Also, this means that these apps will not run afoul of permissions exceptions that do not apply to them unless they actually request functionality that requires the AsyncChannel. While here, this CL no longer catches SecurityException while requesting a messenger from WifiService. That hack appeared to be an artifact of the static instance of sAsyncChannel -- it was not clear to WifiManager which context had permissions to successfully create the messenger, so it was necessary to silently fail the attempt especially since that attempt was made in the constructor. With the restructuring to keep mAsyncChannel per-instance and now only created at the time specific API calls require it, a SecurityException is completely relevant to the caller and should not be discarded. Bug: 27694933 Test: Boot full image, repro b/27694933 with com.google.android.music Change-Id: I680bf2443bc5b057e629544a687f985261201ded --- wifi/java/android/net/wifi/WifiManager.java | 71 +++++++++------------ 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 823fd26c79046..c040b06778df9 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -689,7 +689,6 @@ public class WifiManager { mContext = context; mService = service; mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; - init(); } /** @@ -1478,8 +1477,7 @@ public class WifiManager { * @hide for CTS test only */ public void getTxPacketCount(TxPacketCountListener listener) { - validateChannel(); - mAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); + getChannel().sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); } /** @@ -1972,30 +1970,28 @@ public class WifiManager { } } - private void init() { - Messenger messenger = getWifiServiceMessenger(); - if (messenger == null) { - mAsyncChannel = null; - return; + private synchronized AsyncChannel getChannel() { + if (mAsyncChannel == null) { + Messenger messenger = getWifiServiceMessenger(); + if (messenger == null) { + throw new IllegalStateException( + "getWifiServiceMessenger() returned null! This is invalid."); + } + + mHandlerThread = new HandlerThread("WifiManager"); + mAsyncChannel = new AsyncChannel(); + mConnected = new CountDownLatch(1); + + mHandlerThread.start(); + Handler handler = new ServiceHandler(mHandlerThread.getLooper()); + mAsyncChannel.connect(mContext, handler, messenger); + try { + mConnected.await(); + } catch (InterruptedException e) { + Log.e(TAG, "interrupted wait at init"); + } } - - mHandlerThread = new HandlerThread("WifiManager"); - mAsyncChannel = new AsyncChannel(); - mConnected = new CountDownLatch(1); - - mHandlerThread.start(); - Handler handler = new ServiceHandler(mHandlerThread.getLooper()); - mAsyncChannel.connect(mContext, handler, messenger); - try { - mConnected.await(); - } catch (InterruptedException e) { - Log.e(TAG, "interrupted wait at init"); - } - } - - private void validateChannel() { - if (mAsyncChannel == null) throw new IllegalStateException( - "No permission to access and change wifi or a bad initialization"); + return mAsyncChannel; } /** @@ -2016,10 +2012,9 @@ public class WifiManager { */ public void connect(WifiConfiguration config, ActionListener listener) { if (config == null) throw new IllegalArgumentException("config cannot be null"); - validateChannel(); // Use INVALID_NETWORK_ID for arg1 when passing a config object // arg1 is used to pass network id when the network already exists - mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, + getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, putListener(listener), config); } @@ -2038,8 +2033,7 @@ public class WifiManager { */ public void connect(int networkId, ActionListener listener) { if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); - validateChannel(); - mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); + getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); } /** @@ -2062,8 +2056,7 @@ public class WifiManager { */ public void save(WifiConfiguration config, ActionListener listener) { if (config == null) throw new IllegalArgumentException("config cannot be null"); - validateChannel(); - mAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config); + getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config); } /** @@ -2081,8 +2074,7 @@ public class WifiManager { */ public void forget(int netId, ActionListener listener) { if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); - validateChannel(); - mAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener)); + getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener)); } /** @@ -2096,8 +2088,7 @@ public class WifiManager { */ public void disable(int netId, ActionListener listener) { if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); - validateChannel(); - mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener)); + getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener)); } /** @@ -2125,8 +2116,7 @@ public class WifiManager { */ public void startWps(WpsInfo config, WpsCallback listener) { if (config == null) throw new IllegalArgumentException("config cannot be null"); - validateChannel(); - mAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config); + getChannel().sendMessage(START_WPS, 0, putListener(listener), config); } /** @@ -2137,8 +2127,7 @@ public class WifiManager { * initialized again */ public void cancelWps(WpsCallback listener) { - validateChannel(); - mAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener)); + getChannel().sendMessage(CANCEL_WPS, 0, putListener(listener)); } /** @@ -2153,8 +2142,6 @@ public class WifiManager { return mService.getWifiServiceMessenger(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (SecurityException e) { - return null; } }