Merge "RTL support for print UI." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 5c05305..42eaef0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5499,7 +5499,7 @@
method public void uninstallCaCert(android.content.ComponentName, byte[]);
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
- field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
+ field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
@@ -5509,11 +5509,10 @@
field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
- field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -8908,6 +8907,7 @@
field public static final java.lang.String FEATURE_PRINTING = "android.software.print";
field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
+ field public static final java.lang.String FEATURE_SECURELY_REMOVES_USERS = "android.software.securely_removes_users";
field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
field public static final java.lang.String FEATURE_SENSOR_AMBIENT_TEMPERATURE = "android.hardware.sensor.ambient_temperature";
field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer";
@@ -8932,6 +8932,7 @@
field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND = "android.hardware.touchscreen.multitouch.jazzhand";
field public static final java.lang.String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory";
field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
+ field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -14074,29 +14075,6 @@
method public android.media.AudioAttributes.Builder setUsage(int);
}
- public class AudioDevice {
- field public static final int DEVICE_TYPE_AUX_LINE = 19; // 0x13
- field public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 8; // 0x8
- field public static final int DEVICE_TYPE_BLUETOOTH_SCO = 7; // 0x7
- field public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1; // 0x1
- field public static final int DEVICE_TYPE_BUILTIN_MIC = 15; // 0xf
- field public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 2; // 0x2
- field public static final int DEVICE_TYPE_DOCK = 13; // 0xd
- field public static final int DEVICE_TYPE_FM = 14; // 0xe
- field public static final int DEVICE_TYPE_FM_TUNER = 16; // 0x10
- field public static final int DEVICE_TYPE_HDMI = 9; // 0x9
- field public static final int DEVICE_TYPE_HDMI_ARC = 10; // 0xa
- field public static final int DEVICE_TYPE_LINE_ANALOG = 5; // 0x5
- field public static final int DEVICE_TYPE_LINE_DIGITAL = 6; // 0x6
- field public static final int DEVICE_TYPE_TELEPHONY = 18; // 0x12
- field public static final int DEVICE_TYPE_TV_TUNER = 17; // 0x11
- field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
- field public static final int DEVICE_TYPE_USB_ACCESSORY = 12; // 0xc
- field public static final int DEVICE_TYPE_USB_DEVICE = 11; // 0xb
- field public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4; // 0x4
- field public static final int DEVICE_TYPE_WIRED_HEADSET = 3; // 0x3
- }
-
public class AudioFormat {
method public int getChannelMask();
method public int getEncoding();
@@ -14420,6 +14398,7 @@
field public static final int QUALITY_CIF = 3; // 0x3
field public static final int QUALITY_HIGH = 1; // 0x1
field public static final int QUALITY_HIGH_SPEED_1080P = 2004; // 0x7d4
+ field public static final int QUALITY_HIGH_SPEED_2160P = 2005; // 0x7d5
field public static final int QUALITY_HIGH_SPEED_480P = 2002; // 0x7d2
field public static final int QUALITY_HIGH_SPEED_720P = 2003; // 0x7d3
field public static final int QUALITY_HIGH_SPEED_HIGH = 2001; // 0x7d1
@@ -14664,7 +14643,7 @@
}
public static final class MediaCodec.CodecException extends java.lang.IllegalStateException {
- method public int getErrorCode();
+ method public java.lang.String getDiagnosticInfo();
method public boolean isRecoverable();
method public boolean isTransient();
}
@@ -15002,7 +14981,7 @@
public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
ctor public MediaDrm.MediaDrmStateException(int, java.lang.String);
- method public int getErrorCode();
+ method public java.lang.String getDiagnosticInfo();
}
public static abstract interface MediaDrm.OnEventListener {
@@ -16188,12 +16167,16 @@
method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public boolean getSpeakerAngles(int, int, int[]) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public boolean getStrengthSupported();
- method public int getVirtualizationMode() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
+ method public int getVirtualizationMode() throws java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener);
method public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException;
field public static final int PARAM_STRENGTH = 1; // 0x1
field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0
+ field public static final int VIRTUALIZATION_MODE_AUTO = 1; // 0x1
+ field public static final int VIRTUALIZATION_MODE_BINAURAL = 2; // 0x2
+ field public static final int VIRTUALIZATION_MODE_OFF = 0; // 0x0
+ field public static final int VIRTUALIZATION_MODE_TRANSAURAL = 3; // 0x3
}
public static abstract interface Virtualizer.OnParameterChangeListener {
diff --git a/api/removed.txt b/api/removed.txt
index 3c16276..c8a3b4b 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -22,14 +22,6 @@
}
-package android.service.notification {
-
- public static class NotificationListenerService.Ranking {
- method public boolean meetsInterruptionFilter();
- }
-
-}
-
package android.view {
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index f4e4671..25417ed 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -92,21 +92,27 @@
*/
public static Animator loadAnimator(Resources resources, Theme theme, int id)
throws NotFoundException {
+ return loadAnimator(resources, theme, id, 1);
+ }
+
+ /** @hide */
+ public static Animator loadAnimator(Resources resources, Theme theme, int id,
+ float pathErrorScale) throws NotFoundException {
XmlResourceParser parser = null;
try {
parser = resources.getAnimation(id);
- return createAnimatorFromXml(resources, theme, parser);
+ return createAnimatorFromXml(resources, theme, parser, pathErrorScale);
} catch (XmlPullParserException ex) {
Resources.NotFoundException rnf =
new Resources.NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
+ Integer.toHexString(id));
rnf.initCause(ex);
throw rnf;
} catch (IOException ex) {
Resources.NotFoundException rnf =
new Resources.NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
+ Integer.toHexString(id));
rnf.initCause(ex);
throw rnf;
} finally {
@@ -177,7 +183,7 @@
}
if (animator == null) {
animator = createAnimatorFromXml(context.getResources(),
- context.getTheme(), parser);
+ context.getTheme(), parser, 1f);
}
if (animator == null) {
@@ -248,9 +254,11 @@
* @param arrayAnimator Incoming typed array for Animator's attributes.
* @param arrayObjectAnimator Incoming typed array for Object Animator's
* attributes.
+ * @param pixelSize The relative pixel size, used to calculate the
+ * maximum error for path animations.
*/
private static void parseAnimatorFromTypeArray(ValueAnimator anim,
- TypedArray arrayAnimator, TypedArray arrayObjectAnimator) {
+ TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) {
long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300);
long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0);
@@ -303,7 +311,7 @@
}
if (arrayObjectAnimator != null) {
- setupObjectAnimator(anim, arrayObjectAnimator, getFloats);
+ setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize);
}
}
@@ -351,9 +359,11 @@
* @param anim The target Animator which will be updated.
* @param arrayObjectAnimator TypedArray for the ObjectAnimator.
* @param getFloats True if the value type is float.
+ * @param pixelSize The relative pixel size, used to calculate the
+ * maximum error for path animations.
*/
private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator,
- boolean getFloats) {
+ boolean getFloats, float pixelSize) {
ObjectAnimator oa = (ObjectAnimator) anim;
String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData);
@@ -370,7 +380,8 @@
+ " propertyXName or propertyYName is needed for PathData");
} else {
Path path = PathParser.createPathFromPathData(pathData);
- PathKeyframes keyframeSet = KeyframeSet.ofPath(path);
+ float error = 0.5f * pixelSize; // max half a pixel error
+ PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error);
Keyframes xKeyframes;
Keyframes yKeyframes;
if (getFloats) {
@@ -487,13 +498,15 @@
}
}
- private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser)
+ private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
+ float pixelSize)
throws XmlPullParserException, IOException {
- return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0);
+ return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0,
+ pixelSize);
}
private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
- AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
+ AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
throws XmlPullParserException, IOException {
Animator anim = null;
@@ -513,9 +526,9 @@
String name = parser.getName();
if (name.equals("objectAnimator")) {
- anim = loadObjectAnimator(res, theme, attrs);
+ anim = loadObjectAnimator(res, theme, attrs, pixelSize);
} else if (name.equals("animator")) {
- anim = loadAnimator(res, theme, attrs, null);
+ anim = loadAnimator(res, theme, attrs, null, pixelSize);
} else if (name.equals("set")) {
anim = new AnimatorSet();
TypedArray a;
@@ -526,7 +539,8 @@
}
int ordering = a.getInt(R.styleable.AnimatorSet_ordering,
TOGETHER);
- createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering);
+ createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
+ pixelSize);
a.recycle();
} else {
throw new RuntimeException("Unknown animator name: " + parser.getName());
@@ -556,11 +570,11 @@
}
- private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs)
- throws NotFoundException {
+ private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs,
+ float pathErrorScale) throws NotFoundException {
ObjectAnimator anim = new ObjectAnimator();
- loadAnimator(res, theme, attrs, anim);
+ loadAnimator(res, theme, attrs, anim, pathErrorScale);
return anim;
}
@@ -575,7 +589,7 @@
* ObjectAnimator
*/
private static ValueAnimator loadAnimator(Resources res, Theme theme,
- AttributeSet attrs, ValueAnimator anim)
+ AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
throws NotFoundException {
TypedArray arrayAnimator = null;
@@ -601,7 +615,7 @@
anim = new ValueAnimator();
}
- parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator);
+ parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale);
final int resID =
arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index fc9bbb1..8d15db2 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -154,6 +154,10 @@
return new PathKeyframes(path);
}
+ public static PathKeyframes ofPath(Path path, float error) {
+ return new PathKeyframes(path, error);
+ }
+
/**
* Sets the TypeEvaluator to be used when calculating animated values. This object
* is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet,
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 9f49194..43fa3f0 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -599,17 +599,18 @@
mOriginalAlphas.put(view, view.getAlpha());
}
view.setAlpha(0f);
- view.setTransitionAlpha(0f);
}
}
- protected void showViews(ArrayList<View> views) {
+ protected void showViews(ArrayList<View> views, boolean setTransitionAlpha) {
int count = views.size();
for (int i = 0; i < count; i++) {
View view = views.get(i);
Float alpha = mOriginalAlphas.remove(view);
if (alpha != null) {
view.setAlpha(alpha);
+ }
+ if (setTransitionAlpha) {
view.setTransitionAlpha(1f);
}
}
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index f38c108..9c7728e 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -240,7 +240,7 @@
if (!mIsCanceled) {
mIsCanceled = true;
if (getViewsTransition() == null || mIsViewsTransitionStarted) {
- showViews(mSharedElements);
+ showViews(mSharedElements, true);
} else {
mTransitioningViews.addAll(mSharedElements);
}
@@ -300,7 +300,7 @@
// Now start shared element transition
ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState,
mSharedElementNames);
- showViews(mSharedElements);
+ showViews(mSharedElements, true);
scheduleSetSharedElementEnd(sharedElementSnapshots);
ArrayList<SharedElementOriginalState> originalImageViewState =
setSharedElementState(sharedElementState, sharedElementSnapshots);
@@ -411,7 +411,7 @@
@Override
public void onTransitionStart(Transition transition) {
mEnterViewsTransition = transition;
- showViews(mTransitioningViews);
+ showViews(mTransitioningViews, false);
super.onTransitionStart(transition);
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 982bbc4..e85ec63 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -126,8 +126,8 @@
}
public void resetViews() {
- showViews(mTransitioningViews);
- showViews(mSharedElements);
+ showViews(mTransitioningViews, true);
+ showViews(mSharedElements, true);
mIsHidden = true;
if (!mIsReturning && getDecor() != null) {
getDecor().suppressLayout(false);
@@ -296,7 +296,7 @@
transition.removeListener(this);
exitTransitionComplete();
if (mIsHidden) {
- showViews(mTransitioningViews);
+ showViews(mTransitioningViews, true);
}
if (mSharedElementBundle != null) {
delayCancel();
@@ -323,7 +323,7 @@
transition.removeListener(this);
sharedElementTransitionComplete();
if (mIsHidden) {
- showViews(mSharedElements);
+ showViews(mSharedElements, true);
}
}
});
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 672ef7b..4374622 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -166,11 +166,12 @@
* activity: if the activity is stopped, no fragments inside of it can be
* started; when the activity is destroyed, all fragments will be destroyed.
*
- * <p>All subclasses of Fragment must include a public empty constructor.
+ * <p>All subclasses of Fragment must include a public no-argument constructor.
* The framework will often re-instantiate a fragment class when needed,
* in particular during state restore, and needs to be able to find this
- * constructor to instantiate it. If the empty constructor is not available,
- * a runtime exception will occur in some cases during state restore.
+ * constructor to instantiate it. If the no-argument constructor is not
+ * available, a runtime exception will occur in some cases during state
+ * restore.
*
* <p>Topics covered here:
* <ol>
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2476c4b..f9e4895 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -842,6 +842,13 @@
public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
/**
+ * {@link #extras} key: the user that built the notification.
+ *
+ * @hide
+ */
+ public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
+
+ /**
* Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
* displayed in the heads up space.
*
@@ -1880,6 +1887,11 @@
private int mColor = COLOR_DEFAULT;
/**
+ * The user that built the notification originally.
+ */
+ private int mOriginatingUserId;
+
+ /**
* Contains extras related to rebuilding during the build phase.
*/
private Bundle mRebuildBundle = new Bundle();
@@ -2599,7 +2611,7 @@
// Note: This assumes that the current user can read the profile badge of the
// originating user.
return mContext.getPackageManager().getUserBadgeForDensity(
- new UserHandle(mContext.getUserId()), 0);
+ new UserHandle(mOriginatingUserId), 0);
}
private Bitmap getProfileBadge() {
@@ -2739,9 +2751,9 @@
} else {
contentView.setViewVisibility(R.id.text2, View.GONE);
if (hasProgress && (mProgressMax != 0 || mProgressIndeterminate)) {
+ contentView.setViewVisibility(R.id.progress, View.VISIBLE);
contentView.setProgressBar(
R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
- contentView.setViewVisibility(R.id.progress, View.VISIBLE);
showLine2 = true;
} else {
contentView.setViewVisibility(R.id.progress, View.GONE);
@@ -3070,6 +3082,7 @@
*/
public void populateExtras(Bundle extras) {
// Store original information used in the construction of this object
+ extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
mContext.getApplicationInfo());
extras.putCharSequence(EXTRA_TITLE, mContentTitle);
@@ -3301,6 +3314,7 @@
// Extras.
Bundle extras = n.extras;
+ mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
mContentTitle = extras.getCharSequence(EXTRA_TITLE);
mContentText = extras.getCharSequence(EXTRA_TEXT);
mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3333,6 +3347,7 @@
* object.
*/
public Notification build() {
+ mOriginatingUserId = mContext.getUserId();
mHasThreeLines = hasThreeLines();
Notification n = buildUnstyled();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 926a348..ea041e8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -97,8 +97,7 @@
* Provisioning adds a managed profile and sets the mdm as the profile owner who has full
* control over the profile
*
- * <p>This intent must contain the extras {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}
- * {@link #EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME} and {@link #EXTRA_DEVICE_ADMIN}.
+ * <p>This intent must contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
*
* <p> When managed provisioning has completed, an intent of the type
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -112,7 +111,7 @@
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_MANAGED_PROFILE
- = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
+ = "android.app.action.PROVISION_MANAGED_PROFILE";
/**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
@@ -139,21 +138,18 @@
* message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
- = "android.app.extra.deviceAdminPackageName";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
/**
- * A String extra holding the default name of the profile that is created during managed profile
- * provisioning.
+ * A String extra that, holds the email address of the account which a managed profile is
+ * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
*
- * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
- */
- public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
- = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
-
- /**
- * A bundle key, used in the bundle extra {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. The
- * corresponding value holds the email address of the account which the managed profile is
- * created for.
+ * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
+ * contains this extra, it is forwarded in the
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
+ * device management application that was set as the profile owner during provisioning.
+ * It is usually used to avoid that the user has to enter their email address twice.
*/
public static final String KEY_PROVISIONING_EMAIL_ADDRESS
= "android.app.key.PROVISIONING_EMAIL_ADDRESS";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 36d15a0..5ce968b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1525,6 +1525,22 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports verified boot.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports secure removal of users. When a user is deleted the data associated
+ * with that user is securely deleted and no longer available.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SECURELY_REMOVES_USERS
+ = "android.software.securely_removes_users";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device has a full implementation of the android.webkit.* APIs. Devices
* lacking this feature will not have a functioning WebView implementation.
*/
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 843f117..0057f61 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -143,7 +143,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -166,7 +165,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -188,7 +186,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -211,7 +208,6 @@
}
checkNotClosed();
- checkLegalToCapture();
handler = checkHandler(handler, callback);
@@ -542,13 +538,6 @@
}
}
- private void checkLegalToCapture() {
- if (mAborting) {
- throw new IllegalStateException(
- "Session is aborting captures; new captures are not permitted");
- }
- }
-
private void checkNotClosed() {
if (mClosed) {
throw new IllegalStateException(
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e6ff17b..e6da670 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -374,6 +374,9 @@
}
mIntermediateBufferSize = bestPreviewDimen;
+ mParams.setPreviewSize(mIntermediateBufferSize.getWidth(),
+ mIntermediateBufferSize.getHeight());
+
if (DEBUG) {
Log.d(TAG, "Intermediate buffer selected with dimens: " +
bestPreviewDimen.toString());
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 8df9916..80e5b91 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -223,6 +223,9 @@
* Called by the bearer code when it has a new score for this network.
*/
public void sendNetworkScore(int score) {
+ if (score < 0) {
+ throw new IllegalArgumentException("Score must be >= 0");
+ }
queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f4c2dc8..01fda47 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3739,6 +3739,13 @@
"show_note_about_notification_hiding";
/**
+ * Set to 1 by the system after trust agents have been initialized.
+ * @hide
+ */
+ public static final String TRUST_AGENTS_INITIALIZED =
+ "trust_agents_initialized";
+
+ /**
* The Logging ID (a unique 64-bit value) as a hex string.
* Used as a pseudonymous identifier for logging.
* @deprecated This identifier is poorly initialized and has
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index aa724f0..3a91d1a 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.annotation.SystemApi;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
@@ -28,6 +29,7 @@
*
* @hide
*/
+@SystemApi
public class Condition implements Parcelable {
public static final String SCHEME = "condition";
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 326412f..03ee726 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,6 +17,7 @@
package android.service.notification;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.app.INotificationManager;
import android.app.Service;
import android.content.Context;
@@ -44,6 +45,7 @@
*
* @hide
*/
+@SystemApi
public abstract class ConditionProviderService extends Service {
private final String TAG = ConditionProviderService.class.getSimpleName()
+ "[" + getClass().getSimpleName() + "]";
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index d744070..b22fd9c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -756,15 +756,6 @@
return mVisibilityOverride;
}
- /**
- * Returns whether the notification meets the user's interruption
- * filter.
- *
- * @removed
- */
- public boolean meetsInterruptionFilter() {
- return mMatchesInterruptionFilter;
- }
/**
* Returns whether the notification matches the user's interruption
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 872f911..9cbedab 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -17,6 +17,7 @@
package android.service.notification;
import android.content.ComponentName;
+import android.content.res.Resources;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -55,6 +56,11 @@
public static final int[] WEEKNIGHT_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
Calendar.WEDNESDAY, Calendar.THURSDAY };
+ public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+ private static final int SECONDS_MS = 1000;
+ private static final int MINUTES_MS = 60 * SECONDS_MS;
+ private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
+
private static final int XML_VERSION = 1;
private static final String ZEN_TAG = "zen";
private static final String ZEN_ATT_VERSION = "version";
@@ -445,6 +451,23 @@
return downtime;
}
+ public static Condition toTimeCondition(int minutesFromNow) {
+ final long now = System.currentTimeMillis();
+ final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
+ return toTimeCondition(now + millis, minutesFromNow);
+ }
+
+ public static Condition toTimeCondition(long time, int minutes) {
+ final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
+ final int resId = minutes < 60
+ ? com.android.internal.R.plurals.zen_mode_duration_minutes
+ : com.android.internal.R.plurals.zen_mode_duration_hours;
+ final String caption = Resources.getSystem().getQuantityString(resId, num, num);
+ final Uri id = toCountdownConditionId(time);
+ return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
+ Condition.FLAG_RELEVANT_NOW);
+ }
+
// For built-in conditions
private static final String SYSTEM_AUTHORITY = "android";
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index e7ada27..1671faa 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -211,18 +211,6 @@
}
/**
- * Constructor with no subtype ID specified, overridesImplicitlyEnabledSubtype not specified.
- * Arguments for this constructor have the same meanings as
- * {@link InputMethodSubtype#InputMethodSubtype(int, int, String, String, String, boolean,
- * boolean, int)} except "id" and "overridesImplicitlyEnabledSubtype".
- * @hide
- */
- public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
- boolean isAuxiliary) {
- this(nameId, iconId, locale, mode, extraValue, isAuxiliary, false);
- }
-
- /**
* Constructor with no subtype ID specified.
* @deprecated use {@link InputMethodSubtypeBuilder} instead.
* Arguments for this constructor have the same meanings as
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8a1d5af..bf2d09b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2773,7 +2773,7 @@
android:description="@string/permdesc_bindNotificationListenerService"
android:protectionLevel="signature" />
- <!-- Must be required by an {@link
+ <!-- @SystemApi Must be required by a {@link
android.service.notification.ConditionProviderService},
to ensure that only the system can bind to it.
@hide -->
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index 7e99c5e..aeef3ab 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -45,13 +45,13 @@
android:visibility="gone"
/>
</LinearLayout>
- <ProgressBar
+ <ViewStub
android:id="@android:id/progress"
+ android:layout="@layout/notification_template_progressbar"
android:layout_width="match_parent"
android:layout_height="15dp"
android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
- style="@style/Widget.Material.Light.ProgressBar.Horizontal"
/>
</merge>
diff --git a/core/res/res/layout/notification_template_progressbar.xml b/core/res/res/layout/notification_template_progressbar.xml
new file mode 100644
index 0000000..61480b8
--- /dev/null
+++ b/core/res/res/layout/notification_template_progressbar.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/progress"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ style="@style/Widget.Material.Light.ProgressBar.Horizontal"
+ />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5c932fd..50da1fa 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4877,4 +4877,19 @@
<!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active -->
<string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10.00 PM">%1$s</xliff:g></string>
+
+ <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one">For one minute</item>
+ <item quantity="other">For %d minutes</item>
+ </plurals>
+
+ <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] -->
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one">For one hour</item>
+ <item quantity="other">For %d hours</item>
+ </plurals>
+
+ <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_forever">Indefinitely</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c28f3a6..556c07f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1918,6 +1918,9 @@
<java-symbol type="string" name="timepicker_transition_end_radius_multiplier" />
<java-symbol type="string" name="battery_saver_description" />
<java-symbol type="string" name="downtime_condition_summary" />
+ <java-symbol type="string" name="zen_mode_forever" />
+ <java-symbol type="plurals" name="zen_mode_duration_minutes" />
+ <java-symbol type="plurals" name="zen_mode_duration_hours" />
<java-symbol type="string" name="item_is_selected" />
<java-symbol type="string" name="day_of_week_label_typeface" />
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 77e1c530..80d5668 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -322,8 +322,13 @@
* If the device is already associated with a WiFi, disconnect and forget it,
* We don't verify whether the connection is successful or not, leave this to the test
*/
- protected boolean connectToWifi(String knownSSID) {
- WifiConfiguration config = WifiConfigurationHelper.createOpenConfig(knownSSID);
+ protected boolean connectToWifi(String ssid, String password) {
+ WifiConfiguration config;
+ if (password == null) {
+ config = WifiConfigurationHelper.createOpenConfig(ssid);
+ } else {
+ config = WifiConfigurationHelper.createPskConfig(ssid, password);
+ }
return connectToWifiWithConfiguration(config);
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
index b94306a..b6eb674 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
@@ -35,8 +35,9 @@
*/
public class ConnectivityManagerTestRunner extends InstrumentationTestRunner {
- public boolean mWifiOnlyFlag = false;
- public String mTestSsid = null;
+ public boolean mWifiOnly = false;
+ public String mSsid = null;
+ public String mPassword = null;
@Override
public TestSuite getAllTests() {
@@ -54,13 +55,29 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- String testSSID = (String) icicle.get("ssid");
- if (testSSID != null) {
- mTestSsid = testSSID;
+ String ssid = icicle.getString("ssid");
+ if (ssid != null) {
+ mSsid = ssid;
+ }
+ String password = (String) icicle.get("password");
+ if (password != null) {
+ mPassword = password;
}
String wifiOnlyFlag = (String) icicle.get("wifi-only");
if (wifiOnlyFlag != null) {
- mWifiOnlyFlag = true;
+ mWifiOnly = true;
}
}
+
+ public String getWifiSsid() {
+ return mSsid;
+ }
+
+ public String getWifiPassword() {
+ return mPassword;
+ }
+
+ public boolean isWifiOnly() {
+ return mWifiOnly;
+ }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index b280106..d5051df 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -33,7 +33,8 @@
super(ConnectivityManagerMobileTest.class.getSimpleName());
}
- private String mTestAccessPoint;
+ private String mSsid;
+ private String mPassword;
private boolean mWifiOnlyFlag;
@Override
@@ -41,8 +42,9 @@
super.setUp();
ConnectivityManagerTestRunner mRunner =
(ConnectivityManagerTestRunner)getInstrumentation();
- mTestAccessPoint = mRunner.mTestSsid;
- mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
+ mSsid = mRunner.getWifiSsid();
+ mPassword = mRunner.getWifiPassword();
+ mWifiOnlyFlag = mRunner.isWifiOnly();
// Each test case will start with cellular connection
if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
@@ -120,11 +122,10 @@
// Test case 2: test connection to a given AP
@LargeTest
public void testConnectToWifi() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// assert that we are able to connect to the ap
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
// assert that WifiManager reports correct state
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
@@ -144,14 +145,14 @@
// Test case 3: connect & reconnect to Wifi with known AP
@LargeTest
public void testConnectToWifWithKnownAP() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
// wait for wifi enable
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// Connect to AP
- assertTrue("failed to connect to " + mTestAccessPoint, connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
// verify wifi connected as reported by ConnectivityManager
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -191,7 +192,7 @@
// Test case 4: test disconnect and clear wifi settings
@LargeTest
public void testDisconnectWifi() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
@@ -199,8 +200,7 @@
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -257,7 +257,7 @@
// Test case 6: test connectivity with airplane mode on but wifi enabled
@LargeTest
public void testDataConnectionOverAMWithWifi() {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable airplane mode
mCm.setAirplaneMode(true);
// assert there is active network connection after airplane mode disabled
@@ -265,8 +265,7 @@
waitUntilNoActiveNetworkConnection(LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
// verify that connection actually works
@@ -280,15 +279,14 @@
@LargeTest
public void testDataConnectionWithWifiToAMToWifi () {
// connect to mTestAccessPoint
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
// wait for wifi enable
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
@@ -313,15 +311,14 @@
// Test case 8: test wifi state change while connecting/disconnecting to/from an AP
@LargeTest
public void testWifiStateChange () {
- assertNotNull("SSID is null", mTestAccessPoint);
+ assertNotNull("SSID is null", mSsid);
// enable WiFi
assertTrue("failed to enable wifi", enableWifi());
// wait for wifi enable
assertTrue("wifi not enabled", waitForWifiState(
WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT));
// connect to Wifi
- assertTrue("failed to connect to " + mTestAccessPoint,
- connectToWifi(mTestAccessPoint));
+ assertTrue("failed to connect to " + mSsid, connectToWifi(mSsid, mPassword));
assertTrue("wifi not connected", waitForNetworkState(
ConnectivityManager.TYPE_WIFI, State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
assertNotNull("not associated with any AP", mWifiManager.getConnectionInfo().getBSSID());
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index fa1bd8f..5958c3a 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -26,6 +26,7 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
import java.util.ArrayList;
import java.util.List;
@@ -159,8 +160,15 @@
private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
- return new InputMethodSubtype(0, 0, locale, mode, "", isAuxiliary,
- overridesImplicitlyEnabledSubtype);
+ return new InputMethodSubtypeBuilder()
+ .setSubtypeNameResId(0)
+ .setSubtypeIconResId(0)
+ .setSubtypeLocale(locale)
+ .setSubtypeMode(mode)
+ .setSubtypeExtraValue("")
+ .setIsAuxiliary(isAuxiliary)
+ .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype)
+ .build();
}
private static InputMethodInfo createDefaultAutoDummyVoiceIme() {
diff --git a/docs/html/tools/building/index.jd b/docs/html/tools/building/index.jd
index c64942f..c1f3019 100644
--- a/docs/html/tools/building/index.jd
+++ b/docs/html/tools/building/index.jd
@@ -79,3 +79,14 @@
running on a device.</li>
</ul>
+<p class="note"><b>Note:</b> Apps are limited to a 64K method reference limit. If your app reaches
+this limit, the build process outputs the following error message:
+
+<pre>Unable to execute dex: method ID not in [0, 0xffff]: 65536.</pre>
+
+To avoid this, you can
+<a href="http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html">load
+secondary dex files at runtime</a> and use
+<a href="http://developer.android.com/tools/help/proguard.html">ProGuard</a> to strip out unnecessary
+class references (Proguard only works when building in release mode).
+</p>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index ba22550..e5e2f18 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -252,6 +252,7 @@
throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
+ float pathErrorScale = 1;
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
final String tagName = parser.getName();
@@ -261,9 +262,11 @@
int drawableRes = a.getResourceId(
R.styleable.AnimatedVectorDrawable_drawable, 0);
if (drawableRes != 0) {
- mAnimatedVectorState.mVectorDrawable = (VectorDrawable) res.getDrawable(
+ VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable(
drawableRes, theme).mutate();
- mAnimatedVectorState.mVectorDrawable.setAllowCaching(false);
+ vectorDrawable.setAllowCaching(false);
+ pathErrorScale = vectorDrawable.getPixelSize();
+ mAnimatedVectorState.mVectorDrawable = vectorDrawable;
}
a.recycle();
} else if (TARGET.equals(tagName)) {
@@ -275,7 +278,8 @@
int id = a.getResourceId(
R.styleable.AnimatedVectorDrawableTarget_animation, 0);
if (id != 0) {
- Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id);
+ Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id,
+ pathErrorScale);
setupAnimatorsForTarget(target, objectAnimator);
}
a.recycle();
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 042da5b..a07ccc4 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -368,6 +368,29 @@
}
}
+ /**
+ * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension.
+ * This is used to calculate the path animation accuracy.
+ *
+ * @hide
+ */
+ public float getPixelSize() {
+ if (mVectorState == null && mVectorState.mVPathRenderer == null ||
+ mVectorState.mVPathRenderer.mBaseWidth == 0 ||
+ mVectorState.mVPathRenderer.mBaseHeight == 0 ||
+ mVectorState.mVPathRenderer.mViewportHeight == 0 ||
+ mVectorState.mVPathRenderer.mViewportWidth == 0) {
+ return 1; // fall back to 1:1 pixel mapping.
+ }
+ float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
+ float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
+ float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
+ float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
+ float scaleX = viewportWidth / intrinsicWidth;
+ float scaleY = viewportHeight / intrinsicHeight;
+ return Math.min(scaleX, scaleY);
+ }
+
/** @hide */
public static VectorDrawable create(Resources resources, int rid) {
try {
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDevice.java
index e078354..df4d60d 100644
--- a/media/java/android/media/AudioDevice.java
+++ b/media/java/android/media/AudioDevice.java
@@ -20,90 +20,91 @@
/**
* Class to provide information about the audio devices.
+ * @hide
*/
public class AudioDevice {
/**
* A device type associated with an unknown or uninitialized device.
*/
- public static final int DEVICE_TYPE_UNKNOWN = 0;
+ public static final int TYPE_UNKNOWN = 0;
/**
* A device type describing the attached earphone speaker.
*/
- public static final int DEVICE_TYPE_BUILTIN_EARPIECE = 1;
+ public static final int TYPE_BUILTIN_EARPIECE = 1;
/**
* A device type describing the speaker system (i.e. a mono speaker or stereo speakers) built
* in a device.
*/
- public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 2;
+ public static final int TYPE_BUILTIN_SPEAKER = 2;
/**
* A device type describing a headset, which is the combination of a headphones and microphone.
*/
- public static final int DEVICE_TYPE_WIRED_HEADSET = 3;
+ public static final int TYPE_WIRED_HEADSET = 3;
/**
* A device type describing a pair of wired headphones .
*/
- public static final int DEVICE_TYPE_WIRED_HEADPHONES = 4;
+ public static final int TYPE_WIRED_HEADPHONES = 4;
/**
* A device type describing an analog line-level connection.
*/
- public static final int DEVICE_TYPE_LINE_ANALOG = 5;
+ public static final int TYPE_LINE_ANALOG = 5;
/**
* A device type describing a digital line connection (e.g. SPDIF).
*/
- public static final int DEVICE_TYPE_LINE_DIGITAL = 6;
+ public static final int TYPE_LINE_DIGITAL = 6;
/**
* A device type describing a Bluetooth device typically used for telephony .
*/
- public static final int DEVICE_TYPE_BLUETOOTH_SCO = 7;
+ public static final int TYPE_BLUETOOTH_SCO = 7;
/**
* A device type describing a Bluetooth device supporting the A2DP profile.
*/
- public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 8;
+ public static final int TYPE_BLUETOOTH_A2DP = 8;
/**
* A device type describing an HDMI connection .
*/
- public static final int DEVICE_TYPE_HDMI = 9;
+ public static final int TYPE_HDMI = 9;
/**
* A device type describing the Audio Return Channel of an HDMI connection.
*/
- public static final int DEVICE_TYPE_HDMI_ARC = 10;
+ public static final int TYPE_HDMI_ARC = 10;
/**
* A device type describing a USB audio device.
*/
- public static final int DEVICE_TYPE_USB_DEVICE = 11;
+ public static final int TYPE_USB_DEVICE = 11;
/**
* A device type describing a USB audio device in accessory mode.
*/
- public static final int DEVICE_TYPE_USB_ACCESSORY = 12;
+ public static final int TYPE_USB_ACCESSORY = 12;
/**
* A device type describing the audio device associated with a dock.
*/
- public static final int DEVICE_TYPE_DOCK = 13;
+ public static final int TYPE_DOCK = 13;
/**
* A device type associated with the transmission of audio signals over FM.
*/
- public static final int DEVICE_TYPE_FM = 14;
+ public static final int TYPE_FM = 14;
/**
* A device type describing the microphone(s) built in a device.
*/
- public static final int DEVICE_TYPE_BUILTIN_MIC = 15;
+ public static final int TYPE_BUILTIN_MIC = 15;
/**
* A device type for accessing the audio content transmitted over FM.
*/
- public static final int DEVICE_TYPE_FM_TUNER = 16;
+ public static final int TYPE_FM_TUNER = 16;
/**
* A device type for accessing the audio content transmitted over the TV tuner system.
*/
- public static final int DEVICE_TYPE_TV_TUNER = 17;
+ public static final int TYPE_TV_TUNER = 17;
/**
* A device type describing the transmission of audio signals over the telephony network.
*/
- public static final int DEVICE_TYPE_TELEPHONY = 18;
+ public static final int TYPE_TELEPHONY = 18;
/**
* A device type describing the auxiliary line-level connectors.
*/
- public static final int DEVICE_TYPE_AUX_LINE = 19;
+ public static final int TYPE_AUX_LINE = 19;
AudioDevicePortConfig mConfig;
@@ -135,7 +136,7 @@
* @return
*/
public int getDeviceType() {
- return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), DEVICE_TYPE_UNKNOWN);
+ return INT_TO_EXT_DEVICE_MAPPING.get(mConfig.port().type(), TYPE_UNKNOWN);
}
/**
@@ -154,7 +155,7 @@
/** @hide */
public static int convertInternalDeviceToDeviceType(int intDevice) {
- return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, DEVICE_TYPE_UNKNOWN);
+ return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, TYPE_UNKNOWN);
}
private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING;
@@ -163,43 +164,43 @@
static {
INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray();
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, DEVICE_TYPE_BUILTIN_EARPIECE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, DEVICE_TYPE_BUILTIN_SPEAKER);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, DEVICE_TYPE_WIRED_HEADPHONES);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, DEVICE_TYPE_BLUETOOTH_A2DP);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, DEVICE_TYPE_BLUETOOTH_A2DP);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, DEVICE_TYPE_HDMI);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, DEVICE_TYPE_TELEPHONY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, DEVICE_TYPE_LINE_ANALOG);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, DEVICE_TYPE_HDMI_ARC);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, DEVICE_TYPE_FM);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, DEVICE_TYPE_AUX_LINE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, TYPE_BUILTIN_EARPIECE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER, TYPE_BUILTIN_SPEAKER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADSET, TYPE_WIRED_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, TYPE_WIRED_HEADPHONES);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI, TYPE_HDMI);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_ACCESSORY, TYPE_USB_ACCESSORY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_USB_DEVICE, TYPE_USB_DEVICE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_TELEPHONY_TX, TYPE_TELEPHONY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_LINE, TYPE_LINE_ANALOG);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_HDMI_ARC, TYPE_HDMI_ARC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPDIF, TYPE_LINE_DIGITAL);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, TYPE_FM);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, TYPE_AUX_LINE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, DEVICE_TYPE_BUILTIN_MIC);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, DEVICE_TYPE_BLUETOOTH_SCO);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, DEVICE_TYPE_WIRED_HEADSET);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, DEVICE_TYPE_HDMI);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, DEVICE_TYPE_TELEPHONY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, DEVICE_TYPE_BUILTIN_MIC);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, DEVICE_TYPE_DOCK);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, DEVICE_TYPE_USB_ACCESSORY);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, DEVICE_TYPE_USB_DEVICE);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, DEVICE_TYPE_FM_TUNER);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, DEVICE_TYPE_TV_TUNER);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, DEVICE_TYPE_LINE_ANALOG);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, DEVICE_TYPE_LINE_DIGITAL);
- INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, DEVICE_TYPE_BLUETOOTH_A2DP);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_WIRED_HEADSET, TYPE_WIRED_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_HDMI, TYPE_HDMI);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TELEPHONY_RX, TYPE_TELEPHONY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BACK_MIC, TYPE_BUILTIN_MIC);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET, TYPE_DOCK);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_ACCESSORY, TYPE_USB_ACCESSORY);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_USB_DEVICE, TYPE_USB_DEVICE);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_FM_TUNER, TYPE_FM_TUNER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_TV_TUNER, TYPE_TV_TUNER);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_LINE, TYPE_LINE_ANALOG);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, TYPE_LINE_DIGITAL);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
// not covered here, legacy
//AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
@@ -207,25 +208,25 @@
// privileges mapping to output device
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM, AudioSystem.DEVICE_OUT_FM);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
- EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_FM, AudioSystem.DEVICE_OUT_FM);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_AUX_LINE, AudioSystem.DEVICE_OUT_AUX_LINE);
}
}
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 8883d28..5651fc9 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -177,9 +177,15 @@
*/
public static final int QUALITY_HIGH_SPEED_1080P = 2004;
+ /**
+ * High speed ( >= 100fps) quality level corresponding to the 2160p (3840 x 2160)
+ * resolution.
+ */
+ public static final int QUALITY_HIGH_SPEED_2160P = 2005;
+
// Start and end of high speed quality list
private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW;
- private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_1080P;
+ private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_2160P;
/**
* Default recording duration in seconds before the session is terminated.
@@ -313,6 +319,7 @@
* @see #QUALITY_HIGH_SPEED_480P
* @see #QUALITY_HIGH_SPEED_720P
* @see #QUALITY_HIGH_SPEED_1080P
+ * @see #QUALITY_HIGH_SPEED_2160P
*/
public static CamcorderProfile get(int cameraId, int quality) {
if (!((quality >= QUALITY_LIST_START &&
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 81ebb14..1c7c9ea 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -672,6 +672,11 @@
super(detailMessage);
mErrorCode = errorCode;
mActionCode = actionCode;
+
+ // TODO get this from codec
+ final String sign = errorCode < 0 ? "neg_" : "";
+ mDiagnosticInfo =
+ "android.media.MediaCodec.error_" + sign + Math.abs(errorCode);
}
/**
@@ -696,15 +701,28 @@
* Retrieve the error code associated with a CodecException.
* This is opaque diagnostic information and may depend on
* hardware or API level.
+ *
+ * @hide
*/
public int getErrorCode() {
return mErrorCode;
}
+ /**
+ * Retrieve a human readable diagnostic information string
+ * associated with the exception. DO NOT SHOW THIS TO END-USERS!
+ * This string will not be localized or generally comprehensible
+ * to end-users.
+ */
+ public String getDiagnosticInfo() {
+ return mDiagnosticInfo;
+ }
+
/* Must be in sync with android_media_MediaCodec.cpp */
private final static int ACTION_TRANSIENT = 1;
private final static int ACTION_RECOVERABLE = 2;
+ private final String mDiagnosticInfo;
private final int mErrorCode;
private final int mActionCode;
}
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index ca707d8..1490732 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -188,18 +188,37 @@
*/
public static final class MediaDrmStateException extends java.lang.IllegalStateException {
private final int mErrorCode;
+ private final String mDiagnosticInfo;
public MediaDrmStateException(int errorCode, String detailMessage) {
super(detailMessage);
mErrorCode = errorCode;
+
+ // TODO get this from DRM session
+ final String sign = errorCode < 0 ? "neg_" : "";
+ mDiagnosticInfo =
+ "android.media.MediaDrm.error_" + sign + Math.abs(errorCode);
+
}
/**
* Retrieve the associated error code
+ *
+ * @hide
*/
public int getErrorCode() {
return mErrorCode;
}
+
+ /**
+ * Retrieve a human readable diagnostic information string
+ * associated with the exception. DO NOT SHOW THIS TO END-USERS!
+ * This string will not be localized or generally comprehensible
+ * to end-users.
+ */
+ public String getDiagnosticInfo() {
+ return mDiagnosticInfo;
+ }
}
/**
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 9343aa4..afa0b6e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1929,6 +1929,7 @@
mSubtitleController.setAnchor(anchor);
}
+ private final Object mInbandSubtitleLock = new Object();
private SubtitleTrack[] mInbandSubtitleTracks;
private int mSelectedSubtitleTrackIndex = -1;
private Vector<SubtitleTrack> mOutOfBandSubtitleTracks;
@@ -2036,19 +2037,21 @@
}
TrackInfo[] tracks = getInbandTrackInfo();
- SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length];
- for (int i=0; i < tracks.length; i++) {
- if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
- if (i < mInbandSubtitleTracks.length) {
- inbandTracks[i] = mInbandSubtitleTracks[i];
- } else {
- SubtitleTrack track = mSubtitleController.addTrack(
- tracks[i].getFormat());
- inbandTracks[i] = track;
+ synchronized (mInbandSubtitleLock) {
+ SubtitleTrack[] inbandTracks = new SubtitleTrack[tracks.length];
+ for (int i=0; i < tracks.length; i++) {
+ if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+ if (i < mInbandSubtitleTracks.length) {
+ inbandTracks[i] = mInbandSubtitleTracks[i];
+ } else {
+ SubtitleTrack track = mSubtitleController.addTrack(
+ tracks[i].getFormat());
+ inbandTracks[i] = track;
+ }
}
}
+ mInbandSubtitleTracks = inbandTracks;
}
- mInbandSubtitleTracks = inbandTracks;
mSubtitleController.selectDefaultTrack();
}
@@ -2224,9 +2227,9 @@
try {
Libcore.os.lseek(fd3, offset2, OsConstants.SEEK_SET);
byte[] buffer = new byte[4096];
- for (int total = 0; total < length2;) {
- int remain = (int)length2 - total;
- int bytes = IoBridge.read(fd3, buffer, 0, Math.min(buffer.length, remain));
+ for (long total = 0; total < length2;) {
+ int bytesToRead = (int) Math.min(buffer.length, length2 - total);
+ int bytes = IoBridge.read(fd3, buffer, 0, bytesToRead);
if (bytes < 0) {
break;
} else {
@@ -2358,6 +2361,18 @@
throws IllegalStateException {
// handle subtitle track through subtitle controller
SubtitleTrack track = null;
+ synchronized (mInbandSubtitleLock) {
+ if (mInbandSubtitleTracks.length == 0) {
+ TrackInfo[] tracks = getInbandTrackInfo();
+ mInbandSubtitleTracks = new SubtitleTrack[tracks.length];
+ for (int i=0; i < tracks.length; i++) {
+ if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+ mInbandSubtitleTracks[i] = mSubtitleController.addTrack(tracks[i].getFormat());
+ }
+ }
+ }
+ }
+
if (index < mInbandSubtitleTracks.length) {
track = mInbandSubtitleTracks[index];
} else if (index < mInbandSubtitleTracks.length + mOutOfBandSubtitleTracks.size()) {
@@ -3256,9 +3271,7 @@
if (DEBUG) Log.d(TAG, "scheduleUpdate");
int i = registerListener(listener);
- if (mStopped) {
- scheduleNotification(NOTIFY_STOP, 0 /* delay */);
- } else {
+ if (!mStopped) {
mTimes[i] = 0;
scheduleNotification(NOTIFY_TIME, 0 /* delay */);
}
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index 37adb8c..f82dbe0 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -275,7 +275,7 @@
mSelectedTrack.getFormat().getInteger(
MediaFormat.KEY_IS_FORCED_SUBTITLE, 0) != 0)) {
show();
- } else {
+ } else if (mSelectedTrack != null && !mSelectedTrack.isTimedText()) {
hide();
}
mVisibilityIsExplicit = false;
diff --git a/media/java/android/media/audiofx/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java
index b314c02..be5adc8 100644
--- a/media/java/android/media/audiofx/Virtualizer.java
+++ b/media/java/android/media/audiofx/Virtualizer.java
@@ -16,11 +16,14 @@
package android.media.audiofx;
+import android.annotation.IntDef;
import android.media.AudioDevice;
import android.media.AudioFormat;
import android.media.audiofx.AudioEffect;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.StringTokenizer;
@@ -248,14 +251,114 @@
}
/**
- * Checks if the combination of a channel mask and device type is supported by this virtualizer.
+ * A virtualization mode indicating virtualization processing is not active.
+ * See {@link #getVirtualizationMode()} as one of the possible return value.
+ */
+ public static final int VIRTUALIZATION_MODE_OFF = 0;
+
+ /**
+ * A virtualization mode used to indicate the virtualizer effect must stop forcing the
+ * processing to a particular mode in {@link #forceVirtualizationMode(int)}.
+ */
+ public static final int VIRTUALIZATION_MODE_AUTO = 1;
+ /**
+ * A virtualization mode typically used over headphones.
+ * Binaural virtualization describes an audio processing configuration for virtualization
+ * where the left and right channels are respectively reaching the left and right ear of the
+ * user, without also feeding the opposite ear (as is the case when listening over speakers).
+ * <p>Such a mode is therefore meant to be used when audio is playing over stereo wired
+ * headphones or headsets, but also stereo headphones through a wireless A2DP Bluetooth link.
+ * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
+ */
+ public final static int VIRTUALIZATION_MODE_BINAURAL = 2;
+
+ /**
+ * A virtualization mode typically used over speakers.
+ * Transaural virtualization describes an audio processing configuration that differs from
+ * binaural (as described in {@link #VIRTUALIZATION_MODE_BINAURAL} in that cross-talk is
+ * present, i.e. audio played from the left channel also reaches the right ear of the user,
+ * and vice-versa.
+ * <p>When supported, such a mode is therefore meant to be used when audio is playing over the
+ * built-in stereo speakers of a device, if they are featured.
+ * <p>See {@link #canVirtualize(int, int)} to verify this mode is supported by this Virtualizer.
+ */
+ public final static int VIRTUALIZATION_MODE_TRANSAURAL = 3;
+
+ /** @hide */
+ @IntDef( {
+ VIRTUALIZATION_MODE_BINAURAL,
+ VIRTUALIZATION_MODE_TRANSAURAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VirtualizationMode {}
+
+ /** @hide */
+ @IntDef( {
+ VIRTUALIZATION_MODE_AUTO,
+ VIRTUALIZATION_MODE_BINAURAL,
+ VIRTUALIZATION_MODE_TRANSAURAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ForceVirtualizationMode {}
+
+ private static int getDeviceForModeQuery(@VirtualizationMode int virtualizationMode)
+ throws IllegalArgumentException {
+ switch (virtualizationMode) {
+ case VIRTUALIZATION_MODE_BINAURAL:
+ return AudioDevice.TYPE_WIRED_HEADPHONES;
+ case VIRTUALIZATION_MODE_TRANSAURAL:
+ return AudioDevice.TYPE_BUILTIN_SPEAKER;
+ default:
+ throw (new IllegalArgumentException(
+ "Virtualizer: illegal virtualization mode " + virtualizationMode));
+ }
+ }
+
+ private static int getDeviceForModeForce(@ForceVirtualizationMode int virtualizationMode)
+ throws IllegalArgumentException {
+ if (virtualizationMode == VIRTUALIZATION_MODE_AUTO) {
+ return AudioDevice.TYPE_UNKNOWN;
+ } else {
+ return getDeviceForModeQuery(virtualizationMode);
+ }
+ }
+
+ private static int deviceToMode(int deviceType) {
+ switch (deviceType) {
+ case AudioDevice.TYPE_WIRED_HEADSET:
+ case AudioDevice.TYPE_WIRED_HEADPHONES:
+ case AudioDevice.TYPE_BLUETOOTH_SCO:
+ case AudioDevice.TYPE_BUILTIN_EARPIECE:
+ return VIRTUALIZATION_MODE_BINAURAL;
+ case AudioDevice.TYPE_BUILTIN_SPEAKER:
+ case AudioDevice.TYPE_LINE_ANALOG:
+ case AudioDevice.TYPE_LINE_DIGITAL:
+ case AudioDevice.TYPE_BLUETOOTH_A2DP:
+ case AudioDevice.TYPE_HDMI:
+ case AudioDevice.TYPE_HDMI_ARC:
+ case AudioDevice.TYPE_USB_DEVICE:
+ case AudioDevice.TYPE_USB_ACCESSORY:
+ case AudioDevice.TYPE_DOCK:
+ case AudioDevice.TYPE_FM:
+ case AudioDevice.TYPE_AUX_LINE:
+ return VIRTUALIZATION_MODE_TRANSAURAL;
+ case AudioDevice.TYPE_UNKNOWN:
+ default:
+ return VIRTUALIZATION_MODE_OFF;
+ }
+ }
+
+ /**
+ * Checks if the combination of a channel mask and virtualization mode is supported by this
+ * virtualizer.
* Some virtualizer implementations may only support binaural processing (i.e. only support
- * headphone output), some may support transaural processing (i.e. for speaker output) for the
+ * headphone output, see {@link #VIRTUALIZATION_MODE_BINAURAL}), some may support transaural
+ * processing (i.e. for speaker output, see {@link #VIRTUALIZATION_MODE_TRANSAURAL}) for the
* built-in speakers. Use this method to query the virtualizer implementation capabilities.
* @param inputChannelMask the channel mask of the content to virtualize.
- * @param deviceType the device type for which virtualization processing is to be performed.
- * Valid values are the device types defined in {@link AudioDevice}.
- * @return true if the combination of channel mask and output device type is supported, false
+ * @param virtualizationMode the mode for which virtualization processing is to be performed,
+ * one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
+ * @return true if the combination of channel mask and virtualization mode is supported, false
* otherwise.
* <br>An indication that a certain channel mask is not supported doesn't necessarily mean
* you cannot play content with that channel mask, it more likely implies the content will
@@ -268,22 +371,22 @@
* @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
- public boolean canVirtualize(int inputChannelMask, int deviceType)
+ public boolean canVirtualize(int inputChannelMask, @VirtualizationMode int virtualizationMode)
throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
- return getAnglesInt(inputChannelMask, deviceType, null);
+ return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), null);
}
/**
* Queries the virtual speaker angles (azimuth and elevation) for a combination of a channel
- * mask and device type.
- * If the virtualization configuration (mask and device) is supported (see
+ * mask and virtualization mode.
+ * If the virtualization configuration (mask and mode) is supported (see
* {@link #canVirtualize(int, int)}, the array angles will contain upon return the
* definition of each virtual speaker and its azimuth and elevation angles relative to the
* listener.
* <br>Note that in some virtualizer implementations, the angles may be strength-dependent.
* @param inputChannelMask the channel mask of the content to virtualize.
- * @param deviceType the device type for which virtualization processing is to be performed.
- * Valid values are the device types defined in {@link AudioDevice}.
+ * @param virtualizationMode the mode for which virtualization processing is to be performed,
+ * one of {@link #VIRTUALIZATION_MODE_BINAURAL}, {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
* @param angles a non-null array whose length is 3 times the number of channels in the channel
* mask.
* If the method indicates the configuration is supported, the array will contain upon return
@@ -297,37 +400,39 @@
* <li>the element at index <code>3*i+2</code> contains its corresponding elevation angle
* where +90 is directly above the listener, 0 is the horizontal plane, and -90 is
* directly below the listener.</li>
- * @return true if the combination of channel mask and output device type is supported, false
+ * @return true if the combination of channel mask and virtualization mode is supported, false
* otherwise.
* @throws IllegalStateException
* @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
- public boolean getSpeakerAngles(int inputChannelMask, int deviceType, int[] angles)
+ public boolean getSpeakerAngles(int inputChannelMask,
+ @VirtualizationMode int virtualizationMode, int[] angles)
throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
if (angles == null) {
throw (new IllegalArgumentException(
"Virtualizer: illegal null channel / angle array"));
}
- return getAnglesInt(inputChannelMask, deviceType, angles);
+ return getAnglesInt(inputChannelMask, getDeviceForModeQuery(virtualizationMode), angles);
}
/**
- * Forces the virtualizer effect to use the processing mode used for the given device type.
+ * Forces the virtualizer effect to use the given processing mode.
* The effect must be enabled for the forced mode to be applied.
- * @param deviceType one of the device types defined in {@link AudioDevice}.
- * Use {@link AudioDevice#DEVICE_TYPE_UNKNOWN} to return to the non-forced mode.
- * @return true if the processing mode for the device type is supported, and it is successfully
- * set, or forcing was successfully disabled with {@link AudioDevice#DEVICE_TYPE_UNKNOWN},
- * false otherwise.
+ * @param virtualizationMode one of {@link #VIRTUALIZATION_MODE_BINAURAL},
+ * {@link #VIRTUALIZATION_MODE_TRANSAURAL} to force a particular processing mode, or
+ * {@value #VIRTUALIZATION_MODE_AUTO} to stop forcing a mode.
+ * @return true if the processing mode is supported, and it is successfully set, or
+ * forcing was successfully disabled, false otherwise.
* @throws IllegalStateException
* @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
- public boolean forceVirtualizationMode(int deviceType)
+ public boolean forceVirtualizationMode(@ForceVirtualizationMode int virtualizationMode)
throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
// convert Java device type to internal representation
+ int deviceType = getDeviceForModeForce(virtualizationMode);
int internalDevice = AudioDevice.convertDeviceTypeToInternalDevice(deviceType);
int status = setParameter(PARAM_FORCE_VIRTUALIZATION_MODE, internalDevice);
@@ -335,8 +440,8 @@
if (status >= 0) {
return true;
} else if (status == AudioEffect.ERROR_BAD_VALUE) {
- // a BAD_VALUE return from setParameter indicates the mode can't be forced to that
- // of this device, don't throw an exception, just return false
+ // a BAD_VALUE return from setParameter indicates the mode can't be forced
+ // don't throw an exception, just return false
return false;
} else {
// something wrong may have happened
@@ -349,31 +454,25 @@
}
/**
- * Return the device type which reflects the virtualization mode being used, if any.
- * @return a device type (as defined in {@link AudioDevice}) which reflects the virtualization
- * mode being used.
- * If virtualization is not active, the device type will be
- * {@link AudioDevice#DEVICE_TYPE_UNKNOWN}. Virtualization may not be active either because
- * the effect is not enabled or because the current output device is not compatible with
- * this virtualization implementation.
- * <p>Note that the return value may differ from a device type successfully set with
- * {@link #forceVirtualizationMode(int)} as the implementation
- * may use a single mode for multiple devices. An example of this is with
- * {@link AudioDevice#DEVICE_TYPE_WIRED_HEADSET} that would typically be handled
- * like {@link AudioDevice#DEVICE_TYPE_WIRED_HEADPHONES} from a virtualization
- * standpoint.
+ * Return the virtualization mode being used, if any.
+ * @return the virtualization mode being used.
+ * If virtualization is not active, the virtualization mode will be
+ * {@link #VIRTUALIZATION_MODE_OFF}. Otherwise the value will be
+ * {@link #VIRTUALIZATION_MODE_BINAURAL} or {@link #VIRTUALIZATION_MODE_TRANSAURAL}.
+ * Virtualization may not be active either because the effect is not enabled or
+ * because the current output device is not compatible with this virtualization
+ * implementation.
* @throws IllegalStateException
- * @throws IllegalArgumentException
* @throws UnsupportedOperationException
*/
public int getVirtualizationMode()
- throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+ throws IllegalStateException, UnsupportedOperationException {
int[] value = new int[1];
int status = getParameter(PARAM_VIRTUALIZATION_MODE, value);
if (status >= 0) {
- return AudioDevice.convertInternalDeviceToDeviceType(value[0]);
+ return deviceToMode(AudioDevice.convertInternalDeviceToDeviceType(value[0]));
} else if (status == AudioEffect.ERROR_BAD_VALUE) {
- return AudioDevice.DEVICE_TYPE_UNKNOWN;
+ return VIRTUALIZATION_MODE_OFF;
} else {
// something wrong may have happened
checkStatus(status);
@@ -381,7 +480,7 @@
// unexpected virtualizer behavior
Log.e(TAG, "unexpected status code " + status
+ " after getParameter(PARAM_VIRTUALIZATION_MODE)");
- return AudioDevice.DEVICE_TYPE_UNKNOWN;
+ return VIRTUALIZATION_MODE_OFF;
}
/**
diff --git a/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index cfd5db3..0000000
--- a/packages/Keyguard/res/drawable-hdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index e3cb6db..0000000
--- a/packages/Keyguard/res/drawable-mdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png b/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
deleted file mode 100644
index b9e30e2..0000000
--- a/packages/Keyguard/res/drawable-xhdpi/kg_bouncer_bg_white.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
index 8c8ec7a..0c85dab 100644
--- a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
@@ -36,7 +36,6 @@
<FrameLayout
android:id="@+id/keyguard_bouncer_frame"
- android:background="@drawable/kg_bouncer_bg_white"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index 9e886f2..b7d5d30 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -42,7 +42,6 @@
<!-- Password entry field -->
<FrameLayout
android:id="@+id/keyguard_bouncer_frame"
- android:background="@drawable/kg_bouncer_bg_white"
android:layout_height="wrap_content"
android:layout_width="280dp"
android:layout_gravity="center_horizontal"
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index a126465..bd585b5 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -49,7 +49,6 @@
<FrameLayout
android:id="@+id/keyguard_bouncer_frame"
- android:background="@drawable/kg_bouncer_bg_white"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_selector_view.xml b/packages/Keyguard/res/layout/keyguard_selector_view.xml
index d3064ed..5330363 100644
--- a/packages/Keyguard/res/layout/keyguard_selector_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_selector_view.xml
@@ -48,8 +48,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:background="@drawable/kg_bouncer_bg_white"/>
+ android:layout_marginRight="16dp"/>
<include layout="@layout/keyguard_glow_pad_container" />
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index 2d20b02..d539856 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -152,6 +152,11 @@
mKlondikeText.layout(left, top, left + mKlondikeText.getMeasuredWidth(), bottom);
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
if (mEnableHaptics) {
diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
index f3ba3a7..6497f46 100644
--- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
@@ -145,6 +145,11 @@
}
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
private Rect getCharBounds() {
float textHeight = mTextHeightRaw * getResources().getDisplayMetrics().scaledDensity;
mDrawPaint.setTextSize(textHeight);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index ce0b9b6..b6c36c7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -442,7 +442,8 @@
* mPreviewPageMargin);
final int verticalPadding;
- if (mPageContentHeight + mFooterHeight + mPreviewListPadding > availableHeight) {
+ if (mPageContentHeight + mFooterHeight + mPreviewListPadding
+ + 2 * mPreviewPageMargin > availableHeight) {
verticalPadding = Math.max(0,
(availableHeight - mPageContentHeight - mFooterHeight) / 2
- mPreviewPageMargin);
diff --git a/packages/SystemUI/res/layout/notification_public_default.xml b/packages/SystemUI/res/layout/notification_public_default.xml
new file mode 100644
index 0000000..acfc4bb
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_public_default.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+ android:id="@+id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ internal:layout_minHeight="64dp"
+ internal:layout_maxHeight="64dp"
+ >
+ <ImageView android:id="@+id/icon"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="12dp"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ android:scaleType="centerInside"
+ />
+ <DateTimeView android:id="@+id/time"
+ android:textAppearance="@android:style/TextAppearance.Material.Notification.Time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_alignParentEnd="true"
+ android:layout_alignBaseline="@id/title"
+ android:singleLine="true"
+ android:gravity="center"
+ android:paddingStart="8dp"
+ android:visibility="gone"
+ />
+ <TextView android:id="@+id/title"
+ android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_toEndOf="@id/icon"
+ android:layout_toStartOf="@id/time"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ <ImageView android:id="@+id/profile_badge_line3"
+ android:layout_width="@*android:dimen/notification_badge_size"
+ android:layout_height="@*android:dimen/notification_badge_size"
+ android:layout_below="@id/title"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_alignParentEnd="true"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ />
+ <TextView android:id="@+id/text"
+ android:textAppearance="@android:style/TextAppearance.Material.Notification"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignStart="@id/title"
+ android:layout_below="@id/title"
+ android:layout_toStartOf="@id/profile_badge_line3"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 5cdf819..2eb99ba 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -40,7 +40,6 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:minWidth="132dp"
- android:text="@string/quick_settings_more_settings"
android:textAppearance="@style/TextAppearance.QS.DetailButton"
android:focusable="true" />
@@ -50,9 +49,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="88dp"
- android:text="@string/quick_settings_done"
android:textAppearance="@style/TextAppearance.QS.DetailButton"
android:focusable="true"/>
</LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 6b829e5..e9d86d6 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -52,9 +52,10 @@
android:paddingStart="8dp"
/>
- <include
- layout="@layout/notification_guts"
- android:id="@+id/notification_guts"
+ <ViewStub
+ android:layout="@layout/notification_guts"
+ android:id="@+id/notification_guts_stub"
+ android:inflatedId="@+id/notification_guts"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 147efaf..0445fe8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -736,9 +736,6 @@
<!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
<string name="camera_hint">Swipe left for camera</string>
- <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_forever">Indefinitely</string>
-
<!-- Interruption level: None. [CHAR LIMIT=20] -->
<string name="interruption_level_none">None</string>
@@ -805,18 +802,6 @@
<string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
- <!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one">For one minute</item>
- <item quantity="other">For %d minutes</item>
- </plurals>
-
- <!-- Zen mode condition: time duration in hours. [CHAR LIMIT=NONE] -->
- <plurals name="zen_mode_duration_hours">
- <item quantity="one">For one hour</item>
- <item quantity="other">For %d hours</item>
- </plurals>
-
<!-- Battery saver notification title. [CHAR LIMIT=60]-->
<string name="battery_saver_notification_title">Battery saver is on</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
index b86e67c..a9fdc86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
@@ -23,7 +23,6 @@
import android.text.TextUtils.TruncateAt;
import android.view.Gravity;
import android.view.View;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -41,7 +40,7 @@
* truncate.
* Second line: ellipsis if necessary
*/
-public class QSDualTileLabel extends FrameLayout {
+public class QSDualTileLabel extends LinearLayout {
private final Context mContext;
private final TextView mFirstLine;
@@ -54,6 +53,7 @@
public QSDualTileLabel(Context context) {
super(context);
mContext = context;
+ setOrientation(LinearLayout.VERTICAL);
mHorizontalPaddingPx = mContext.getResources()
.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_horizontal);
@@ -70,13 +70,13 @@
mFirstLineCaret.setScaleType(ImageView.ScaleType.MATRIX);
mFirstLineCaret.setClickable(false);
firstLineLayout.addView(mFirstLineCaret);
- addView(firstLineLayout, newFrameLayoutParams());
+ addView(firstLineLayout, newLinearLayoutParams());
mSecondLine = initTextView();
mSecondLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
mSecondLine.setEllipsize(TruncateAt.END);
mSecondLine.setVisibility(GONE);
- addView(mSecondLine, newFrameLayoutParams());
+ addView(mSecondLine, newLinearLayoutParams());
addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
@@ -89,7 +89,7 @@
});
}
- private static LayoutParams newFrameLayoutParams() {
+ private static LayoutParams newLinearLayoutParams() {
final LayoutParams lp =
new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER_HORIZONTAL;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 6bfe0a4..2fafb2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -89,6 +89,7 @@
mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2);
mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1);
+ updateDetailText();
mDetail.setVisibility(GONE);
mDetail.setClickable(true);
mBrightnessView = LayoutInflater.from(context).inflate(
@@ -112,6 +113,11 @@
});
}
+ private void updateDetailText() {
+ mDetailDoneButton.setText(R.string.quick_settings_done);
+ mDetailSettingsButton.setText(R.string.quick_settings_more_settings);
+ }
+
public void setBrightnessMirror(BrightnessMirrorController c) {
super.onFinishInflate();
ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
@@ -150,6 +156,7 @@
if (mListening) {
refreshAllTiles();
}
+ updateDetailText();
}
@Override
@@ -525,6 +532,12 @@
};
private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() {
+ public void onAnimationCancel(Animator animation) {
+ // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get
+ // called, this will avoid accidentally turning off the grid when we don't want to.
+ animation.removeListener(this);
+ };
+
@Override
public void onAnimationEnd(Animator animation) {
setGridContentVisibility(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 4d85352..907a13f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -69,6 +69,7 @@
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewStub;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
@@ -764,17 +765,95 @@
}, false /* afterKeyguardGone */);
}
+ private void inflateGuts(ExpandableNotificationRow row) {
+ ViewStub stub = (ViewStub) row.findViewById(R.id.notification_guts_stub);
+ if (stub != null) {
+ stub.inflate();
+ }
+ final StatusBarNotification sbn = row.getStatusBarNotification();
+ PackageManager pmUser = getPackageManagerForUser(
+ sbn.getUser().getIdentifier());
+ row.setTag(sbn.getPackageName());
+ final View guts = row.findViewById(R.id.notification_guts);
+ final String pkg = sbn.getPackageName();
+ String appname = pkg;
+ Drawable pkgicon = null;
+ int appUid = -1;
+ try {
+ final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS);
+ if (info != null) {
+ appname = String.valueOf(pmUser.getApplicationLabel(info));
+ pkgicon = pmUser.getApplicationIcon(info);
+ appUid = info.uid;
+ }
+ } catch (NameNotFoundException e) {
+ // app is gone, just show package name and generic icon
+ pkgicon = pmUser.getDefaultActivityIcon();
+ }
+ ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
+ ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(sbn.getPostTime());
+ ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
+ final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
+ final View appSettingsButton
+ = guts.findViewById(R.id.notification_inspect_app_provided_settings);
+ if (appUid >= 0) {
+ final int appUidF = appUid;
+ settingsButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ startAppNotificationSettingsActivity(pkg, appUidF);
+ }
+ });
+
+ final Intent appSettingsQueryIntent
+ = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+ .setPackage(pkg);
+ List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
+ if (infos.size() > 0) {
+ appSettingsButton.setVisibility(View.VISIBLE);
+ appSettingsButton.setContentDescription(
+ mContext.getResources().getString(
+ R.string.status_bar_notification_app_settings_title,
+ appname
+ ));
+ final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
+ .setClassName(pkg, infos.get(0).activityInfo.name);
+ appSettingsButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
+ sbn.getId(),
+ sbn.getTag(),
+ appUidF);
+ }
+ });
+ } else {
+ appSettingsButton.setVisibility(View.GONE);
+ }
+ } else {
+ settingsButton.setVisibility(View.GONE);
+ appSettingsButton.setVisibility(View.GONE);
+ }
+
+ }
+
protected SwipeHelper.LongPressListener getNotificationLongClicker() {
return new SwipeHelper.LongPressListener() {
@Override
public boolean onLongPress(View v, int x, int y) {
dismissPopups();
+ if (!(v instanceof ExpandableNotificationRow)) {
+ return false;
+ }
if (v.getWindowToken() == null) {
Log.e(TAG, "Trying to show notification guts, but not attached to window");
return false;
}
+ inflateGuts((ExpandableNotificationRow) v);
+
// Assume we are a status_bar_notification_row
final NotificationGuts guts = (NotificationGuts) v.findViewById(
R.id.notification_guts);
@@ -1190,67 +1269,6 @@
row.setExpansionLogger(this, entry.notification.getKey());
}
- // the notification inspector (see SwipeHelper.setLongPressListener)
- row.setTag(sbn.getPackageName());
- final View guts = row.findViewById(R.id.notification_guts);
- final String pkg = entry.notification.getPackageName();
- String appname = pkg;
- Drawable pkgicon = null;
- int appUid = -1;
- try {
- final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
- PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
- if (info != null) {
- appname = String.valueOf(pmUser.getApplicationLabel(info));
- pkgicon = pmUser.getApplicationIcon(info);
- appUid = info.uid;
- }
- } catch (NameNotFoundException e) {
- // app is gone, just show package name and generic icon
- pkgicon = pmUser.getDefaultActivityIcon();
- }
- ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
- ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(entry.notification.getPostTime());
- ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
- final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
- final View appSettingsButton
- = guts.findViewById(R.id.notification_inspect_app_provided_settings);
- if (appUid >= 0) {
- final int appUidF = appUid;
- settingsButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- startAppNotificationSettingsActivity(pkg, appUidF);
- }
- });
-
- final Intent appSettingsQueryIntent
- = new Intent(Intent.ACTION_MAIN)
- .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
- .setPackage(pkg);
- List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
- if (infos.size() > 0) {
- appSettingsButton.setVisibility(View.VISIBLE);
- appSettingsButton.setContentDescription(
- mContext.getResources().getString(
- R.string.status_bar_notification_app_settings_title,
- appname
- ));
- final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
- .setClassName(pkg, infos.get(0).activityInfo.name);
- appSettingsButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
- sbn.getId(),
- sbn.getTag(),
- appUidF);
- }
- });
- }
- } else {
- settingsButton.setVisibility(View.GONE);
- appSettingsButton.setVisibility(View.GONE);
- }
-
workAroundBadLayerDrawableOpacity(row);
View vetoButton = updateNotificationVetoButton(row, sbn);
vetoButton.setContentDescription(mContext.getString(
@@ -1331,12 +1349,12 @@
if (publicViewLocal == null) {
// Add a basic notification template
publicViewLocal = LayoutInflater.from(mContext).inflate(
- com.android.internal.R.layout.notification_template_material_base,
+ R.layout.notification_public_default,
expandedPublic, false);
publicViewLocal.setIsRootNamespace(true);
expandedPublic.setContractedChild(publicViewLocal);
- final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
+ final TextView title = (TextView) publicViewLocal.findViewById(R.id.title);
try {
title.setText(pmUser.getApplicationLabel(
pmUser.getApplicationInfo(entry.notification.getPackageName(), 0)));
@@ -1344,10 +1362,9 @@
title.setText(entry.notification.getPackageName());
}
- final ImageView icon = (ImageView) publicViewLocal.findViewById(
- com.android.internal.R.id.icon);
+ final ImageView icon = (ImageView) publicViewLocal.findViewById(R.id.icon);
final ImageView profileBadge = (ImageView) publicViewLocal.findViewById(
- com.android.internal.R.id.profile_badge_line3);
+ R.id.profile_badge_line3);
final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(),
entry.notification.getUser(),
@@ -1383,16 +1400,13 @@
}
final View privateTime = contentViewLocal.findViewById(com.android.internal.R.id.time);
+ final DateTimeView time = (DateTimeView) publicViewLocal.findViewById(R.id.time);
if (privateTime != null && privateTime.getVisibility() == View.VISIBLE) {
- final View timeStub = publicViewLocal.findViewById(com.android.internal.R.id.time);
- timeStub.setVisibility(View.VISIBLE);
- final DateTimeView dateTimeView = (DateTimeView)
- publicViewLocal.findViewById(com.android.internal.R.id.time);
- dateTimeView.setTime(entry.notification.getNotification().when);
+ time.setVisibility(View.VISIBLE);
+ time.setTime(entry.notification.getNotification().when);
}
- final TextView text = (TextView) publicViewLocal.findViewById(
- com.android.internal.R.id.text);
+ final TextView text = (TextView) publicViewLocal.findViewById(R.id.text);
if (text != null) {
text.setText(R.string.notification_hidden_text);
text.setTextAppearance(mContext,
@@ -1432,7 +1446,7 @@
row.setUserExpanded(userExpanded);
}
row.setUserLocked(userLocked);
-
+ row.setStatusBarNotification(entry.notification);
return true;
}
@@ -1946,6 +1960,7 @@
} else {
entry.row.setOnClickListener(null);
}
+ entry.row.setStatusBarNotification(notification);
entry.row.notifyContentUpdated();
entry.row.resetHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index c13593a..2ad6859 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -20,9 +20,11 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
@@ -67,6 +69,8 @@
private boolean mWasReset;
private NotificationGuts mGuts;
+ private StatusBarNotification mStatusBarNotification;
+
public void setIconAnimationRunning(boolean running) {
setIconAnimationRunning(running, mPublicLayout);
setIconAnimationRunning(running, mPrivateLayout);
@@ -112,6 +116,14 @@
}
}
+ public void setStatusBarNotification(StatusBarNotification statusBarNotification) {
+ mStatusBarNotification = statusBarNotification;
+ }
+
+ public StatusBarNotification getStatusBarNotification() {
+ return mStatusBarNotification;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -155,7 +167,15 @@
super.onFinishInflate();
mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
- mGuts = (NotificationGuts) findViewById(R.id.notification_guts);
+ ViewStub gutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
+ gutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+ @Override
+ public void onInflate(ViewStub stub, View inflated) {
+ mGuts = (NotificationGuts) inflated;
+ mGuts.setClipTopAmount(getClipTopAmount());
+ mGuts.setActualHeight(getActualHeight());
+ }
+ });
mVetoButton = findViewById(R.id.veto);
}
@@ -421,7 +441,9 @@
public void setActualHeight(int height, boolean notifyListeners) {
mPrivateLayout.setActualHeight(height);
mPublicLayout.setActualHeight(height);
- mGuts.setActualHeight(height);
+ if (mGuts != null) {
+ mGuts.setActualHeight(height);
+ }
invalidate();
super.setActualHeight(height, notifyListeners);
}
@@ -443,7 +465,9 @@
super.setClipTopAmount(clipTopAmount);
mPrivateLayout.setClipTopAmount(clipTopAmount);
mPublicLayout.setClipTopAmount(clipTopAmount);
- mGuts.setClipTopAmount(clipTopAmount);
+ if (mGuts != null) {
+ mGuts.setClipTopAmount(clipTopAmount);
+ }
}
public void notifyContentUpdated() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 9585e17..902123d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -631,9 +631,10 @@
}
private boolean isInQsArea(float x, float y) {
- return mStatusBarState != StatusBarState.SHADE
- || y <= mNotificationStackScroller.getBottomMostNotificationBottom()
- || y <= mQsContainer.getY() + mQsContainer.getHeight();
+ return mStatusBarState != StatusBarState.SHADE ||
+ (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) &&
+ (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+ || y <= mQsContainer.getY() + mQsContainer.getHeight());
}
private void handleQsDown(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7261ea1..2f21781 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -684,7 +684,7 @@
removeCallbacks(mPeekRunnable);
mPeekRunnable.run();
}
- } else if (!isFullyCollapsed() && !mTracking) {
+ } else if (!isFullyCollapsed() && !mTracking && !mClosing) {
if (mHeightAnimator != null) {
mHeightAnimator.cancel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 6949ffb..fa43f32 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -431,6 +431,9 @@
public void onConfigurationChanged(Configuration newConfig) {
updateWidth();
+ if (mZenPanel != null) {
+ mZenPanel.updateLocale();
+ }
}
private void updateWidth() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index ac7fc25..f829994 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -60,7 +60,7 @@
private static final int[] MINUTE_BUCKETS = DEBUG
? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
- : new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+ : ZenModeConfig.MINUTE_BUCKETS;
private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
@@ -68,7 +68,6 @@
private static final int TIME_CONDITION_INDEX = 1;
private static final int FIRST_CONDITION_INDEX = 2;
private static final float SILENT_HINT_PULSE_SCALE = 1.1f;
- private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -121,10 +120,7 @@
super.onFinishInflate();
mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
- mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
- mZenButtons.addButton(R.string.interruption_level_priority,
- Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
+ addZenButtons();
mZenButtons.setCallback(mZenButtonsCallback);
mZenSubhead = findViewById(R.id.zen_subhead);
@@ -174,6 +170,13 @@
setExpanded(false);
}
+ private void addZenButtons() {
+ mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
+ mZenButtons.addButton(R.string.interruption_level_priority,
+ Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
+ }
+
public void setHidden(boolean hidden) {
if (mHidden == hidden) return;
mHidden = hidden;
@@ -213,7 +216,7 @@
mBucketIndex = -1;
} else {
mBucketIndex = DEFAULT_BUCKET_INDEX;
- mTimeCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
}
if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
mConditions = null; // reset conditions
@@ -234,6 +237,11 @@
mController.addCallback(mZenCallback);
}
+ public void updateLocale() {
+ mZenButtons.removeAllViews();
+ addZenButtons();
+ }
+
private void setExitCondition(Condition exitCondition) {
if (sameConditionId(mExitCondition, exitCondition)) return;
mExitCondition = exitCondition;
@@ -254,7 +262,7 @@
}
private void refreshExitConditionText() {
- final String forever = mContext.getString(R.string.zen_mode_forever);
+ final String forever = mContext.getString(com.android.internal.R.string.zen_mode_forever);
if (mExitCondition == null) {
mExitConditionText = forever;
} else if (ZenModeConfig.isValidCountdownConditionId(mExitCondition.id)) {
@@ -330,24 +338,7 @@
if (time == 0) return null;
final long span = time - System.currentTimeMillis();
if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
- return timeCondition(time, Math.round(span / (float)MINUTES_MS));
- }
-
- private Condition newTimeCondition(int minutesFromNow) {
- final long now = System.currentTimeMillis();
- final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
- return timeCondition(now + millis, minutesFromNow);
- }
-
- private Condition timeCondition(long time, int minutes) {
- final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
- final int resId = minutes < 60
- ? R.plurals.zen_mode_duration_minutes
- : R.plurals.zen_mode_duration_hours;
- final String caption = mContext.getResources().getQuantityString(resId, num, num);
- final Uri id = ZenModeConfig.toCountdownConditionId(time);
- return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
- Condition.FLAG_RELEVANT_NOW);
+ return ZenModeConfig.toTimeCondition(time, Math.round(span / (float) MINUTES_MS));
}
private void handleUpdateConditions(Condition[] conditions) {
@@ -401,7 +392,7 @@
if (favoriteIndex == -1) {
getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
} else {
- mTimeCondition = newTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
+ mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
mBucketIndex = favoriteIndex;
bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true);
@@ -457,7 +448,7 @@
});
final TextView title = (TextView) row.findViewById(android.R.id.title);
if (condition == null) {
- title.setText(R.string.zen_mode_forever);
+ title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
} else {
title.setText(condition.summary);
}
@@ -494,7 +485,7 @@
} else {
final long span = time - System.currentTimeMillis();
button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
- final Condition maxCondition = newTimeCondition(MAX_BUCKET_MINUTES);
+ final Condition maxCondition = ZenModeConfig.toTimeCondition(MAX_BUCKET_MINUTES);
button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
}
@@ -520,18 +511,18 @@
final long bucketTime = now + bucketMinutes * MINUTES_MS;
if (up && bucketTime > time || !up && bucketTime < time) {
mBucketIndex = j;
- newCondition = timeCondition(bucketTime, bucketMinutes);
+ newCondition = ZenModeConfig.toTimeCondition(bucketTime, bucketMinutes);
break;
}
}
if (newCondition == null) {
mBucketIndex = DEFAULT_BUCKET_INDEX;
- newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
}
} else {
// on a known index, simply increment or decrement
mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
- newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
}
mTimeCondition = newCondition;
bind(mTimeCondition, row);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3062a92..75090db 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4746,6 +4746,11 @@
private void updateNetworkScore(NetworkAgentInfo nai, int score) {
if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+ if (score < 0) {
+ loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
+ "). Bumping score to min of 0");
+ score = 0;
+ }
nai.currentScore = score;
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index c8718e3e..060c8e3 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -106,6 +106,7 @@
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@@ -3455,9 +3456,14 @@
parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
final boolean isAuxiliary = "1".equals(String.valueOf(
parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
- final InputMethodSubtype subtype =
- new InputMethodSubtype(label, icon, imeSubtypeLocale,
- imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
+ final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
+ .setSubtypeNameResId(label)
+ .setSubtypeIconResId(icon)
+ .setSubtypeLocale(imeSubtypeLocale)
+ .setSubtypeMode(imeSubtypeMode)
+ .setSubtypeExtraValue(imeSubtypeExtraValue)
+ .setIsAuxiliary(isAuxiliary)
+ .build();
tempSubtypesArray.add(subtype);
}
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index f6beb9a..9292d45 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -16,6 +16,7 @@
package com.android.server.content;
+import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
@@ -478,7 +479,7 @@
mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
UserHandle.ALL,
new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
- null, null);
+ Manifest.permission.ACCOUNT_MANAGER, null);
}
// Pick a random second in a day to seed all periodic syncs
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c8b5b3e..fefbe0a 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -33,6 +33,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
@@ -48,6 +49,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -97,6 +99,7 @@
private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
/* package */ final TrustArchive mArchive = new TrustArchive();
private final Context mContext;
+ private final LockPatternUtils mLockPatternUtils;
private UserManager mUserManager;
@@ -104,6 +107,7 @@
super(context);
mContext = context;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mLockPatternUtils = new LockPatternUtils(context);
}
@Override
@@ -116,6 +120,7 @@
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
mReceiver.register(mContext);
+ maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
refreshAgentList(UserHandle.USER_ALL);
}
}
@@ -159,6 +164,11 @@
void refreshAgentList(int userId) {
if (DEBUG) Slog.d(TAG, "refreshAgentList()");
+ if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
+ Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+ + " must be USER_ALL or a specific user.", new Throwable("here"));
+ userId = UserHandle.USER_ALL;
+ }
PackageManager pm = mContext.getPackageManager();
List<UserInfo> userInfos;
@@ -168,12 +178,13 @@
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userId));
}
- LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+ LockPatternUtils lockPatternUtils = mLockPatternUtils;
ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
obsoleteAgents.addAll(mActiveAgents);
for (UserInfo userInfo : userInfos) {
+ if (!userInfo.supportsSwitchTo()) continue;
if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
@@ -186,22 +197,11 @@
if (enabledAgents == null) {
continue;
}
- List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
- PackageManager.GET_META_DATA, userInfo.id);
+ List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
for (ResolveInfo resolveInfo : resolveInfos) {
- if (resolveInfo.serviceInfo == null) continue;
-
- String packageName = resolveInfo.serviceInfo.packageName;
- if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
- != PackageManager.PERMISSION_GRANTED) {
- Log.w(TAG, "Skipping agent because package " + packageName
- + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
- continue;
- }
-
ComponentName name = getComponentName(resolveInfo);
- if (!enabledAgents.contains(name)) continue;
+ if (!enabledAgents.contains(name)) continue;
if (disableTrustAgents) {
List<String> features =
dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
@@ -228,11 +228,13 @@
boolean trustMayHaveChanged = false;
for (int i = 0; i < obsoleteAgents.size(); i++) {
AgentInfo info = obsoleteAgents.valueAt(i);
- if (info.agent.isManagingTrust()) {
- trustMayHaveChanged = true;
+ if (userId == UserHandle.USER_ALL || userId == info.userId) {
+ if (info.agent.isManagingTrust()) {
+ trustMayHaveChanged = true;
+ }
+ info.agent.unbind();
+ mActiveAgents.remove(info);
}
- info.agent.unbind();
- mActiveAgents.remove(info);
}
if (trustMayHaveChanged) {
@@ -342,6 +344,54 @@
return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
}
+ private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
+ if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
+ return;
+ }
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
+ ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ ComponentName componentName = getComponentName(resolveInfo);
+ int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
+ if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
+ + "is not a system package.");
+ continue;
+ }
+ discoveredAgents.add(componentName);
+ }
+
+ List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
+ if (previouslyEnabledAgents != null) {
+ discoveredAgents.addAll(previouslyEnabledAgents);
+ }
+ utils.setEnabledTrustAgents(discoveredAgents, userId);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
+ }
+
+ private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
+ List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+ 0 /* flags */, userId);
+ ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ if (resolveInfo.serviceInfo == null) continue;
+ if (resolveInfo.serviceInfo.applicationInfo == null) continue;
+ String packageName = resolveInfo.serviceInfo.packageName;
+ if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
+ != PackageManager.PERMISSION_GRANTED) {
+ ComponentName name = getComponentName(resolveInfo);
+ Log.w(TAG, "Skipping agent " + name + " because package does not have"
+ + " permission " + PERMISSION_PROVIDE_AGENT + ".");
+ continue;
+ }
+ allowedAgents.add(resolveInfo);
+ }
+ return allowedAgents;
+ }
+
// Agent dispatch and aggregation
private boolean aggregateIsTrusted(int userId) {
@@ -414,6 +464,7 @@
}
}
mTrustListeners.add(listener);
+ updateTrustAll();
}
private void removeListener(ITrustListener listener) {
@@ -616,12 +667,19 @@
@Override
public void onReceive(Context context, Intent intent) {
- if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
- intent.getAction())) {
+ String action = intent.getAction();
+ if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
refreshAgentList(getSendingUserId());
updateDevicePolicyFeatures();
- } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+ } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
updateUserHasAuthenticated(getSendingUserId());
+ } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
+ if (userId > 0) {
+ maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
+ } else {
+ Log.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
+ }
}
}
@@ -629,6 +687,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
filter.addAction(Intent.ACTION_USER_PRESENT);
+ filter.addAction(Intent.ACTION_USER_ADDED);
context.registerReceiverAsUser(this,
UserHandle.ALL,
filter,
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 348c36c..8b8e8eb 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -60,13 +60,14 @@
if (connection != NULL_CONNECTION && mPendingConnections.contains(connection)) {
mPendingConnections.remove(connection);
// Unconditionally initialize the connection ...
- connection.setState(parcel.getState());
connection.setCallCapabilities(parcel.getCapabilities());
connection.setHandle(
parcel.getHandle(), parcel.getHandlePresentation());
connection.setCallerDisplayName(
parcel.getCallerDisplayName(),
parcel.getCallerDisplayNamePresentation());
+ // Set state after handle so that the client can identify the connection.
+ connection.setState(parcel.getState());
List<RemoteConnection> conferenceable = new ArrayList<>();
for (String confId : parcel.getConferenceableConnectionIds()) {
if (mConnectionById.containsKey(confId)) {
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 65c00bd..aaa2f98 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -76,6 +76,8 @@
public static final int REASON_INVALID_LISTENER = -2;
/** Invalid request */
public static final int REASON_INVALID_REQUEST = -3;
+ /** Invalid request */
+ public static final int REASON_NOT_AUTHORIZED = -4;
/** @hide */
public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";