summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt18
-rw-r--r--api/removed.txt4
-rw-r--r--api/system-current.txt18
-rw-r--r--api/system-removed.txt4
-rw-r--r--api/test-current.txt18
-rw-r--r--api/test-removed.txt4
-rw-r--r--core/java/android/app/ActivityManagerNative.java1
-rw-r--r--core/java/android/app/Notification.java24
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java20
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java367
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java21
-rw-r--r--core/java/android/webkit/WebViewFactory.java15
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessStats.java166
-rw-r--r--core/res/res/layout/work_widget_mask_view.xml3
-rw-r--r--core/res/res/values/dimens.xml2
-rw-r--r--core/res/res/values/strings.xml3
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--media/java/android/media/AudioManager.java21
-rw-r--r--media/java/android/media/IAudioService.aidl2
-rw-r--r--media/java/android/media/IRecordingConfigDispatcher.aidl2
-rw-r--r--media/java/android/media/MediaCodecInfo.java34
-rw-r--r--packages/PrintSpooler/res/layout/add_printer_list_header.xml3
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipUI.java2
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java12
-rw-r--r--services/core/java/com/android/server/AppOpsService.java15
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java271
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java30
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java2
-rw-r--r--services/core/java/com/android/server/audio/RecordingActivityMonitor.java15
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java1
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java4
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java23
-rw-r--r--services/net/java/android/net/dhcp/DhcpClient.java177
-rw-r--r--services/net/java/android/net/ip/IpManager.java36
-rw-r--r--services/tests/servicestests/src/android/net/apf/ApfTest.java38
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);