diff options
53 files changed, 1078 insertions, 488 deletions
diff --git a/api/current.txt b/api/current.txt index 56390c2331d7..7d40c5fa1083 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5048,7 +5048,7 @@ package android.app { public static class Notification.BigPictureStyle extends android.app.Notification.Style { ctor public Notification.BigPictureStyle(); - ctor public Notification.BigPictureStyle(android.app.Notification.Builder); + ctor public deprecated Notification.BigPictureStyle(android.app.Notification.Builder); method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap); method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon); method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap); @@ -5058,7 +5058,7 @@ package android.app { public static class Notification.BigTextStyle extends android.app.Notification.Style { ctor public Notification.BigTextStyle(); - ctor public Notification.BigTextStyle(android.app.Notification.Builder); + ctor public deprecated Notification.BigTextStyle(android.app.Notification.Builder); method public android.app.Notification.BigTextStyle bigText(java.lang.CharSequence); method public android.app.Notification.BigTextStyle setBigContentTitle(java.lang.CharSequence); method public android.app.Notification.BigTextStyle setSummaryText(java.lang.CharSequence); @@ -5159,12 +5159,10 @@ package android.app { public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style { ctor public Notification.DecoratedCustomViewStyle(); - ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder); } public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle { ctor public Notification.DecoratedMediaCustomViewStyle(); - ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder); } public static abstract interface Notification.Extender { @@ -5173,7 +5171,7 @@ package android.app { public static class Notification.InboxStyle extends android.app.Notification.Style { ctor public Notification.InboxStyle(); - ctor public Notification.InboxStyle(android.app.Notification.Builder); + ctor public deprecated Notification.InboxStyle(android.app.Notification.Builder); method public android.app.Notification.InboxStyle addLine(java.lang.CharSequence); method public android.app.Notification.InboxStyle setBigContentTitle(java.lang.CharSequence); method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence); @@ -5181,7 +5179,7 @@ package android.app { public static class Notification.MediaStyle extends android.app.Notification.Style { ctor public Notification.MediaStyle(); - ctor public Notification.MediaStyle(android.app.Notification.Builder); + ctor public deprecated Notification.MediaStyle(android.app.Notification.Builder); method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSession.Token); method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...); } @@ -19585,7 +19583,7 @@ package android.media { method public void adjustVolume(int, int); method public void dispatchMediaKeyEvent(android.view.KeyEvent); method public int generateAudioSessionId(); - method public android.media.AudioRecordingConfiguration[] getActiveRecordingConfigurations(); + method public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations(); method public android.media.AudioDeviceInfo[] getDevices(int); method public int getMode(); method public java.lang.String getParameters(java.lang.String); @@ -19731,7 +19729,7 @@ package android.media { public static abstract class AudioManager.AudioRecordingCallback { ctor public AudioManager.AudioRecordingCallback(); - method public void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]); + method public void onRecordingConfigChanged(java.util.List<android.media.AudioRecordingConfiguration>); } public static abstract interface AudioManager.OnAudioFocusChangeListener { @@ -34633,8 +34631,8 @@ package android.service.notification { method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap); method public final void requestInterruptionFilter(int); method public final void requestListenerHints(int); - method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException; - method public final void requestUnbind() throws android.os.RemoteException; + method public static void requestRebind(android.content.ComponentName); + method public final void requestUnbind(); method public final void setNotificationsShown(java.lang.String[]); field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4 field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1 diff --git a/api/removed.txt b/api/removed.txt index 42c64ea62cce..73a439c82d48 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -196,6 +196,10 @@ package android.media { ctor public AudioFormat(); } + public static abstract class AudioManager.AudioRecordingCallback { + method public deprecated void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]); + } + } package android.media.tv { diff --git a/api/system-current.txt b/api/system-current.txt index 27188f0d654d..b92058a01829 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5195,7 +5195,7 @@ package android.app { public static class Notification.BigPictureStyle extends android.app.Notification.Style { ctor public Notification.BigPictureStyle(); - ctor public Notification.BigPictureStyle(android.app.Notification.Builder); + ctor public deprecated Notification.BigPictureStyle(android.app.Notification.Builder); method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap); method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon); method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap); @@ -5205,7 +5205,7 @@ package android.app { public static class Notification.BigTextStyle extends android.app.Notification.Style { ctor public Notification.BigTextStyle(); - ctor public Notification.BigTextStyle(android.app.Notification.Builder); + ctor public deprecated Notification.BigTextStyle(android.app.Notification.Builder); method public android.app.Notification.BigTextStyle bigText(java.lang.CharSequence); method public android.app.Notification.BigTextStyle setBigContentTitle(java.lang.CharSequence); method public android.app.Notification.BigTextStyle setSummaryText(java.lang.CharSequence); @@ -5306,12 +5306,10 @@ package android.app { public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style { ctor public Notification.DecoratedCustomViewStyle(); - ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder); } public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle { ctor public Notification.DecoratedMediaCustomViewStyle(); - ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder); } public static abstract interface Notification.Extender { @@ -5320,7 +5318,7 @@ package android.app { public static class Notification.InboxStyle extends android.app.Notification.Style { ctor public Notification.InboxStyle(); - ctor public Notification.InboxStyle(android.app.Notification.Builder); + ctor public deprecated Notification.InboxStyle(android.app.Notification.Builder); method public android.app.Notification.InboxStyle addLine(java.lang.CharSequence); method public android.app.Notification.InboxStyle setBigContentTitle(java.lang.CharSequence); method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence); @@ -5328,7 +5326,7 @@ package android.app { public static class Notification.MediaStyle extends android.app.Notification.Style { ctor public Notification.MediaStyle(); - ctor public Notification.MediaStyle(android.app.Notification.Builder); + ctor public deprecated Notification.MediaStyle(android.app.Notification.Builder); method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSession.Token); method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...); } @@ -21092,7 +21090,7 @@ package android.media { method public void adjustVolume(int, int); method public void dispatchMediaKeyEvent(android.view.KeyEvent); method public int generateAudioSessionId(); - method public android.media.AudioRecordingConfiguration[] getActiveRecordingConfigurations(); + method public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations(); method public android.media.AudioDeviceInfo[] getDevices(int); method public int getMode(); method public java.lang.String getParameters(java.lang.String); @@ -21246,7 +21244,7 @@ package android.media { public static abstract class AudioManager.AudioRecordingCallback { ctor public AudioManager.AudioRecordingCallback(); - method public void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]); + method public void onRecordingConfigChanged(java.util.List<android.media.AudioRecordingConfiguration>); } public static abstract interface AudioManager.OnAudioFocusChangeListener { @@ -37359,8 +37357,8 @@ package android.service.notification { method public void registerAsSystemService(android.content.Context, android.content.ComponentName, int) throws android.os.RemoteException; method public final void requestInterruptionFilter(int); method public final void requestListenerHints(int); - method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException; - method public final void requestUnbind() throws android.os.RemoteException; + method public static void requestRebind(android.content.ComponentName); + method public final void requestUnbind(); method public final void setNotificationsShown(java.lang.String[]); method public final void setOnNotificationPostedTrim(int); method public void unregisterAsSystemService() throws android.os.RemoteException; diff --git a/api/system-removed.txt b/api/system-removed.txt index 4873605d4e1d..0a758f81655f 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -194,6 +194,10 @@ package android.media { ctor public AudioFormat(); } + public static abstract class AudioManager.AudioRecordingCallback { + method public deprecated void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]); + } + } package android.media.tv { diff --git a/api/test-current.txt b/api/test-current.txt index 15a2d304ea42..a51886a9cef6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5049,7 +5049,7 @@ package android.app { public static class Notification.BigPictureStyle extends android.app.Notification.Style { ctor public Notification.BigPictureStyle(); - ctor public Notification.BigPictureStyle(android.app.Notification.Builder); + ctor public deprecated Notification.BigPictureStyle(android.app.Notification.Builder); method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap); method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon); method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap); @@ -5059,7 +5059,7 @@ package android.app { public static class Notification.BigTextStyle extends android.app.Notification.Style { ctor public Notification.BigTextStyle(); - ctor public Notification.BigTextStyle(android.app.Notification.Builder); + ctor public deprecated Notification.BigTextStyle(android.app.Notification.Builder); method public android.app.Notification.BigTextStyle bigText(java.lang.CharSequence); method public android.app.Notification.BigTextStyle setBigContentTitle(java.lang.CharSequence); method public android.app.Notification.BigTextStyle setSummaryText(java.lang.CharSequence); @@ -5160,12 +5160,10 @@ package android.app { public static class Notification.DecoratedCustomViewStyle extends android.app.Notification.Style { ctor public Notification.DecoratedCustomViewStyle(); - ctor public Notification.DecoratedCustomViewStyle(android.app.Notification.Builder); } public static class Notification.DecoratedMediaCustomViewStyle extends android.app.Notification.MediaStyle { ctor public Notification.DecoratedMediaCustomViewStyle(); - ctor public Notification.DecoratedMediaCustomViewStyle(android.app.Notification.Builder); } public static abstract interface Notification.Extender { @@ -5174,7 +5172,7 @@ package android.app { public static class Notification.InboxStyle extends android.app.Notification.Style { ctor public Notification.InboxStyle(); - ctor public Notification.InboxStyle(android.app.Notification.Builder); + ctor public deprecated Notification.InboxStyle(android.app.Notification.Builder); method public android.app.Notification.InboxStyle addLine(java.lang.CharSequence); method public android.app.Notification.InboxStyle setBigContentTitle(java.lang.CharSequence); method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence); @@ -5182,7 +5180,7 @@ package android.app { public static class Notification.MediaStyle extends android.app.Notification.Style { ctor public Notification.MediaStyle(); - ctor public Notification.MediaStyle(android.app.Notification.Builder); + ctor public deprecated Notification.MediaStyle(android.app.Notification.Builder); method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSession.Token); method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...); } @@ -19654,7 +19652,7 @@ package android.media { method public void adjustVolume(int, int); method public void dispatchMediaKeyEvent(android.view.KeyEvent); method public int generateAudioSessionId(); - method public android.media.AudioRecordingConfiguration[] getActiveRecordingConfigurations(); + method public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations(); method public android.media.AudioDeviceInfo[] getDevices(int); method public int getMode(); method public java.lang.String getParameters(java.lang.String); @@ -19800,7 +19798,7 @@ package android.media { public static abstract class AudioManager.AudioRecordingCallback { ctor public AudioManager.AudioRecordingCallback(); - method public void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]); + method public void onRecordingConfigChanged(java.util.List<android.media.AudioRecordingConfiguration>); } public static abstract interface AudioManager.OnAudioFocusChangeListener { @@ -34710,8 +34708,8 @@ package android.service.notification { method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap); method public final void requestInterruptionFilter(int); method public final void requestListenerHints(int); - method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException; - method public final void requestUnbind() throws android.os.RemoteException; + method public static void requestRebind(android.content.ComponentName); + method public final void requestUnbind(); method public final void setNotificationsShown(java.lang.String[]); field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4 field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1 diff --git a/api/test-removed.txt b/api/test-removed.txt index 42c64ea62cce..73a439c82d48 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -196,6 +196,10 @@ package android.media { ctor public AudioFormat(); } + public static abstract class AudioManager.AudioRecordingCallback { + method public deprecated void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]); + } + } package android.media.tv { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 6ba6b0f07bc5..cd9a05b7bf0f 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -7015,6 +7015,7 @@ class ActivityManagerProxy implements IActivityManager data.writeInt(0); } mRemote.transact(SEND_INTENT_SENDER_TRANSACTION, data, reply, 0); + reply.readException(); final int res = reply.readInt(); data.recycle(); reply.recycle(); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 50780584ed37..4a8203bf1193 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4087,6 +4087,10 @@ public class Notification implements Parcelable public BigPictureStyle() { } + /** + * @deprecated use {@code BigPictureStyle()}. + */ + @Deprecated public BigPictureStyle(Builder builder) { setBuilder(builder); } @@ -4243,6 +4247,10 @@ public class Notification implements Parcelable public BigTextStyle() { } + /** + * @deprecated use {@code BigTextStyle()}. + */ + @Deprecated public BigTextStyle(Builder builder) { setBuilder(builder); } @@ -4785,6 +4793,10 @@ public class Notification implements Parcelable public InboxStyle() { } + /** + * @deprecated use {@code InboxStyle()}. + */ + @Deprecated public InboxStyle(Builder builder) { setBuilder(builder); } @@ -4957,6 +4969,10 @@ public class Notification implements Parcelable public MediaStyle() { } + /** + * @deprecated use {@code MediaStyle()}. + */ + @Deprecated public MediaStyle(Builder builder) { setBuilder(builder); } @@ -5164,10 +5180,6 @@ public class Notification implements Parcelable public DecoratedCustomViewStyle() { } - public DecoratedCustomViewStyle(Builder builder) { - setBuilder(builder); - } - /** * @hide */ @@ -5284,10 +5296,6 @@ public class Notification implements Parcelable public DecoratedMediaCustomViewStyle() { } - public DecoratedMediaCustomViewStyle(Builder builder) { - setBuilder(builder); - } - /** * @hide */ diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index cd8f1260b590..bb5f7a1d606e 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -19,6 +19,7 @@ package android.appwidget; import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; @@ -150,7 +151,7 @@ public class AppWidgetHostView extends FrameLayout { // We add padding to the AppWidgetHostView if necessary Rect padding = getDefaultPaddingForWidget(mContext, info.provider, null); setPadding(padding.left, padding.top, padding.right, padding.bottom); - setContentDescription(info.label); + updateContentDescription(info); } } @@ -459,6 +460,7 @@ public class AppWidgetHostView extends FrameLayout { } applyContent(content, recycled, exception); + updateContentDescription(mInfo); } private void applyContent(View content, boolean recycled, Exception exception) { @@ -493,6 +495,22 @@ public class AppWidgetHostView extends FrameLayout { } } + private void updateContentDescription(AppWidgetProviderInfo info) { + if (info != null) { + LauncherApps launcherApps = getContext().getSystemService(LauncherApps.class); + ApplicationInfo appInfo = launcherApps.getApplicationInfo( + info.provider.getPackageName(), 0, info.getProfile()); + if (appInfo != null && + (appInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0) { + setContentDescription( + Resources.getSystem().getString( + com.android.internal.R.string.suspended_widget_accessibility, info.label)); + } else { + setContentDescription(info.label); + } + } + } + private void inflateAsync(RemoteViews remoteViews) { // Prepare a local reference to the remote Context so we're ready to // inflate any requested LayoutParams. diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index d036d96257ef..4c8657810c71 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -57,6 +57,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} @@ -483,6 +484,8 @@ public final class BluetoothAdapter { private final IBluetoothManager mManagerService; private IBluetooth mService; + private final ReentrantReadWriteLock mServiceLock = + new ReentrantReadWriteLock(); private final Object mLock = new Object(); private final Map<LeScanCallback, ScanCallback> mLeScanClients; @@ -517,8 +520,13 @@ public final class BluetoothAdapter { throw new IllegalArgumentException("bluetooth manager service is null"); } try { + mServiceLock.writeLock().lock(); mService = managerService.registerAdapter(mManagerCallback); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.writeLock().unlock(); + } mManagerService = managerService; mLeScanClients = new HashMap<LeScanCallback, ScanCallback>(); mToken = new Binder(); @@ -605,10 +613,14 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) public boolean isEnabled() { try { - synchronized(mManagerCallback) { - if (mService != null) return mService.isEnabled(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.isEnabled(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + return false; } @@ -639,12 +651,12 @@ public final class BluetoothAdapter { * or OFF if BT is in BLE_ON state */ private void notifyUserAction(boolean enable) { - if (mService == null) { - Log.e(TAG, "mService is null"); - return; - } - try { + mServiceLock.readLock().lock(); + if (mService == null) { + Log.e(TAG, "mService is null"); + return; + } if (enable) { mService.onLeServiceUp(); //NA:TODO implementation pending } else { @@ -652,6 +664,8 @@ public final class BluetoothAdapter { } } catch (RemoteException e) { Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); } } @@ -783,26 +797,28 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState public int getState() { + int state = BluetoothAdapter.STATE_OFF; + try { - synchronized(mManagerCallback) { - if (mService != null) - { - int state= mService.getState(); - if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state); - //consider all internal states as OFF - if (state == BluetoothAdapter.STATE_BLE_ON - || state == BluetoothAdapter.STATE_BLE_TURNING_ON - || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) { - if (VDBG) Log.d(TAG, "Consider internal state as OFF"); - state = BluetoothAdapter.STATE_OFF; - } - return state; - } - // TODO(BT) there might be a small gap during STATE_TURNING_ON that - // mService is null, handle that case + mServiceLock.readLock().lock(); + if (mService != null) { + state = mService.getState(); } - } catch (RemoteException e) {Log.e(TAG, "", e);} - return STATE_OFF; + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + + // Consider all internal states as OFF + if (state == BluetoothAdapter.STATE_BLE_ON + || state == BluetoothAdapter.STATE_BLE_TURNING_ON + || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) { + if (VDBG) Log.d(TAG, "Consider internal state as OFF"); + state = BluetoothAdapter.STATE_OFF; + } + if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state); + return state; } /** @@ -825,19 +841,21 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState public int getLeState() { + int state = BluetoothAdapter.STATE_OFF; + try { - synchronized(mManagerCallback) { - if (mService != null) - { - int state= mService.getState(); - if (VDBG) Log.d(TAG,"getLeState() returning " + state); - return state; - } + mServiceLock.readLock().lock(); + if (mService != null) { + state = mService.getState(); } } catch (RemoteException e) { Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); } - return BluetoothAdapter.STATE_OFF; + + if (VDBG) Log.d(TAG,"getLeState() returning " + state); + return state; } boolean getLeAccess() { @@ -879,16 +897,21 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean enable() { - int state = STATE_OFF; - if (isEnabled() == true){ + int state = BluetoothAdapter.STATE_OFF; + if (isEnabled() == true) { if (DBG) Log.d(TAG, "enable(): BT is already enabled..!"); return true; } - //Use service interface to get the exact state - if (mService != null) { - try { - state = mService.getState(); - } catch (RemoteException e) {Log.e(TAG, "", e);} + // Use service interface to get the exact state + try { + mServiceLock.readLock().lock(); + if (mService != null) { + state = mService.getState(); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); } if (state == BluetoothAdapter.STATE_BLE_ON) { @@ -993,10 +1016,13 @@ public final class BluetoothAdapter { */ public boolean configHciSnoopLog(boolean enable) { try { - synchronized(mManagerCallback) { - if (mService != null) return mService.configHciSnoopLog(enable); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.configHciSnoopLog(enable); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1012,12 +1038,16 @@ public final class BluetoothAdapter { */ public boolean factoryReset() { try { + mServiceLock.readLock().lock(); if (mService != null) { return mService.factoryReset(); - } else { - SystemProperties.set("persist.bluetooth.factoryreset", "true"); } - } catch (RemoteException e) {Log.e(TAG, "", e);} + SystemProperties.set("persist.bluetooth.factoryreset", "true"); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1032,10 +1062,13 @@ public final class BluetoothAdapter { public ParcelUuid[] getUuids() { if (getState() != STATE_ON) return null; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.getUuids(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.getUuids(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return null; } @@ -1058,10 +1091,13 @@ public final class BluetoothAdapter { public boolean setName(String name) { if (getState() != STATE_ON) return false; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.setName(name); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.setName(name); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1086,10 +1122,13 @@ public final class BluetoothAdapter { public int getScanMode() { if (getState() != STATE_ON) return SCAN_MODE_NONE; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.getScanMode(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.getScanMode(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return SCAN_MODE_NONE; } @@ -1124,10 +1163,13 @@ public final class BluetoothAdapter { public boolean setScanMode(@ScanMode int mode, int duration) { if (getState() != STATE_ON) return false; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.setScanMode(mode, duration); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.setScanMode(mode, duration); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1142,10 +1184,13 @@ public final class BluetoothAdapter { public int getDiscoverableTimeout() { if (getState() != STATE_ON) return -1; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.getDiscoverableTimeout(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.getDiscoverableTimeout(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return -1; } @@ -1153,10 +1198,13 @@ public final class BluetoothAdapter { public void setDiscoverableTimeout(int timeout) { if (getState() != STATE_ON) return; try { - synchronized(mManagerCallback) { - if (mService != null) mService.setDiscoverableTimeout(timeout); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) mService.setDiscoverableTimeout(timeout); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } } /** @@ -1193,10 +1241,13 @@ public final class BluetoothAdapter { public boolean startDiscovery() { if (getState() != STATE_ON) return false; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.startDiscovery(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.startDiscovery(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1221,10 +1272,13 @@ public final class BluetoothAdapter { public boolean cancelDiscovery() { if (getState() != STATE_ON) return false; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.cancelDiscovery(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.cancelDiscovery(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1251,10 +1305,13 @@ public final class BluetoothAdapter { public boolean isDiscovering() { if (getState() != STATE_ON) return false; try { - synchronized(mManagerCallback) { - if (mService != null ) return mService.isDiscovering(); - } - } catch (RemoteException e) {Log.e(TAG, "", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.isDiscovering(); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return false; } @@ -1266,9 +1323,12 @@ public final class BluetoothAdapter { public boolean isMultipleAdvertisementSupported() { if (getState() != STATE_ON) return false; try { - return mService.isMultiAdvertisementSupported(); + mServiceLock.readLock().lock(); + if (mService != null) return mService.isMultiAdvertisementSupported(); } catch (RemoteException e) { Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e); + } finally { + mServiceLock.readLock().unlock(); } return false; } @@ -1301,9 +1361,12 @@ public final class BluetoothAdapter { public boolean isPeripheralModeSupported() { if (getState() != STATE_ON) return false; try { - return mService.isPeripheralModeSupported(); + mServiceLock.readLock().lock(); + if (mService != null) return mService.isPeripheralModeSupported(); } catch (RemoteException e) { Log.e(TAG, "failed to get peripheral mode capability: ", e); + } finally { + mServiceLock.readLock().unlock(); } return false; } @@ -1316,9 +1379,12 @@ public final class BluetoothAdapter { public boolean isOffloadedFilteringSupported() { if (!getLeAccess()) return false; try { - return mService.isOffloadedFilteringSupported(); + mServiceLock.readLock().lock(); + if (mService != null) return mService.isOffloadedFilteringSupported(); } catch (RemoteException e) { Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e); + } finally { + mServiceLock.readLock().unlock(); } return false; } @@ -1331,9 +1397,12 @@ public final class BluetoothAdapter { public boolean isOffloadedScanBatchingSupported() { if (!getLeAccess()) return false; try { - return mService.isOffloadedScanBatchingSupported(); + mServiceLock.readLock().lock(); + if (mService != null) return mService.isOffloadedScanBatchingSupported(); } catch (RemoteException e) { Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e); + } finally { + mServiceLock.readLock().unlock(); } return false; } @@ -1399,15 +1468,15 @@ public final class BluetoothAdapter { */ public void requestControllerActivityEnergyInfo(ResultReceiver result) { try { - synchronized(mManagerCallback) { - if (mService != null) { - mService.requestActivityInfo(result); - result = null; - } + mServiceLock.readLock().lock(); + if (mService != null) { + mService.requestActivityInfo(result); + result = null; } } catch (RemoteException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); } finally { + mServiceLock.readLock().unlock(); if (result != null) { // Only send an immediate result if we failed. result.send(0, null); @@ -1432,11 +1501,14 @@ public final class BluetoothAdapter { return toDeviceSet(new BluetoothDevice[0]); } try { - synchronized(mManagerCallback) { - if (mService != null) return toDeviceSet(mService.getBondedDevices()); - } + mServiceLock.readLock().lock(); + if (mService != null) return toDeviceSet(mService.getBondedDevices()); return toDeviceSet(new BluetoothDevice[0]); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } return null; } @@ -1456,10 +1528,13 @@ public final class BluetoothAdapter { public int getConnectionState() { if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.getAdapterConnectionState(); - } - } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);} + mServiceLock.readLock().lock(); + if (mService != null) return mService.getAdapterConnectionState(); + } catch (RemoteException e) { + Log.e(TAG, "getConnectionState:", e); + } finally { + mServiceLock.readLock().unlock(); + } return BluetoothAdapter.STATE_DISCONNECTED; } @@ -1482,11 +1557,12 @@ public final class BluetoothAdapter { public int getProfileConnectionState(int profile) { if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED; try { - synchronized(mManagerCallback) { - if (mService != null) return mService.getProfileConnectionState(profile); - } + mServiceLock.readLock().lock(); + if (mService != null) return mService.getProfileConnectionState(profile); } catch (RemoteException e) { Log.e(TAG, "getProfileConnectionState:", e); + } finally { + mServiceLock.readLock().unlock(); } return BluetoothProfile.STATE_DISCONNECTED; } @@ -1790,7 +1866,9 @@ public final class BluetoothAdapter { byte[] hash; byte[] randomizer; - byte[] ret = mService.readOutOfBandData(); + byte[] ret = null; + mServiceLock.readLock().lock(); + if (mService != null) mService.readOutOfBandData(); if (ret == null || ret.length != 32) return null; @@ -1803,7 +1881,12 @@ public final class BluetoothAdapter { } return new Pair<byte[], byte[]>(hash, randomizer); - } catch (RemoteException e) {Log.e(TAG, "", e);}*/ + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + */ return null; } @@ -1939,17 +2022,21 @@ public final class BluetoothAdapter { new IBluetoothManagerCallback.Stub() { public void onBluetoothServiceUp(IBluetooth bluetoothService) { if (VDBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); - synchronized (mManagerCallback) { - mService = bluetoothService; - synchronized (mProxyServiceStateCallbacks) { - for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ - try { - if (cb != null) { - cb.onBluetoothServiceUp(bluetoothService); - } else { - Log.d(TAG, "onBluetoothServiceUp: cb is null!!!"); - } - } catch (Exception e) { Log.e(TAG,"",e);} + + mServiceLock.writeLock().lock(); + mService = bluetoothService; + mServiceLock.writeLock().unlock(); + + synchronized (mProxyServiceStateCallbacks) { + for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ) { + try { + if (cb != null) { + cb.onBluetoothServiceUp(bluetoothService); + } else { + Log.d(TAG, "onBluetoothServiceUp: cb is null!!!"); + } + } catch (Exception e) { + Log.e(TAG,"",e); } } } @@ -1957,20 +2044,24 @@ public final class BluetoothAdapter { public void onBluetoothServiceDown() { if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); - synchronized (mManagerCallback) { - mService = null; - if (mLeScanClients != null) mLeScanClients.clear(); - if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); - if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); - synchronized (mProxyServiceStateCallbacks) { - for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ - try { - if (cb != null) { - cb.onBluetoothServiceDown(); - } else { - Log.d(TAG, "onBluetoothServiceDown: cb is null!!!"); - } - } catch (Exception e) { Log.e(TAG,"",e);} + + mServiceLock.writeLock().lock(); + mService = null; + if (mLeScanClients != null) mLeScanClients.clear(); + if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); + if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); + mServiceLock.writeLock().unlock(); + + synchronized (mProxyServiceStateCallbacks) { + for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ + try { + if (cb != null) { + cb.onBluetoothServiceDown(); + } else { + Log.d(TAG, "onBluetoothServiceDown: cb is null!!!"); + } + } catch (Exception e) { + Log.e(TAG,"",e); } } } @@ -2033,11 +2124,17 @@ public final class BluetoothAdapter { //TODO(BT) /* try { - return mService.changeApplicationBluetoothState(on, new + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.changeApplicationBluetoothState(on, new StateChangeCallbackWrapper(callback), new Binder()); + } } catch (RemoteException e) { Log.e(TAG, "changeBluetoothState", e); - }*/ + } finally { + mServiceLock.readLock().unlock(); + } + */ return false; } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 25fe4ffaa471..1557a2718b55 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -790,11 +790,14 @@ public abstract class NotificationListenerService extends Service { * <p>This method will fail for listeners that have * not been granted the permission by the user. */ - public static void requestRebind(ComponentName componentName) - throws RemoteException { + public static void requestRebind(ComponentName componentName) { INotificationManager noMan = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - noMan.requestBindListener(componentName); + try { + noMan.requestBindListener(componentName); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } } /** @@ -807,12 +810,16 @@ public abstract class NotificationListenerService extends Service { * <p>The service should wait for the {@link #onListenerConnected()} event * before performing this operation. I know it's tempting, but you must wait. */ - public final void requestUnbind() throws RemoteException { + public final void requestUnbind() { if (mWrapper != null) { INotificationManager noMan = getNotificationInterface(); - noMan.requestUnbindListener(mWrapper); - // Disable future messages. - isConnected = false; + try { + noMan.requestUnbindListener(mWrapper); + // Disable future messages. + isConnected = false; + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } } } diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 5db0f1659871..2d1e0bd30590 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -142,13 +142,17 @@ public final class WebViewFactory { public static int loadWebViewNativeLibraryFromPackage(String packageName, ClassLoader clazzLoader) { int ret = waitForProviderAndSetPackageInfo(); - if (ret != LIBLOAD_SUCCESS) { + if (ret != LIBLOAD_SUCCESS && ret != LIBLOAD_FAILED_WAITING_FOR_RELRO) { return ret; } if (!sPackageInfo.packageName.equals(packageName)) return LIBLOAD_WRONG_PACKAGE_NAME; - return loadNativeLibrary(clazzLoader); + int loadNativeRet = loadNativeLibrary(clazzLoader); + // If we failed waiting for relro we want to return that fact even if we successfully load + // the relro file. + if (loadNativeRet == LIBLOAD_SUCCESS) return ret; + return loadNativeRet; } static WebViewFactoryProvider getProvider() { @@ -240,7 +244,8 @@ public final class WebViewFactory { } finally { Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); } - if (response.status != LIBLOAD_SUCCESS) { + if (response.status != LIBLOAD_SUCCESS + && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) { throw new MissingWebViewPackageException("Failed to load WebView provider: " + getWebViewPreparationErrorReason(response.status)); } @@ -599,8 +604,10 @@ public final class WebViewFactory { try { response = getUpdateService().waitForAndGetProvider(); - if (response.status == WebViewFactory.LIBLOAD_SUCCESS) + if (response.status == LIBLOAD_SUCCESS + || response.status == LIBLOAD_FAILED_WAITING_FOR_RELRO) { sPackageInfo = response.packageInfo; + } } catch (RemoteException e) { Log.e(LOGTAG, "error waiting for relro creation", e); return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN; diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java index fb2337e447e4..35b53c2298bb 100644 --- a/core/java/com/android/internal/app/procstats/ProcessStats.java +++ b/core/java/com/android/internal/app/procstats/ProcessStats.java @@ -43,6 +43,8 @@ import com.android.internal.app.procstats.DumpUtils.*; import dalvik.system.VMRuntime; import libcore.util.EmptyArray; +import java.io.BufferedReader; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; @@ -51,6 +53,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Objects; +import java.util.regex.Pattern; +import java.util.regex.Matcher; public final class ProcessStats implements Parcelable { public static final String TAG = "ProcessStats"; @@ -151,7 +155,7 @@ public final class ProcessStats implements Parcelable { }; // Current version of the parcel format. - private static final int PARCEL_VERSION = 20; + private static final int PARCEL_VERSION = 21; // In-memory Parcel magic number, used to detect attempts to unmarshall bad data private static final int MAGIC = 0x50535454; @@ -188,6 +192,12 @@ public final class ProcessStats implements Parcelable { // For reading parcels. ArrayList<String> mIndexToCommonString; + private static final Pattern sPageTypeRegex = Pattern.compile( + "^Node\\s+(\\d+),.*. type\\s+(\\w+)\\s+([\\s\\d]+?)\\s*$"); + private final ArrayList<Integer> mPageTypeZones = new ArrayList<Integer>(); + private final ArrayList<String> mPageTypeLabels = new ArrayList<String>(); + private final ArrayList<int[]> mPageTypeSizes = new ArrayList<int[]>(); + public ProcessStats(boolean running) { mRunning = running; reset(); @@ -493,6 +503,7 @@ public final class ProcessStats implements Parcelable { mReadError = null; mFlags = 0; evaluateSystemProperties(true); + updateFragmentation(); } public boolean evaluateSystemProperties(boolean update) { @@ -515,6 +526,101 @@ public final class ProcessStats implements Parcelable { static final int[] BAD_TABLE = new int[0]; + + /** + * Load the system's memory fragmentation info. + */ + public void updateFragmentation() { + // Parse /proc/pagetypeinfo and store the values. + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader("/proc/pagetypeinfo")); + final Matcher matcher = sPageTypeRegex.matcher(""); + mPageTypeZones.clear(); + mPageTypeLabels.clear(); + mPageTypeSizes.clear(); + while (true) { + final String line = reader.readLine(); + if (line == null) { + break; + } + matcher.reset(line); + if (matcher.matches()) { + final Integer zone = Integer.valueOf(matcher.group(1), 10); + if (zone == null) { + continue; + } + mPageTypeZones.add(zone); + mPageTypeLabels.add(matcher.group(2)); + mPageTypeSizes.add(splitAndParseNumbers(matcher.group(3))); + } + } + } catch (IOException ex) { + mPageTypeZones.clear(); + mPageTypeLabels.clear(); + mPageTypeSizes.clear(); + return; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException allHopeIsLost) { + } + } + } + } + + /** + * Split the string of digits separaed by spaces. There must be no + * leading or trailing spaces. The format is ensured by the regex + * above. + */ + private static int[] splitAndParseNumbers(String s) { + // These are always positive and the numbers can't be so big that we'll overflow + // so just do the parsing inline. + boolean digit = false; + int count = 0; + final int N = s.length(); + // Count the numbers + for (int i=0; i<N; i++) { + final char c = s.charAt(i); + if (c >= '0' && c <= '9') { + if (!digit) { + digit = true; + count++; + } + } else { + digit = false; + } + } + // Parse the numbers + final int[] result = new int[count]; + int p = 0; + int val = 0; + for (int i=0; i<N; i++) { + final char c = s.charAt(i); + if (c >= '0' && c <= '9') { + if (!digit) { + digit = true; + val = c - '0'; + } else { + val *= 10; + val += c - '0'; + } + } else { + if (digit) { + digit = false; + result[p++] = val; + } + } + } + if (count > 0) { + result[count-1] = val; + } + return result; + } + + private void writeCompactedLongArray(Parcel out, long[] array, int num) { for (int i=0; i<num; i++) { long val = array[i]; @@ -717,6 +823,15 @@ public final class ProcessStats implements Parcelable { } } + // Fragmentation info (/proc/pagetypeinfo) + final int NPAGETYPES = mPageTypeLabels.size(); + out.writeInt(NPAGETYPES); + for (int i=0; i<NPAGETYPES; i++) { + out.writeInt(mPageTypeZones.get(i)); + out.writeString(mPageTypeLabels.get(i)); + out.writeIntArray(mPageTypeSizes.get(i)); + } + mCommonStringToIndex = null; } @@ -981,6 +1096,20 @@ public final class ProcessStats implements Parcelable { } } + // Fragmentation info + final int NPAGETYPES = in.readInt(); + mPageTypeZones.clear(); + mPageTypeZones.ensureCapacity(NPAGETYPES); + mPageTypeLabels.clear(); + mPageTypeLabels.ensureCapacity(NPAGETYPES); + mPageTypeSizes.clear(); + mPageTypeSizes.ensureCapacity(NPAGETYPES); + for (int i=0; i<NPAGETYPES; i++) { + mPageTypeZones.add(in.readInt()); + mPageTypeLabels.add(in.readString()); + mPageTypeSizes.add(in.createIntArray()); + } + mIndexToCommonString = null; if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!"); @@ -1271,6 +1400,8 @@ public final class ProcessStats implements Parcelable { */ pw.print(" mRunning="); pw.println(mRunning); } + + dumpFragmentationLocked(pw); } public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) { @@ -1282,6 +1413,21 @@ public final class ProcessStats implements Parcelable { dumpTotalsLocked(pw, now); } + private void dumpFragmentationLocked(PrintWriter pw) { + pw.println(); + pw.println("Available pages by page size:"); + final int NPAGETYPES = mPageTypeLabels.size(); + for (int i=0; i<NPAGETYPES; i++) { + pw.format("Zone %3d %14s ", mPageTypeZones.get(i), mPageTypeLabels.get(i)); + final int[] sizes = mPageTypeSizes.get(i); + final int N = sizes == null ? 0 : sizes.length; + for (int j=0; j<N; j++) { + pw.format("%6d", sizes[j]); + } + pw.println(); + } + } + long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight, long totalTime, long curTotalMem, int samples) { if (memWeight != 0) { @@ -1540,6 +1686,24 @@ public final class ProcessStats implements Parcelable { pw.print(totalMem.processStateSamples[i]); } pw.println(); + + final int NPAGETYPES = mPageTypeLabels.size(); + for (int i=0; i<NPAGETYPES; i++) { + pw.print("availablepages,"); + pw.print(mPageTypeLabels.get(i)); + pw.print(","); + pw.print(mPageTypeZones.get(i)); + pw.print(","); + final int[] sizes = mPageTypeSizes.get(i); + final int N = sizes == null ? 0 : sizes.length; + for (int j=0; j<N; j++) { + if (j != 0) { + pw.print(","); + } + pw.print(sizes[j]); + } + pw.println(); + } } diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml index 3c4770552383..39e1bbb467b4 100644 --- a/core/res/res/layout/work_widget_mask_view.xml +++ b/core/res/res/layout/work_widget_mask_view.xml @@ -19,7 +19,8 @@ Copyright (C) 2015 The Android Open Source Project android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F3374248" - android:clickable="true" > + android:importantForAccessibility="noHideDescendants" + android:clickable="true"> <ImageView android:id="@+id/work_widget_app_icon" android:layout_width="wrap_content" diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 3ba6ce1be034..573b066f0dfb 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -24,6 +24,8 @@ <dimen name="thumbnail_height">192dp</dimen> <!-- The amount to scale a fullscreen screenshot thumbnail. --> <item name="thumbnail_fullscreen_scale" type="fraction">60%</item> + <!-- The width used to calculate scale for full screen thumbnail on TV --> + <integer name="thumbnail_width_tv">240</integer> <!-- The standard size (both width and height) of an application icon that will be displayed in the app launcher and elsewhere. --> <dimen name="app_icon_size">48dip</dimen> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index dffab2c9c59b..45ee778f3a9e 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4317,4 +4317,7 @@ <!-- Description of notification shown when device has been forced to safe mode after a security compromise. --> <string name="audit_safemode_notification_details">Touch to learn more.</string> + <!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] --> + <string name="suspended_widget_accessibility">Suspended <xliff:g id="label" example="Calendar">%1$s</xliff:g></string> + </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 3f1de6d646f6..e99d57f0fa76 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1496,6 +1496,7 @@ <java-symbol type="integer" name="config_dockedStackDividerSnapMode" /> <java-symbol type="fraction" name="docked_stack_divider_fixed_ratio" /> <java-symbol type="fraction" name="thumbnail_fullscreen_scale" /> + <java-symbol type="integer" name="thumbnail_width_tv" /> <java-symbol type="dimen" name="resize_shadow_size" /> <java-symbol type="color" name="resize_shadow_start_color" /> <java-symbol type="color" name="resize_shadow_end_color" /> @@ -2594,4 +2595,5 @@ <!-- Pinner Service --> <java-symbol type="array" name="config_defaultPinnerServiceFiles" /> + <java-symbol type="string" name="suspended_widget_accessibility" /> </resources> diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 23ae691ddca9..7178313485b8 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2747,11 +2747,18 @@ public class AudioManager { */ public static abstract class AudioRecordingCallback { /** + * This method is deprecated, override {@link #onRecordingConfigChanged(List)} instead. + * @param configs + * @removed + */ + @Deprecated + public void onRecordingConfigChanged(AudioRecordingConfiguration[] configs) {} + /** * Called whenever the device recording configuration has changed. - * @param configs array containing the results of + * @param configs list containing the results of * {@link AudioManager#getActiveRecordingConfigurations()}. */ - public void onRecordingConfigChanged(AudioRecordingConfiguration[] configs) {} + public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {} } private static class AudioRecordingCallbackInfo { @@ -2765,10 +2772,10 @@ public class AudioManager { private final static class RecordConfigChangeCallbackData { final AudioRecordingCallback mCb; - final AudioRecordingConfiguration[] mConfigs; + final List<AudioRecordingConfiguration> mConfigs; RecordConfigChangeCallbackData(AudioRecordingCallback cb, - AudioRecordingConfiguration[] configs) { + List<AudioRecordingConfiguration> configs) { mCb = cb; mConfigs = configs; } @@ -2848,10 +2855,10 @@ public class AudioManager { /** * Returns the current active audio recording configurations of the device. - * @return a non-null array of recording configurations. An array of length 0 indicates there is + * @return a non-null list of recording configurations. An empty list indicates there is * no recording active when queried. */ - public @NonNull AudioRecordingConfiguration[] getActiveRecordingConfigurations() { + public @NonNull List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { final IAudioService service = getService(); try { return service.getActiveRecordingConfigurations(); @@ -2909,7 +2916,7 @@ public class AudioManager { private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() { - public void dispatchRecordingConfigChange(AudioRecordingConfiguration[] configs) { + public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) { synchronized(mRecordCallbackLock) { if (mRecordCallbackList != null) { for (int i=0 ; i < mRecordCallbackList.size() ; i++) { diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 97f670b17114..c7931fcd297b 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -164,5 +164,5 @@ interface IAudioService { oneway void unregisterRecordingCallback(in IRecordingConfigDispatcher rcdb); - AudioRecordingConfiguration[] getActiveRecordingConfigurations(); + List<AudioRecordingConfiguration> getActiveRecordingConfigurations(); } diff --git a/media/java/android/media/IRecordingConfigDispatcher.aidl b/media/java/android/media/IRecordingConfigDispatcher.aidl index e8032831af88..f4e98b20af7c 100644 --- a/media/java/android/media/IRecordingConfigDispatcher.aidl +++ b/media/java/android/media/IRecordingConfigDispatcher.aidl @@ -25,6 +25,6 @@ import android.media.AudioRecordingConfiguration; */ oneway interface IRecordingConfigDispatcher { - void dispatchRecordingConfigChange(in AudioRecordingConfiguration[] configs); + void dispatchRecordingConfigChange(in List<AudioRecordingConfiguration> configs); } diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index b9ed269fe9dc..08c184270d5b 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -1918,13 +1918,15 @@ public final class MediaCodecInfo { case CodecProfileLevel.MPEG2ProfileMain: switch (profileLevel.level) { case CodecProfileLevel.MPEG2LevelLL: - FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 4000; break; + FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 4000; break; case CodecProfileLevel.MPEG2LevelML: - FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 15000; break; + FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 15000; break; case CodecProfileLevel.MPEG2LevelH14: - FR = 60; W = 90; H = 68; MBPS = 367200; FS = 6120; BR = 60000; break; + FR = 60; W = 90; H = 68; MBPS = 183600; FS = 6120; BR = 60000; break; case CodecProfileLevel.MPEG2LevelHL: - FR = 60; W = 120; H = 68; MBPS = 489600; FS = 8160; BR = 80000; break; + FR = 60; W = 120; H = 68; MBPS = 244800; FS = 8160; BR = 80000; break; + case CodecProfileLevel.MPEG2LevelHP: + FR = 60; W = 120; H = 68; MBPS = 489600; FS = 8160; BR = 80000; break; default: Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile + "/" @@ -1982,15 +1984,12 @@ public final class MediaCodecInfo { FR = 30; W = 22; H = 18; MBPS = 5940; FS = 396; BR = 128; break; case CodecProfileLevel.MPEG4Level3: FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break; - case CodecProfileLevel.MPEG4Level4: case CodecProfileLevel.MPEG4Level4a: + FR = 30; W = 40; H = 30; MBPS = 36000; FS = 1200; BR = 4000; break; case CodecProfileLevel.MPEG4Level5: - // While MPEG4 SP does not have level 4 or 5, some vendors - // report it. Use the same limits as level 3, but mark as - // unsupported. - FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; - supported = false; - break; + FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 8000; break; + case CodecProfileLevel.MPEG4Level6: + FR = 30; W = 80; H = 45; MBPS = 108000; FS = 3600; BR = 12000; break; default: Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile + "/" @@ -2007,12 +2006,9 @@ public final class MediaCodecInfo { FR = 30; W = 22; H = 18; MBPS = 5940; FS = 396; BR = 384; break; case CodecProfileLevel.MPEG4Level3: FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 768; break; - // case CodecProfileLevel.MPEG4Level3b: - // TODO: MPEG4 level 3b is not defined in OMX - // MBPS = 11880; FS = 396; BR = 1500; break; + case CodecProfileLevel.MPEG4Level3b: + FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 1500; break; case CodecProfileLevel.MPEG4Level4: - case CodecProfileLevel.MPEG4Level4a: - // TODO: MPEG4 level 4a is not defined in spec FR = 30; W = 44; H = 36; MBPS = 23760; FS = 792; BR = 3000; break; case CodecProfileLevel.MPEG4Level5: FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break; @@ -2640,9 +2636,13 @@ public final class MediaCodecInfo { public static final int MPEG4Level1 = 0x04; public static final int MPEG4Level2 = 0x08; public static final int MPEG4Level3 = 0x10; + /** @hide */ + public static final int MPEG4Level3b = 0x18; public static final int MPEG4Level4 = 0x20; public static final int MPEG4Level4a = 0x40; public static final int MPEG4Level5 = 0x80; + /** @hide */ + public static final int MPEG4Level6 = 0x100; // from OMX_VIDEO_MPEG2PROFILETYPE public static final int MPEG2ProfileSimple = 0x00; @@ -2657,6 +2657,8 @@ public final class MediaCodecInfo { public static final int MPEG2LevelML = 0x01; public static final int MPEG2LevelH14 = 0x02; public static final int MPEG2LevelHL = 0x03; + /** @hide */ + public static final int MPEG2LevelHP = 0x04; // from OMX_AUDIO_AACPROFILETYPE public static final int AACObjectMain = 1; diff --git a/packages/PrintSpooler/res/layout/add_printer_list_header.xml b/packages/PrintSpooler/res/layout/add_printer_list_header.xml index ff342cbbb0fa..9eee0c46c124 100644 --- a/packages/PrintSpooler/res/layout/add_printer_list_header.xml +++ b/packages/PrintSpooler/res/layout/add_printer_list_header.xml @@ -16,7 +16,8 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" - android:layout_height="?android:attr/listPreferredItemHeightSmall" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeightSmall" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:orientation="horizontal" diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 7a8c6f29f20e..89c46d74e710 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -809,7 +809,8 @@ <!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] --> <string name="home">Settings Home</string> - <string-array name="battery_labels" translatable="false"> + <!-- Labels on the side of batter graph in Quick Settings and Settings [CHAR LIMIT=8] --> + <string-array name="battery_labels"> <item>0%</item> <item>50%</item> <item>100%</item> diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java index 4341ab9cd869..ecb64f626650 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java @@ -54,9 +54,9 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; import com.android.systemui.recents.tv.animations.HomeRecentsEnterExitAnimationHolder; import com.android.systemui.recents.tv.views.RecentsTvView; +import com.android.systemui.recents.tv.views.TaskCardView; import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView; import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter; -import com.android.systemui.recents.views.AnimationProps; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.tv.pip.PipManager; import com.android.systemui.tv.pip.PipRecentsOverlayManager; @@ -184,12 +184,14 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener { if (!plan.hasTasks()) { loader.preloadTasks(plan, -1, !launchState.launchedFromHome); } + + int numVisibleTasks = TaskCardView.getNumberOfVisibleTasks(getApplicationContext()); mLaunchedFromHome = launchState.launchedFromHome; TaskStack stack = plan.getTaskStack(); RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options(); loadOpts.runningTaskId = launchState.launchedToTaskId; - loadOpts.numVisibleTasks = stack.getStackTaskCount(); - loadOpts.numVisibleTaskThumbnails = stack.getStackTaskCount(); + loadOpts.numVisibleTasks = numVisibleTasks; + loadOpts.numVisibleTaskThumbnails = numVisibleTasks; loader.loadTasks(this, plan, loadOpts); diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java index 85fb50ebbb78..2eede999f478 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java @@ -288,7 +288,6 @@ public class TaskCardView extends LinearLayout { lp.height = LayoutParams.MATCH_PARENT; screenshotView.setLayoutParams(lp); - screenshotView.setImageBitmap(screenshot); screenshotView.setClipToOutline(true); screenshotView.setOutlineProvider(new ViewOutlineProvider() { @Override @@ -296,6 +295,7 @@ public class TaskCardView extends LinearLayout { outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mCornerRadius); } }); + screenshotView.setImageBitmap(screenshot); } private void setAsBannerView(Drawable banner, ImageView bannerView) { @@ -304,7 +304,6 @@ public class TaskCardView extends LinearLayout { .getDimensionPixelSize(R.dimen.recents_tv_banner_width); lp.height = getResources() .getDimensionPixelSize(R.dimen.recents_tv_banner_height); - bannerView.setLayoutParams(lp); bannerView.setImageDrawable(banner); } @@ -327,4 +326,16 @@ public class TaskCardView extends LinearLayout { public View getDismissIconView() { return mDismissIconView; } + + public static int getNumberOfVisibleTasks(Context context) { + Resources res = context.getResources(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + Point size = new Point(); + display.getSize(size); + int screenWidth = size.x; + int cardWidth = res.getDimensionPixelSize(R.dimen.recents_tv_card_width); + int spacing = res.getDimensionPixelSize(R.dimen.recents_tv_gird_card_spacing); + return (int) (1.0 + Math.ceil(screenWidth / (cardWidth + spacing * 2.0))); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java index 0a6d1ed1a294..b6b86b409948 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java @@ -23,9 +23,11 @@ import android.view.View; import android.view.ViewGroup; import com.android.systemui.R; +import com.android.systemui.recents.Recents; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.LaunchTvTaskEvent; import com.android.systemui.recents.events.ui.DeleteTaskDataEvent; +import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.views.AnimationProps; @@ -122,7 +124,10 @@ public class TaskStackHorizontalViewAdapter extends @Override public void onBindViewHolder(ViewHolder holder, int position) { - holder.init(mTaskList.get(position)); + Task task = mTaskList.get(position); + // Retrives from caches, loading only if necessary + Recents.getTaskLoader().loadTaskData(task); + holder.init(task); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 64eaeec98948..f728aa438aa5 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -1065,9 +1065,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, mEntranceAnimationRunning = true; resizeStack(position, mSnapAlgorithm.getMiddleTarget().position, mSnapAlgorithm.getMiddleTarget()); - - // Vibrate after docking - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); } public final void onBusEvent(RecentsDrawnEvent drawnEvent) { @@ -1105,9 +1102,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, mExitStartPosition = getCurrentPosition(); stopDragging(mExitStartPosition, target, 336 /* duration */, 100 /* startDelay */, 0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN); - - // Vibrate after undocking - performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java index 182075f15186..0df12044c46e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java @@ -215,17 +215,23 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged public boolean isOnlyChildInSuppressedGroup(StatusBarNotification sbn) { return isGroupSuppressed(sbn.getGroupKey()) - && isOnlyChildInGroup(sbn); + && isOnlyChild(sbn); } - public boolean isOnlyChildInGroup(StatusBarNotification sbn) { + private boolean isOnlyChild(StatusBarNotification sbn) { return !sbn.getNotification().isGroupSummary() && getTotalNumberOfChildren(sbn) == 1; } + public boolean isOnlyChildInGroup(StatusBarNotification sbn) { + return isOnlyChild(sbn) && getLogicalGroupSummary(sbn) != null; + } + private int getTotalNumberOfChildren(StatusBarNotification sbn) { - return getNumberOfIsolatedChildren(sbn.getGroupKey()) - + mGroupMap.get(sbn.getGroupKey()).children.size(); + int isolatedChildren = getNumberOfIsolatedChildren(sbn.getGroupKey()); + NotificationGroup group = mGroupMap.get(sbn.getGroupKey()); + int realChildren = group != null ? group.children.size() : 0; + return isolatedChildren + realChildren; } private boolean isGroupSuppressed(String groupKey) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 9dbec6da2bc2..6a37099d0b7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -39,6 +39,7 @@ import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import android.widget.TextView; + import com.android.internal.logging.MetricsLogger; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.AutoReinflateContainer; @@ -2291,6 +2292,12 @@ public class NotificationPanelView extends PanelView implements setLaunchingAffordance(false); } + @Override + public void setAlpha(float alpha) { + super.setAlpha(alpha); + mNotificationStackScroller.setParentFadingOut(alpha != 1.0f); + } + /** * Set whether we are currently launching an affordance. This is currently only set when * launched via a camera gesture. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index e3ce1e27f3e6..073994f8a5ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -3865,6 +3865,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mScrimController.forceHideScrims(true /* hide */); updateMediaMetaData(false, true); mNotificationPanel.setAlpha(1); + mStackScroller.setParentFadingOut(true); mNotificationPanel.animate() .alpha(0) .setStartDelay(FADE_KEYGUARD_START_DELAY) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 493b23f7a258..29b4db174375 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -211,7 +211,7 @@ public class QSTileHost implements QSTile.Host, Tunable { public void animateToggleQSExpansion() { // TODO: Better path to animated panel expansion. - mHeader.performClick(); + mHeader.callOnClick(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index eae0b8e47614..9c4480e60efa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -322,6 +322,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, if (scrim instanceof ScrimView) { float alpha2 = getDozeAlpha(scrim); float alpha = 1 - (1 - alpha1) * (1 - alpha2); + alpha = Math.max(0, Math.min(1.0f, alpha)); ((ScrimView) scrim).setScrimColor(Color.argb((int) (alpha * 255), 0, 0, 0)); } else { scrim.setAlpha(alpha1); @@ -468,6 +469,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, PropertyValuesHolder[] values = previousAnimator.getValues(); float relativeDiff = alpha - previousEndValue; float newStartValue = previousStartValue + relativeDiff; + newStartValue = Math.max(0, Math.min(1.0f, newStartValue)); values[0].setFloatValues(newStartValue, alpha); scrim.setTag(TAG_START_ALPHA, newStartValue); scrim.setTag(TAG_END_ALPHA, alpha); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java index ddded49d2e36..21d03fd8443a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java @@ -53,7 +53,7 @@ public class BrightnessMirrorController { public void showMirror() { mBrightnessMirror.setVisibility(View.VISIBLE); - mStackScroller.setFadedOut(true); + mStackScroller.setFadingOut(true); mScrimBehind.animateViewAlpha(0.0f, TRANSITION_DURATION_OUT, Interpolators.ALPHA_OUT); outAnimation(mNotificationPanel.animate()) .withLayer(); @@ -67,7 +67,7 @@ public class BrightnessMirrorController { @Override public void run() { mBrightnessMirror.setVisibility(View.INVISIBLE); - mStackScroller.setFadedOut(false); + mStackScroller.setFadingOut(false); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 70d4aec0f8df..f7a2d2b173c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -333,7 +333,8 @@ public class NotificationStackScrollLayout extends ViewGroup private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); private boolean mPulsing; private boolean mDrawBackgroundAsSrc; - private boolean mFadedOut; + private boolean mFadingOut; + private boolean mParentFadingOut; private boolean mGroupExpandedForMeasure; private View mForcedScroll; private float mBackgroundFadeAmount = 1.0f; @@ -470,7 +471,8 @@ public class NotificationStackScrollLayout extends ViewGroup } private void updateSrcDrawing() { - mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && !mFadedOut ? mSrcMode : null); + mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && (!mFadingOut && !mParentFadingOut) + ? mSrcMode : null); invalidate(); } @@ -1871,7 +1873,7 @@ public class NotificationStackScrollLayout extends ViewGroup } private void applyCurrentBackgroundBounds() { - if (!mFadedOut) { + if (!mFadingOut) { mScrimController.setExcludedBackgroundArea(mCurrentBounds); } invalidate(); @@ -3610,22 +3612,33 @@ public class NotificationStackScrollLayout extends ViewGroup updateNotificationAnimationStates(); } - public void setFadedOut(boolean fadingOut) { - if (fadingOut != mFadedOut) { - mFadedOut = fadingOut; - if (fadingOut) { - mScrimController.setExcludedBackgroundArea(null); - } else { - applyCurrentBackgroundBounds(); - } - updateSrcDrawing(); + public void setFadingOut(boolean fadingOut) { + if (fadingOut != mFadingOut) { + mFadingOut = fadingOut; + updateFadingState(); + } + } + + public void setParentFadingOut(boolean fadingOut) { + if (fadingOut != mParentFadingOut) { + mParentFadingOut = fadingOut; + updateFadingState(); } } + private void updateFadingState() { + if (mFadingOut || mParentFadingOut || mAmbientState.isDark()) { + mScrimController.setExcludedBackgroundArea(null); + } else { + applyCurrentBackgroundBounds(); + } + updateSrcDrawing(); + } + @Override public void setAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) { super.setAlpha(alpha); - setFadedOut(alpha != 1.0f); + setFadingOut(alpha != 1.0f); } /** diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java index 74f0cd3ac0a2..476598d3afc7 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java @@ -227,6 +227,13 @@ public class PipManager { } /** + * Updates the PIP per configuration changed. + */ + void onConfigurationChanged() { + mPipRecentsOverlayManager.onConfigurationChanged(mContext); + } + + /** * Shows the picture-in-picture menu if an activity is in picture-in-picture mode. */ public void showTvPictureInPictureMenu() { diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java index fe5d8bce1741..6e4a5938d7b5 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java +++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java @@ -42,9 +42,9 @@ public class PipRecentsOverlayManager { private final PipManager mPipManager = PipManager.getInstance(); private final WindowManager mWindowManager; - private final View mOverlayView; - private final PipRecentsControlsView mPipControlsView; - private final View mRecentsView; + private View mOverlayView; + private PipRecentsControlsView mPipControlsView; + private View mRecentsView; private final LayoutParams mPipRecentsControlsViewLayoutParams; private final LayoutParams mPipRecentsControlsViewFocusedLayoutParams; @@ -73,6 +73,21 @@ public class PipRecentsOverlayManager { PipRecentsOverlayManager(Context context) { mWindowManager = (WindowManager) context.getSystemService(WindowManager.class); + mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, + LayoutParams.TYPE_SYSTEM_DIALOG, + LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE, + PixelFormat.TRANSLUCENT); + mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, + LayoutParams.TYPE_SYSTEM_DIALOG, + 0, + PixelFormat.TRANSLUCENT); + + initViews(context); + } + + private void initViews(Context context) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mOverlayView = inflater.inflate(R.layout.tv_pip_recents_overlay, null); @@ -86,17 +101,6 @@ public class PipRecentsOverlayManager { } } }); - - mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, - LayoutParams.TYPE_SYSTEM_DIALOG, - LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE, - PixelFormat.TRANSLUCENT); - mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, - LayoutParams.TYPE_SYSTEM_DIALOG, - 0, - PixelFormat.TRANSLUCENT); } /** @@ -210,4 +214,14 @@ public class PipRecentsOverlayManager { boolean isRecentsShown() { return mIsRecentsShown; } + + /** + * Updates the PIP per configuration changed. + */ + void onConfigurationChanged(Context context) { + if (mIsRecentsShown) { + Log.w(TAG, "Configuration is changed while Recents is shown"); + } + initViews(context); + } } diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java index 182b9b0deb81..b3e9f43f5542 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java +++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java @@ -48,6 +48,6 @@ public class PipUI extends SystemUI { if (!mSupportPip) { return; } - // TODO: handle configuration change. + PipManager.getInstance().onConfigurationChanged(); } } diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 1edc9b18c697..8ad6e6afcce5 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -125,6 +125,8 @@ class AlarmManagerService extends SystemService { long mNativeData; private long mNextWakeup; private long mNextNonWakeup; + private long mLastWakeupSet; + private long mLastWakeup; int mBroadcastRefCount = 0; PowerManager.WakeLock mWakeLock; boolean mLastWakeLockUnimportantForLogging; @@ -1400,6 +1402,9 @@ class AlarmManagerService extends SystemService { pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC))); pw.print(" Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw); pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC))); + pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw); + pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw); + pw.println(); pw.print(" Num time change events: "); pw.println(mNumTimeChanged); pw.println(" mDeviceIdleUserWhitelist=" + Arrays.toString(mDeviceIdleUserWhitelist)); @@ -1838,6 +1843,7 @@ class AlarmManagerService extends SystemService { final Batch firstBatch = mAlarmBatches.get(0); if (firstWakeup != null && mNextWakeup != firstWakeup.start) { mNextWakeup = firstWakeup.start; + mLastWakeupSet = SystemClock.elapsedRealtime(); setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start); } if (firstBatch != firstWakeup) { @@ -2436,6 +2442,7 @@ class AlarmManagerService extends SystemService { while (true) { int result = waitForAlarm(mNativeData); + mLastWakeup = SystemClock.elapsedRealtime(); triggerList.clear(); @@ -2536,6 +2543,11 @@ class AlarmManagerService extends SystemService { deliverAlarmsLocked(triggerList, nowELAPSED); } } + + } else { + // Just in case -- even though no wakeup flag was set, make sure + // we have updated the kernel to the next alarm time. + rescheduleKernelAlarmsLocked(); } } } diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index ca3c39f51e62..dab7d706a6d2 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -1316,13 +1316,14 @@ public class AppOpsService extends IAppOpsService.Stub { // For each client, check that the given op is not restricted, or that the given // package is exempt from the restriction. ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i); - if (restrictionState.hasRestriction(code, packageName, userHandle) - && AppOpsManager.opAllowSystemBypassRestriction(code)) { - // If we are the system, bypass user restrictions for certain codes - synchronized (this) { - Ops ops = getOpsRawLocked(uid, packageName, true); - if ((ops != null) && ops.isPrivileged) { - return false; + if (restrictionState.hasRestriction(code, packageName, userHandle)) { + if (AppOpsManager.opAllowSystemBypassRestriction(code)) { + // If we are the system, bypass user restrictions for certain codes + synchronized (this) { + Ops ops = getOpsRawLocked(uid, packageName, true); + if ((ops != null) && ops.isPrivileged) { + return false; + } } } return true; diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 5e8687a904c1..f30a126ba60e 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -52,6 +52,7 @@ import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -126,6 +127,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private IBinder mBluetoothBinder; private IBluetooth mBluetooth; private IBluetoothGatt mBluetoothGatt; + private final ReentrantReadWriteLock mBluetoothLock = + new ReentrantReadWriteLock(); private boolean mBinding; private boolean mUnbinding; // used inside handler thread @@ -190,12 +193,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } int st = BluetoothAdapter.STATE_OFF; - if (mBluetooth != null) { - try { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { st = mBluetooth.getState(); - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call getState", e); } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call getState", e); + } finally { + mBluetoothLock.readLock().unlock(); } Slog.d(TAG, "state" + st); @@ -208,12 +214,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (st == BluetoothAdapter.STATE_BLE_ON) { //if state is BLE_ON make sure you trigger disableBLE part try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { mBluetooth.onBrEdrDown(); mEnableExternal = false; } - } catch(RemoteException e) { + } catch (RemoteException e) { Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().lock(); } } else if (st == BluetoothAdapter.STATE_ON){ // disable without persisting the setting @@ -366,9 +375,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); msg.obj = callback; mHandler.sendMessage(msg); - synchronized(mConnection) { - return mBluetooth; - } + + return mBluetooth; } public void unregisterAdapter(IBluetoothManagerCallback callback) { @@ -406,12 +414,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } - synchronized(mConnection) { - try { - return (mBluetooth != null && mBluetooth.isEnabled()); - } catch (RemoteException e) { - Slog.e(TAG, "isEnabled()", e); - } + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.isEnabled(); + } catch (RemoteException e) { + Slog.e(TAG, "isEnabled()", e); + } finally { + mBluetoothLock.readLock().unlock(); } return false; } @@ -424,11 +433,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBleAppCount == 0) { if (DBG) Slog.d(TAG, "Disabling LE only mode after application crash"); try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { mBluetooth.onBrEdrDown(); } - } catch(RemoteException e) { + } catch (RemoteException e) { Slog.e(TAG,"Unable to call onBrEdrDown", e); + } finally { + mBluetoothLock.readLock().unlock(); } } } @@ -456,9 +468,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { disableBleScanMode(); clearBleApps(); try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) mBluetooth.onBrEdrDown(); } catch (RemoteException e) { Slog.e(TAG, "error when disabling bluetooth", e); + } finally { + mBluetoothLock.readLock().unlock(); } } } @@ -472,12 +487,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Disable ble scan only mode. private void disableBleScanMode() { try { + mBluetoothLock.writeLock().lock(); if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { if (DBG) Slog.d(TAG, "Reseting the mEnable flag for clean disable"); mEnable = false; } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.writeLock().unlock(); } } @@ -536,7 +554,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private void onBluetoothGattServiceUp() { if (DBG) Slog.d(TAG,"BluetoothGatt Service is Up"); - try{ + try { + mBluetoothLock.readLock().lock(); if (isBleAppPresent() == false && mBluetooth != null && mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { mBluetooth.onLeServiceUp(); @@ -546,8 +565,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); Binder.restoreCallingIdentity(callingIdentity); } - } catch(RemoteException e) { - Slog.e(TAG,"Unable to call onServiceUp", e); + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call onServiceUp", e); + } finally { + mBluetoothLock.readLock().unlock(); } } @@ -558,22 +579,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void sendBrEdrDownCallback() { if (DBG) Slog.d(TAG,"Calling sendBrEdrDownCallback callbacks"); - if(mBluetooth == null) { + if (mBluetooth == null) { Slog.w(TAG, "Bluetooth handle is null"); return; } if (isBleAppPresent() == false) { try { - mBluetooth.onBrEdrDown(); - } catch(RemoteException e) { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) mBluetooth.onBrEdrDown(); + } catch (RemoteException e) { Slog.e(TAG, "Call to onBrEdrDown() failed.", e); + } finally { + mBluetoothLock.readLock().unlock(); } } else { // Need to stay at BLE ON. Disconnect all Gatt connections - try{ + try { mBluetoothGatt.unregAll(); - } catch(RemoteException e) { + } catch (RemoteException e) { Slog.e(TAG, "Unable to disconnect all apps.", e); } } @@ -673,7 +697,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { " mBinding = " + mBinding); } - synchronized (mConnection) { + try { + mBluetoothLock.writeLock().lock(); if (mUnbinding) return; mUnbinding = true; if (mBluetooth != null) { @@ -695,6 +720,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mUnbinding=false; } mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } } @@ -1010,14 +1037,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return BluetoothAdapter.DEFAULT_MAC_ADDRESS; } - synchronized(mConnection) { - if (mBluetooth != null) { - try { - return mBluetooth.getAddress(); - } catch (RemoteException e) { - Slog.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e); - } - } + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.getAddress(); + } catch (RemoteException e) { + Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e); + } finally { + mBluetoothLock.readLock().unlock(); } // mAddress is accessed from outside. @@ -1036,15 +1062,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return null; } - synchronized(mConnection) { - if (mBluetooth != null) { - try { - return mBluetooth.getName(); - } catch (RemoteException e) { - Slog.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e); - } - } + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) return mBluetooth.getName(); + } catch (RemoteException e) { + Slog.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); + } finally { + mBluetoothLock.readLock().unlock(); } + // mName is accessed from outside. // It alright without a lock. Here, bluetooth is off, no other thread is // changing mName @@ -1101,7 +1127,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { switch (msg.what) { case MESSAGE_GET_NAME_AND_ADDRESS: if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { if (DBG) Slog.d(TAG, "Binding to service to get name and address"); mGetNameAddressOnly = true; @@ -1127,6 +1154,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mGetNameAddressOnly = false; } + } finally { + mBluetoothLock.writeLock().unlock(); } break; @@ -1209,7 +1238,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); IBinder service = (IBinder) msg.obj; - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); onBluetoothGattServiceUp(); @@ -1264,6 +1294,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException e) { Slog.e(TAG,"Unable to call enable()",e); } + } finally { + mBluetoothLock.writeLock().unlock(); } if (!mEnable) { @@ -1275,9 +1307,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } case MESSAGE_TIMEOUT_BIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_BIND"); - synchronized(mConnection) { - mBinding = false; - } + mBluetoothLock.writeLock().lock(); + mBinding = false; + mBluetoothLock.writeLock().unlock(); + break; } case MESSAGE_BLUETOOTH_STATE_CHANGE: @@ -1312,7 +1345,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTH) { // if service is unbinded already, do nothing and return if (mBluetooth == null) break; @@ -1324,6 +1358,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "Bad msg.arg1: " + msg.arg1); break; } + } finally { + mBluetoothLock.writeLock().unlock(); } if (mEnable) { @@ -1369,9 +1405,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_TIMEOUT_UNBIND: { Slog.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); - synchronized(mConnection) { - mUnbinding = false; - } + mBluetoothLock.writeLock().lock(); + mUnbinding = false; + mBluetoothLock.writeLock().unlock(); break; } @@ -1381,15 +1417,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /* disable and enable BT when detect a user switch */ if (mEnable && mBluetooth != null) { - synchronized (mConnection) { + try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { - //Unregister callback object - try { - mBluetooth.unregisterCallback(mBluetoothCallback); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to unregister",re); - } + mBluetooth.unregisterCallback(mBluetoothCallback); } + } catch (RemoteException re) { + Slog.e(TAG, "Unable to unregister", re); + } finally { + mBluetoothLock.readLock().unlock(); } if (mState == BluetoothAdapter.STATE_TURNING_OFF) { @@ -1420,14 +1456,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); sendBluetoothServiceDownCallback(); - synchronized (mConnection) { - if (mBluetooth != null) { - mBluetooth = null; - //Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; + + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); } + mBluetoothGatt = null; + mBluetoothLock.writeLock().unlock(); + SystemClock.sleep(100); mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); @@ -1450,14 +1488,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED"); mHandler.removeMessages(MESSAGE_USER_SWITCHED); - synchronized (mConnection) { - if (mEnable && !mBinding && (mBluetooth == null)) { - // We should be connected, but we gave up for some - // reason; maybe the Bluetooth service wasn't encryption - // aware, so try binding again. - if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); - handleEnable(mQuietEnable); - } + if (mEnable && !mBinding && (mBluetooth == null)) { + // We should be connected, but we gave up for some + // reason; maybe the Bluetooth service wasn't encryption + // aware, so try binding again. + if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock"); + handleEnable(mQuietEnable); } } } @@ -1467,7 +1503,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void handleEnable(boolean quietMode) { mQuietEnable = quietMode; - synchronized(mConnection) { + try { + mBluetoothLock.writeLock().lock(); if ((mBluetooth == null) && (!mBinding)) { //Start bind timeout and bind Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); @@ -1496,6 +1533,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG,"Unable to call enable()",e); } } + } finally { + mBluetoothLock.writeLock().unlock(); } } @@ -1510,18 +1549,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private void handleDisable() { - synchronized(mConnection) { + try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { if (DBG) Slog.d(TAG,"Sending off request."); - - try { - if(!mBluetooth.disable()) { - Slog.e(TAG,"IBluetooth.disable() returned false"); - } - } catch (RemoteException e) { - Slog.e(TAG,"Unable to call disable()",e); + if (!mBluetooth.disable()) { + Slog.e(TAG,"IBluetooth.disable() returned false"); } } + } catch (RemoteException e) { + Slog.e(TAG,"Unable to call disable()",e); + } finally { + mBluetoothLock.readLock().unlock(); } } @@ -1648,20 +1687,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean waitForOnOff(boolean on, boolean off) { int i = 0; while (i < 10) { - synchronized(mConnection) { - try { - if (mBluetooth == null) break; - if (on) { - if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; - } else if (off) { - if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; - } else { - if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; - } - } catch (RemoteException e) { - Slog.e(TAG, "getState()", e); - break; + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth == null) break; + if (on) { + if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; + } else if (off) { + if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; + } else { + if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; } + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + break; + } finally { + mBluetoothLock.readLock().unlock(); } if (on || off) { SystemClock.sleep(300); @@ -1684,34 +1724,36 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private boolean canUnbindBluetoothService() { - synchronized(mConnection) { + try { //Only unbind with mEnable flag not set //For race condition: disable and enable back-to-back //Avoid unbind right after enable due to callback from disable //Only unbind with Bluetooth at OFF state //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message - try { - if (mEnable || (mBluetooth == null)) return false; - if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; - return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); - } catch (RemoteException e) { - Slog.e(TAG, "getState()", e); - } + mBluetoothLock.readLock().lock(); + if (mEnable || (mBluetooth == null)) return false; + if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; + return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.readLock().unlock(); } return false; } private void recoverBluetoothServiceFromError() { Slog.e(TAG,"recoverBluetoothServiceFromError"); - synchronized (mConnection) { + try { + mBluetoothLock.readLock().lock(); if (mBluetooth != null) { //Unregister callback object - try { - mBluetooth.unregisterCallback(mBluetoothCallback); - } catch (RemoteException re) { - Slog.e(TAG, "Unable to unregister",re); - } + mBluetooth.unregisterCallback(mBluetoothCallback); } + } catch (RemoteException re) { + Slog.e(TAG, "Unable to unregister", re); + } finally { + mBluetoothLock.readLock().unlock(); } SystemClock.sleep(500); @@ -1722,14 +1764,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { waitForOnOff(false, true); sendBluetoothServiceDownCallback(); - synchronized (mConnection) { - if (mBluetooth != null) { - mBluetooth = null; - //Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; + + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); } + mBluetoothGatt = null; + mBluetoothLock.writeLock().unlock(); mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3194d891a0e0..7a5970347667 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -272,6 +272,7 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION; import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES; import static android.provider.Settings.Global.DEBUG_APP; import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; @@ -12822,12 +12823,18 @@ public final class ActivityManagerService extends ActivityManagerNative com.android.internal.R.dimen.thumbnail_width); mThumbnailHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.thumbnail_height); - mFullscreenThumbnailScale = res.getFraction( - com.android.internal.R.fraction.thumbnail_fullscreen_scale, 1, 1); mDefaultPinnedStackBounds = Rect.unflattenFromString(res.getString( com.android.internal.R.string.config_defaultPictureInPictureBounds)); mAppErrors.loadAppsNotReportingCrashesFromConfigLocked(res.getString( com.android.internal.R.string.config_appsNotReportingCrashes)); + if ((mConfiguration.uiMode & UI_MODE_TYPE_TELEVISION) == UI_MODE_TYPE_TELEVISION) { + mFullscreenThumbnailScale = (float) res + .getInteger(com.android.internal.R.integer.thumbnail_width_tv) / + (float) mConfiguration.screenWidthDp; + } else { + mFullscreenThumbnailScale = res.getFraction( + com.android.internal.R.fraction.thumbnail_fullscreen_scale, 1, 1); + } } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 3811b616a7f2..8b637e0ae44d 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1819,22 +1819,24 @@ final class ActivityStack { private boolean shouldBeVisible(ActivityRecord r, boolean behindTranslucentActivity, boolean stackVisibleBehind, ActivityRecord visibleBehind, boolean behindFullscreenActivity) { - // mLaunchingBehind: Activities launching behind are at the back of the task stack - // but must be drawn initially for the animation as though they were visible. - final boolean activityVisibleBehind = - (behindTranslucentActivity || stackVisibleBehind) && visibleBehind == r; if (!okToShowLocked(r)) { return false; } + // mLaunchingBehind: Activities launching behind are at the back of the task stack + // but must be drawn initially for the animation as though they were visible. + final boolean activityVisibleBehind = + (behindTranslucentActivity || stackVisibleBehind) && visibleBehind == r; + boolean isVisible = !behindFullscreenActivity || r.mLaunchTaskBehind || activityVisibleBehind; if (isVisible && r.isRecentsActivity()) { - // Recents activity can only be visible if the home stack isn't fullscreen or is the - // focused stack. - isVisible = !mFullscreen || mStackSupervisor.isFocusedStack(this); + // Recents activity can only be visible if the home stack is the focused stack or we are + // in split-screen mode. + isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null + || mStackSupervisor.isFocusedStack(this); } return isVisible; @@ -2256,6 +2258,20 @@ final class ActivityStack { } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; + } else if (mResumedActivity == next && next.state == ActivityState.RESUMED && + mStackSupervisor.allResumedActivitiesComplete()) { + // It is possible for the activity to be resumed when we paused back stacks above if the + // next activity doesn't have to wait for pause to complete. + // So, nothing else to-do except: + // Make sure we have executed any pending transitions, since there + // should be nothing left to do at this point. + mWindowManager.executeAppTransition(); + mNoAnimActivities.clear(); + ActivityOptions.abort(options); + if (DEBUG_STATES) Slog.d(TAG_STATES, + "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next); + if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); + return true; } // If the most recent activity was noHistory but was only stopped rather diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 0874fa7a58e5..7777ae23ff29 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -6342,7 +6342,7 @@ public class AudioService extends IAudioService.Stub { mRecordMonitor.unregisterRecordingCallback(rcdb); } - public AudioRecordingConfiguration[] getActiveRecordingConfigurations() { + public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { return mRecordMonitor.getActiveRecordingConfigurations(); } diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java index 7a085e143599..57d55de8d002 100644 --- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java +++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java @@ -29,6 +29,7 @@ import android.util.Log; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; /** * Class to receive and dispatch updates from AudioSystem about recording configurations. @@ -54,7 +55,7 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin if (MediaRecorder.isSystemOnlyAudioSource(source)) { return; } - final AudioRecordingConfiguration[] configs = + final List<AudioRecordingConfiguration> configs = updateSnapshot(event, session, source, recordingInfo); if (configs != null){ synchronized(mClients) { @@ -104,9 +105,9 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin } } - AudioRecordingConfiguration[] getActiveRecordingConfigurations() { + List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { synchronized(mRecordConfigs) { - return mRecordConfigs.values().toArray(new AudioRecordingConfiguration[0]); + return new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values()); } } @@ -118,13 +119,13 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin * @param recordingFormat see * {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} * for the definition of the contents of the array - * @return null if the list of active recording sessions has not been modified, an array + * @return null if the list of active recording sessions has not been modified, a list * with the current active configurations otherwise. */ - private AudioRecordingConfiguration[] updateSnapshot(int event, int session, int source, + private List<AudioRecordingConfiguration> updateSnapshot(int event, int session, int source, int[] recordingInfo) { final boolean configChanged; - final AudioRecordingConfiguration[] configs; + final ArrayList<AudioRecordingConfiguration> configs; synchronized(mRecordConfigs) { switch (event) { case AudioManager.RECORD_CONFIG_EVENT_STOP: @@ -171,7 +172,7 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin configChanged = false; } if (configChanged) { - configs = mRecordConfigs.values().toArray(new AudioRecordingConfiguration[0]); + configs = new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values()); } else { configs = null; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 04be34a81579..946e4f7e7067 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2252,6 +2252,7 @@ public class NotificationManagerService extends SystemService { .setGroup(newAutoBundleKey) .setFlag(Notification.FLAG_AUTOGROUP_SUMMARY, true) .setFlag(Notification.FLAG_GROUP_SUMMARY, true) + .setColor(adjustedSbn.getNotification().color) .build(); summaryNotification.extras.putAll(extras); Intent appIntent = getContext().getPackageManager() diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java index 91de797cf98c..ecab009ed12c 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java @@ -217,7 +217,7 @@ public class WebViewUpdateServiceImpl { mSystemInterface = systemInterface; } - private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000. + private static final int WAIT_TIMEOUT_MS = 1000; // KEY_DISPATCHING_TIMEOUT is 5000. // Keeps track of the number of running relro creations private int mNumRelroCreationsStarted = 0; @@ -487,6 +487,10 @@ public class WebViewUpdateServiceImpl { // Either the current relro creation isn't done yet, or the new relro creatioin // hasn't kicked off yet (the last relro creation used an out-of-date WebView). webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO; + Slog.e(TAG, "Timed out waiting for relro creation, relros started " + + mNumRelroCreationsStarted + + " relros finished " + mNumRelroCreationsFinished + + " package dirty? " + mWebViewPackageDirty); } } if (!webViewReady) Slog.w(TAG, "creating relro file timed out"); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 82cd0fa0c25d..aaed8ca9181d 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2359,7 +2359,13 @@ public class WindowManagerService extends IWindowManager.Stub // immediately after the enter animation is done. If the app is not yet drawn then // it will show up as a flicker. win.mRemoveOnExit = true; - win.mWindowRemovalAllowed = true; + // Request a focus update as this window's input channel is already gone. Otherwise + // we could have no focused window in input manager. + final boolean focusChanged = updateFocusedWindowLocked( + UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); + if (focusChanged) { + mInputMonitor.updateInputWindowsLw(false /*force*/); + } Binder.restoreCallingIdentity(origId); return; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index e5e74a663eb0..c15afb339646 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1265,8 +1265,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { * @return true if the window should be considered while evaluating allDrawn flags. */ boolean mightAffectAllDrawn(boolean visibleOnly) { - final boolean isViewVisible = (mViewVisibility == View.VISIBLE) - && (mAppToken == null || !mAppToken.clientHidden); + final boolean isViewVisible = (mAppToken == null || !mAppToken.clientHidden) + && (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed; return (isOnScreenIgnoringKeyguard() && (!visibleOnly || isViewVisible) || mWinAnimator.mAttrType == TYPE_BASE_APPLICATION) && !mAnimatingExit && !mDestroying; @@ -1822,7 +1822,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { /** @return true if this window desires key events. */ boolean canReceiveKeys() { return isVisibleOrAdding() - && (mViewVisibility == View.VISIBLE) + && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0) && (mAppToken == null || mAppToken.windowsAreFocusable()) && !isAdjustedForMinimizedDock(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index a5eb0b217d1f..c1913decde16 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -484,7 +484,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } }); } - if (Intent.ACTION_BOOT_COMPLETED.equals(action) + if (Intent.ACTION_USER_UNLOCKED.equals(action) + || Intent.ACTION_USER_STARTED.equals(action) || KeyChain.ACTION_STORAGE_CHANGED.equals(action)) { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL); new MonitoringCertNotificationTask().execute(userId); @@ -1582,6 +1583,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_REMOVED); filter.addAction(Intent.ACTION_USER_STARTED); + filter.addAction(Intent.ACTION_USER_UNLOCKED); filter.addAction(KeyChain.ACTION_STORAGE_CHANGED); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 7079b9eb5b89..538e8f879a3d 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -648,14 +648,31 @@ public class ApfFilter { // Here's a basic summary of what the IPv6 filter program does: // // if it's not ICMPv6: + // if it's multicast and we're dropping multicast: + // drop // pass // if it's ICMPv6 NA to ff02::1: // drop - // If not ICMPv6, pass gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET); - // TODO: Drop multicast if the multicast filter is enabled. - gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, gen.PASS_LABEL); + + // Drop multicast if the multicast filter is enabled. + if (mMulticastFilter) { + // Don't touch ICMPv6 multicast here, we deal with it in more detail later. + String skipIpv6MulticastFilterLabel = "skipIPv6MulticastFilter"; + gen.addJumpIfR0Equals(IPPROTO_ICMPV6, skipIpv6MulticastFilterLabel); + + // Drop all other packets sent to ff00::/8. + gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET); + gen.addJumpIfR0Equals(0xff, gen.DROP_LABEL); + // Not multicast and not ICMPv6. Pass. + gen.addJump(gen.PASS_LABEL); + gen.defineLabel(skipIpv6MulticastFilterLabel); + } else { + // If not ICMPv6, pass. + gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, gen.PASS_LABEL); + } + // Add unsolicited multicast neighbor announcements filter String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA"; // If not neighbor announcements, skip unsolicited multicast NA filter diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index 505d15a061e9..99b10c3da1c0 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -125,17 +125,18 @@ public class DhcpClient extends StateMachine { public static final int CMD_CONFIGURE_LINKADDRESS = PUBLIC_BASE + 8; public static final int EVENT_LINKADDRESS_CONFIGURED = PUBLIC_BASE + 9; - /* Message.arg1 arguments to CMD_POST_DHCP notification */ + /* Message.arg1 arguments to CMD_POST_DHCP_ACTION notification */ public static final int DHCP_SUCCESS = 1; public static final int DHCP_FAILURE = 2; - // Messages. + // Internal messages. private static final int PRIVATE_BASE = Protocol.BASE_DHCP + 100; private static final int CMD_KICK = PRIVATE_BASE + 1; private static final int CMD_RECEIVED_PACKET = PRIVATE_BASE + 2; private static final int CMD_TIMEOUT = PRIVATE_BASE + 3; private static final int CMD_RENEW_DHCP = PRIVATE_BASE + 4; - private static final int CMD_EXPIRE_DHCP = PRIVATE_BASE + 5; + private static final int CMD_REBIND_DHCP = PRIVATE_BASE + 5; + private static final int CMD_EXPIRE_DHCP = PRIVATE_BASE + 6; // For message logging. private static final Class[] sMessageClasses = { DhcpClient.class }; @@ -177,6 +178,7 @@ public class DhcpClient extends StateMachine { private final WakeupMessage mKickAlarm; private final WakeupMessage mTimeoutAlarm; private final WakeupMessage mRenewAlarm; + private final WakeupMessage mRebindAlarm; private final WakeupMessage mExpiryAlarm; private final String mIfaceName; @@ -241,8 +243,9 @@ public class DhcpClient extends StateMachine { mKickAlarm = makeWakeupMessage("KICK", CMD_KICK); // Used to time out PacketRetransmittingStates. mTimeoutAlarm = makeWakeupMessage("TIMEOUT", CMD_TIMEOUT); - // Used to schedule DHCP renews. + // Used to schedule DHCP reacquisition. mRenewAlarm = makeWakeupMessage("RENEW", CMD_RENEW_DHCP); + mRebindAlarm = makeWakeupMessage("REBIND", CMD_REBIND_DHCP); mExpiryAlarm = makeWakeupMessage("EXPIRY", CMD_EXPIRE_DHCP); } @@ -276,6 +279,10 @@ public class DhcpClient extends StateMachine { } private boolean initSockets() { + return initPacketSocket() && initUdpSocket(); + } + + private boolean initPacketSocket() { try { mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP); PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex()); @@ -285,6 +292,10 @@ public class DhcpClient extends StateMachine { Log.e(TAG, "Error creating packet socket", e); return false; } + return true; + } + + private boolean initUdpSocket() { try { mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1); @@ -363,16 +374,25 @@ public class DhcpClient extends StateMachine { return (short) ((SystemClock.elapsedRealtime() - mTransactionStartMillis) / 1000); } - private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) { + private boolean transmitPacket(ByteBuffer buf, String description, int encap, Inet4Address to) { try { - if (to.equals(INADDR_BROADCAST)) { + if (encap == DhcpPacket.ENCAP_L2) { if (DBG) Log.d(TAG, "Broadcasting " + description); Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr); + } else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) { + if (DBG) Log.d(TAG, "Broadcasting " + description); + // We only send L3-encapped broadcasts in DhcpRebindingState, + // where we have an IP address and an unconnected UDP socket. + // + // N.B.: We only need this codepath because DhcpRequestPacket + // hardcodes the source IP address to 0.0.0.0. We could reuse + // the packet socket if this ever changes. + Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER); } else { // It's safe to call getpeername here, because we only send unicast packets if we - // have an IP address, and we connect the UDP socket before - // ConfiguringInterfaceState#exit. - if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock)); + // have an IP address, and we connect the UDP socket in DhcpBoundState#enter. + if (DBG) Log.d(TAG, String.format("Unicasting %s to %s", + description, Os.getpeername(mUdpSock))); Os.write(mUdpSock, buf); } } catch(ErrnoException|IOException e) { @@ -386,14 +406,15 @@ public class DhcpClient extends StateMachine { ByteBuffer packet = DhcpPacket.buildDiscoverPacket( DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr, DO_UNICAST, REQUESTED_PARAMS); - return transmitPacket(packet, "DHCPDISCOVER", INADDR_BROADCAST); + return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST); } private boolean sendRequestPacket( Inet4Address clientAddress, Inet4Address requestedAddress, Inet4Address serverAddress, Inet4Address to) { // TODO: should we use the transaction ID from the server? - int encap = to.equals(INADDR_BROADCAST) ? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP; + final int encap = INADDR_ANY.equals(clientAddress) + ? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP; ByteBuffer packet = DhcpPacket.buildRequestPacket( encap, mTransactionId, getSecs(), clientAddress, @@ -403,7 +424,7 @@ public class DhcpClient extends StateMachine { String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() + " request=" + requestedAddress.getHostAddress() + " serverid=" + serverStr; - return transmitPacket(packet, description, to); + return transmitPacket(packet, description, encap, to); } private void scheduleLeaseTimers() { @@ -413,14 +434,21 @@ public class DhcpClient extends StateMachine { } final long now = SystemClock.elapsedRealtime(); - long renewTime = (now + mDhcpLeaseExpiry) / 2; - mRenewAlarm.schedule(renewTime); - long secondsHence = (renewTime - now) / 1000; - Log.d(TAG, "Scheduling renewal in " + secondsHence + "s"); - mExpiryAlarm.schedule(mDhcpLeaseExpiry); - secondsHence = (mDhcpLeaseExpiry - now) / 1000; - Log.d(TAG, "Scheduling expiry in " + secondsHence + "s"); + // TODO: consider getting the renew and rebind timers from T1 and T2. + // See also: + // https://tools.ietf.org/html/rfc2131#section-4.4.5 + // https://tools.ietf.org/html/rfc1533#section-9.9 + // https://tools.ietf.org/html/rfc1533#section-9.10 + final long remainingDelay = mDhcpLeaseExpiry - now; + final long renewDelay = remainingDelay / 2; + final long rebindDelay = remainingDelay * 7 / 8; + mRenewAlarm.schedule(now + renewDelay); + mRebindAlarm.schedule(now + rebindDelay); + mExpiryAlarm.schedule(now + remainingDelay); + Log.d(TAG, "Scheduling renewal in " + (renewDelay / 1000) + "s"); + Log.d(TAG, "Scheduling rebind in " + (rebindDelay / 1000) + "s"); + Log.d(TAG, "Scheduling expiry in " + (remainingDelay / 1000) + "s"); } private void notifySuccess() { @@ -719,7 +747,6 @@ public class DhcpClient extends StateMachine { class DhcpRequestingState extends PacketRetransmittingState { public DhcpRequestingState() { - super(); mTimeout = DHCP_TIMEOUT_MS / 2; } @@ -777,7 +804,11 @@ public class DhcpClient extends StateMachine { @Override public void exit() { + // Clear any extant alarms. + mRenewAlarm.cancel(); + mRebindAlarm.cancel(); mExpiryAlarm.cancel(); + clearDhcpState(); // Tell IpManager to clear the IPv4 address. There is no need to // wait for confirmation since any subsequent packets are sent from // INADDR_ANY anyway (DISCOVER, REQUEST). @@ -797,21 +828,7 @@ public class DhcpClient extends StateMachine { super.processMessage(message); switch (message.what) { case EVENT_LINKADDRESS_CONFIGURED: - if (mDhcpLease.serverAddress != null && - !connectUdpSock(mDhcpLease.serverAddress)) { - // There's likely no point in going into DhcpInitState here, we'll probably - // just repeat the transaction, get the same IP address as before, and fail. - // - // NOTE: It is observed that connectUdpSock() basically never fails, due to - // SO_BINDTODEVICE. Examining the local socket address shows it will happily - // return an IPv4 address from another interface, or even return "0.0.0.0". - // - // TODO: Consider deleting this check, following testing on several kernels. - notifyFailure(); - transitionTo(mStoppedState); - } else { - transitionTo(mDhcpBoundState); - } + transitionTo(mDhcpBoundState); return HANDLED; default: return NOT_HANDLED; @@ -823,8 +840,19 @@ public class DhcpClient extends StateMachine { @Override public void enter() { super.enter(); - // TODO: DhcpStateMachine only supported renewing at 50% of the lease time, - // and did not support rebinding. Now that the legacy DHCP client is gone, fix this. + if (mDhcpLease.serverAddress != null && !connectUdpSock(mDhcpLease.serverAddress)) { + // There's likely no point in going into DhcpInitState here, we'll probably + // just repeat the transaction, get the same IP address as before, and fail. + // + // NOTE: It is observed that connectUdpSock() basically never fails, due to + // SO_BINDTODEVICE. Examining the local socket address shows it will happily + // return an IPv4 address from another interface, or even return "0.0.0.0". + // + // TODO: Consider deleting this check, following testing on several kernels. + notifyFailure(); + transitionTo(mStoppedState); + } + scheduleLeaseTimers(); } @@ -843,18 +871,10 @@ public class DhcpClient extends StateMachine { return NOT_HANDLED; } } - - @Override - public void exit() { - mRenewAlarm.cancel(); - } } - class DhcpRenewingState extends PacketRetransmittingState { - public DhcpRenewingState() { - super(); - mTimeout = DHCP_TIMEOUT_MS; - } + abstract class DhcpReacquiringState extends PacketRetransmittingState { + protected String mLeaseMsg; @Override public void enter() { @@ -862,16 +882,14 @@ public class DhcpClient extends StateMachine { startNewTransaction(); } + abstract protected Inet4Address packetDestination(); + protected boolean sendPacket() { - // Not specifying a SERVER_IDENTIFIER option is a violation of RFC 2131, but... - // http://b/25343517 . Try to make things work anyway by using broadcast renews. - Inet4Address to = (mDhcpLease.serverAddress != null) ? - mDhcpLease.serverAddress : INADDR_BROADCAST; return sendRequestPacket( (Inet4Address) mDhcpLease.ipAddress.getAddress(), // ciaddr INADDR_ANY, // DHCP_REQUESTED_IP null, // DHCP_SERVER_IDENTIFIER - to); // packet destination address + packetDestination()); // packet destination address } protected void receivePacket(DhcpPacket packet) { @@ -890,7 +908,7 @@ public class DhcpClient extends StateMachine { // in IpManager and by any overridden relevant handlers of // the registered IpManager.Callback. IP address changes // are not supported here. - acceptDhcpResults(results, "Renewed"); + acceptDhcpResults(results, mLeaseMsg); transitionTo(mDhcpBoundState); } } else if (packet instanceof DhcpNakPacket) { @@ -901,8 +919,57 @@ public class DhcpClient extends StateMachine { } } - // Not implemented--yet. DhcpStateMachine did not implement it either. - class DhcpRebindingState extends LoggingState { + class DhcpRenewingState extends DhcpReacquiringState { + public DhcpRenewingState() { + mLeaseMsg = "Renewed"; + } + + @Override + public boolean processMessage(Message message) { + if (super.processMessage(message) == HANDLED) { + return HANDLED; + } + + switch (message.what) { + case CMD_REBIND_DHCP: + transitionTo(mDhcpRebindingState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + + @Override + protected Inet4Address packetDestination() { + // Not specifying a SERVER_IDENTIFIER option is a violation of RFC 2131, but... + // http://b/25343517 . Try to make things work anyway by using broadcast renews. + return (mDhcpLease.serverAddress != null) ? + mDhcpLease.serverAddress : INADDR_BROADCAST; + } + } + + class DhcpRebindingState extends DhcpReacquiringState { + public DhcpRebindingState() { + mLeaseMsg = "Rebound"; + } + + @Override + public void enter() { + super.enter(); + + // We need to broadcast and possibly reconnect the socket to a + // completely different server. + closeQuietly(mUdpSock); + if (!initUdpSocket()) { + Log.e(TAG, "Failed to recreate UDP socket"); + transitionTo(mDhcpInitState); + } + } + + @Override + protected Inet4Address packetDestination() { + return INADDR_BROADCAST; + } } class DhcpInitRebootState extends LoggingState { diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java index d8eab355c8cd..cece6c8c0cac 100644 --- a/services/net/java/android/net/ip/IpManager.java +++ b/services/net/java/android/net/ip/IpManager.java @@ -1027,6 +1027,8 @@ public class IpManager extends StateMachine { } class StartedState extends State { + private boolean mDhcpActionInFlight; + @Override public void enter() { mStartTimeMillis = SystemClock.elapsedRealtime(); @@ -1066,7 +1068,7 @@ public class IpManager extends StateMachine { @Override public void exit() { mProvisioningTimeoutAlarm.cancel(); - mDhcpActionTimeoutAlarm.cancel(); + stopDhcpAction(); if (mIpReachabilityMonitor != null) { mIpReachabilityMonitor.stop(); @@ -1086,16 +1088,22 @@ public class IpManager extends StateMachine { resetLinkProperties(); } - private void startDhcpAction() { - mCallback.onPreDhcpAction(); - final long alarmTime = SystemClock.elapsedRealtime() + - mConfiguration.mRequestedPreDhcpActionMs; - mDhcpActionTimeoutAlarm.schedule(alarmTime); + private void ensureDhcpAction() { + if (!mDhcpActionInFlight) { + mCallback.onPreDhcpAction(); + mDhcpActionInFlight = true; + final long alarmTime = SystemClock.elapsedRealtime() + + mConfiguration.mRequestedPreDhcpActionMs; + mDhcpActionTimeoutAlarm.schedule(alarmTime); + } } private void stopDhcpAction() { mDhcpActionTimeoutAlarm.cancel(); - mCallback.onPostDhcpAction(); + if (mDhcpActionInFlight) { + mCallback.onPostDhcpAction(); + mDhcpActionInFlight = false; + } } @Override @@ -1165,9 +1173,8 @@ public class IpManager extends StateMachine { break; case DhcpClient.CMD_PRE_DHCP_ACTION: - if (VDBG) { Log.d(mTag, "onPreDhcpAction()"); } if (mConfiguration.mRequestedPreDhcpActionMs > 0) { - startDhcpAction(); + ensureDhcpAction(); } else { sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE); } @@ -1193,18 +1200,18 @@ public class IpManager extends StateMachine { // This message is only received when: // // a) initial address acquisition succeeds, - // b) renew succeeds, - // c) renew fails, + // b) renew succeeds or is NAK'd, + // c) rebind succeeds or is NAK'd, or + // c) the lease expires, // // but never when initial address acquisition fails. The latter // condition is now governed by the provisioning timeout. - case DhcpClient.CMD_POST_DHCP_ACTION: { + case DhcpClient.CMD_POST_DHCP_ACTION: stopDhcpAction(); - final DhcpResults dhcpResults = (DhcpResults) msg.obj; switch (msg.arg1) { case DhcpClient.DHCP_SUCCESS: - handleIPv4Success(dhcpResults); + handleIPv4Success((DhcpResults) msg.obj); break; case DhcpClient.DHCP_FAILURE: handleIPv4Failure(); @@ -1213,7 +1220,6 @@ public class IpManager extends StateMachine { Log.e(mTag, "Unknown CMD_POST_DHCP_ACTION status:" + msg.arg1); } break; - } case DhcpClient.CMD_ON_QUIT: // DHCPv4 quit early for some reason. diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java index e9c5bdda419f..9e04d2301ad9 100644 --- a/services/tests/servicestests/src/android/net/apf/ApfTest.java +++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java @@ -720,36 +720,52 @@ public class ApfTest extends AndroidTestCase { } @LargeTest - public void testApfFilterIPv4Multicast() throws Exception { + public void testApfFilterMulticast() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */); byte[] program = ipManagerCallback.getApfProgram(); + // Construct IPv4 and IPv6 multicast packets. + ByteBuffer v4packet = ByteBuffer.wrap(new byte[100]); + v4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); + v4packet.position(IPV4_DEST_ADDR_OFFSET); + v4packet.put(new byte[]{(byte)224,0,0,1}); + + ByteBuffer v6packet = ByteBuffer.wrap(new byte[100]); + v6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); + v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP); + v6packet.position(IPV6_DEST_ADDR_OFFSET); + v6packet.put(new byte[]{(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}); + // Verify initially disabled multicast filter is off - ByteBuffer packet = ByteBuffer.wrap(new byte[100]); - packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); - packet.position(IPV4_DEST_ADDR_OFFSET); - packet.put(new byte[]{(byte)224,0,0,1}); - assertPass(program, packet.array(), 0); + assertPass(program, v4packet.array(), 0); + assertPass(program, v6packet.array(), 0); // Turn on multicast filter and verify it works ipManagerCallback.resetApfProgramWait(); apfFilter.setMulticastFilter(true); program = ipManagerCallback.getApfProgram(); - assertDrop(program, packet.array(), 0); + assertDrop(program, v4packet.array(), 0); + assertDrop(program, v6packet.array(), 0); // Turn off multicast filter and verify it's off ipManagerCallback.resetApfProgramWait(); apfFilter.setMulticastFilter(false); program = ipManagerCallback.getApfProgram(); - assertPass(program, packet.array(), 0); + assertPass(program, v4packet.array(), 0); + assertPass(program, v6packet.array(), 0); // Verify it can be initialized to on ipManagerCallback.resetApfProgramWait(); apfFilter.shutdown(); apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */); program = ipManagerCallback.getApfProgram(); - assertDrop(program, packet.array(), 0); + assertDrop(program, v4packet.array(), 0); + assertDrop(program, v6packet.array(), 0); + + // Verify that ICMPv6 multicast is not dropped. + v6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); + assertPass(program, v6packet.array(), 0); apfFilter.shutdown(); } @@ -839,7 +855,7 @@ public class ApfTest extends AndroidTestCase { @LargeTest public void testApfFilterRa() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); - TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, false /* multicastFilter */); + TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, true /* multicastFilter */); byte[] program = ipManagerCallback.getApfProgram(); // Verify RA is passed the first time @@ -848,6 +864,8 @@ public class ApfTest extends AndroidTestCase { basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT); basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)1000); + basePacket.position(IPV6_DEST_ADDR_OFFSET); + basePacket.put(IPV6_ALL_NODES_ADDRESS); assertPass(program, basePacket.array(), 0); testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000); |