From 46bb6d6cb7ee4002fe6c306a1f027d536272f617 Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Tue, 25 Jun 2013 11:41:53 -0700 Subject: [PATCH 1/4] Fix power issues around wifi scans. - Sending a broadcast indicating when scan requests could be serviced so that apps don't request scans we won't do anything with. - Fix our batt stats accounting so we only count it if we send the request to the driver. bug: 8868201 bug: 9496690 Change-Id: I64a4f1c294c848ac64c50d8854ed4a6a1a47f603 --- core/res/AndroidManifest.xml | 1 + .../com/android/server/wifi/WifiService.java | 56 +------------------ wifi/java/android/net/wifi/WifiManager.java | 12 ++++ .../android/net/wifi/WifiStateMachine.java | 56 +++++++++++++++++-- 4 files changed, 65 insertions(+), 60 deletions(-) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 619a10b9ef75d..9624f15ceb3ac 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -156,6 +156,7 @@ + diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java index 66ef97808dd12..a70978ee6c4b5 100644 --- a/services/java/com/android/server/wifi/WifiService.java +++ b/services/java/com/android/server/wifi/WifiService.java @@ -114,10 +114,6 @@ public final class WifiService extends IWifiManager.Stub { /* Tracks the persisted states for wi-fi & airplane mode */ final WifiSettingsStore mSettingsStore; - /* The work source (UID) that triggered the current WIFI scan, synchronized - * on this */ - private WorkSource mScanWorkSource; - /** * Asynchronous channel to WifiStateMachine */ @@ -255,17 +251,6 @@ public final class WifiService extends IWifiManager.Stub { }, new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals( - WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { - noteScanEnd(); - } - } - }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - // Adding optimizations of only receiving broadcasts when wifi is enabled // can result in race conditions when apps toggle wifi in the background // without active user involvement. Always receive broadcasts. @@ -274,44 +259,6 @@ public final class WifiService extends IWifiManager.Stub { private WifiController mWifiController; - /** Tell battery stats about a new WIFI scan */ - private void noteScanStart() { - WorkSource scanWorkSource = null; - synchronized (WifiService.this) { - if (mScanWorkSource != null) { - // Scan already in progress, don't add this one to battery stats - return; - } - scanWorkSource = new WorkSource(Binder.getCallingUid()); - mScanWorkSource = scanWorkSource; - } - - long id = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteWifiScanStartedFromSource(scanWorkSource); - } catch (RemoteException e) { - Log.w(TAG, e); - } finally { - Binder.restoreCallingIdentity(id); - } - } - - /** Tell battery stats that the current WIFI scan has completed */ - private void noteScanEnd() { - WorkSource scanWorkSource = null; - synchronized (WifiService.this) { - scanWorkSource = mScanWorkSource; - mScanWorkSource = null; - } - if (scanWorkSource != null) { - try { - mBatteryStats.noteWifiScanStoppedFromSource(scanWorkSource); - } catch (RemoteException e) { - Log.w(TAG, e); - } - } - } - /** * Check if Wi-Fi needs to be enabled and start * if needed @@ -352,8 +299,7 @@ public final class WifiService extends IWifiManager.Stub { */ public void startScan() { enforceChangePermission(); - mWifiStateMachine.startScan(); - noteScanStart(); + mWifiStateMachine.startScan(Binder.getCallingUid()); } private void enforceAccessPermission() { diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index ec76a8b5ee372..a3c172adad3af 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -69,6 +69,18 @@ public class WifiManager { */ public static final int ERROR_AUTHENTICATING = 1; + /** + * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently + * @hide + */ + public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available"; + + /** + * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED + * @hide + */ + public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled"; + /** * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, * enabling, disabling, or unknown. One extra provides this state as an int. diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 32d48ac16320c..58ae8dcee4f55 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -141,6 +141,8 @@ public class WifiStateMachine extends StateMachine { */ private int mOperationalMode = CONNECT_MODE; private boolean mScanResultIsPending = false; + private WorkSource mScanWorkSource = null; + private static final int UNKNOWN_SCAN_SOURCE = -1; /* Tracks if state machine has received any screen state change broadcast yet. * We can miss one of these at boot. */ @@ -601,7 +603,7 @@ public class WifiStateMachine extends StateMachine { new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - startScan(); + startScan(UNKNOWN_SCAN_SOURCE); } }, new IntentFilter(ACTION_START_SCAN)); @@ -694,6 +696,11 @@ public class WifiStateMachine extends StateMachine { //start the state machine start(); + + final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } /********************************************************* @@ -716,8 +723,31 @@ public class WifiStateMachine extends StateMachine { /** * TODO: doc */ - public void startScan() { - sendMessage(CMD_START_SCAN); + public void startScan(int callingUid) { + sendMessage(CMD_START_SCAN, callingUid); + } + + private void noteScanStart(int callingUid) { + if (mScanWorkSource == null && callingUid != UNKNOWN_SCAN_SOURCE) { + mScanWorkSource = new WorkSource(callingUid); + try { + mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource); + } catch (RemoteException e) { + log(e.toString()); + } + } + } + + private void noteScanEnd() { + if (mScanWorkSource != null) { + try { + mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource); + } catch (RemoteException e) { + log(e.toString()); + } finally { + mScanWorkSource = null; + } + } } private void startScanNative(int type) { @@ -1544,6 +1574,7 @@ public class WifiStateMachine extends StateMachine { } private void sendScanResultsAvailableBroadcast() { + noteScanEnd(); Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); @@ -1888,6 +1919,7 @@ public class WifiStateMachine extends StateMachine { } break; /* Discard */ + case CMD_START_SCAN: case CMD_START_SUPPLICANT: case CMD_STOP_SUPPLICANT: case CMD_STOP_SUPPLICANT_FAILED: @@ -1902,7 +1934,6 @@ public class WifiStateMachine extends StateMachine { case CMD_STOP_AP: case CMD_TETHER_STATE_CHANGE: case CMD_TETHER_NOTIFICATION_TIMED_OUT: - case CMD_START_SCAN: case CMD_DISCONNECT: case CMD_RECONNECT: case CMD_REASSOCIATE: @@ -2405,11 +2436,18 @@ public class WifiStateMachine extends StateMachine { mWifiNative.setPowerSave(true); if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); + + final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } + @Override public boolean processMessage(Message message) { switch(message.what) { case CMD_START_SCAN: + noteScanStart(message.arg1); startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP); break; case CMD_SET_COUNTRY_CODE: @@ -2530,6 +2568,12 @@ public class WifiStateMachine extends StateMachine { mIsRunning = false; updateBatteryWorkSource(null); mScanResults = new ArrayList(); + + final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + noteScanEnd(); // wrap up any pending request. } } @@ -2680,6 +2724,7 @@ public class WifiStateMachine extends StateMachine { // Handle scan. All the connection related commands are // handled only in ConnectModeState case CMD_START_SCAN: + noteScanStart(message.arg1); startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP); break; default: @@ -2943,6 +2988,7 @@ public class WifiStateMachine extends StateMachine { break; case CMD_START_SCAN: /* Do not attempt to connect when we are already connected */ + noteScanStart(message.arg1); startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP); break; /* Ignore connection to same network */ @@ -3260,7 +3306,7 @@ public class WifiStateMachine extends StateMachine { if (mP2pConnected.get()) break; if (message.arg1 == mPeriodicScanToken && mWifiConfigStore.getConfiguredNetworks().size() == 0) { - sendMessage(CMD_START_SCAN); + sendMessage(CMD_START_SCAN, UNKNOWN_SCAN_SOURCE); sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs); } From f63fdf8680b4f17b815a4173924c063983abfdf2 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Thu, 27 Jun 2013 10:58:10 -0700 Subject: [PATCH 2/4] Recreate TextureView's display list on attach Bug #9425270 When a TextureView is detached from its window and immediately re-attached, the display list is not destroyed but reused as is. TextureView will however destroy the layer and surface texture reference by the display list. The solution is to force TextureView to invalidate its display list on re-attach if it previously had a surface/layer pair. Change-Id: I475096ffa7e5709155c4c943bf1bfaaaedbd4a1d --- core/java/android/view/TextureView.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 5c3934d820775..244dc337d6f98 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -108,6 +108,7 @@ public class TextureView extends View { private HardwareLayer mLayer; private SurfaceTexture mSurface; private SurfaceTextureListener mListener; + private boolean mHadSurface; private boolean mOpaque = true; @@ -202,6 +203,11 @@ public class TextureView extends View { Log.w(LOG_TAG, "A TextureView or a subclass can only be " + "used with hardware acceleration enabled."); } + + if (mHadSurface) { + invalidate(true); + mHadSurface = false; + } } @Override @@ -241,6 +247,8 @@ public class TextureView extends View { if (shouldRelease) mSurface.release(); mSurface = null; mLayer = null; + + mHadSurface = true; } } From 937db2d48f1af5f82cbdfc4e2c1bb02a58f9e4bf Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Thu, 27 Jun 2013 15:12:01 -0700 Subject: [PATCH 3/4] When a new user AID is generated, dump it to dropbox Bug: 9595851 Change-Id: I6fde757eed84d7914db180e80c9d68448b3e5780 --- .../providers/settings/SettingsProvider.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 659651b887c41..0177504437368 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -43,6 +43,7 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.DropBoxManager; import android.os.FileObserver; import android.os.ParcelFileDescriptor; import android.os.SystemProperties; @@ -107,6 +108,9 @@ public class SettingsProvider extends ContentProvider { */ static final HashSet sSecureGlobalKeys; static final HashSet sSystemGlobalKeys; + + private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid"; + static { // Keys (name column) from the 'secure' table that are now in the owner user's 'global' // table, shared across all users @@ -486,6 +490,16 @@ public class SettingsProvider extends ContentProvider { } Slog.d(TAG, "Generated and saved new ANDROID_ID [" + newAndroidIdValue + "] for user " + userHandle); + // Write a dropbox entry if it's a restricted profile + if (mUserManager.getUserInfo(userHandle).isRestricted()) { + DropBoxManager dbm = (DropBoxManager) + getContext().getSystemService(Context.DROPBOX_SERVICE); + if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) { + dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis() + + ",restricted_profile_ssaid," + + newAndroidIdValue + "\n"); + } + } } return true; } finally { From d971caa5d529355d44b4d469eda8ef31daeb3bab Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Thu, 27 Jun 2013 17:15:24 -0700 Subject: [PATCH 4/4] Fix out of range glCopyTexImage2D Bug #9425270 A better solution would be to use glCopyTexImage2D whenever possible but this change would be a little more dangerous. Change-Id: Ib1aaceda39d838716285ef97f356721416822dbb --- libs/hwui/OpenGLRenderer.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ddb190e3fec19..7735819a20a0a 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -882,15 +882,18 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto layer->bindTexture(); if (!bounds.isEmpty()) { if (layer->isEmpty()) { - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - bounds.left, mSnapshot->height - bounds.bottom, - layer->getWidth(), layer->getHeight(), 0); + // Workaround for some GL drivers. When reading pixels lying outside + // of the window we should get undefined values for those pixels. + // Unfortunately some drivers will turn the entire target texture black + // when reading outside of the window. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->getWidth(), layer->getHeight(), + 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); layer->setEmpty(false); - } else { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, - mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight()); } + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, + mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight()); + // Enqueue the buffer coordinates to clear the corresponding region later mLayers.push(new Rect(bounds)); }