diff options
Diffstat (limited to 'services')
6 files changed, 813 insertions, 154 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index cc1566b..ae4e168 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -314,14 +314,14 @@ public class ConnectivityService extends IConnectivityManager.Stub { case ConnectivityManager.TYPE_WIFI: if (DBG) Slog.v(TAG, "Starting Wifi Service."); WifiStateTracker wst = new WifiStateTracker(context, mHandler); - WifiService wifiService = new WifiService(context, wst); + WifiService wifiService = new WifiService(context); ServiceManager.addService(Context.WIFI_SERVICE, wifiService); - wifiService.startWifi(); + wifiService.checkAndStartWifi(); mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst; wst.startMonitoring(); //TODO: as part of WWS refactor, create only when needed - mWifiWatchdogService = new WifiWatchdogService(context, wst); + mWifiWatchdogService = new WifiWatchdogService(context); break; case ConnectivityManager.TYPE_MOBILE: @@ -1205,16 +1205,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { sendConnectedBroadcast(info); } - private void handleScanResultsAvailable(NetworkInfo info) { - int networkType = info.getType(); - if (networkType != ConnectivityManager.TYPE_WIFI) { - if (DBG) Slog.v(TAG, "Got ScanResultsAvailable for " + - info.getTypeName() + " network. Don't know how to handle."); - } - - mNetTrackers[networkType].interpretScanResultsAvailable(); - } - private void handleNotificationChange(boolean visible, int id, Notification notification) { NotificationManager notificationManager = (NotificationManager) mContext @@ -1619,11 +1609,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } break; - case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE: - info = (NetworkInfo) msg.obj; - handleScanResultsAvailable(info); - break; - case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED: handleNotificationChange(msg.arg1 == 1, msg.arg2, (Notification) msg.obj); diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 3fd9907..164142e 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -466,6 +466,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt); + mStatusBar = statusBar; + statusBar.setIconVisibility("ime", false); + buildInputMethodListLocked(mMethodList, mMethodMap); final String enabledStr = Settings.Secure.getString( @@ -509,9 +512,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - mStatusBar = statusBar; - statusBar.setIconVisibility("ime", false); - mSettingsObserver = new SettingsObserver(mHandler); updateFromSettingsLocked(); } @@ -1220,6 +1220,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (mCurClient == null || client == null || mCurClient.client.asBinder() != client.asBinder()) { Slog.w(TAG, "Ignoring showInputMethodDialogFromClient of: " + client); + return; } mHandler.sendEmptyMessage(MSG_SHOW_IM_PICKER); diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index ef5e9cc..d604886 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -16,34 +16,42 @@ package com.android.server; +import com.android.internal.app.IMediaContainerService; import com.android.server.am.ActivityManagerService; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.res.ObbInfo; -import android.content.res.ObbScanner; import android.net.Uri; -import android.os.storage.IMountService; -import android.os.storage.IMountServiceListener; -import android.os.storage.IMountShutdownObserver; -import android.os.storage.StorageResultCode; import android.os.Binder; +import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; -import android.os.IBinder; -import android.os.Environment; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.storage.IMountService; +import android.os.storage.IMountServiceListener; +import android.os.storage.IMountShutdownObserver; +import android.os.storage.IObbActionListener; +import android.os.storage.StorageResultCode; import android.util.Slog; + import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; /** * MountService implements back-end services for platform storage @@ -137,9 +145,77 @@ class MountService extends IMountService.Stub final private HashSet<String> mAsecMountSet = new HashSet<String>(); /** - * Private hash of currently mounted filesystem images. + * Mounted OBB tracking information. Used to track the current state of all + * OBBs. + */ + final private Map<IObbActionListener, ObbState> mObbMounts = new HashMap<IObbActionListener, ObbState>(); + final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>(); + + class ObbState implements IBinder.DeathRecipient { + public ObbState(String filename, IObbActionListener token, int callerUid) { + this.filename = filename; + this.token = token; + this.callerUid = callerUid; + mounted = false; + } + + // OBB source filename + String filename; + + // Token of remote Binder caller + IObbActionListener token; + + // Binder.callingUid() + public int callerUid; + + // Whether this is mounted currently. + boolean mounted; + + @Override + public void binderDied() { + ObbAction action = new UnmountObbAction(this, true); + mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); + + removeObbState(this); + + token.asBinder().unlinkToDeath(this, 0); + } + } + + // OBB Action Handler + final private ObbActionHandler mObbActionHandler; + + // OBB action handler messages + private static final int OBB_RUN_ACTION = 1; + private static final int OBB_MCS_BOUND = 2; + private static final int OBB_MCS_UNBIND = 3; + private static final int OBB_MCS_RECONNECT = 4; + private static final int OBB_MCS_GIVE_UP = 5; + + /* + * Default Container Service information */ - final private HashSet<String> mObbMountSet = new HashSet<String>(); + static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName( + "com.android.defcontainer", "com.android.defcontainer.DefaultContainerService"); + + final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection(); + + class DefaultContainerConnection implements ServiceConnection { + public void onServiceConnected(ComponentName name, IBinder service) { + if (DEBUG_OBB) + Slog.i(TAG, "onServiceConnected"); + IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service); + mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs)); + } + + public void onServiceDisconnected(ComponentName name) { + if (DEBUG_OBB) + Slog.i(TAG, "onServiceDisconnected"); + } + }; + + // Used in the ObbActionHandler + private IMediaContainerService mContainerService = null; // Handler messages private static final int H_UNMOUNT_PM_UPDATE = 1; @@ -363,7 +439,7 @@ class MountService extends IMountService.Stub public void binderDied() { if (LOCAL_LOGD) Slog.d(TAG, "An IMountServiceListener has died!"); - synchronized(mListeners) { + synchronized (mListeners) { mListeners.remove(this); mListener.asBinder().unlinkToDeath(this, 0); } @@ -917,6 +993,9 @@ class MountService extends IMountService.Stub mHandlerThread.start(); mHandler = new MountServiceHandler(mHandlerThread.getLooper()); + // Add OBB Action Handler to MountService thread. + mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper()); + /* * Vold does not run in the simulator, so pretend the connector thread * ran and did its thing. @@ -1013,7 +1092,7 @@ class MountService extends IMountService.Stub private void setUmsEnabling(boolean enable) { synchronized (mListeners) { - mUmsEnabling = true; + mUmsEnabling = enable; } } @@ -1351,12 +1430,16 @@ class MountService extends IMountService.Stub mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); } - private boolean isCallerOwnerOfPackage(String packageName) { + private boolean isCallerOwnerOfPackageOrSystem(String packageName) { final int callerUid = Binder.getCallingUid(); - return isUidOwnerOfPackage(packageName, callerUid); + return isUidOwnerOfPackageOrSystem(packageName, callerUid); } - private boolean isUidOwnerOfPackage(String packageName, int callerUid) { + private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) { + if (callerUid == android.os.Process.SYSTEM_UID) { + return true; + } + if (packageName == null) { return false; } @@ -1375,12 +1458,6 @@ class MountService extends IMountService.Stub waitForReady(); warnOnNotMounted(); - // XXX replace with call to IMediaContainerService - ObbInfo obbInfo = ObbScanner.getObbInfo(filename); - if (!isCallerOwnerOfPackage(obbInfo.packageName)) { - throw new IllegalArgumentException("Caller package does not match OBB file"); - } - try { ArrayList<String> rsp = mConnector.doCommand(String.format("obb path %s", filename)); String []tok = rsp.get(0).split(" "); @@ -1392,7 +1469,7 @@ class MountService extends IMountService.Stub } catch (NativeDaemonConnectorException e) { int code = e.getCode(); if (code == VoldResponseCode.OpFailedStorageNotFound) { - throw new IllegalArgumentException(String.format("OBB '%s' not found", filename)); + return null; } else { throw new IllegalStateException(String.format("Unexpected response code %d", code)); } @@ -1400,95 +1477,390 @@ class MountService extends IMountService.Stub } public boolean isObbMounted(String filename) { + synchronized (mObbMounts) { + return mObbPathToStateMap.containsKey(filename); + } + } + + public void mountObb(String filename, String key, IObbActionListener token) { waitForReady(); warnOnNotMounted(); - // XXX replace with call to IMediaContainerService - ObbInfo obbInfo = ObbScanner.getObbInfo(filename); - if (!isCallerOwnerOfPackage(obbInfo.packageName)) { - throw new IllegalArgumentException("Caller package does not match OBB file"); + final ObbState obbState; + + synchronized (mObbMounts) { + if (isObbMounted(filename)) { + throw new IllegalArgumentException("OBB file is already mounted"); + } + + if (mObbMounts.containsKey(token)) { + throw new IllegalArgumentException("You may only have one OBB mounted at a time"); + } + + final int callerUid = Binder.getCallingUid(); + obbState = new ObbState(filename, token, callerUid); + addObbState(obbState); } - synchronized (mObbMountSet) { - return mObbMountSet.contains(filename); + try { + token.asBinder().linkToDeath(obbState, 0); + } catch (RemoteException rex) { + Slog.e(TAG, "Failed to link to listener death"); } + + MountObbAction action = new MountObbAction(obbState, key); + mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); + + if (DEBUG_OBB) + Slog.i(TAG, "Send to OBB handler: " + action.toString()); } - public int mountObb(String filename, String key) { - waitForReady(); - warnOnNotMounted(); + public void unmountObb(String filename, boolean force, IObbActionListener token) { + final ObbState obbState; - synchronized (mObbMountSet) { - if (mObbMountSet.contains(filename)) { - return StorageResultCode.OperationFailedStorageMounted; + synchronized (mObbMounts) { + if (!isObbMounted(filename)) { + throw new IllegalArgumentException("OBB is not mounted"); } + obbState = mObbPathToStateMap.get(filename); } - final int callerUid = Binder.getCallingUid(); + UnmountObbAction action = new UnmountObbAction(obbState, force); + mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action)); + + if (DEBUG_OBB) + Slog.i(TAG, "Send to OBB handler: " + action.toString()); + } - // XXX replace with call to IMediaContainerService - ObbInfo obbInfo = ObbScanner.getObbInfo(filename); - if (!isUidOwnerOfPackage(obbInfo.packageName, callerUid)) { - throw new IllegalArgumentException("Caller package does not match OBB file"); + private void addObbState(ObbState obbState) { + synchronized (mObbMounts) { + mObbMounts.put(obbState.token, obbState); + mObbPathToStateMap.put(obbState.filename, obbState); } + } - if (key == null) { - key = "none"; + private void removeObbState(ObbState obbState) { + synchronized (mObbMounts) { + mObbMounts.remove(obbState.token); + mObbPathToStateMap.remove(obbState.filename); } + } - int rc = StorageResultCode.OperationSucceeded; - String cmd = String.format("obb mount %s %s %d", filename, key, callerUid); - try { - mConnector.doCommand(cmd); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code != VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedInternalError; + private class ObbActionHandler extends Handler { + private boolean mBound = false; + private List<ObbAction> mActions = new LinkedList<ObbAction>(); + + ObbActionHandler(Looper l) { + super(l); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case OBB_RUN_ACTION: { + ObbAction action = (ObbAction) msg.obj; + + if (DEBUG_OBB) + Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString()); + + // If a bind was already initiated we don't really + // need to do anything. The pending install + // will be processed later on. + if (!mBound) { + // If this is the only one pending we might + // have to bind to the service again. + if (!connectToService()) { + Slog.e(TAG, "Failed to bind to media container service"); + action.handleError(); + return; + } else { + // Once we bind to the service, the first + // pending request will be processed. + mActions.add(action); + } + } else { + // Already bound to the service. Just make + // sure we trigger off processing the first request. + if (mActions.size() == 0) { + mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND); + } + + mActions.add(action); + } + break; + } + case OBB_MCS_BOUND: { + if (DEBUG_OBB) + Slog.i(TAG, "OBB_MCS_BOUND"); + if (msg.obj != null) { + mContainerService = (IMediaContainerService) msg.obj; + } + if (mContainerService == null) { + // Something seriously wrong. Bail out + Slog.e(TAG, "Cannot bind to media container service"); + for (ObbAction action : mActions) { + // Indicate service bind error + action.handleError(); + } + mActions.clear(); + } else if (mActions.size() > 0) { + ObbAction action = mActions.get(0); + if (action != null) { + action.execute(this); + } + } else { + // Should never happen ideally. + Slog.w(TAG, "Empty queue"); + } + break; + } + case OBB_MCS_RECONNECT: { + if (DEBUG_OBB) + Slog.i(TAG, "OBB_MCS_RECONNECT"); + if (mActions.size() > 0) { + if (mBound) { + disconnectService(); + } + if (!connectToService()) { + Slog.e(TAG, "Failed to bind to media container service"); + for (ObbAction action : mActions) { + // Indicate service bind error + action.handleError(); + } + mActions.clear(); + } + } + break; + } + case OBB_MCS_UNBIND: { + if (DEBUG_OBB) + Slog.i(TAG, "OBB_MCS_UNBIND"); + + // Delete pending install + if (mActions.size() > 0) { + mActions.remove(0); + } + if (mActions.size() == 0) { + if (mBound) { + disconnectService(); + } + } else { + // There are more pending requests in queue. + // Just post MCS_BOUND message to trigger processing + // of next pending install. + mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND); + } + break; + } + case OBB_MCS_GIVE_UP: { + if (DEBUG_OBB) + Slog.i(TAG, "OBB_MCS_GIVE_UP"); + mActions.remove(0); + break; + } } } - if (rc == StorageResultCode.OperationSucceeded) { - synchronized (mObbMountSet) { - mObbMountSet.add(filename); + private boolean connectToService() { + if (DEBUG_OBB) + Slog.i(TAG, "Trying to bind to DefaultContainerService"); + + Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); + if (mContext.bindService(service, mDefContainerConn, Context.BIND_AUTO_CREATE)) { + mBound = true; + return true; } + return false; + } + + private void disconnectService() { + mContainerService = null; + mBound = false; + mContext.unbindService(mDefContainerConn); } - return rc; } - public int unmountObb(String filename, boolean force) { - waitForReady(); - warnOnNotMounted(); + abstract class ObbAction { + private static final int MAX_RETRIES = 3; + private int mRetries; + + ObbState mObbState; - ObbInfo obbInfo = ObbScanner.getObbInfo(filename); - if (!isCallerOwnerOfPackage(obbInfo.packageName)) { - throw new IllegalArgumentException("Caller package does not match OBB file"); + ObbAction(ObbState obbState) { + mObbState = obbState; } - synchronized (mObbMountSet) { - if (!mObbMountSet.contains(filename)) { - return StorageResultCode.OperationFailedStorageNotMounted; + public void execute(ObbActionHandler handler) { + try { + if (DEBUG_OBB) + Slog.i(TAG, "Starting to execute action: " + this.toString()); + mRetries++; + if (mRetries > MAX_RETRIES) { + Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up"); + mObbActionHandler.sendEmptyMessage(OBB_MCS_GIVE_UP); + handleError(); + return; + } else { + handleExecute(); + if (DEBUG_OBB) + Slog.i(TAG, "Posting install MCS_UNBIND"); + mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND); + } + } catch (RemoteException e) { + if (DEBUG_OBB) + Slog.i(TAG, "Posting install MCS_RECONNECT"); + mObbActionHandler.sendEmptyMessage(OBB_MCS_RECONNECT); + } catch (Exception e) { + if (DEBUG_OBB) + Slog.d(TAG, "Error handling OBB action", e); + handleError(); } - } + } - int rc = StorageResultCode.OperationSucceeded; - String cmd = String.format("obb unmount %s%s", filename, (force ? " force" : "")); - try { - mConnector.doCommand(cmd); - } catch (NativeDaemonConnectorException e) { - int code = e.getCode(); - if (code == VoldResponseCode.OpFailedStorageBusy) { - rc = StorageResultCode.OperationFailedStorageBusy; + abstract void handleExecute() throws RemoteException; + abstract void handleError(); + } + + class MountObbAction extends ObbAction { + private String mKey; + + MountObbAction(ObbState obbState, String key) { + super(obbState); + mKey = key; + } + + public void handleExecute() throws RemoteException { + ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename); + if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) { + throw new IllegalArgumentException("Caller package does not match OBB file"); + } + + if (mKey == null) { + mKey = "none"; + } + + int rc = StorageResultCode.OperationSucceeded; + String cmd = String.format("obb mount %s %s %d", mObbState.filename, mKey, + mObbState.callerUid); + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + int code = e.getCode(); + if (code != VoldResponseCode.OpFailedStorageBusy) { + rc = StorageResultCode.OperationFailedInternalError; + } + } + + if (rc == StorageResultCode.OperationSucceeded) { + try { + mObbState.token.onObbResult(mObbState.filename, "mounted"); + } catch (RemoteException e) { + Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged"); + } } else { - rc = StorageResultCode.OperationFailedInternalError; + Slog.e(TAG, "Couldn't mount OBB file"); + + // We didn't succeed, so remove this from the mount-set. + removeObbState(mObbState); } } - if (rc == StorageResultCode.OperationSucceeded) { - synchronized (mObbMountSet) { - mObbMountSet.remove(filename); + public void handleError() { + removeObbState(mObbState); + + try { + mObbState.token.onObbResult(mObbState.filename, "error"); + } catch (RemoteException e) { + Slog.e(TAG, "Couldn't send back OBB mount error for " + mObbState.filename); } } - return rc; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("MountObbAction{"); + sb.append("filename="); + sb.append(mObbState.filename); + sb.append(",callerUid="); + sb.append(mObbState.callerUid); + sb.append(",token="); + sb.append(mObbState.token != null ? mObbState.token.toString() : "NULL"); + sb.append('}'); + return sb.toString(); + } + } + + class UnmountObbAction extends ObbAction { + private boolean mForceUnmount; + + UnmountObbAction(ObbState obbState, boolean force) { + super(obbState); + mForceUnmount = force; + } + + public void handleExecute() throws RemoteException { + ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename); + + if (!isCallerOwnerOfPackageOrSystem(obbInfo.packageName)) { + throw new IllegalArgumentException("Caller package does not match OBB file"); + } + + int rc = StorageResultCode.OperationSucceeded; + String cmd = String.format("obb unmount %s%s", mObbState.filename, + (mForceUnmount ? " force" : "")); + try { + mConnector.doCommand(cmd); + } catch (NativeDaemonConnectorException e) { + int code = e.getCode(); + if (code == VoldResponseCode.OpFailedStorageBusy) { + rc = StorageResultCode.OperationFailedStorageBusy; + } else { + rc = StorageResultCode.OperationFailedInternalError; + } + } + + if (rc == StorageResultCode.OperationSucceeded) { + removeObbState(mObbState); + + try { + mObbState.token.onObbResult(mObbState.filename, "unmounted"); + } catch (RemoteException e) { + Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged"); + } + } else { + try { + mObbState.token.onObbResult(mObbState.filename, "error"); + } catch (RemoteException e) { + Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged"); + } + } + } + + public void handleError() { + removeObbState(mObbState); + + try { + mObbState.token.onObbResult(mObbState.filename, "error"); + } catch (RemoteException e) { + Slog.e(TAG, "Couldn't send back OBB unmount error for " + mObbState.filename); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("UnmountObbAction{"); + sb.append("filename="); + sb.append(mObbState.filename != null ? mObbState.filename : "null"); + sb.append(",force="); + sb.append(mForceUnmount); + sb.append(",callerUid="); + sb.append(mObbState.callerUid); + sb.append(",token="); + sb.append(mObbState.token != null ? mObbState.token.toString() : "null"); + sb.append('}'); + return sb.toString(); + } } } diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 15080b2..b43b33e 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -17,6 +17,8 @@ package com.android.server; import android.app.AlarmManager; +import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; @@ -26,25 +28,30 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.net.wifi.IWifiManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import android.net.wifi.WifiStateTracker; +import android.net.wifi.WifiStateMachine; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.ConnectivityManager; import android.net.InterfaceConfiguration; -import android.net.NetworkStateTracker; import android.net.DhcpInfo; +import android.net.NetworkInfo; +import android.net.NetworkInfo.State; import android.os.Binder; +import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkManagementService; +import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; +import android.text.TextUtils; import android.util.Slog; import java.util.ArrayList; @@ -72,7 +79,7 @@ public class WifiService extends IWifiManager.Stub { private static final String TAG = "WifiService"; private static final boolean DBG = true; - private final WifiStateTracker mWifiStateTracker; + private final WifiStateMachine mWifiStateMachine; private Context mContext; @@ -123,10 +130,63 @@ public class WifiService extends IWifiManager.Stub { private boolean mIsReceiverRegistered = false; - WifiService(Context context, WifiStateTracker tracker) { + + NetworkInfo mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", ""); + + // Variables relating to the 'available networks' notification + /** + * The icon to show in the 'available networks' notification. This will also + * be the ID of the Notification given to the NotificationManager. + */ + private static final int ICON_NETWORKS_AVAILABLE = + com.android.internal.R.drawable.stat_notify_wifi_in_range; + /** + * When a notification is shown, we wait this amount before possibly showing it again. + */ + private final long NOTIFICATION_REPEAT_DELAY_MS; + /** + * Whether the user has set the setting to show the 'available networks' notification. + */ + private boolean mNotificationEnabled; + /** + * Observes the user setting to keep {@link #mNotificationEnabled} in sync. + */ + private NotificationEnabledSettingObserver mNotificationEnabledSettingObserver; + /** + * The {@link System#currentTimeMillis()} must be at least this value for us + * to show the notification again. + */ + private long mNotificationRepeatTime; + /** + * The Notification object given to the NotificationManager. + */ + private Notification mNotification; + /** + * Whether the notification is being shown, as set by us. That is, if the + * user cancels the notification, we will not receive the callback so this + * will still be true. We only guarantee if this is false, then the + * notification is not showing. + */ + private boolean mNotificationShown; + /** + * The number of continuous scans that must occur before consider the + * supplicant in a scanning state. This allows supplicant to associate with + * remembered networks that are in the scan results. + */ + private static final int NUM_SCANS_BEFORE_ACTUALLY_SCANNING = 3; + /** + * The number of scans since the last network state change. When this + * exceeds {@link #NUM_SCANS_BEFORE_ACTUALLY_SCANNING}, we consider the + * supplicant to actually be scanning. When the network state changes to + * something other than scanning, we reset this to 0. + */ + private int mNumScansSinceNetworkStateChange; + + + WifiService(Context context) { mContext = context; - mWifiStateTracker = tracker; - mWifiStateTracker.enableRssiPolling(true); + mWifiStateMachine = new WifiStateMachine(mContext); + mWifiStateMachine.enableRssiPolling(true); mBatteryStats = BatteryStatsService.getService(); mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); @@ -164,6 +224,42 @@ public class WifiService extends IWifiManager.Stub { } },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)); + + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + + mContext.registerReceiver( + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + // reset & clear notification on any wifi state change + resetNotification(); + } else if (intent.getAction().equals( + WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + mNetworkInfo = (NetworkInfo) intent.getParcelableExtra( + WifiManager.EXTRA_NETWORK_INFO); + // reset & clear notification on a network connect & disconnect + switch(mNetworkInfo.getDetailedState()) { + case CONNECTED: + case DISCONNECTED: + resetNotification(); + break; + } + } else if (intent.getAction().equals( + WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { + checkAndSetNotification(); + } + } + }, filter); + + // Setting is in seconds + NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l; + mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler()); + mNotificationEnabledSettingObserver.register(); } /** @@ -172,7 +268,7 @@ public class WifiService extends IWifiManager.Stub { * * This function is used only at boot time */ - public void startWifi() { + public void checkAndStartWifi() { /* Start if Wi-Fi is enabled or the saved state indicates Wi-Fi was on */ boolean wifiEnabled = !isAirplaneModeOn() && (getPersistedWifiEnabled() || testAndClearWifiSavedState()); @@ -255,17 +351,13 @@ public class WifiService extends IWifiManager.Stub { Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, enabled ? 1 : 0); } - NetworkStateTracker getNetworkStateTracker() { - return mWifiStateTracker; - } - /** * see {@link android.net.wifi.WifiManager#pingSupplicant()} * @return {@code true} if the operation succeeds, {@code false} otherwise */ public boolean pingSupplicant() { enforceAccessPermission(); - return mWifiStateTracker.pingSupplicant(); + return mWifiStateMachine.pingSupplicant(); } /** @@ -274,7 +366,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean startScan(boolean forceActive) { enforceChangePermission(); - return mWifiStateTracker.startScan(forceActive); + return mWifiStateMachine.startScan(forceActive); } private void enforceAccessPermission() { @@ -304,7 +396,7 @@ public class WifiService extends IWifiManager.Stub { enforceChangePermission(); if (DBG) { - Slog.e(TAG, "Invoking mWifiStateTracker.setWifiEnabled\n"); + Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n"); } // set a flag if the user is enabling Wifi while in airplane mode @@ -312,7 +404,7 @@ public class WifiService extends IWifiManager.Stub { mAirplaneModeOverwridden.set(true); } - mWifiStateTracker.setWifiEnabled(enable); + mWifiStateMachine.setWifiEnabled(enable); persistWifiEnabled(enable); if (enable) { @@ -338,7 +430,7 @@ public class WifiService extends IWifiManager.Stub { */ public int getWifiEnabledState() { enforceAccessPermission(); - return mWifiStateTracker.getWifiState(); + return mWifiStateMachine.getWifiState(); } /** @@ -362,7 +454,7 @@ public class WifiService extends IWifiManager.Stub { setWifiApConfiguration(wifiConfig); } - mWifiStateTracker.setWifiApEnabled(wifiConfig, enabled); + mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled); return true; } @@ -377,7 +469,7 @@ public class WifiService extends IWifiManager.Stub { */ public int getWifiApEnabledState() { enforceAccessPermission(); - return mWifiStateTracker.getWifiApState(); + return mWifiStateMachine.getWifiApState(); } /** @@ -427,7 +519,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean disconnect() { enforceChangePermission(); - return mWifiStateTracker.disconnectCommand(); + return mWifiStateMachine.disconnectCommand(); } /** @@ -436,7 +528,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean reconnect() { enforceChangePermission(); - return mWifiStateTracker.reconnectCommand(); + return mWifiStateMachine.reconnectCommand(); } /** @@ -445,7 +537,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean reassociate() { enforceChangePermission(); - return mWifiStateTracker.reassociateCommand(); + return mWifiStateMachine.reassociateCommand(); } /** @@ -454,7 +546,7 @@ public class WifiService extends IWifiManager.Stub { */ public List<WifiConfiguration> getConfiguredNetworks() { enforceAccessPermission(); - return mWifiStateTracker.getConfiguredNetworks(); + return mWifiStateMachine.getConfiguredNetworks(); } /** @@ -464,7 +556,7 @@ public class WifiService extends IWifiManager.Stub { */ public int addOrUpdateNetwork(WifiConfiguration config) { enforceChangePermission(); - return mWifiStateTracker.addOrUpdateNetwork(config); + return mWifiStateMachine.addOrUpdateNetwork(config); } /** @@ -475,7 +567,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean removeNetwork(int netId) { enforceChangePermission(); - return mWifiStateTracker.removeNetwork(netId); + return mWifiStateMachine.removeNetwork(netId); } /** @@ -487,7 +579,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean enableNetwork(int netId, boolean disableOthers) { enforceChangePermission(); - return mWifiStateTracker.enableNetwork(netId, disableOthers); + return mWifiStateMachine.enableNetwork(netId, disableOthers); } /** @@ -498,7 +590,7 @@ public class WifiService extends IWifiManager.Stub { */ public boolean disableNetwork(int netId) { enforceChangePermission(); - return mWifiStateTracker.disableNetwork(netId); + return mWifiStateMachine.disableNetwork(netId); } /** @@ -511,7 +603,7 @@ public class WifiService extends IWifiManager.Stub { * Make sure we have the latest information, by sending * a status request to the supplicant. */ - return mWifiStateTracker.requestConnectionInfo(); + return mWifiStateMachine.requestConnectionInfo(); } /** @@ -521,7 +613,7 @@ public class WifiService extends IWifiManager.Stub { */ public List<ScanResult> getScanResults() { enforceAccessPermission(); - return mWifiStateTracker.getScanResultsList(); + return mWifiStateMachine.getScanResultsList(); } /** @@ -533,7 +625,7 @@ public class WifiService extends IWifiManager.Stub { public boolean saveConfiguration() { boolean result = true; enforceChangePermission(); - return mWifiStateTracker.saveConfig(); + return mWifiStateMachine.saveConfig(); } /** @@ -576,7 +668,7 @@ public class WifiService extends IWifiManager.Stub { numChannels); } - mWifiStateTracker.setNumAllowedChannels(numChannels); + mWifiStateMachine.setNumAllowedChannels(numChannels); return true; } @@ -596,7 +688,7 @@ public class WifiService extends IWifiManager.Stub { * Wi-Fi is not currently enabled), get the value from * Settings. */ - numChannels = mWifiStateTracker.getNumAllowedChannels(); + numChannels = mWifiStateMachine.getNumAllowedChannels(); if (numChannels < 0) { numChannels = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS, @@ -622,9 +714,59 @@ public class WifiService extends IWifiManager.Stub { */ public DhcpInfo getDhcpInfo() { enforceAccessPermission(); - return mWifiStateTracker.getDhcpInfo(); + return mWifiStateMachine.getDhcpInfo(); + } + + /** + * see {@link android.net.wifi.WifiManager#startWifi} + * + */ + public void startWifi() { + enforceChangePermission(); + /* TODO: may be add permissions for access only to connectivity service + * TODO: if a start issued, keep wifi alive until a stop issued irrespective + * of WifiLock & device idle status unless wifi enabled status is toggled + */ + + mWifiStateMachine.setDriverStart(true); + mWifiStateMachine.reconnectCommand(); + } + + /** + * see {@link android.net.wifi.WifiManager#stopWifi} + * + */ + public void stopWifi() { + enforceChangePermission(); + /* TODO: may be add permissions for access only to connectivity service + * TODO: if a stop is issued, wifi is brought up only by startWifi + * unless wifi enabled status is toggled + */ + mWifiStateMachine.setDriverStart(false); + } + + + /** + * see {@link android.net.wifi.WifiManager#addToBlacklist} + * + */ + public void addToBlacklist(String bssid) { + enforceChangePermission(); + + mWifiStateMachine.addToBlacklist(bssid); + } + + /** + * see {@link android.net.wifi.WifiManager#clearBlacklist} + * + */ + public void clearBlacklist() { + enforceChangePermission(); + + mWifiStateMachine.clearBlacklist(); } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -641,11 +783,11 @@ public class WifiService extends IWifiManager.Stub { mAlarmManager.cancel(mIdleIntent); mDeviceIdle = false; mScreenOff = false; - mWifiStateTracker.enableRssiPolling(true); + mWifiStateMachine.enableRssiPolling(true); } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { Slog.d(TAG, "ACTION_SCREEN_OFF"); mScreenOff = true; - mWifiStateTracker.enableRssiPolling(false); + mWifiStateMachine.enableRssiPolling(false); /* * Set a timer to put Wi-Fi to sleep, but only if the screen is off * AND the "stay on while plugged in" setting doesn't match the @@ -653,7 +795,7 @@ public class WifiService extends IWifiManager.Stub { * or plugged in to AC). */ if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) { - WifiInfo info = mWifiStateTracker.requestConnectionInfo(); + WifiInfo info = mWifiStateMachine.requestConnectionInfo(); if (info.getSupplicantState() != SupplicantState.COMPLETED) { // we used to go to sleep immediately, but this caused some race conditions // we don't have time to track down for this release. Delay instead, @@ -704,7 +846,7 @@ public class WifiService extends IWifiManager.Stub { isBluetoothPlaying = true; } } - mWifiStateTracker.setBluetoothScanMode(isBluetoothPlaying); + mWifiStateMachine.setBluetoothScanMode(isBluetoothPlaying); } else { return; @@ -771,21 +913,21 @@ public class WifiService extends IWifiManager.Stub { /* Disable tethering when airplane mode is enabled */ if (airplaneMode) { - mWifiStateTracker.setWifiApEnabled(null, false); + mWifiStateMachine.setWifiApEnabled(null, false); } if (wifiShouldBeEnabled) { if (wifiShouldBeStarted) { - mWifiStateTracker.setWifiEnabled(true); - mWifiStateTracker.setScanOnlyMode( + mWifiStateMachine.setWifiEnabled(true); + mWifiStateMachine.setScanOnlyMode( strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY); - mWifiStateTracker.startWifi(true); + mWifiStateMachine.setDriverStart(true); } else { - mWifiStateTracker.requestCmWakeLock(); - mWifiStateTracker.disconnectAndStop(); + mWifiStateMachine.requestCmWakeLock(); + mWifiStateMachine.setDriverStart(false); } } else { - mWifiStateTracker.setWifiEnabled(false); + mWifiStateMachine.setWifiEnabled(false); } } @@ -832,17 +974,17 @@ public class WifiService extends IWifiManager.Stub { + ", uid=" + Binder.getCallingUid()); return; } - pw.println("Wi-Fi is " + mWifiStateTracker.getWifiStateByName()); + pw.println("Wi-Fi is " + mWifiStateMachine.getWifiStateByName()); pw.println("Stay-awake conditions: " + Settings.System.getInt(mContext.getContentResolver(), Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0)); pw.println(); pw.println("Internal state:"); - pw.println(mWifiStateTracker); + pw.println(mWifiStateMachine); pw.println(); pw.println("Latest scan results:"); - List<ScanResult> scanResults = mWifiStateTracker.getScanResultsList(); + List<ScanResult> scanResults = mWifiStateMachine.getScanResultsList(); if (scanResults != null && scanResults.size() != 0) { pw.println(" BSSID Frequency RSSI Flags SSID"); for (ScanResult r : scanResults) { @@ -1069,7 +1211,7 @@ public class WifiService extends IWifiManager.Stub { if (mMulticasters.size() != 0) { return; } else { - mWifiStateTracker.startPacketFiltering(); + mWifiStateMachine.startPacketFiltering(); } } } @@ -1084,7 +1226,7 @@ public class WifiService extends IWifiManager.Stub { // our new size == 1 (first call), but this function won't // be called often and by making the stopPacket call each // time we're less fragile and self-healing. - mWifiStateTracker.stopPacketFiltering(); + mWifiStateMachine.stopPacketFiltering(); } int uid = Binder.getCallingUid(); @@ -1121,7 +1263,7 @@ public class WifiService extends IWifiManager.Stub { removed.unlinkDeathRecipient(); } if (mMulticasters.size() == 0) { - mWifiStateTracker.startPacketFiltering(); + mWifiStateMachine.startPacketFiltering(); } Long ident = Binder.clearCallingIdentity(); @@ -1140,4 +1282,166 @@ public class WifiService extends IWifiManager.Stub { return (mMulticasters.size() > 0); } } + + private void checkAndSetNotification() { + // If we shouldn't place a notification on available networks, then + // don't bother doing any of the following + if (!mNotificationEnabled) return; + + State state = mNetworkInfo.getState(); + if ((state == NetworkInfo.State.DISCONNECTED) + || (state == NetworkInfo.State.UNKNOWN)) { + // Look for an open network + List<ScanResult> scanResults = mWifiStateMachine.getScanResultsList(); + if (scanResults != null) { + int numOpenNetworks = 0; + for (int i = scanResults.size() - 1; i >= 0; i--) { + ScanResult scanResult = scanResults.get(i); + + if (TextUtils.isEmpty(scanResult.capabilities)) { + numOpenNetworks++; + } + } + + if (numOpenNetworks > 0) { + if (++mNumScansSinceNetworkStateChange >= NUM_SCANS_BEFORE_ACTUALLY_SCANNING) { + /* + * We've scanned continuously at least + * NUM_SCANS_BEFORE_NOTIFICATION times. The user + * probably does not have a remembered network in range, + * since otherwise supplicant would have tried to + * associate and thus resetting this counter. + */ + setNotificationVisible(true, numOpenNetworks, false, 0); + } + return; + } + } + } + + // No open networks in range, remove the notification + setNotificationVisible(false, 0, false, 0); + } + + /** + * Clears variables related to tracking whether a notification has been + * shown recently and clears the current notification. + */ + private void resetNotification() { + mNotificationRepeatTime = 0; + mNumScansSinceNetworkStateChange = 0; + setNotificationVisible(false, 0, false, 0); + } + + /** + * Display or don't display a notification that there are open Wi-Fi networks. + * @param visible {@code true} if notification should be visible, {@code false} otherwise + * @param numNetworks the number networks seen + * @param force {@code true} to force notification to be shown/not-shown, + * even if it is already shown/not-shown. + * @param delay time in milliseconds after which the notification should be made + * visible or invisible. + */ + private void setNotificationVisible(boolean visible, int numNetworks, boolean force, + int delay) { + + // Since we use auto cancel on the notification, when the + // mNetworksAvailableNotificationShown is true, the notification may + // have actually been canceled. However, when it is false we know + // for sure that it is not being shown (it will not be shown any other + // place than here) + + // If it should be hidden and it is already hidden, then noop + if (!visible && !mNotificationShown && !force) { + return; + } + + NotificationManager notificationManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + + Message message; + if (visible) { + + // Not enough time has passed to show the notification again + if (System.currentTimeMillis() < mNotificationRepeatTime) { + return; + } + + if (mNotification == null) { + // Cache the Notification mainly so we can remove the + // EVENT_NOTIFICATION_CHANGED message with this Notification from + // the queue later + mNotification = new Notification(); + mNotification.when = 0; + mNotification.icon = ICON_NETWORKS_AVAILABLE; + mNotification.flags = Notification.FLAG_AUTO_CANCEL; + mNotification.contentIntent = PendingIntent.getActivity(mContext, 0, + new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK), 0); + } + + CharSequence title = mContext.getResources().getQuantityText( + com.android.internal.R.plurals.wifi_available, numNetworks); + CharSequence details = mContext.getResources().getQuantityText( + com.android.internal.R.plurals.wifi_available_detailed, numNetworks); + mNotification.tickerText = title; + mNotification.setLatestEventInfo(mContext, title, details, mNotification.contentIntent); + + mNotificationRepeatTime = System.currentTimeMillis() + NOTIFICATION_REPEAT_DELAY_MS; + + notificationManager.notify(ICON_NETWORKS_AVAILABLE, mNotification); + /* + * TODO: Clean up connectivity service & remove this + */ + /* message = mCsHandler.obtainMessage(EVENT_NOTIFICATION_CHANGED, 1, + ICON_NETWORKS_AVAILABLE, mNotification); */ + + + } else { + + notificationManager.cancel(ICON_NETWORKS_AVAILABLE); + /* + * TODO: Clean up connectivity service & remove this + */ + /* + // Remove any pending messages to show the notification + mCsHandler.removeMessages(EVENT_NOTIFICATION_CHANGED, mNotification); + + message = mCsHandler.obtainMessage(EVENT_NOTIFICATION_CHANGED, 0, + ICON_NETWORKS_AVAILABLE); + */ + } + + //mCsHandler.sendMessageDelayed(message, delay); + + mNotificationShown = visible; + } + + private class NotificationEnabledSettingObserver extends ContentObserver { + + public NotificationEnabledSettingObserver(Handler handler) { + super(handler); + } + + public void register() { + ContentResolver cr = mContext.getContentResolver(); + cr.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this); + mNotificationEnabled = getValue(); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + + mNotificationEnabled = getValue(); + resetNotification(); + } + + private boolean getValue() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1) == 1; + } + } + + } diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java index be14cd3..46d6bef 100644 --- a/services/java/com/android/server/WifiWatchdogService.java +++ b/services/java/com/android/server/WifiWatchdogService.java @@ -27,7 +27,6 @@ import android.net.DhcpInfo; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import android.net.wifi.WifiStateTracker; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -77,7 +76,6 @@ public class WifiWatchdogService { private Context mContext; private ContentResolver mContentResolver; - private WifiStateTracker mWifiStateTracker; private WifiManager mWifiManager; /** @@ -108,10 +106,9 @@ public class WifiWatchdogService { /** Whether the current AP check should be canceled. */ private boolean mShouldCancel; - WifiWatchdogService(Context context, WifiStateTracker wifiStateTracker) { + WifiWatchdogService(Context context) { mContext = context; mContentResolver = context.getContentResolver(); - mWifiStateTracker = wifiStateTracker; mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); createThread(); @@ -752,7 +749,7 @@ public class WifiWatchdogService { // Black list this "bad" AP, this will cause an attempt to connect to another blacklistAp(ap.bssid); // Initiate an association to an alternate AP - mWifiStateTracker.reassociateCommand(); + mWifiManager.reassociate(); } private void blacklistAp(String bssid) { @@ -763,7 +760,7 @@ public class WifiWatchdogService { // Before taking action, make sure we should not cancel our processing if (shouldCancel()) return; - mWifiStateTracker.addToBlacklist(bssid); + mWifiManager.addToBlacklist(bssid); if (D) { myLogD("Blacklisting " + bssid); @@ -858,7 +855,7 @@ public class WifiWatchdogService { * (and blacklisted them). Clear the blacklist so the AP with best * signal is chosen. */ - mWifiStateTracker.clearBlacklist(); + mWifiManager.clearBlacklist(); if (V) { myLogV("handleSleep: Set state to SLEEP and cleared blacklist"); @@ -929,7 +926,7 @@ public class WifiWatchdogService { * should revert anything done by the watchdog monitoring. */ private void handleReset() { - mWifiStateTracker.clearBlacklist(); + mWifiManager.clearBlacklist(); setIdleState(true); } diff --git a/services/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp index 5f83636..e8b2ebf 100644 --- a/services/surfaceflinger/LayerBuffer.cpp +++ b/services/surfaceflinger/LayerBuffer.cpp @@ -495,7 +495,7 @@ status_t LayerBuffer::BufferSource::initTempBuffer() const const ISurface::BufferHeap& buffers(mBufferHeap); uint32_t w = mLayer.mTransformedBounds.width(); uint32_t h = mLayer.mTransformedBounds.height(); - if (buffers.w * h != buffers.h * w) { + if (mLayer.getOrientation() & (Transform::ROT_90 | Transform::ROT_270)) { int t = w; w = h; h = t; } |