Merge "Adding SBAS offset to Gps/Gnss SvStatus converter" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 8e3b8ff..70ea1c5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5048,7 +5048,7 @@
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 @@
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 @@
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 @@
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 @@
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...);
}
@@ -19778,6 +19776,7 @@
method public void stop() throws java.lang.IllegalStateException;
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+ field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
field public static final int READ_BLOCKING = 0; // 0x0
field public static final int READ_NON_BLOCKING = 1; // 0x1
@@ -19900,6 +19899,7 @@
method public int write(java.nio.ByteBuffer, int, int, long);
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+ field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
field public static final int MODE_STATIC = 0; // 0x0
field public static final int MODE_STREAM = 1; // 0x1
@@ -20557,6 +20557,7 @@
field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
+ field public static final int MPEG2LevelHP = 4; // 0x4
field public static final int MPEG2LevelLL = 0; // 0x0
field public static final int MPEG2LevelML = 1; // 0x1
field public static final int MPEG2Profile422 = 2; // 0x2
@@ -20570,9 +20571,11 @@
field public static final int MPEG4Level1 = 4; // 0x4
field public static final int MPEG4Level2 = 8; // 0x8
field public static final int MPEG4Level3 = 16; // 0x10
+ field public static final int MPEG4Level3b = 24; // 0x18
field public static final int MPEG4Level4 = 32; // 0x20
field public static final int MPEG4Level4a = 64; // 0x40
field public static final int MPEG4Level5 = 128; // 0x80
+ field public static final int MPEG4Level6 = 256; // 0x100
field public static final int MPEG4ProfileAdvancedCoding = 4096; // 0x1000
field public static final int MPEG4ProfileAdvancedCore = 8192; // 0x2000
field public static final int MPEG4ProfileAdvancedRealTime = 1024; // 0x400
diff --git a/api/system-current.txt b/api/system-current.txt
index 4623b7b..a6f612d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5195,7 +5195,7 @@
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 @@
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 @@
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 @@
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 @@
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...);
}
@@ -21294,6 +21292,7 @@
method public void stop() throws java.lang.IllegalStateException;
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+ field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
field public static final int READ_BLOCKING = 0; // 0x0
field public static final int READ_NON_BLOCKING = 1; // 0x1
@@ -21418,6 +21417,7 @@
method public int write(java.nio.ByteBuffer, int, int, long);
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+ field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
field public static final int MODE_STATIC = 0; // 0x0
field public static final int MODE_STREAM = 1; // 0x1
@@ -22075,6 +22075,7 @@
field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
+ field public static final int MPEG2LevelHP = 4; // 0x4
field public static final int MPEG2LevelLL = 0; // 0x0
field public static final int MPEG2LevelML = 1; // 0x1
field public static final int MPEG2Profile422 = 2; // 0x2
@@ -22088,9 +22089,11 @@
field public static final int MPEG4Level1 = 4; // 0x4
field public static final int MPEG4Level2 = 8; // 0x8
field public static final int MPEG4Level3 = 16; // 0x10
+ field public static final int MPEG4Level3b = 24; // 0x18
field public static final int MPEG4Level4 = 32; // 0x20
field public static final int MPEG4Level4a = 64; // 0x40
field public static final int MPEG4Level5 = 128; // 0x80
+ field public static final int MPEG4Level6 = 256; // 0x100
field public static final int MPEG4ProfileAdvancedCoding = 4096; // 0x1000
field public static final int MPEG4ProfileAdvancedCore = 8192; // 0x2000
field public static final int MPEG4ProfileAdvancedRealTime = 1024; // 0x400
diff --git a/api/test-current.txt b/api/test-current.txt
index 9a4752e..37bc7af 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5049,7 +5049,7 @@
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 @@
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 @@
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 @@
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 @@
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...);
}
@@ -19847,6 +19845,7 @@
method public void stop() throws java.lang.IllegalStateException;
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+ field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
field public static final int READ_BLOCKING = 0; // 0x0
field public static final int READ_NON_BLOCKING = 1; // 0x1
@@ -19969,6 +19968,7 @@
method public int write(java.nio.ByteBuffer, int, int, long);
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+ field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
field public static final int MODE_STATIC = 0; // 0x0
field public static final int MODE_STREAM = 1; // 0x1
@@ -20626,6 +20626,7 @@
field public static final int HEVCProfileMain10HDR10 = 4096; // 0x1000
field public static final int MPEG2LevelH14 = 2; // 0x2
field public static final int MPEG2LevelHL = 3; // 0x3
+ field public static final int MPEG2LevelHP = 4; // 0x4
field public static final int MPEG2LevelLL = 0; // 0x0
field public static final int MPEG2LevelML = 1; // 0x1
field public static final int MPEG2Profile422 = 2; // 0x2
@@ -20639,9 +20640,11 @@
field public static final int MPEG4Level1 = 4; // 0x4
field public static final int MPEG4Level2 = 8; // 0x8
field public static final int MPEG4Level3 = 16; // 0x10
+ field public static final int MPEG4Level3b = 24; // 0x18
field public static final int MPEG4Level4 = 32; // 0x20
field public static final int MPEG4Level4a = 64; // 0x40
field public static final int MPEG4Level5 = 128; // 0x80
+ field public static final int MPEG4Level6 = 256; // 0x100
field public static final int MPEG4ProfileAdvancedCoding = 4096; // 0x1000
field public static final int MPEG4ProfileAdvancedCore = 8192; // 0x2000
field public static final int MPEG4ProfileAdvancedRealTime = 1024; // 0x400
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6ba6b0f..cd9a05b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -7015,6 +7015,7 @@
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 5078058..4a8203b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4087,6 +4087,10 @@
public BigPictureStyle() {
}
+ /**
+ * @deprecated use {@code BigPictureStyle()}.
+ */
+ @Deprecated
public BigPictureStyle(Builder builder) {
setBuilder(builder);
}
@@ -4243,6 +4247,10 @@
public BigTextStyle() {
}
+ /**
+ * @deprecated use {@code BigTextStyle()}.
+ */
+ @Deprecated
public BigTextStyle(Builder builder) {
setBuilder(builder);
}
@@ -4785,6 +4793,10 @@
public InboxStyle() {
}
+ /**
+ * @deprecated use {@code InboxStyle()}.
+ */
+ @Deprecated
public InboxStyle(Builder builder) {
setBuilder(builder);
}
@@ -4957,6 +4969,10 @@
public MediaStyle() {
}
+ /**
+ * @deprecated use {@code MediaStyle()}.
+ */
+ @Deprecated
public MediaStyle(Builder builder) {
setBuilder(builder);
}
@@ -5164,10 +5180,6 @@
public DecoratedCustomViewStyle() {
}
- public DecoratedCustomViewStyle(Builder builder) {
- setBuilder(builder);
- }
-
/**
* @hide
*/
@@ -5284,10 +5296,6 @@
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 cd8f126..bb5f7a1 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -19,6 +19,7 @@
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 @@
// 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 @@
}
applyContent(content, recycled, exception);
+ updateContentDescription(mInfo);
}
private void applyContent(View content, boolean recycled, Exception exception) {
@@ -493,6 +495,22 @@
}
}
+ 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 d036d96..4c86578 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -57,6 +57,7 @@
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 @@
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 @@
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 @@
@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 @@
* 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 @@
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
+ } finally {
+ mServiceLock.readLock().unlock();
}
}
@@ -783,26 +797,28 @@
@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 @@
@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 @@
*/
@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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 @@
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 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 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 @@
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 @@
}
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 @@
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 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 @@
//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/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 5db0f16..2d1e0bd 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -142,13 +142,17 @@
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 @@
} 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 @@
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/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 1bc4285..1fc08ed 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -479,17 +479,13 @@
static inline
jint interpretReadSizeError(ssize_t readSize) {
- ALOGE_IF(readSize != WOULD_BLOCK, "Error %zd during AudioRecord native read", readSize);
- switch (readSize) {
- case WOULD_BLOCK:
+ if (readSize == WOULD_BLOCK) {
return (jint)0;
- case BAD_VALUE:
- return (jint)AUDIO_JAVA_BAD_VALUE;
- default:
- // may be possible for other errors such as
- // NO_INIT to happen if restoreRecord_l fails.
- case INVALID_OPERATION:
- return (jint)AUDIO_JAVA_INVALID_OPERATION;
+ } else if (readSize == NO_INIT) {
+ return AUDIO_JAVA_DEAD_OBJECT;
+ } else {
+ ALOGE("Error %zd during AudioRecord native read", readSize);
+ return nativeToJavaStatus(readSize);
}
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 024c21d..982a1f8 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -606,6 +606,18 @@
env->ReleaseFloatArrayElements(array, elems, mode);
}
+static inline
+jint interpretWriteSizeError(ssize_t writeSize) {
+ if (writeSize == WOULD_BLOCK) {
+ return (jint)0;
+ } else if (writeSize == NO_INIT) {
+ return AUDIO_JAVA_DEAD_OBJECT;
+ } else {
+ ALOGE("Error %zd during AudioTrack native read", writeSize);
+ return nativeToJavaStatus(writeSize);
+ }
+}
+
// ----------------------------------------------------------------------------
template <typename T>
static jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data,
@@ -628,11 +640,10 @@
memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes);
written = sizeInBytes;
}
- if (written > 0) {
+ if (written >= 0) {
return written / sizeof(T);
}
- // for compatibility, error codes pass through unchanged
- return written;
+ return interpretWriteSizeError(written);
}
// ----------------------------------------------------------------------------
diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml
index 3c47705..39e1bbb 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 @@
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/strings.xml b/core/res/res/values/strings.xml
index dffab2c..45ee778 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 3cb1876..e99d57f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2595,4 +2595,5 @@
<!-- Pinner Service -->
<java-symbol type="array" name="config_defaultPinnerServiceFiles" />
+ <java-symbol type="string" name="suspended_widget_accessibility" />
</resources>
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index c85ef7e..3aab5bd 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -237,7 +237,7 @@
"title":"Test Your App",
"summary":"This document describes key concepts related to Android app testing. It assumes you have a basic knowledge of the JUnit testing framework. Android testing is based on JUnit. In general, a JUnit test is a method whose statements test a part of the application\u2026",
"url":"studio/test/index.html",
- "image":"images/testing/test_framework.png",
+ "image":"studio/images/test/test-framework.png",
"type":"studio",
"keywords": [],
"tags": [],
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 4504e69..8efd599 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -94,6 +94,11 @@
* Denotes a failure due to the improper use of a method.
*/
public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION;
+ /**
+ * An error code indicating that the object reporting it is no longer valid and needs to
+ * be recreated.
+ */
+ public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT;
// Error codes:
// to keep in sync with frameworks/base/core/jni/android_media_AudioRecord.cpp
@@ -1046,10 +1051,16 @@
* @param audioData the array to which the recorded audio data is written.
* @param offsetInBytes index in audioData from which the data is written expressed in bytes.
* @param sizeInBytes the number of requested bytes.
- * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of bytes will not exceed sizeInBytes.
+ * @return zero or the positive number of bytes that were read, or one of the following
+ * error codes. The number of bytes will not exceed sizeInBytes.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
return read(audioData, offsetInBytes, sizeInBytes, READ_BLOCKING);
@@ -1070,11 +1081,17 @@
* is read.
* <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
* reading as much audio data as possible without blocking.
- * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of bytes will be a multiple of the frame size in bytes
+ * @return zero or the positive number of bytes that were read, or one of the following
+ * error codes. The number of bytes will be a multiple of the frame size in bytes
* not to exceed sizeInBytes.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@ReadMode int readMode) {
@@ -1106,10 +1123,17 @@
* Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInShorts the number of requested shorts.
* Must not be negative, or cause the data access to go out of bounds of the array.
- * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
+ * @return zero or the positive number of shorts that were read, or one of the following
+ * error codes. The number of shorts will be a multiple of the channel count not to exceed
+ * sizeInShorts.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
return read(audioData, offsetInShorts, sizeInShorts, READ_BLOCKING);
@@ -1129,10 +1153,17 @@
* is read.
* <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
* reading as much audio data as possible without blocking.
- * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
+ * @return zero or the positive number of shorts that were read, or one of the following
+ * error codes. The number of shorts will be a multiple of the channel count not to exceed
+ * sizeInShorts.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@ReadMode int readMode) {
@@ -1169,10 +1200,17 @@
* is read.
* <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
* reading as much audio data as possible without blocking.
- * @return the number of floats that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of floats will be a multiple of the channel count not to exceed sizeInFloats.
+ * @return zero or the positive number of floats that were read, or one of the following
+ * error codes. The number of floats will be a multiple of the channel count not to exceed
+ * sizeInFloats.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@ReadMode int readMode) {
@@ -1213,11 +1251,17 @@
* @param sizeInBytes the number of requested bytes. It is recommended but not enforced
* that the number of bytes requested be a multiple of the frame size (sample size in
* bytes multiplied by the channel count).
- * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of bytes will not exceed sizeInBytes.
- * The number of bytes read will be truncated to be a multiple of the frame size.
+ * @return zero or the positive number of bytes that were read, or one of the following
+ * error codes. The number of bytes will not exceed sizeInBytes and will be truncated to be
+ * a multiple of the frame size.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes) {
return read(audioBuffer, sizeInBytes, READ_BLOCKING);
@@ -1240,11 +1284,17 @@
* is read.
* <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
* reading as much audio data as possible without blocking.
- * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
- * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes.
- * The number of bytes will not exceed sizeInBytes.
- * The number of bytes read will be truncated to be a multiple of the frame size.
+ * @return zero or the positive number of bytes that were read, or one of the following
+ * error codes. The number of bytes will not exceed sizeInBytes and will be truncated to be
+ * a multiple of the frame size.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next read()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) {
if (mState != STATE_INITIALIZED) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 12e88a2..9a81668 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -156,7 +156,6 @@
/**
* An error code indicating that the object reporting it is no longer valid and needs to
* be recreated.
- * @hide
*/
public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT;
/**
@@ -1840,17 +1839,17 @@
* Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInBytes the number of bytes to write in audioData after the offset.
* Must not be negative, or cause the data access to go out of bounds of the array.
- * @return zero or the positive number of bytes that were written, or
- * {@link #ERROR_INVALID_OPERATION}
- * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
- * The number of bytes will be a multiple of the frame size in bytes
+ * @return zero or the positive number of bytes that were written, or one of the following
+ * error codes. The number of bytes will be a multiple of the frame size in bytes
* not to exceed sizeInBytes.
- *
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
* This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code>
* set to {@link #WRITE_BLOCKING}.
*/
@@ -1888,16 +1887,17 @@
* to the audio sink.
* <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return zero or the positive number of bytes that were written, or
- * {@link #ERROR_INVALID_OPERATION}
- * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
- * The number of bytes will be a multiple of the frame size in bytes
+ * @return zero or the positive number of bytes that were written, or one of the following
+ * error codes. The number of bytes will be a multiple of the frame size in bytes
* not to exceed sizeInBytes.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@WriteMode int writeMode) {
@@ -1950,16 +1950,17 @@
* Must not be negative, or cause the data access to go out of bounds of the array.
* @param sizeInShorts the number of shorts to read in audioData after the offset.
* Must not be negative, or cause the data access to go out of bounds of the array.
- * @return zero or the positive number of shorts that were written, or
- * {@link #ERROR_INVALID_OPERATION}
- * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
- * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
- *
+ * @return zero or the positive number of shorts that were written, or one of the following
+ * error codes. The number of shorts will be a multiple of the channel count not to
+ * exceed sizeInShorts.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
* This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code>
* set to {@link #WRITE_BLOCKING}.
*/
@@ -1995,15 +1996,17 @@
* to the audio sink.
* <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return zero or the positive number of shorts that were written, or
- * {@link #ERROR_INVALID_OPERATION}
- * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
- * The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
+ * @return zero or the positive number of shorts that were written, or one of the following
+ * error codes. The number of shorts will be a multiple of the channel count not to
+ * exceed sizeInShorts.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@WriteMode int writeMode) {
@@ -2074,15 +2077,17 @@
* to the audio sink.
* <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return zero or the positive number of floats that were written, or
- * {@link #ERROR_INVALID_OPERATION}
- * if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
- * the parameters don't resolve to valid data and indexes, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
- * The number of floats will be a multiple of the channel count not to exceed sizeInFloats.
+ * @return zero or the positive number of floats that were written, or one of the following
+ * error codes. The number of floats will be a multiple of the channel count not to
+ * exceed sizeInFloats.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@WriteMode int writeMode) {
@@ -2154,12 +2159,16 @@
* to the audio sink.
* <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
- * @return zero or the positive number of bytes that were written, or
- * {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
+ * @return zero or the positive number of bytes that were written, or one of the following
+ * error codes.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
@WriteMode int writeMode) {
@@ -2223,12 +2232,16 @@
* <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
* @param timestamp The timestamp of the first decodable audio frame in the provided audioData.
- * @return zero or a positive number of bytes that were written, or
- * {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
- * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
- * needs to be recreated.
- * The dead object error code is not returned if some data was successfully transferred.
- * In this case, the error is returned at the next write().
+ * @return zero or the positive number of bytes that were written, or one of the following
+ * error codes.
+ * <ul>
+ * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+ * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+ * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated. The dead object error code is not returned if some data was
+ * successfully transferred. In this case, the error is returned at the next write()</li>
+ * <li>{@link #ERROR} in case of other error</li>
+ * </ul>
*/
public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
@WriteMode int writeMode, long timestamp) {
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index b9ed269..87c6d88 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1918,13 +1918,15 @@
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 @@
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 @@
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,11 @@
public static final int MPEG4Level1 = 0x04;
public static final int MPEG4Level2 = 0x08;
public static final int MPEG4Level3 = 0x10;
+ public static final int MPEG4Level3b = 0x18;
public static final int MPEG4Level4 = 0x20;
public static final int MPEG4Level4a = 0x40;
public static final int MPEG4Level5 = 0x80;
+ public static final int MPEG4Level6 = 0x100;
// from OMX_VIDEO_MPEG2PROFILETYPE
public static final int MPEG2ProfileSimple = 0x00;
@@ -2657,6 +2655,7 @@
public static final int MPEG2LevelML = 0x01;
public static final int MPEG2LevelH14 = 0x02;
public static final int MPEG2LevelHL = 0x03;
+ public static final int MPEG2LevelHP = 0x04;
// from OMX_AUDIO_AACPROFILETYPE
public static final int AACObjectMain = 1;
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 474e3e6..6bc4df7 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -815,6 +815,14 @@
*/
private void onBugreportFinished(int id, Intent intent) {
final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
+ // Since BugreportProvider and BugreportProgressService aren't tightly coupled,
+ // we need to make sure they are explicitly tied to a single unique notification URI
+ // so that the service can alert the provider of changes it has done (ie. new bug
+ // reports)
+ // See { @link Cursor#setNotificationUri } and {@link ContentResolver#notifyChanges }
+ final Uri notificationUri = BugreportStorageProvider.getNotificationUri();
+ mContext.getContentResolver().notifyChange(notificationUri, null, false);
+
if (bugreportFile == null) {
// Should never happen, dumpstate always set the file.
Log.wtf(TAG, "Missing " + EXTRA_BUGREPORT + " on intent " + intent);
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 0f92fa6..8b07599 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -19,9 +19,11 @@
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
+import android.net.Uri;
import android.os.CancellationSignal;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
@@ -32,6 +34,7 @@
import java.io.FileNotFoundException;
public class BugreportStorageProvider extends DocumentsProvider {
+ private static final String AUTHORITY = "com.android.shell.documents";
private static final String DOC_ID_ROOT = "bugreport";
private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
@@ -103,6 +106,7 @@
for (File file : files) {
addFileRow(result, file);
}
+ result.setNotificationUri(getContext().getContentResolver(), getNotificationUri());
}
}
return result;
@@ -130,6 +134,12 @@
}
}
+ // This is used by BugreportProgressService so that the notification uri shared by
+ // BugreportProgressService and BugreportStorageProvider are guaranteed the same and unique
+ protected static Uri getNotificationUri() {
+ return DocumentsContract.buildChildDocumentsUri(AUTHORITY, DOC_ID_ROOT);
+ }
+
private static String[] resolveRootProjection(String[] projection) {
return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
}
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 493b23f..29b4db1 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 void animateToggleQSExpansion() {
// TODO: Better path to animated panel expansion.
- mHeader.performClick();
+ mHeader.callOnClick();
}
@Override
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 74f0cd3..476598d 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 @@
}
/**
+ * 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 fe5d8bc..6e4a593 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 @@
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 @@
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 @@
}
}
});
-
- 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 @@
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 182b9b0..b3e9f43 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 @@
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 1edc9b1..8ad6e6a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -125,6 +125,8 @@
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 @@
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 @@
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 @@
while (true)
{
int result = waitForAlarm(mNativeData);
+ mLastWakeup = SystemClock.elapsedRealtime();
triggerList.clear();
@@ -2536,6 +2543,11 @@
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/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 5e8687a..f30a126 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.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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
*/
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 @@
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 @@
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 @@
" mBinding = " + mBinding);
}
- synchronized (mConnection) {
+ try {
+ mBluetoothLock.writeLock().lock();
if (mUnbinding) return;
mUnbinding = true;
if (mBluetooth != null) {
@@ -695,6 +720,8 @@
mUnbinding=false;
}
mBluetoothGatt = null;
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
}
@@ -1010,14 +1037,13 @@
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 @@
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 @@
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 @@
}
mGetNameAddressOnly = false;
}
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
break;
@@ -1209,7 +1238,8 @@
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 @@
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call enable()",e);
}
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
if (!mEnable) {
@@ -1275,9 +1307,10 @@
}
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 @@
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 @@
Slog.e(TAG, "Bad msg.arg1: " + msg.arg1);
break;
}
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
if (mEnable) {
@@ -1369,9 +1405,9 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
Slog.e(TAG,"Unable to call enable()",e);
}
}
+ } finally {
+ mBluetoothLock.writeLock().unlock();
}
}
@@ -1510,18 +1549,18 @@
}
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 @@
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 @@
}
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 @@
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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index c096fa5f..95a9781 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4066,7 +4066,8 @@
synchronized(mRulesLock) {
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
}
- if ((uidRules & RULE_ALLOW_ALL) == 0) {
+ if (mRestrictBackground && (uidRules & RULE_ALLOW_METERED) == 0
+ && (uidRules & RULE_TEMPORARY_ALLOW_METERED) == 0) {
// we could silently fail or we can filter the available nets to only give
// them those they have access to. Chose the more useful option.
networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 04be34a..946e4f7 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 @@
.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 91de797..ecab009 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 @@
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 @@
// 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/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index aea395d..42eddd5 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1334,7 +1334,17 @@
final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
if (wallpaperTarget != null) {
final Task task = wallpaperTarget.getTask();
- if (task != null && !task.isFullscreen()) {
+ final WindowStateAnimator winAnimator = wallpaperTarget.mWinAnimator;
+ // We can only crop the wallpaper using final crop with stack bounds if the target
+ // is not animating, or if it's animating with clip mode STACK_CLIP_AFTER_ANIM.
+ // If it's animating with mode STACK_CLIP_NONE, we shouldn't crop either the task
+ // itself or the wallpaper. If it's animating with STACK_CLIP_BEFORE_ANIM, the crop
+ // is before the transform on the task itself.
+ final boolean useFinalCropOnWallpaper = !winAnimator.isAnimationSet()
+ || winAnimator.resolveStackClip() == STACK_CLIP_AFTER_ANIM;
+ if (task != null && !task.isFullscreen()
+ && task.cropWindowsToStackBounds()
+ && useFinalCropOnWallpaper){
final TaskStack stack = task.mStack;
if (stack != null && !stack.isFullscreen()) {
stack.getDimBounds(mTmpStackBounds);
@@ -1459,7 +1469,7 @@
// We need to ensure for each surface, that we disable transformation matrix
// scaling in the same transaction which we resize the surface in.
// As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
- // then take over the scaling until the new buffer arrives, and things
+ // then take over the scaling until the new buffer arrives, and things
// will be seamless.
mForceScaleUntilResize = true;
} else {
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 7079b9e..538e8f8 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -648,14 +648,31 @@
// 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 505d15a..99b10c3 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -125,17 +125,18 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
class DhcpRequestingState extends PacketRetransmittingState {
public DhcpRequestingState() {
- super();
mTimeout = DHCP_TIMEOUT_MS / 2;
}
@@ -777,7 +804,11 @@
@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 @@
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 @@
@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 @@
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 @@
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 @@
// 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 @@
}
}
- // 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 d8eab35..cece6c8 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -1027,6 +1027,8 @@
}
class StartedState extends State {
+ private boolean mDhcpActionInFlight;
+
@Override
public void enter() {
mStartTimeMillis = SystemClock.elapsedRealtime();
@@ -1066,7 +1068,7 @@
@Override
public void exit() {
mProvisioningTimeoutAlarm.cancel();
- mDhcpActionTimeoutAlarm.cancel();
+ stopDhcpAction();
if (mIpReachabilityMonitor != null) {
mIpReachabilityMonitor.stop();
@@ -1086,16 +1088,22 @@
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 @@
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 @@
// 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 @@
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 e9c5bdd..9e04d23 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 @@
}
@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 @@
@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 @@
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);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 57d68fd..51f5899 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1101,7 +1101,7 @@
if (hit && doit) {
// The user is force stopping our current interactor/recognizer.
// Clear the current settings and restore default state.
- synchronized (VoiceInteractionManagerService.this) {
+ synchronized (VoiceInteractionManagerServiceStub.this) {
unloadAllKeyphraseModels();
if (mImpl != null) {
mImpl.shutdownLocked();
@@ -1126,7 +1126,7 @@
int userHandle = getChangingUserId();
if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle);
- synchronized (VoiceInteractionManagerService.this) {
+ synchronized (VoiceInteractionManagerServiceStub.this) {
ComponentName curInteractor = getCurInteractor(userHandle);
ComponentName curRecognizer = getCurRecognizer(userHandle);
if (curRecognizer == null) {